Some refactoring and improvements to gobal motion

To facilitate further experiments.
Fixes border, uses standard interpolation filters for
translation only global model, and some refactoring.

Change-Id: I38af6cb83723f92baed23e28d7fc9a0a9544757e
diff --git a/av1/common/mv.h b/av1/common/mv.h
index 43b74c0..7e2304d 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -152,12 +152,12 @@
     return AFFINE;
 }
 
-static INLINE void set_default_gmparams(WarpedMotionParams *gm) {
-  static const int32_t default_gm_params[8] = {
+static INLINE void set_default_gmparams(WarpedMotionParams *wm) {
+  static const int32_t default_wm_mat[8] = {
     0, 0, (1 << WARPEDMODEL_PREC_BITS), 0, 0, (1 << WARPEDMODEL_PREC_BITS), 0, 0
   };
-  memcpy(gm->wmmat, default_gm_params, sizeof(gm->wmmat));
-  gm->wmtype = IDENTITY;
+  memcpy(wm->wmmat, default_wm_mat, sizeof(wm->wmmat));
+  wm->wmtype = IDENTITY;
 }
 #endif  // CONFIG_GLOBAL_MOTION
 
diff --git a/av1/common/reconinter.c b/av1/common/reconinter.c
index a0c4e10..3642f90 100644
--- a/av1/common/reconinter.c
+++ b/av1/common/reconinter.c
@@ -558,7 +558,7 @@
   for (ref = 0; ref < 1 + is_compound; ++ref) {
     gm[ref] = &xd->global_motion[mi->mbmi.ref_frame[ref]];
     is_global[ref] =
-        (get_y_mode(mi, block) == ZEROMV && gm[ref]->wmtype != IDENTITY);
+        (get_y_mode(mi, block) == ZEROMV && gm[ref]->wmtype > TRANSLATION);
   }
   // TODO(sarahparker) remove these once gm works with all experiments
   (void)gm;
diff --git a/av1/common/warped_motion.c b/av1/common/warped_motion.c
index dab6eb9..222585d 100644
--- a/av1/common/warped_motion.c
+++ b/av1/common/warped_motion.c
@@ -531,8 +531,8 @@
       gm_err = dst[(j - p_col) + (i - p_row) * p_stride] -
                highbd_warp_interpolate(ref, out[0], out[1], width, height,
                                        stride, bd);
-      no_gm_err = dst[(j - p_col) + (i - p_row) * p_stride] -
-                  ref[(j - p_col) + (i - p_row) * stride];
+      no_gm_err =
+          dst[(j - p_col) + (i - p_row) * p_stride] - ref[j + i * stride];
       gm_sumerr += highbd_error_measure(gm_err, bd);
       no_gm_sumerr += highbd_error_measure(no_gm_err, bd);
     }
@@ -596,8 +596,8 @@
       out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, 4);
       gm_err = dst[(j - p_col) + (i - p_row) * p_stride] -
                warp_interpolate(ref, out[0], out[1], width, height, stride);
-      no_gm_err = dst[(j - p_col) + (i - p_row) * p_stride] -
-                  ref[(j - p_col) + (i - p_row) * stride];
+      no_gm_err =
+          dst[(j - p_col) + (i - p_row) * p_stride] - ref[j + i * stride];
       gm_sumerr += error_measure(gm_err);
       no_gm_sumerr += error_measure(no_gm_err);
     }
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index bc1c77e..ab1a1c9 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4613,114 +4613,17 @@
 
 #if CONFIG_GLOBAL_MOTION
 #define MIN_TRANS_THRESH (1 * GM_TRANS_DECODE_FACTOR)
-#define GLOBAL_MOTION_ADVANTAGE_THRESH 0.75
 
