Improve the alt_ref_search_fp speed feature

            Encode Time      Quality Impact(%)
CPU-used    reduction(%)       (AWCY)
  4          1.73               0.04

STATS_CHANGED

Change-Id: I8ade221ac48e3874c4ae0af00666056ea557810a
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 067ed15..965e4cc 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -256,6 +256,7 @@
   unsigned int simple_motion_pred_sse;
   unsigned int pred_sse[REF_FRAMES];
   int pred_mv_sad[REF_FRAMES];
+  int best_pred_mv_sad;
 
   int nmv_vec_cost[MV_JOINTS];
   int *nmvcost[2];
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 0a662f7..8ce5a11 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4423,6 +4423,24 @@
                 cpi->oxcf.max_reference_frames);
 }
 
+// Set the relative distance of a reference frame w.r.t. current frame
+static void set_rel_frame_dist(AV1_COMP *cpi) {
+  const AV1_COMMON *const cm = &cpi->common;
+  const SPEED_FEATURES *const sf = &cpi->sf;
+  const OrderHintInfo *const order_hint_info = &cm->seq_params.order_hint_info;
+  MV_REFERENCE_FRAME ref_frame;
+  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+    cpi->ref_relative_dist[ref_frame - LAST_FRAME] = 0;
+    if (sf->alt_ref_search_fp) {
+      int dist = av1_encoder_get_relative_dist(
+          order_hint_info,
+          cm->cur_frame->ref_display_order_hint[ref_frame - LAST_FRAME],
+          cm->current_frame.display_order_hint);
+      cpi->ref_relative_dist[ref_frame - LAST_FRAME] = dist;
+    }
+  }
+}
+
 // Enforce the number of references for each arbitrary frame based on user
 // options and speed.
 static void enforce_max_ref_frames(AV1_COMP *cpi) {
@@ -5004,6 +5022,7 @@
 
   av1_setup_frame_buf_refs(cm);
   enforce_max_ref_frames(cpi);
+  set_rel_frame_dist(cpi);
   av1_setup_frame_sign_bias(cm);
 
 #if CHECK_PRECOMPUTED_REF_FRAME_MAP
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index a3bb24b..17dbcc8 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1037,6 +1037,9 @@
   // whether any no-zero delta_q was actually used
   int deltaq_used;
 
+  // Indicates the true relative distance of ref frame w.r.t. current frame
+  int8_t ref_relative_dist[INTER_REFS_PER_FRAME];
+
   double *ssim_rdmult_scaling_factors;
 
   // Whether writing to bitstream. It allows us to encode one frame multiple
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index b3804b5..83c210d 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -11479,10 +11479,18 @@
     }
   }
 
-  if (sf->alt_ref_search_fp)
-    if (!cm->show_frame && x->pred_mv_sad[GOLDEN_FRAME] < INT_MAX)
-      if (x->pred_mv_sad[ALTREF_FRAME] > (x->pred_mv_sad[GOLDEN_FRAME] << 1))
-        mask->pred_modes[ALTREF_FRAME] |= INTER_ALL;
+  if (sf->alt_ref_search_fp) {
+    if (!cm->show_frame && x->best_pred_mv_sad < INT_MAX) {
+      int sad_thresh = x->best_pred_mv_sad + (x->best_pred_mv_sad >> 3);
+      // Conservatively skip the modes w.r.t. BWDREF, ALTREF2 and ALTREF, if
+      // those are past frames
+      for (ref_frame = BWDREF_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
+        if (cpi->ref_relative_dist[ref_frame - LAST_FRAME] < 0)
+          if (x->pred_mv_sad[ref_frame] > sad_thresh)
+            mask->pred_modes[ref_frame] |= INTER_ALL;
+      }
+    }
+  }
 
   if (sf->adaptive_mode_search) {
     if (cm->show_frame && !cpi->rc.is_src_frame_alt_ref &&
@@ -11544,6 +11552,7 @@
                            ref_costs_comp);
 
   MV_REFERENCE_FRAME ref_frame;
+  x->best_pred_mv_sad = INT_MAX;
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
     x->pred_mv_sad[ref_frame] = INT_MAX;
     x->mbmi_ext->mode_context[ref_frame] = 0;
@@ -11569,6 +11578,11 @@
       setup_buffer_ref_mvs_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
                                  yv12_mb);
     }
+    // Store the best pred_mv_sad across all past frames
+    if (cpi->sf.alt_ref_search_fp &&
+        cpi->ref_relative_dist[ref_frame - LAST_FRAME] < 0)
+      x->best_pred_mv_sad =
+          AOMMIN(x->best_pred_mv_sad, x->pred_mv_sad[ref_frame]);
   }
   // ref_frame = ALTREF_FRAME
   for (; ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {