Merge "Allow OVERLAY frames to use the show_exsiting_frame flag" into nextgenv2
diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h
index 6314e05..4c46cbb 100644
--- a/vp10/common/blockd.h
+++ b/vp10/common/blockd.h
@@ -388,6 +388,9 @@
int corrupted;
struct vpx_internal_error_info *error_info;
+#if CONFIG_GLOBAL_MOTION
+ Global_Motion_Params *global_motion;
+#endif // CONFIG_GLOBAL_MOTION
} MACROBLOCKD;
static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h
index 71e79d9..a898038 100644
--- a/vp10/common/entropymode.h
+++ b/vp10/common/entropymode.h
@@ -118,6 +118,9 @@
vpx_prob ext_intra_probs[PLANE_TYPES];
vpx_prob intra_filter_probs[INTRA_FILTERS + 1][INTRA_FILTERS - 1];
#endif // CONFIG_EXT_INTRA
+#if CONFIG_GLOBAL_MOTION
+ vpx_prob global_motion_types_prob[GLOBAL_MOTION_TYPES - 1];
+#endif // CONFIG_GLOBAL_MOTION
} FRAME_CONTEXT;
typedef struct FRAME_COUNTS {
diff --git a/vp10/common/entropymv.c b/vp10/common/entropymv.c
index 87c6421..ae6209d 100644
--- a/vp10/common/entropymv.c
+++ b/vp10/common/entropymv.c
@@ -120,6 +120,17 @@
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10
};
+#if CONFIG_GLOBAL_MOTION
+const vpx_tree_index vp10_global_motion_types_tree
+ [TREE_SIZE(GLOBAL_MOTION_TYPES)] = {
+ -GLOBAL_ZERO, 2,
+ -GLOBAL_TRANSLATION, -GLOBAL_ROTZOOM
+};
+
+static const vpx_prob default_global_motion_types_prob
+ [GLOBAL_MOTION_TYPES - 1] = {224, 128};
+#endif // CONFIG_GLOBAL_MOTION
+
static INLINE int mv_class_base(MV_CLASS_TYPE c) {
return c ? CLASS0_SIZE << (c + 2) : 0;
}
@@ -277,4 +288,7 @@
#else
cm->fc->nmvc = default_nmv_context;
#endif
+#if CONFIG_GLOBAL_MOTION
+ vp10_copy(cm->fc->global_motion_types_prob, default_global_motion_types_prob);
+#endif // CONFIG_GLOBAL_MOTION
}
diff --git a/vp10/common/entropymv.h b/vp10/common/entropymv.h
index f8ade34..af69a2d 100644
--- a/vp10/common/entropymv.h
+++ b/vp10/common/entropymv.h
@@ -132,6 +132,11 @@
void vp10_inc_mv(const MV *mv, nmv_context_counts *mvctx, const int usehp);
+#if CONFIG_GLOBAL_MOTION
+extern const vpx_tree_index vp10_global_motion_types_tree
+ [TREE_SIZE(GLOBAL_MOTION_TYPES)];
+#endif // CONFIG_GLOBAL_MOTION
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp10/common/mv.h b/vp10/common/mv.h
index 8b9348b..255a724 100644
--- a/vp10/common/mv.h
+++ b/vp10/common/mv.h
@@ -13,6 +13,9 @@
#include "vp10/common/common.h"
#include "vpx_dsp/vpx_filter.h"
+#if CONFIG_GLOBAL_MOTION
+#include "vp10/common/warped_motion.h"
+#endif // CONFIG_GLOBAL_MOTION
#ifdef __cplusplus
extern "C" {
@@ -33,6 +36,64 @@
int32_t col;
} MV32;
+#if CONFIG_GLOBAL_MOTION
+// ALPHA here refers to parameters a and b in rotzoom model:
+// | a b|
+// |-b a|
+//
+// Anything ending in PREC_BITS is the number of bits of precision
+// to maintain when converting from double to integer.
+//
+// The ABS parameters are used to create an upper and lower bound
+// for each parameter. In other words, after a parameter is integerized
+// it is clamped between -(1 << ABS_XXX_BITS) and (1 << ABS_XXX_BITS)
+//
+// XXX_PREC_DIFF and XXX_DECODE_FACTOR are computed once here to
+// prevent repetetive computation on the decoder side. These are
+// to allow the global motion parameters to be encoded in a lower
+// precision than the warped model precision. This means that they
+// need to be changed to warped precision when they are decoded.
+//
+// XX_MIN, XX_MAX are also computed to avoid repeated computation
+
+#define GM_TRANS_PREC_BITS 3
+#define GM_TRANS_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_TRANS_PREC_BITS)
+#define GM_TRANS_DECODE_FACTOR (1 << GM_TRANS_PREC_DIFF)
+
+#define GM_ALPHA_PREC_BITS 5
+#define GM_ALPHA_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_ALPHA_PREC_BITS)
+#define GM_ALPHA_DECODE_FACTOR (1 << GM_ALPHA_PREC_DIFF)
+
+#define GM_ABS_ALPHA_BITS 5
+#define GM_ABS_TRANS_BITS 5
+
+#define GM_TRANS_MAX (1 << GM_ABS_TRANS_BITS)
+#define GM_ALPHA_MAX (1 << GM_ABS_ALPHA_BITS)
+#define GM_TRANS_MIN -GM_TRANS_MAX
+#define GM_ALPHA_MIN -GM_ALPHA_MAX
+
+typedef enum {
+ GLOBAL_ZERO = 0,
+ GLOBAL_TRANSLATION = 1,
+ GLOBAL_ROTZOOM = 2,
+ GLOBAL_MOTION_TYPES
+} GLOBAL_MOTION_TYPE;
+
+typedef struct {
+ GLOBAL_MOTION_TYPE gmtype;
+ WarpedMotionParams motion_params;
+} Global_Motion_Params;
+
+static INLINE GLOBAL_MOTION_TYPE get_gmtype(const Global_Motion_Params *gm) {
+ if (gm->motion_params.wmmat[2] == 0 && gm->motion_params.wmmat[3] == 0) {
+ return ((gm->motion_params.wmmat[0] | gm->motion_params.wmmat[1]) ?
+ GLOBAL_TRANSLATION : GLOBAL_ZERO);
+ } else {
+ return GLOBAL_ROTZOOM;
+ }
+}
+#endif // CONFIG_GLOBAL_MOTION
+
#if CONFIG_REF_MV
typedef struct candidate_mv {
int_mv this_mv;
diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h
index b2d65b5..37f7631 100644
--- a/vp10/common/onyxc_int.h
+++ b/vp10/common/onyxc_int.h
@@ -350,6 +350,9 @@
// - this is intentionally not placed in FRAME_CONTEXT since it's reset upon
// each keyframe and not used afterwards
vpx_prob kf_y_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1];
+#if CONFIG_GLOBAL_MOTION
+ Global_Motion_Params global_motion[MAX_REF_FRAMES];
+#endif
BLOCK_SIZE sb_size; // Size of the superblock used for this frame
int mib_size; // Size of the superblock in units of MI blocks
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index d4c7d5e..66b44a3 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -3443,6 +3443,55 @@
}
#endif // CONFIG_SUPERTX
+#if CONFIG_GLOBAL_MOTION
+static void read_global_motion_params(Global_Motion_Params *params,
+ vpx_prob *probs,
+ vp10_reader *r) {
+ GLOBAL_MOTION_TYPE gmtype = vp10_read_tree(r, vp10_global_motion_types_tree,
+ probs);
+ params->gmtype = gmtype;
+ switch (gmtype) {
+ case GLOBAL_ZERO:
+ break;
+ case GLOBAL_TRANSLATION:
+ params->motion_params.wmtype = TRANSLATION;
+ params->motion_params.wmmat[0] =
+ vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
+ GM_TRANS_DECODE_FACTOR;
+ params->motion_params.wmmat[1] =
+ vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
+ GM_TRANS_DECODE_FACTOR;
+ break;
+ case GLOBAL_ROTZOOM:
+ params->motion_params.wmtype = ROTZOOM;
+ params->motion_params.wmmat[2] =
+ vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
+ GM_TRANS_DECODE_FACTOR;
+ params->motion_params.wmmat[3] =
+ vp10_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
+ GM_TRANS_DECODE_FACTOR;
+ params->motion_params.wmmat[0] =
+ (vp10_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ GM_ALPHA_DECODE_FACTOR) + (1 << WARPEDMODEL_PREC_BITS);
+ params->motion_params.wmmat[1] =
+ vp10_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ GM_ALPHA_DECODE_FACTOR;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void read_global_motion(VP10_COMMON *cm, vp10_reader *r) {
+ int frame;
+ memset(cm->global_motion, 0, sizeof(cm->global_motion));
+ for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
+ read_global_motion_params(
+ &cm->global_motion[frame], cm->fc->global_motion_types_prob, r);
+ }
+}
+#endif // CONFIG_GLOBAL_MOTION
+
static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data,
size_t partition_size) {
VP10_COMMON *const cm = &pbi->common;
@@ -3585,6 +3634,9 @@
if (!xd->lossless[0])
read_supertx_probs(fc, &r);
#endif
+#if CONFIG_GLOBAL_MOTION
+ read_global_motion(cm, &r);
+#endif // CONFIG_GLOBAL_MOTION
}
return vp10_reader_has_error(&r);
@@ -3714,6 +3766,9 @@
init_read_bit_buffer(pbi, &rb, data, data_end, clear_data));
YV12_BUFFER_CONFIG *const new_fb = get_frame_new_buffer(cm);
xd->cur_buf = new_fb;
+#if CONFIG_GLOBAL_MOTION
+ xd->global_motion = cm->global_motion;
+#endif // CONFIG_GLOBAL_MOTION
if (!first_partition_size) {
// showing a frame directly
diff --git a/vp10/decoder/dsubexp.c b/vp10/decoder/dsubexp.c
index 4d53e12..49695cc 100644
--- a/vp10/decoder/dsubexp.c
+++ b/vp10/decoder/dsubexp.c
@@ -74,3 +74,13 @@
*p = (vpx_prob)inv_remap_prob(delp, *p);
}
}
+
+int vp10_read_primitive_symmetric(vp10_reader *r, unsigned int mag_bits) {
+ if (vp10_read_bit(r)) {
+ int s = vp10_read_bit(r);
+ int x = vp10_read_literal(r, mag_bits) + 1;
+ return (s > 0 ? -x : x);
+ } else {
+ return 0;
+ }
+}
diff --git a/vp10/decoder/dsubexp.h b/vp10/decoder/dsubexp.h
index c05ec6e..eaccf1f 100644
--- a/vp10/decoder/dsubexp.h
+++ b/vp10/decoder/dsubexp.h
@@ -24,4 +24,9 @@
} // extern "C"
#endif
+// mag_bits is number of bits for magnitude. The alphabet is of size
+// 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
+// indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
+// and 1 more bit for the sign if non-zero.
+int vp10_read_primitive_symmetric(vp10_reader *r, unsigned int mag_bits);
#endif // VP10_DECODER_DSUBEXP_H_
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index 4ef16a8..6430a710 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -111,6 +111,9 @@
#else
static struct vp10_token ext_tx_encodings[TX_TYPES];
#endif // CONFIG_EXT_TX
+#if CONFIG_GLOBAL_MOTION
+static struct vp10_token global_motion_types_encodings[GLOBAL_MOTION_TYPES];
+#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_EXT_INTRA
static struct vp10_token intra_filter_encodings[INTRA_FILTERS];
#endif // CONFIG_EXT_INTRA
@@ -142,6 +145,10 @@
#if CONFIG_OBMC || CONFIG_WARPED_MOTION
vp10_tokens_from_tree(motvar_encodings, vp10_motvar_tree);
#endif // CONFIG_OBMC || CONFIG_WARPED_MOTION
+#if CONFIG_GLOBAL_MOTION
+ vp10_tokens_from_tree(global_motion_types_encodings,
+ vp10_global_motion_types_tree);
+#endif // CONFIG_GLOBAL_MOTION
}
static void write_intra_mode(vp10_writer *w, PREDICTION_MODE mode,
@@ -3180,6 +3187,50 @@
write_tile_info(cm, wb);
}
+#if CONFIG_GLOBAL_MOTION
+static void write_global_motion_params(Global_Motion_Params *params,
+ vpx_prob *probs,
+ vp10_writer *w) {
+ GLOBAL_MOTION_TYPE gmtype = get_gmtype(params);
+ vp10_write_token(w, vp10_global_motion_types_tree, probs,
+ &global_motion_types_encodings[gmtype]);
+ switch (gmtype) {
+ case GLOBAL_ZERO:
+ break;
+ case GLOBAL_TRANSLATION:
+ vp10_write_primitive_symmetric(w, params->motion_params.wmmat[0],
+ GM_ABS_TRANS_BITS);
+ vp10_write_primitive_symmetric(w, params->motion_params.wmmat[1],
+ GM_ABS_TRANS_BITS);
+ break;
+ case GLOBAL_ROTZOOM:
+ vp10_write_primitive_symmetric(w, params->motion_params.wmmat[0],
+ GM_ABS_TRANS_BITS);
+ vp10_write_primitive_symmetric(w, params->motion_params.wmmat[1],
+ GM_ABS_TRANS_BITS);
+ vp10_write_primitive_symmetric(w, params->motion_params.wmmat[2],
+ GM_ABS_ALPHA_BITS);
+ vp10_write_primitive_symmetric(w, params->motion_params.wmmat[3],
+ GM_ABS_ALPHA_BITS);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void write_global_motion(VP10_COMP *cpi, vp10_writer *w) {
+ VP10_COMMON *const cm = &cpi->common;
+ int frame;
+ for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
+ if (!cpi->global_motion_used[frame]) {
+ memset(&cm->global_motion[frame], 0,
+ sizeof(*cm->global_motion));
+ }
+ write_global_motion_params(
+ &cm->global_motion[frame], cm->fc->global_motion_types_prob, w);
+ }
+}
+#endif
static uint32_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) {
VP10_COMMON *const cm = &cpi->common;
@@ -3348,7 +3399,9 @@
update_supertx_probs(cm, header_bc);
#endif // CONFIG_SUPERTX
}
-
+#if CONFIG_GLOBAL_MOTION
+ write_global_motion(cpi, header_bc);
+#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_ANS
ans_write_init(&header_ans, data);
buf_ans_flush(header_bc, &header_ans);
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 3119acf..b91615b 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -4536,6 +4536,78 @@
}
#endif
+#if CONFIG_GLOBAL_MOTION
+#define MIN_TRANS_THRESH 8
+
+static void convert_translation_to_params(
+ double *H, Global_Motion_Params *model) {
+ model->motion_params.wmmat[0] = (int) floor(H[0] *
+ (1 << GM_TRANS_PREC_BITS) + 0.5);
+ model->motion_params.wmmat[1] = (int) floor(H[1] *
+ (1 << GM_TRANS_PREC_BITS) + 0.5);
+ if (abs(model->motion_params.wmmat[0]) < MIN_TRANS_THRESH &&
+ abs(model->motion_params.wmmat[1]) < MIN_TRANS_THRESH) {
+ model->motion_params.wmmat[0] = 0;
+ model->motion_params.wmmat[1] = 0;
+ } else {
+ model->motion_params.wmmat[0] =
+ clamp(model->motion_params.wmmat[0],
+ GM_TRANS_MIN, GM_TRANS_MAX);
+ model->motion_params.wmmat[1] =
+ clamp(model->motion_params.wmmat[1],
+ GM_TRANS_MIN, GM_TRANS_MAX);
+ }
+}
+
+static void convert_rotzoom_to_params(double *H, Global_Motion_Params *model) {
+ model->motion_params.wmmat[0] = (int) floor(H[0] *
+ (1 << GM_TRANS_PREC_BITS) + 0.5);
+ model->motion_params.wmmat[1] = (int) floor(H[1] *
+ (1 << GM_TRANS_PREC_BITS) + 0.5);
+ model->motion_params.wmmat[0] =
+ clamp(model->motion_params.wmmat[0],
+ GM_TRANS_MIN, GM_TRANS_MAX);
+ model->motion_params.wmmat[1] =
+ clamp(model->motion_params.wmmat[1],
+ GM_TRANS_MIN, GM_TRANS_MAX);
+
+ model->motion_params.wmmat[2] = (int) floor(H[2] *
+ (1 << GM_ALPHA_PREC_BITS) + 0.5) -
+ (1 << GM_ALPHA_PREC_BITS);
+ model->motion_params.wmmat[3] = (int) floor(H[3] *
+ (1 << GM_ALPHA_PREC_BITS) + 0.5);
+
+ model->motion_params.wmmat[2] = clamp(model->motion_params.wmmat[2],
+ GM_ALPHA_MIN, GM_ALPHA_MAX);
+ model->motion_params.wmmat[3] = clamp(model->motion_params.wmmat[3],
+ GM_ALPHA_MIN, GM_ALPHA_MAX);
+
+ if (model->motion_params.wmmat[2] == 0 &&
+ model->motion_params.wmmat[3] == 0) {
+ if (abs(model->motion_params.wmmat[0]) < MIN_TRANS_THRESH &&
+ abs(model->motion_params.wmmat[1]) < MIN_TRANS_THRESH) {
+ model->motion_params.wmmat[0] = 0;
+ model->motion_params.wmmat[1] = 0;
+ }
+ }
+}
+
+static void convert_model_to_params(double *H, TransformationType type,
+ Global_Motion_Params *model) {
+ switch (type) {
+ case ROTZOOM:
+ convert_rotzoom_to_params(H, model);
+ break;
+ case TRANSLATION:
+ convert_translation_to_params(H, model);
+ break;
+ default:
+ break;
+ }
+ model->gmtype = get_gmtype(model);
+}
+#endif // CONFIG_GLOBAL_MOTION
+
static void encode_frame_internal(VP10_COMP *cpi) {
ThreadData *const td = &cpi->td;
MACROBLOCK *const x = &td->mb;
@@ -4556,6 +4628,18 @@
rdc->m_search_count = 0; // Count of motion search hits.
rdc->ex_search_count = 0; // Exhaustive mesh search hits.
+#if CONFIG_GLOBAL_MOTION
+ // TODO(sarahparker) this is a placeholder for gm computation
+ vpx_clear_system_state();
+ vp10_zero(cpi->global_motion_used);
+ if (cpi->common.frame_type == INTER_FRAME && cpi->Source) {
+ int frame;
+ double H[9] = {0, 0, 0, 0, 0, 0, 0, 0, 1};
+ for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame)
+ convert_model_to_params(H, ROTZOOM, &cm->global_motion[frame]);
+ }
+#endif // CONFIG_GLOBAL_MOTION
+
for (i = 0; i < MAX_SEGMENTS; ++i) {
const int qindex = cm->seg.enabled ?
vp10_get_qindex(&cm->seg, i, cm->base_qindex) : cm->base_qindex;
@@ -4569,7 +4653,6 @@
x->optimize = 0;
cm->tx_mode = select_tx_mode(cpi, xd);
-
vp10_frame_init_quantizer(cpi);
vp10_initialize_rd_consts(cpi);
diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h
index c8555f2..63a1669 100644
--- a/vp10/encoder/encoder.h
+++ b/vp10/encoder/encoder.h
@@ -616,6 +616,9 @@
int existing_fb_idx_to_show;
int is_arf_filter_off;
#endif // CONFIG_EXT_REFS
+#if CONFIG_GLOBAL_MOTION
+ int global_motion_used[MAX_REF_FRAMES];
+#endif
} VP10_COMP;
void vp10_initialize_enc(void);
diff --git a/vp10/encoder/subexp.c b/vp10/encoder/subexp.c
index 4aaffae..3a2e09f 100644
--- a/vp10/encoder/subexp.c
+++ b/vp10/encoder/subexp.c
@@ -286,3 +286,16 @@
upd);
return savings;
}
+
+void vp10_write_primitive_symmetric(vp10_writer *w, int word,
+ unsigned int abs_bits) {
+ if (word == 0) {
+ vp10_write_bit(w, 0);
+ } else {
+ const int x = abs(word);
+ const int s = word < 0;
+ vp10_write_bit(w, 1);
+ vp10_write_bit(w, s);
+ vp10_write_literal(w, x - 1, abs_bits);
+ }
+}
diff --git a/vp10/encoder/subexp.h b/vp10/encoder/subexp.h
index 756b499..dbd48ff 100644
--- a/vp10/encoder/subexp.h
+++ b/vp10/encoder/subexp.h
@@ -50,6 +50,13 @@
int stepsize, int n);
#endif // CONFIG_ENTROPY
+//
+// mag_bits is number of bits for magnitude. The alphabet is of size
+// 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
+// indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
+// and 1 more bit for the sign if non-zero.
+void vp10_write_primitive_symmetric(vp10_writer *w, int word,
+ unsigned int mag_bits);
#ifdef __cplusplus
} // extern "C"
#endif