-// Adds some offset to a global motion parameter and handles
-// all of the necessary precision shifts, clamping, and
-// zero-centering.
-static int32_t add_param_offset(int param_index, int32_t param_value,
-                                int32_t offset) {
-  const int scale_vals[3] = { GM_TRANS_PREC_DIFF, GM_ALPHA_PREC_DIFF,
-                              GM_ROW3HOMO_PREC_DIFF };
-  const int clamp_vals[3] = { GM_TRANS_MAX, GM_ALPHA_MAX, GM_ROW3HOMO_MAX };
-  // type of param: 0 - translation, 1 - affine, 2 - homography
-  const int param_type = (param_index < 2 ? 0 : (param_index < 6 ? 1 : 2));
-  const int is_one_centered = (param_index == 2 || param_index == 5);
+// Border over which to compute the global motion
+#define ERRORADV_BORDER 0
 
-  // Make parameter zero-centered and offset the shift that was done to make
-  // it compatible with the warped model
-  param_value = (param_value - (is_one_centered << WARPEDMODEL_PREC_BITS)) >>
-                scale_vals[param_type];
-  // Add desired offset to the rescaled/zero-centered parameter
-  param_value += offset;
-  // Clamp the parameter so it does not overflow the number of bits allotted
-  // to it in the bitstream
-  param_value = (int32_t)clamp(param_value, -clamp_vals[param_type],
-                               clamp_vals[param_type]);
-  // Rescale the parameter to WARPEDMODEL_PRECISION_BITS so it is compatible
-  // with the warped motion library
-  param_value *= (1 << scale_vals[param_type]);
-
-  // Undo the zero-centering step if necessary
-  return param_value + (is_one_centered << WARPEDMODEL_PREC_BITS);
-}
-
-static void refine_integerized_param(WarpedMotionParams *wm,
-#if CONFIG_AOM_HIGHBITDEPTH
-                                     int use_hbd, int bd,
-#endif  // CONFIG_AOM_HIGHBITDEPTH
-                                     uint8_t *ref, int r_width, int r_height,
-                                     int r_stride, uint8_t *dst, int d_width,
-                                     int d_height, int d_stride,
-                                     int n_refinements) {
-  int i = 0, p;
-  int n_params = n_trans_model_params[wm->wmtype];
-  int32_t *param_mat = wm->wmmat;
-  double step_error;
-  int32_t step;
-  int32_t *param;
-  int32_t curr_param;
-  int32_t best_param;
-
-  double best_error =
-      av1_warp_erroradv(wm,
-#if CONFIG_AOM_HIGHBITDEPTH
-                        use_hbd, bd,
-#endif  // CONFIG_AOM_HIGHBITDEPTH
-                        ref, r_width, r_height, r_stride, dst, 0, 0, d_width,
-                        d_height, d_stride, 0, 0, 16, 16);
-  for (p = 0; p < n_params; ++p) {
-    param = param_mat + p;
-    step = 1 << (n_refinements + 1);
-    curr_param = *param;
-    best_param = curr_param;
-    for (i = 0; i < n_refinements; i++) {
-      // look to the left
-      *param = add_param_offset(p, curr_param, -step);
-      step_error =
-          av1_warp_erroradv(wm,
-#if CONFIG_AOM_HIGHBITDEPTH
-                            use_hbd, bd,
-#endif  // CONFIG_AOM_HIGHBITDEPTH
-                            ref, r_width, r_height, r_stride, dst, 0, 0,
-                            d_width, d_height, d_stride, 0, 0, 16, 16);
-      if (step_error < best_error) {
-        step >>= 1;
-        best_error = step_error;
-        best_param = *param;
-        curr_param = best_param;
-        continue;
-      }
-
-      // look to the right
-      *param = add_param_offset(p, curr_param, step);
-      step_error =
-          av1_warp_erroradv(wm,
-#if CONFIG_AOM_HIGHBITDEPTH
-                            use_hbd, bd,
-#endif  // CONFIG_AOM_HIGHBITDEPTH
-                            ref, r_width, r_height, r_stride, dst, 0, 0,
-                            d_width, d_height, d_stride, 0, 0, 16, 16);
-      if (step_error < best_error) {
-        step >>= 1;
-        best_error = step_error;
-        best_param = *param;
-        curr_param = best_param;
-        continue;
-      }
-
-      // no improvement found-> means we're either already at a minimum or
-      // step is too wide
-      step >>= 1;
-    }
-    *param = best_param;
-  }
-  // For rotzoom model enforce the constraints on mat[4] and mat[5]
-  if (wm->wmtype == ROTZOOM) {
-    param_mat[5] = param_mat[2];
-    param_mat[4] = -param_mat[3];
-  }
-}
+static const double gm_advantage_thresh[TRANS_TYPES] = {
+  1.00,  // Identity (not used)
+  0.85,  // Translation
+  0.75,  // Rot zoom
+  0.65,  // Affine
+  0.50,  // Homography
+};
 
 static void convert_to_params(const double *params, int32_t *model) {
   int i;
@@ -4760,6 +4663,132 @@
   convert_to_params(params, model->wmmat);
   model->wmtype = get_gmtype(model);
 }
