Skip repeated mv when searching with second_best_mv

This CL adds the missing feature to skip subpel search in second_best_mv
when subpel_search_method is SUBPEL_TREE_PRUNED or above.

An average speed up of 0.1% to 0.2% is observed on speed 3-5.

BUG=aomedia:2594

Change-Id: I23864f5e4b8fbf02e0aee93e274e501e245a5740
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 1b48c2b..d3ba114 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -87,18 +87,19 @@
   init_mv_cost_params(&ms_params->mv_cost_params, x, ref_mv);
 }
 
-void av1_make_default_subpel_ms_params(
-    SUBPEL_MOTION_SEARCH_PARAMS *ms_params, const struct AV1_COMP *cpi,
-    const MACROBLOCK *x, BLOCK_SIZE bsize, const MV *ref_mv,
-    const int *cost_list, const uint8_t *second_pred, const uint8_t *mask,
-    int mask_stride, int invert_mask, int do_reset_fractional_mv) {
+void av1_make_default_subpel_ms_params(SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
+                                       const struct AV1_COMP *cpi,
+                                       const MACROBLOCK *x, BLOCK_SIZE bsize,
+                                       const MV *ref_mv, const int *cost_list,
+                                       const uint8_t *second_pred,
+                                       const uint8_t *mask, int mask_stride,
+                                       int invert_mask) {
   const AV1_COMMON *cm = &cpi->common;
   // High level params
   ms_params->allow_hp = cm->features.allow_high_precision_mv;
   ms_params->forced_stop = cpi->sf.mv_sf.subpel_force_stop;
   ms_params->iters_per_step = cpi->sf.mv_sf.subpel_iters_per_step;
   ms_params->cost_list = cond_cost_list_const(cpi, cost_list);
-  ms_params->do_reset_fractional_mv = do_reset_fractional_mv;
 
   av1_set_subpel_mv_search_range(&ms_params->mv_limits, &x->mv_limits, ref_mv);
 
@@ -2507,12 +2508,26 @@
                          (cost_list[4] - 2 * cost_list[0] + cost_list[2]));
 }
 
