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