Disable global motion param estimation based on stats

In speed 2, global motion param estimation has been disabled
based on number of GM models found so far in the same GF group.

cpu-used  Instruction Count     BD-Rate Loss(%)
           Reduction(%)     avg.psnr  ovr.psnr  ssim
   2          3.9            -0.0007   -0.0013	-0.0006

STATS_CHANGED

Change-Id: Id83dbfe92e87ee9b4791dd2ed0fb4377b61f04ad
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 4b657c8..6886d75 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4114,11 +4114,34 @@
 }
 #endif
 
+// Updates frame level stats related to global motion
+static AOM_INLINE void update_gm_stats(AV1_COMP *cpi) {
+  FRAME_UPDATE_TYPE update_type =
+      cpi->ppi->gf_group.update_type[cpi->gf_frame_index];
+  int i, is_gm_present = 0;
+
+  // Check if the current frame has any valid global motion model across its
+  // reference frames
+  for (i = 0; i < REF_FRAMES; i++) {
+    if (cpi->common.global_motion[i].wmtype != IDENTITY) {
+      is_gm_present = 1;
+      break;
+    }
+  }
+  if (cpi->ppi->valid_gm_model_found[update_type] == INT32_MAX) {
+    cpi->ppi->valid_gm_model_found[update_type] = is_gm_present;
+  } else {
+    cpi->ppi->valid_gm_model_found[update_type] |= is_gm_present;
+  }
+}
+
 void av1_post_encode_updates(AV1_COMP *const cpi,
                              const AV1_COMP_DATA *const cpi_data) {
   AV1_PRIMARY *const ppi = cpi->ppi;
   AV1_COMMON *const cm = &cpi->common;
 
+  update_gm_stats(cpi);
+
 #if !CONFIG_REALTIME_ONLY
   // Update the total stats remaining structure.
   if (cpi->twopass_frame.this_frame != NULL &&
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 26a66db..0204d1c 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -2559,6 +2559,14 @@
    * Probabilities for pruning of various AV1 tools.
    */
   FrameProbInfo frame_probs;
+
+  /*!
+   * Indicates if a valid global motion model has been found in the different
+   * frame update types of a GF group.
+   * valid_gm_model_found[i] indicates if valid global motion model has been
+   * found in the frame update type with enum value equal to i
+   */
+  int valid_gm_model_found[FRAME_UPDATE_TYPES];
 } AV1_PRIMARY;
 
 /*!
diff --git a/av1/encoder/global_motion_facade.c b/av1/encoder/global_motion_facade.c
index f91ef04..8d9908e 100644
--- a/av1/encoder/global_motion_facade.c
+++ b/av1/encoder/global_motion_facade.c
@@ -253,6 +253,27 @@
   return 0;
 }
 
+static int disable_gm_search_based_on_stats(const AV1_COMP *const cpi) {
+  int is_gm_present = 1;
+
+  // Check number of GM models only in GF groups with ARF frames. GM param
+  // estimation is always done in the case of GF groups with no ARF frames (flat
+  // gops)
+  if (cpi->ppi->gf_group.arf_index > -1) {
+    // valid_gm_model_found is initialized to INT32_MAX in the beginning of
+    // every GF group.
+    // Therefore, GM param estimation is always done for all frames until
+    // atleast 1 frame each of ARF_UPDATE, INTNL_ARF_UPDATE and LF_UPDATE are
+    // encoded in a GF group For subsequent frames, GM param estimation is
+    // disabled, if no valid models have been found in all the three update
+    // types.
+    is_gm_present = (cpi->ppi->valid_gm_model_found[ARF_UPDATE] != 0) ||
+                    (cpi->ppi->valid_gm_model_found[INTNL_ARF_UPDATE] != 0) ||
+                    (cpi->ppi->valid_gm_model_found[LF_UPDATE] != 0);
+  }
+  return !is_gm_present;
+}
+
 // Prunes reference frames for global motion estimation based on the speed
 // feature 'gm_search_type'.
 static int do_gm_search_logic(SPEED_FEATURES *const sf, int frame) {
@@ -282,6 +303,11 @@
   const GF_GROUP *gf_group = &cpi->ppi->gf_group;
   int ref_pruning_enabled = is_frame_eligible_for_ref_pruning(
       gf_group, cpi->sf.inter_sf.selective_ref_frame, 1, cpi->gf_frame_index);
+  int cur_frame_gm_disabled = 0;
+
+  if (cpi->sf.gm_sf.disable_gm_search_based_on_stats) {
+    cur_frame_gm_disabled = disable_gm_search_based_on_stats(cpi);
+  }
 
   for (int frame = ALTREF_FRAME; frame >= LAST_FRAME; --frame) {
     const MV_REFERENCE_FRAME ref_frame[2] = { frame, NONE_FRAME };
@@ -305,7 +331,8 @@
 
     if (ref_buf[frame]->y_crop_width == cpi->source->y_crop_width &&
         ref_buf[frame]->y_crop_height == cpi->source->y_crop_height &&
-        do_gm_search_logic(&cpi->sf, frame) && !prune_ref_frames) {
+        do_gm_search_logic(&cpi->sf, frame) && !prune_ref_frames &&
+        !cur_frame_gm_disabled) {
       assert(ref_buf[frame] != NULL);
       const int relative_frame_dist = av1_encoder_get_relative_dist(
           buf->display_order_hint, cm->cur_frame->display_order_hint);
@@ -429,6 +456,13 @@
   AV1_COMMON *const cm = &cpi->common;
   GlobalMotionInfo *const gm_info = &cpi->gm_info;
 
+  if (cpi->oxcf.tool_cfg.enable_global_motion) {
+    if (cpi->gf_frame_index == 0) {
+      for (int i = 0; i < FRAME_UPDATE_TYPES; i++)
+        cpi->ppi->valid_gm_model_found[i] = INT32_MAX;
+    }
+  }
+
   if (cpi->common.current_frame.frame_type == INTER_FRAME && cpi->source &&
       cpi->oxcf.tool_cfg.enable_global_motion && !gm_info->search_done) {
     setup_global_motion_info_params(cpi);
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 7fc4b3f..cd4a439 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -906,6 +906,8 @@
 
     sf->fp_sf.skip_motion_search_threshold = 25;
 
+    sf->gm_sf.disable_gm_search_based_on_stats = 1;
+
     sf->part_sf.reuse_best_prediction_for_part_ab =
         !frame_is_intra_only(&cpi->common);
 
@@ -1586,6 +1588,7 @@
   gm_sf->gm_search_type = GM_FULL_SEARCH;
   gm_sf->prune_ref_frame_for_gm_search = 0;
   gm_sf->prune_zero_mv_with_sse = 0;
+  gm_sf->disable_gm_search_based_on_stats = 0;
 }
 
 static AOM_INLINE void init_part_sf(PARTITION_SPEED_FEATURES *part_sf) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 41a56a6..6202191 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -455,6 +455,10 @@
   // When the current GM type is set to ZEROMV, prune ZEROMV if its performance
   // is worse than NEWMV under SSE metric.
   int prune_zero_mv_with_sse;
+
+  // Disable global motion estimation based on stats of previous frames in the
+  // GF group
+  int disable_gm_search_based_on_stats;
 } GLOBAL_MOTION_SPEED_FEATURES;
 
 typedef struct PARTITION_SPEED_FEATURES {