+
+// Adds some offset to a global motion parameter and handles
+// all of the necessary precision shifts, clamping, and
+// zero-centering.
+static int32_t add_param_offset(int param_index, int32_t param_value,
+                                int32_t offset) {
+  const int scale_vals[3] = { GM_TRANS_PREC_DIFF, GM_ALPHA_PREC_DIFF,
+                              GM_ROW3HOMO_PREC_DIFF };
+  const int clamp_vals[3] = { GM_TRANS_MAX, GM_ALPHA_MAX, GM_ROW3HOMO_MAX };
+  // type of param: 0 - translation, 1 - affine, 2 - homography
+  const int param_type = (param_index < 2 ? 0 : (param_index < 6 ? 1 : 2));
+  const int is_one_centered = (param_index == 2 || param_index == 5);
+
+  // Make parameter zero-centered and offset the shift that was done to make
+  // it compatible with the warped model
+  param_value = (param_value - (is_one_centered << WARPEDMODEL_PREC_BITS)) >>
+                scale_vals[param_type];
+  // Add desired offset to the rescaled/zero-centered parameter
+  param_value += offset;
+  // Clamp the parameter so it does not overflow the number of bits allotted
+  // to it in the bitstream
+  param_value = (int32_t)clamp(param_value, -clamp_vals[param_type],
+                               clamp_vals[param_type]);
+  // Rescale the parameter to WARPEDMODEL_PRECISION_BITS so it is compatible
+  // with the warped motion library
+  param_value *= (1 << scale_vals[param_type]);
+
+  // Undo the zero-centering step if necessary
+  return param_value + (is_one_centered << WARPEDMODEL_PREC_BITS);
+}
+
+static void force_wmtype(WarpedMotionParams *wm, TransformationType wmtype) {
+  switch (wmtype) {
+    case IDENTITY: wm->wmmat[0] = 0; wm->wmmat[1] = 0;
+    case TRANSLATION:
+      wm->wmmat[2] = 1 << WARPEDMODEL_PREC_BITS;
+      wm->wmmat[3] = 0;
+    case ROTZOOM: wm->wmmat[4] = -wm->wmmat[3]; wm->wmmat[5] = wm->wmmat[2];
+    case AFFINE: wm->wmmat[6] = wm->wmmat[7] = 0;
+    case HOMOGRAPHY: break;
+    default: assert(0);
+  }
+  wm->wmtype = wmtype;
+}
+
+static double refine_integerized_param(WarpedMotionParams *wm,
+                                       TransformationType wmtype,
+#if CONFIG_AOM_HIGHBITDEPTH
+                                       int use_hbd, int bd,
+#endif  // CONFIG_AOM_HIGHBITDEPTH
+                                       uint8_t *ref, int r_width, int r_height,
+                                       int r_stride, uint8_t *dst, int d_width,
+                                       int d_height, int d_stride,
+                                       int n_refinements) {
+  const int border = ERRORADV_BORDER;
+  int i = 0, p;
+  int n_params = n_trans_model_params[wmtype];
+  int32_t *param_mat = wm->wmmat;
+  double step_error;
+  int32_t step;
+  int32_t *param;
+  int32_t curr_param;
+  int32_t best_param;
+  double best_error;
+
+  force_wmtype(wm, wmtype);
+  best_error = av1_warp_erroradv(wm,
+#if CONFIG_AOM_HIGHBITDEPTH
+                                 use_hbd, bd,
+#endif  // CONFIG_AOM_HIGHBITDEPTH
+                                 ref, r_width, r_height, r_stride,
+                                 dst + border * d_stride + border, border,
+                                 border, d_width - 2 * border,
+                                 d_height - 2 * border, d_stride, 0, 0, 16, 16);
+  for (p = 0; p < n_params; ++p) {
+    param = param_mat + p;
+    step = 1 << (n_refinements + 1);
+    curr_param = *param;
+    best_param = curr_param;
+    for (i = 0; i < n_refinements; i++) {
+      // look to the left
+      *param = add_param_offset(p, curr_param, -step);
+      step_error = av1_warp_erroradv(
+          wm,
+#if CONFIG_AOM_HIGHBITDEPTH
+          use_hbd, bd,
+#endif  // CONFIG_AOM_HIGHBITDEPTH
+          ref, r_width, r_height, r_stride, dst + border * d_stride + border,
+          border, border, d_width - 2 * border, d_height - 2 * border, d_stride,
+          0, 0, 16, 16);
+      if (step_error < best_error) {
+        step >>= 1;
+        best_error = step_error;
+        best_param = *param;
+        curr_param = best_param;
+        continue;
+      }
+
+      // look to the right
+      *param = add_param_offset(p, curr_param, step);
+      step_error = av1_warp_erroradv(
+          wm,
+#if CONFIG_AOM_HIGHBITDEPTH
+          use_hbd, bd,
+#endif  // CONFIG_AOM_HIGHBITDEPTH
+          ref, r_width, r_height, r_stride, dst + border * d_stride + border,
+          border, border, d_width - 2 * border, d_height - 2 * border, d_stride,
+          0, 0, 16, 16);
+      if (step_error < best_error) {
+        step >>= 1;
+        best_error = step_error;
+        best_param = *param;
+        curr_param = best_param;
+        continue;
+      }
+
+      // no improvement found-> means we're either already at a minimum or
+      // step is too wide
+      step >>= 1;
+    }
+    *param = best_param;
+  }
+  force_wmtype(wm, wmtype);
+  wm->wmtype = get_gmtype(wm);
+  return best_error;
+}
 #endif  // CONFIG_GLOBAL_MOTION
 
 static void encode_frame_internal(AV1_COMP *cpi) {
@@ -4803,27 +4832,18 @@
                                                 params)) {
           convert_model_to_params(params, &cm->global_motion[frame]);
           if (cm->global_motion[frame].wmtype != IDENTITY) {
-            refine_integerized_param(
-                &cm->global_motion[frame],
+            erroradvantage = refine_integerized_param(
+                &cm->global_motion[frame], cm->global_motion[frame].wmtype,
 #if CONFIG_AOM_HIGHBITDEPTH
                 xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
 #endif  // CONFIG_AOM_HIGHBITDEPTH
                 ref_buf->y_buffer, ref_buf->y_width, ref_buf->y_height,
                 ref_buf->y_stride, cpi->Source->y_buffer, cpi->Source->y_width,
                 cpi->Source->y_height, cpi->Source->y_stride, 3);
-            // compute the advantage of using gm parameters over 0 motion
-            erroradvantage = av1_warp_erroradv(
-                &cm->global_motion[frame],
-#if CONFIG_AOM_HIGHBITDEPTH
-                xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
-#endif  // CONFIG_AOM_HIGHBITDEPTH
-                ref_buf->y_buffer, ref_buf->y_width, ref_buf->y_height,
-                ref_buf->y_stride, cpi->Source->y_buffer, 0, 0,
-                cpi->Source->y_width, cpi->Source->y_height,
-                cpi->Source->y_stride, 0, 0, 16, 16);
-            if (erroradvantage > GLOBAL_MOTION_ADVANTAGE_THRESH)
-              // Not enough advantage in using a global model. Make identity.
+            if (erroradvantage >
+                gm_advantage_thresh[cm->global_motion[frame].wmtype]) {
               set_default_gmparams(&cm->global_motion[frame]);
+            }
           }
         }
         aom_clear_system_state();