+// Checks the list of mvs searched in the last iteration and see if we are
+// repeating it. If so, return 1. Otherwise we update the last_mv_search_list
+// with current_mv and return 0.
+static INLINE int check_repeated_mv_and_update(int_mv *last_mv_search_list,
+                                               const MV current_mv, int iter) {
+  if (last_mv_search_list) {
+    if (CHECK_MV_EQUAL(last_mv_search_list[iter].as_mv, current_mv)) {
+      return 1;
+    }
+
+    last_mv_search_list[iter].as_mv = current_mv;
+  }
+  return 0;
+}
+
 int av1_find_best_sub_pixel_tree_pruned_evenmore(
     MACROBLOCKD *xd, const AV1_COMMON *const cm,
     const SUBPEL_MOTION_SEARCH_PARAMS *ms_params, MV start_mv, MV *bestmv,
     int *distortion, unsigned int *sse1, int_mv *last_mv_search_list) {
   (void)cm;
-  (void)last_mv_search_list;
   const int allow_hp = ms_params->allow_hp;
   const int forced_stop = ms_params->forced_stop;
   const int iters_per_step = ms_params->iters_per_step;
@@ -2521,13 +2536,21 @@
   const MV_COST_PARAMS *mv_cost_params = &ms_params->mv_cost_params;
   const SUBPEL_SEARCH_VAR_PARAMS *var_params = &ms_params->var_params;
 
+  // The iteration we are current searching for. Iter 0 corresponds to fullpel
+  // mv, iter 1 to half pel, and so on
+  int iter = 0;
+  int hstep = INIT_SUBPEL_STEP_SIZE;  // Step size, initialized to 4/8=1/2 pel
   unsigned int besterr = INT_MAX;
-  int hstep = INIT_SUBPEL_STEP_SIZE;
   *bestmv = start_mv;
 
   besterr = setup_center_error(xd, bestmv, var_params, mv_cost_params, sse1,
                                distortion);
 
+  if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+    return INT_MAX;
+  }
+  iter++;
+
   if (cost_list && cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
       cost_list[2] != INT_MAX && cost_list[3] != INT_MAX &&
       cost_list[4] != INT_MAX && is_cost_list_wellbehaved(cost_list)) {
@@ -2547,6 +2570,11 @@
     // Each subsequent iteration checks at least one point in common with
     // the last iteration could be 2 ( if diag selected) 1/4 pel
     if (forced_stop != HALF_PEL) {
+      if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+        return INT_MAX;
+      }
+      iter++;
+
       hstep >>= 1;
       start_mv = *bestmv;
       two_level_checks_fast(start_mv, bestmv, hstep, mv_limits, var_params,
@@ -2556,6 +2584,11 @@
   }
 
   if (allow_hp && forced_stop == EIGHTH_PEL) {
+    if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+      return INT_MAX;
+    }
+    iter++;
+
     hstep >>= 1;
     start_mv = *bestmv;
     two_level_checks_fast(start_mv, bestmv, hstep, mv_limits, var_params,
@@ -2571,7 +2604,6 @@
     const SUBPEL_MOTION_SEARCH_PARAMS *ms_params, MV start_mv, MV *bestmv,
     int *distortion, unsigned int *sse1, int_mv *last_mv_search_list) {
   (void)cm;
-  (void)last_mv_search_list;
   const int allow_hp = ms_params->allow_hp;
   const int forced_stop = ms_params->forced_stop;
   const int iters_per_step = ms_params->iters_per_step;
@@ -2580,12 +2612,21 @@
   const MV_COST_PARAMS *mv_cost_params = &ms_params->mv_cost_params;
   const SUBPEL_SEARCH_VAR_PARAMS *var_params = &ms_params->var_params;
 
+  // The iteration we are current searching for. Iter 0 corresponds to fullpel
+  // mv, iter 1 to half pel, and so on
+  int iter = 0;
+  int hstep = INIT_SUBPEL_STEP_SIZE;  // Step size, initialized to 4/8=1/2 pel
   unsigned int besterr = INT_MAX;
-  int hstep = INIT_SUBPEL_STEP_SIZE;
   *bestmv = start_mv;
 
   besterr = setup_center_error(xd, bestmv, var_params, mv_cost_params, sse1,
                                distortion);
+
+  if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+    return INT_MAX;
+  }
+  iter++;
+
   if (cost_list && cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
       cost_list[2] != INT_MAX && cost_list[3] != INT_MAX &&
       cost_list[4] != INT_MAX && is_cost_list_wellbehaved(cost_list)) {
@@ -2607,6 +2648,11 @@
   // Each subsequent iteration checks at least one point in common with
   // the last iteration could be 2 ( if diag selected) 1/4 pel
   if (forced_stop != HALF_PEL) {
+    if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+      return INT_MAX;
+    }
+    iter++;
+
     hstep >>= 1;
     start_mv = *bestmv;
     two_level_checks_fast(start_mv, bestmv, hstep, mv_limits, var_params,
@@ -2615,6 +2661,11 @@
   }
 
   if (allow_hp && forced_stop == EIGHTH_PEL) {
+    if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+      return INT_MAX;
+    }
+    iter++;
+
     hstep >>= 1;
     start_mv = *bestmv;
     two_level_checks_fast(start_mv, bestmv, hstep, mv_limits, var_params,
@@ -2630,7 +2681,6 @@
     const SUBPEL_MOTION_SEARCH_PARAMS *ms_params, MV start_mv, MV *bestmv,
     int *distortion, unsigned int *sse1, int_mv *last_mv_search_list) {
   (void)cm;
-  (void)last_mv_search_list;
   const int allow_hp = ms_params->allow_hp;
   const int forced_stop = ms_params->forced_stop;
   const int iters_per_step = ms_params->iters_per_step;
@@ -2639,12 +2689,25 @@
   const MV_COST_PARAMS *mv_cost_params = &ms_params->mv_cost_params;
   const SUBPEL_SEARCH_VAR_PARAMS *var_params = &ms_params->var_params;
 
+  // The iteration we are current searching for. Iter 0 corresponds to fullpel
+  // mv, iter 1 to half pel, and so on
+  int iter = 0;
+  int hstep = INIT_SUBPEL_STEP_SIZE;  // Step size, initialized to 4/8=1/2 pel
   unsigned int besterr = INT_MAX;
-  int hstep = INIT_SUBPEL_STEP_SIZE;
   *bestmv = start_mv;
 
+  const int do_reset_fractional_mv = ms_params->do_reset_fractional_mv;
+  if (do_reset_fractional_mv && last_mv_search_list) {
+    av1_set_fractional_mv(last_mv_search_list);
+  }
+
   besterr = setup_center_error(xd, bestmv, var_params, mv_cost_params, sse1,
                                distortion);
+  if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+    return INT_MAX;
+  }
+  iter++;
+
   if (cost_list && cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
       cost_list[2] != INT_MAX && cost_list[3] != INT_MAX &&
       cost_list[4] != INT_MAX) {
@@ -2706,6 +2769,11 @@
   // Each subsequent iteration checks at least one point in common with
   // the last iteration could be 2 ( if diag selected) 1/4 pel
   if (forced_stop != HALF_PEL) {
+    if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+      return INT_MAX;
+    }
+    iter++;
+
     hstep >>= 1;
     start_mv = *bestmv;
     two_level_checks_fast(start_mv, bestmv, hstep, mv_limits, var_params,
@@ -2714,6 +2782,11 @@
   }
 
   if (allow_hp && forced_stop == EIGHTH_PEL) {
+    if (check_repeated_mv_and_update(last_mv_search_list, *bestmv, iter)) {
+      return INT_MAX;
+    }
+    iter++;
+
     hstep >>= 1;
     start_mv = *bestmv;
     two_level_checks_fast(start_mv, bestmv, hstep, mv_limits, var_params,
@@ -2739,8 +2812,10 @@
       ms_params->var_params.subpel_search_type;
   const SubpelMvLimits *mv_limits = &ms_params->mv_limits;
 
+  // How many steps to take. A round of 0 means fullpel search only, 1 means
+  // half-pel, and so on.
   const int round = AOMMIN(FULL_PEL - forced_stop, 3 - !allow_hp);
-  int hstep = INIT_SUBPEL_STEP_SIZE;
+  int hstep = INIT_SUBPEL_STEP_SIZE;  // Step size, initialized to 4/8=1/2 pel
 
   unsigned int besterr = INT_MAX;
 
@@ -2760,12 +2835,9 @@
 
   for (int iter = 0; iter < round; ++iter) {
     MV iter_center_mv = *bestmv;
-    if (last_mv_search_list) {
-      if (CHECK_MV_EQUAL(last_mv_search_list[iter].as_mv, iter_center_mv)) {
-        return INT_MAX;
-      }
-
-      last_mv_search_list[iter].as_mv = iter_center_mv;
+    if (check_repeated_mv_and_update(last_mv_search_list, iter_center_mv,
+                                     iter)) {
+      return INT_MAX;
     }
 
     MV diag_step;
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index b9e5b80..5af577a 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -272,11 +272,13 @@
   SUBPEL_SEARCH_VAR_PARAMS var_params;
 } SUBPEL_MOTION_SEARCH_PARAMS;
 
-void av1_make_default_subpel_ms_params(
-    SUBPEL_MOTION_SEARCH_PARAMS *ms_params, const struct AV1_COMP *cpi,
-    const MACROBLOCK *x, BLOCK_SIZE bsize, const MV *ref_mv,
-    const int *cost_list, const uint8_t *second_pred, const uint8_t *mask,
-    int mask_stride, int invert_mask, int do_reset_fractional_mv);
+void av1_make_default_subpel_ms_params(SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
+                                       const struct AV1_COMP *cpi,
+                                       const MACROBLOCK *x, BLOCK_SIZE bsize,
+                                       const MV *ref_mv, const int *cost_list,
+                                       const uint8_t *second_pred,
+                                       const uint8_t *mask, int mask_stride,
+                                       int invert_mask);
 
 typedef int(fractional_mv_step_fp)(MACROBLOCKD *xd, const AV1_COMMON *const cm,
                                    const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index 7a0c38f..0259aa3 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -200,7 +200,6 @@
     const uint8_t *mask = NULL;
     const int mask_stride = 0;
     const int invert_mask = 1;
-    const int reset_fractional_mv = 1;
     int_mv fractional_ms_list[3];
     av1_set_fractional_mv(fractional_ms_list);
     int dis; /* TODO: use dis in distortion calculation later. */
@@ -208,7 +207,7 @@
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list, second_pred, mask, mask_stride,
-                                      invert_mask, reset_fractional_mv);
+                                      invert_mask);
     MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
 
     switch (mbmi->motion_mode) {
@@ -225,8 +224,6 @@
             subpel_start_mv = get_mv_from_fullmv(&second_best_mv.as_fullmv);
             if (av1_is_subpelmv_in_range(&ms_params.mv_limits,
                                          subpel_start_mv)) {
-              ms_params.do_reset_fractional_mv = !reset_fractional_mv;
-
               const int this_var = cpi->find_fractional_mv_step(
                   xd, cm, &ms_params, subpel_start_mv, &this_best_mv, &dis,
                   &x->pred_sse[ref], fractional_ms_list);
@@ -411,7 +408,7 @@
       SUBPEL_MOTION_SEARCH_PARAMS ms_params;
       av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize,
                                         &ref_mv[id].as_mv, NULL, second_pred,
-                                        mask, mask_stride, id, 1);
+                                        mask, mask_stride, id);
       ms_params.forced_stop = EIGHTH_PEL;
       MV start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
       bestsme = cpi->find_fractional_mv_step(
@@ -531,7 +528,7 @@
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv.as_mv,
                                       NULL, second_pred, mask, mask_stride,
-                                      ref_idx, 1);
+                                      ref_idx);
     ms_params.forced_stop = EIGHTH_PEL;
     MV start_mv = get_mv_from_fullmv(&best_int_mv->as_fullmv);
     bestsme = cpi->find_fractional_mv_step(
@@ -727,11 +724,10 @@
     const uint8_t *mask = NULL;
     const int mask_stride = 0;
     const int invert_mask = 0;
-    const int reset_fractional_mv = 1;
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list, second_pred, mask, mask_stride,
-                                      invert_mask, reset_fractional_mv);
+                                      invert_mask);
     MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
 
     cpi->find_fractional_mv_step(xd, cm, &ms_params, subpel_start_mv,
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 60e0a85..faeb77c 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -177,11 +177,10 @@
     const uint8_t *mask = NULL;
     const int mask_stride = 0;
     const int invert_mask = 0;
-    const int reset_fractional_mv = 1;
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list, second_pred, mask, mask_stride,
-                                      invert_mask, reset_fractional_mv);
+                                      invert_mask);
     MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
     cpi->find_fractional_mv_step(xd, cm, &ms_params, subpel_start_mv,
                                  &x->best_mv.as_mv, &dis, &x->pred_sse[ref],
@@ -240,11 +239,10 @@
     const uint8_t *mask = NULL;
     const int mask_stride = 0;
     const int invert_mask = 0;
-    const int reset_fractional_mv = 1;
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list, second_pred, mask, mask_stride,
-                                      invert_mask, reset_fractional_mv);
+                                      invert_mask);
     MV start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
     cpi->find_fractional_mv_step(xd, cm, &ms_params, start_mv,
                                  &x->best_mv.as_mv, &dis,
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index d8062f8..e27a79f 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -85,7 +85,6 @@
   const uint8_t *mask = NULL;
   const int mask_stride = 0;
   const int invert_mask = 0;
-  const int do_reset_fractional_mv = 1;
   FULLPEL_MOTION_SEARCH_PARAMS full_ms_params;
   SUBPEL_MOTION_SEARCH_PARAMS ms_params;
 
@@ -143,9 +142,9 @@
         frame_to_filter->y_buffer + y_offset, y_stride, &sse);
     mb->e_mbd.mi[0]->mv[0] = mb->best_mv;
   } else {  // Do fractional search on the entire block and all sub-blocks.
-    av1_make_default_subpel_ms_params(
-        &ms_params, cpi, mb, block_size, &baseline_mv, cost_list, second_pred,
-        mask, mask_stride, invert_mask, do_reset_fractional_mv);
+    av1_make_default_subpel_ms_params(&ms_params, cpi, mb, block_size,
+                                      &baseline_mv, cost_list, second_pred,
+                                      mask, mask_stride, invert_mask);
     ms_params.forced_stop = EIGHTH_PEL;
     ms_params.var_params.subpel_search_type = subpel_search_type;
     MV subpel_start_mv = get_mv_from_fullmv(&mb->best_mv.as_fullmv);
@@ -182,8 +181,7 @@
         mb->mv_cost_type = MV_COST_NONE;
         av1_make_default_subpel_ms_params(&ms_params, cpi, mb, subblock_size,
                                           &baseline_mv, cost_list, second_pred,
-                                          mask, mask_stride, invert_mask,
-                                          do_reset_fractional_mv);
+                                          mask, mask_stride, invert_mask);
         ms_params.forced_stop = EIGHTH_PEL;
         ms_params.var_params.subpel_search_type = subpel_search_type;
         subpel_start_mv = get_mv_from_fullmv(&mb->best_mv.as_fullmv);
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 8ce2b32..9520dc3 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -159,11 +159,10 @@
   const uint8_t *mask = NULL;
   const int mask_stride = 0;
   const int invert_mask = 0;
-  const int do_reset_fractional_mv = 1;
   SUBPEL_MOTION_SEARCH_PARAMS ms_params;
   av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &center_mv,
                                     cost_list, second_pred, mask, mask_stride,
-                                    invert_mask, do_reset_fractional_mv);
+                                    invert_mask);
   ms_params.forced_stop = EIGHTH_PEL;
   ms_params.var_params.subpel_search_type = USE_2_TAPS;
   ms_params.mv_cost_params.mv_cost_type = MV_COST_NONE;