Fix some minor issues in global motion code

* Fix a check which was supposed to be "is model type IDENTITY or
  TRANSLATION?" but was actually written as "is model type not ROTZOOM?"

* Track ref_frame_error for the best warp model found, and use this when
  deciding whether to use that model. We were accidentally using the
  ref_frame_error for the last model considered instead.

* Also strengthen some checks on when to skip models, in cases where
  they definitely won't be useful.

None of these change the encoder output currently - we currently only
consider one model per ref frame, of type ROTZOOM - but this helps
future-proof things so that we can more accurately evaluate multiple
models or use AFFINE type models in the future.

Change-Id: Ieb7edd200ab99dcc2ba98e42b46c79166c260f79
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index ba93299..08e773f 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -2278,7 +2278,7 @@
     // INVALID/TRANSLATION/IDENTITY, skip the evaluation of global motion w.r.t
     // the remaining ref frames in that direction.
     if (cpi->sf.gm_sf.prune_ref_frame_for_gm_search &&
-        cpi->common.global_motion[ref_buf_idx].wmtype != ROTZOOM)
+        cpi->common.global_motion[ref_buf_idx].wmtype <= TRANSLATION)
       job_info->early_exit[cur_dir] = 1;
 
 #if CONFIG_MULTITHREAD
diff --git a/av1/encoder/global_motion_facade.c b/av1/encoder/global_motion_facade.c
index 7a3acb1..448215a 100644
--- a/av1/encoder/global_motion_facade.c
+++ b/av1/encoder/global_motion_facade.c
@@ -101,66 +101,66 @@
   int num_refinements = cpi->sf.gm_sf.num_refinement_steps;
 
   for (model = ROTZOOM; model < GLOBAL_TRANS_TYPES_ENC; ++model) {
-    int64_t best_warp_error = INT64_MAX;
-
     if (!aom_compute_global_motion(model, cpi->source, ref_buf[frame],
                                    bit_depth, global_motion_method,
                                    motion_models, RANSAC_NUM_MOTIONS)) {
       continue;
     }
 
-    int64_t ref_frame_error = 0;
+    int64_t best_ref_frame_error = 0;
+    int64_t best_warp_error = INT64_MAX;
     for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
       if (motion_models[i].num_inliers == 0) continue;
 
       params_this_motion = motion_models[i].params;
       av1_convert_model_to_params(params_this_motion, &tmp_wm_params);
 
-      // Work around a bug in the AV1 specification
+      // Skip models that we won't use (IDENTITY or TRANSLATION)
+      //
+      // For IDENTITY type models, we don't need to evaluate anything because
+      // all the following logic is effectively comparing the estimated model
+      // to an identity model.
       //
       // For TRANSLATION type global motion models, gm_get_motion_vector() gives
       // the wrong motion vector (see comments in that function for details).
       // As translation-type models do not give much gain, we can avoid this bug
       // by never choosing a TRANSLATION type model
-      if (tmp_wm_params.wmtype == TRANSLATION) {
-        continue;
-      }
+      if (tmp_wm_params.wmtype <= TRANSLATION) continue;
 
-      if (tmp_wm_params.wmtype != IDENTITY) {
-        av1_compute_feature_segmentation_map(
-            segment_map, segment_map_w, segment_map_h, motion_models[i].inliers,
-            motion_models[i].num_inliers);
+      av1_compute_feature_segmentation_map(
+          segment_map, segment_map_w, segment_map_h, motion_models[i].inliers,
+          motion_models[i].num_inliers);
 
-        ref_frame_error = av1_segmented_frame_error(
-            is_cur_buf_hbd(xd), xd->bd, ref_buf[frame]->y_buffer,
-            ref_buf[frame]->y_stride, cpi->source->y_buffer, src_width,
-            src_height, src_stride, segment_map, segment_map_w);
+      int64_t ref_frame_error = av1_segmented_frame_error(
+          is_cur_buf_hbd(xd), xd->bd, ref_buf[frame]->y_buffer,
+          ref_buf[frame]->y_stride, cpi->source->y_buffer, src_width,
+          src_height, src_stride, segment_map, segment_map_w);
 
-        const int64_t erroradv_threshold =
-            calc_erroradv_threshold(ref_frame_error);
+      if (ref_frame_error == 0) continue;
 
-        const int64_t warp_error = av1_refine_integerized_param(
-            &tmp_wm_params, tmp_wm_params.wmtype, is_cur_buf_hbd(xd), xd->bd,
-            ref_buf[frame]->y_buffer, ref_buf[frame]->y_crop_width,
-            ref_buf[frame]->y_crop_height, ref_buf[frame]->y_stride,
-            cpi->source->y_buffer, src_width, src_height, src_stride,
-            num_refinements, best_warp_error, segment_map, segment_map_w,
-            erroradv_threshold);
+      const int64_t erroradv_threshold =
+          calc_erroradv_threshold(ref_frame_error);
 
-        // av1_refine_integerized_param() can return a TRANSLATION type model
-        // even if its input is some other type, so we have to skip those too
-        if (tmp_wm_params.wmtype == TRANSLATION) {
-          continue;
-        }
+      const int64_t warp_error = av1_refine_integerized_param(
+          &tmp_wm_params, tmp_wm_params.wmtype, is_cur_buf_hbd(xd), xd->bd,
+          ref_buf[frame]->y_buffer, ref_buf[frame]->y_crop_width,
+          ref_buf[frame]->y_crop_height, ref_buf[frame]->y_stride,
+          cpi->source->y_buffer, src_width, src_height, src_stride,
+          num_refinements, best_warp_error, segment_map, segment_map_w,
+          erroradv_threshold);
 
-        if (warp_error < best_warp_error) {
-          best_warp_error = warp_error;
-          // Save the wm_params modified by
-          // av1_refine_integerized_param() rather than motion index to
-          // avoid rerunning refine() below.
-          memcpy(&(cm->global_motion[frame]), &tmp_wm_params,
-                 sizeof(WarpedMotionParams));
-        }
+      // av1_refine_integerized_param() can return a simpler model type than
+      // its input, so re-check model type here
+      if (tmp_wm_params.wmtype <= TRANSLATION) continue;
+
+      if (warp_error < best_warp_error) {
+        best_ref_frame_error = ref_frame_error;
+        best_warp_error = warp_error;
+        // Save the wm_params modified by
+        // av1_refine_integerized_param() rather than motion index to
+        // avoid rerunning refine() below.
+        memcpy(&(cm->global_motion[frame]), &tmp_wm_params,
+               sizeof(WarpedMotionParams));
       }
     }
     assert(cm->global_motion[frame].wmtype <= AFFINE);
@@ -183,12 +183,15 @@
 
     if (cm->global_motion[frame].wmtype == IDENTITY) continue;
 
-    if (ref_frame_error == 0) continue;
+    // Once we get here, best_ref_frame_error must be > 0. This is because
+    // of the logic above, which skips  over any models which have
+    // ref_frame_error == 0
+    assert(best_ref_frame_error > 0);
 
     // If the best error advantage found doesn't meet the threshold for
     // this motion type, revert to IDENTITY.
     if (!av1_is_enough_erroradvantage(
-            (double)best_warp_error / ref_frame_error,
+            (double)best_warp_error / best_ref_frame_error,
             gm_get_params_cost(&cm->global_motion[frame], ref_params,
                                cm->features.allow_high_precision_mv))) {
       cm->global_motion[frame] = default_warp_params;
@@ -231,7 +234,7 @@
     // INVALID/TRANSLATION/IDENTITY, skip the evaluation of global motion w.r.t
     // the remaining ref frames in that direction.
     if (cpi->sf.gm_sf.prune_ref_frame_for_gm_search &&
-        cm->global_motion[ref_frame].wmtype != ROTZOOM)
+        cm->global_motion[ref_frame].wmtype <= TRANSLATION)
       break;
   }
 }