Reduce the number of bits sent for global translation model
When a global translation model is found, the only 3 bits
of precision are used for the motion parameters. This case
uses a smaller precision than the translation parameters
in a global model that is rotzoom or greater.
Change-Id: Ic972e9edf46e301f2894cce2b723960d0297c8e8
diff --git a/av1/common/mv.h b/av1/common/mv.h
index a22a5c8..67f36b6 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -123,8 +123,11 @@
#define GM_TRANS_PREC_BITS 6
#define GM_ABS_TRANS_BITS 12
+#define GM_ABS_TRANS_ONLY_BITS (GM_ABS_TRANS_BITS - GM_TRANS_PREC_BITS + 3)
#define GM_TRANS_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_TRANS_PREC_BITS)
+#define GM_TRANS_ONLY_PREC_DIFF (WARPEDMODEL_PREC_BITS - 3)
#define GM_TRANS_DECODE_FACTOR (1 << GM_TRANS_PREC_DIFF)
+#define GM_TRANS_ONLY_DECODE_FACTOR (1 << GM_TRANS_ONLY_PREC_DIFF)
#define GM_ALPHA_PREC_BITS 15
#define GM_ABS_ALPHA_BITS 12
@@ -158,6 +161,13 @@
return mi_row * MI_SIZE + bh / 2 - 1;
}
+static INLINE int convert_to_trans_prec(int allow_hp, int coor) {
+ const int shift =
+ allow_hp ? WARPEDMODEL_PREC_BITS - 3 : WARPEDMODEL_PREC_BITS - 2;
+ const int scale = allow_hp ? 0 : 1;
+ return (ROUND_POWER_OF_TWO_SIGNED(coor, shift) << scale);
+}
+
// Convert a global motion translation vector (which may have more bits than a
// regular motion vector) into a motion vector
static INLINE int_mv gm_get_motion_vector(const WarpedMotionParams *gm,
@@ -168,6 +178,13 @@
int_mv res;
const int32_t *mat = gm->wmmat;
int xc, yc, x, y;
+
+ if (gm->wmtype == TRANSLATION) {
+ res.as_mv.row = gm->wmmat[0] >> GM_TRANS_ONLY_PREC_DIFF;
+ res.as_mv.col = gm->wmmat[1] >> GM_TRANS_ONLY_PREC_DIFF;
+ return res;
+ }
+
if (bsize >= BLOCK_8X8 || unify_bsize) {
x = block_center_x(mi_col, bsize);
y = block_center_y(mi_row, bsize);
@@ -177,8 +194,6 @@
x += (block_idx & 1) * MI_SIZE / 2;
y += (block_idx & 2) * MI_SIZE / 4;
}
- int shift = allow_hp ? WARPEDMODEL_PREC_BITS - 3 : WARPEDMODEL_PREC_BITS - 2;
- int scale = allow_hp ? 0 : 1;
if (gm->wmtype == ROTZOOM) {
assert(gm->wmmat[5] == gm->wmmat[2]);
@@ -196,8 +211,8 @@
yc = yc > 0 ? (yc + Z / 2) / Z : (yc - Z / 2) / Z;
}
- int tx = (ROUND_POWER_OF_TWO_SIGNED(xc, shift) << scale) - (x << 3);
- int ty = (ROUND_POWER_OF_TWO_SIGNED(yc, shift) << scale) - (y << 3);
+ int tx = convert_to_trans_prec(allow_hp, xc) - (x << 3);
+ int ty = convert_to_trans_prec(allow_hp, yc) - (y << 3);
res.as_mv.row = ty;
res.as_mv.col = tx;
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 3867e2b..fd223f3 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -4395,9 +4395,12 @@
#if CONFIG_GLOBAL_MOTION
static void read_global_motion_params(WarpedMotionParams *params,
- aom_prob *probs, aom_reader *r) {
+ aom_prob *probs, aom_reader *r,
+ int allow_hp) {
TransformationType type =
aom_read_tree(r, av1_global_motion_types_tree, probs, ACCT_STR);
+ int trans_bits;
+ int trans_dec_factor;
set_default_gmparams(params);
params->wmtype = type;
switch (type) {
@@ -4434,10 +4437,15 @@
}
// fallthrough intended
case TRANSLATION:
- params->wmmat[0] = aom_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
- GM_TRANS_DECODE_FACTOR;
- params->wmmat[1] = aom_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
- GM_TRANS_DECODE_FACTOR;
+ trans_bits = (type == TRANSLATION) ? GM_ABS_TRANS_ONLY_BITS - !allow_hp
+ : GM_ABS_TRANS_BITS;
+ trans_dec_factor = (type == TRANSLATION)
+ ? GM_TRANS_ONLY_DECODE_FACTOR * (1 << !allow_hp)
+ : GM_TRANS_DECODE_FACTOR;
+ params->wmmat[0] =
+ aom_read_primitive_symmetric(r, trans_bits) * trans_dec_factor;
+ params->wmmat[1] =
+ aom_read_primitive_symmetric(r, trans_bits) * trans_dec_factor;
break;
case IDENTITY: break;
default: assert(0);
@@ -4450,7 +4458,8 @@
int frame;
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
read_global_motion_params(&cm->global_motion[frame],
- cm->fc->global_motion_types_prob, r);
+ cm->fc->global_motion_types_prob, r,
+ cm->allow_high_precision_mv);
/*
printf("Dec Ref %d [%d/%d]: %d %d %d %d\n",
frame, cm->current_video_frame, cm->show_frame,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index d705ce2..f802662 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -4571,8 +4571,11 @@
#if CONFIG_GLOBAL_MOTION
static void write_global_motion_params(WarpedMotionParams *params,
- aom_prob *probs, aom_writer *w) {
+ aom_prob *probs, aom_writer *w,
+ int allow_hp) {
TransformationType type = params->wmtype;
+ int trans_bits;
+ int trans_prec_diff;
av1_write_token(w, av1_global_motion_types_tree, probs,
&global_motion_types_encodings[type]);
switch (type) {
@@ -4608,10 +4611,15 @@
}
// fallthrough intended
case TRANSLATION:
- aom_write_primitive_symmetric(w, (params->wmmat[0] >> GM_TRANS_PREC_DIFF),
- GM_ABS_TRANS_BITS);
- aom_write_primitive_symmetric(w, (params->wmmat[1] >> GM_TRANS_PREC_DIFF),
- GM_ABS_TRANS_BITS);
+ trans_bits = (type == TRANSLATION) ? GM_ABS_TRANS_ONLY_BITS - !allow_hp
+ : GM_ABS_TRANS_BITS;
+ trans_prec_diff = (type == TRANSLATION)
+ ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
+ : GM_TRANS_PREC_DIFF;
+ aom_write_primitive_symmetric(w, (params->wmmat[0] >> trans_prec_diff),
+ trans_bits);
+ aom_write_primitive_symmetric(w, (params->wmmat[1] >> trans_prec_diff),
+ trans_bits);
break;
case IDENTITY: break;
default: assert(0);
@@ -4631,7 +4639,8 @@
}
#endif
write_global_motion_params(&cm->global_motion[frame],
- cm->fc->global_motion_types_prob, w);
+ cm->fc->global_motion_types_prob, w,
+ cm->allow_high_precision_mv);
/*
printf("Frame %d/%d: Enc Ref %d (used %d): %d %d %d %d\n",
cm->current_video_frame, cm->show_frame, frame,
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 0701aaf..d101f02 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -5153,7 +5153,19 @@
if (!get_shear_params(&cm->global_motion[frame]))
set_default_gmparams(&cm->global_motion[frame]);
- if (cm->global_motion[frame].wmtype != IDENTITY) break;
+ if (cm->global_motion[frame].wmtype != IDENTITY) {
+ if (cm->global_motion[frame].wmtype == TRANSLATION) {
+ cm->global_motion[frame].wmmat[0] =
+ convert_to_trans_prec(cm->allow_high_precision_mv,
+ cm->global_motion[frame].wmmat[0]) *
+ GM_TRANS_ONLY_DECODE_FACTOR;
+ cm->global_motion[frame].wmmat[1] =
+ convert_to_trans_prec(cm->allow_high_precision_mv,
+ cm->global_motion[frame].wmmat[1]) *
+ GM_TRANS_ONLY_DECODE_FACTOR;
+ }
+ break;
+ }
}
aom_clear_system_state();
}
diff --git a/av1/encoder/global_motion.h b/av1/encoder/global_motion.h
index 232489f..f738bbe 100644
--- a/av1/encoder/global_motion.h
+++ b/av1/encoder/global_motion.h
@@ -24,8 +24,6 @@
extern const double gm_advantage_thresh[TRANS_TYPES];
-void convert_to_params(const double *params, int32_t *model);
-
void convert_model_to_params(const double *params, WarpedMotionParams *model);
// Adds some offset to a global motion parameter and handles