Remove best_mv from macroblock

BUG=aomedia:2618

Change-Id: Iaaca1210f5e39cf62182fbaebe067115e085d61e
diff --git a/av1/common/mv.h b/av1/common/mv.h
index 28fb358..be539e8 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -24,6 +24,10 @@
 #define GET_MV_RAWPEL(x) (((x) + 3 + ((x) >= 0)) >> 3)
 #define GET_MV_SUBPEL(x) ((x)*8)
 
+#define MARK_MV_INVALID(mv)                \
+  do {                                     \
+    ((int_mv *)(mv))->as_int = INVALID_MV; \
+  } while (0);
 #define CHECK_MV_EQUAL(x, y) (((x).row == (y).row) && ((x).col == (y).col))
 
 // The motion vector in units of full pixel
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 51c84d8..55391c7 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -395,12 +395,6 @@
   // Used to store sub partition's choices.
   MV pred_mv[REF_FRAMES];
 
-  // Store the best motion vector during motion search
-  int_mv best_mv;
-
-  // Store the fractional best motion vector during sub/Qpel-pixel motion search
-  int_mv fractional_best_mv[3];
-
   // Ref frames that are selected by square partition blocks within a super-
   // block, in MI resolution. They can be used to prune ref frames for
   // rectangular blocks.
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 245ae7d..bbe37e6 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -230,7 +230,6 @@
   const int new_mv_mode_penalty = NEW_MV_MODE_PENALTY;
   const int sr = get_search_range(cpi);
   const int step_param = 3 + sr;
-  int cost_list[5];
 
   const search_site_config *first_pass_search_sites =
       &cpi->mv_search_params.ss_cfg[SS_CFG_FPF];
@@ -239,17 +238,18 @@
                                      first_pass_search_sites);
   ms_params.search_method = NSTEP;
 
-  tmp_err = av1_full_pixel_search(start_mv, &ms_params, step_param, cost_list,
-                                  &x->best_mv.as_fullmv, NULL);
+  FULLPEL_MV this_best_mv;
+  tmp_err = av1_full_pixel_search(start_mv, &ms_params, step_param, NULL,
+                                  &this_best_mv, NULL);
 
   if (tmp_err < INT_MAX) {
-    tmp_err = av1_get_mvpred_sse(x, &x->best_mv.as_fullmv, ref_mv, &v_fn_ptr) +
+    tmp_err = av1_get_mvpred_sse(x, &this_best_mv, ref_mv, &v_fn_ptr) +
               new_mv_mode_penalty;
   }
 
   if (tmp_err < *best_motion_err) {
     *best_motion_err = tmp_err;
-    *best_mv = x->best_mv.as_fullmv;
+    *best_mv = this_best_mv;
   }
 }
 
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index b0e6339..750cdbb 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -1408,13 +1408,16 @@
                           const int step_param, int *cost_list,
                           FULLPEL_MV *best_mv, FULLPEL_MV *second_best_mv) {
   const BLOCK_SIZE bsize = ms_params->bsize;
-
   const SEARCH_METHODS search_method = ms_params->search_method;
 
   const int is_intra_mode = ms_params->is_intra_mode;
   int run_mesh_search = ms_params->run_mesh_search;
 
   int var = 0;
+  MARK_MV_INVALID(best_mv);
+  if (second_best_mv) {
+    MARK_MV_INVALID(second_best_mv);
+  }
 
   assert(ms_params->ms_buffers.second_pred == NULL &&
          ms_params->ms_buffers.mask == NULL &&
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index 0219bc4..70ce23f 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -39,7 +39,8 @@
 
 void av1_single_motion_search(const AV1_COMP *const cpi, MACROBLOCK *x,
                               BLOCK_SIZE bsize, int ref_idx, int *rate_mv,
-                              int search_range, inter_mode_info *mode_info) {
+                              int search_range, inter_mode_info *mode_info,
+                              int_mv *best_mv) {
   MACROBLOCKD *xd = &x->e_mbd;
   const AV1_COMMON *cm = &cpi->common;
   const MotionVectorSearchParams *mv_search_params = &cpi->mv_search_params;
@@ -103,7 +104,7 @@
         if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
           x->pred_mv[ref].row = 0;
           x->pred_mv[ref].col = 0;
-          x->best_mv.as_int = INVALID_MV;
+          best_mv->as_int = INVALID_MV;
 
           if (scaled_ref_frame) {
             // Swap back the original buffers before returning.
@@ -201,7 +202,7 @@
 
   int cost_list[5];
   int_mv second_best_mv;
-  x->best_mv.as_int = second_best_mv.as_int = INVALID_MV;
+  best_mv->as_int = second_best_mv.as_int = INVALID_MV;
 
   const search_site_config *src_search_sites =
       &mv_search_params->ss_cfg[SS_CFG_SRC];
@@ -211,35 +212,29 @@
 
   switch (mbmi->motion_mode) {
     case SIMPLE_TRANSLATION: {
-      int cur_bestsme = bestsme;
-      FULLPEL_MV best_mv;
       int sum_weight = 0;
-      FULLPEL_MV second_best_mv0;
 
       for (int m = 0; m < cnt; m++) {
         FULLPEL_MV smv = cand[m].fmv;
-        bestsme = av1_full_pixel_search(
-            smv, &full_ms_params, step_param, cond_cost_list(cpi, cost_list),
-            &x->best_mv.as_fullmv, &second_best_mv.as_fullmv);
+        FULLPEL_MV this_best_mv, this_second_best_mv;
 
-        if (!m || bestsme < cur_bestsme) {
-          cur_bestsme = bestsme;
-          best_mv = x->best_mv.as_fullmv;
-          second_best_mv0 = second_best_mv.as_fullmv;
+        int thissme = av1_full_pixel_search(
+            smv, &full_ms_params, step_param, cond_cost_list(cpi, cost_list),
+            &this_best_mv, &this_second_best_mv);
+
+        if (thissme < bestsme) {
+          bestsme = thissme;
+          best_mv->as_fullmv = this_best_mv;
+          second_best_mv.as_fullmv = this_second_best_mv;
         }
 
         sum_weight += cand[m].weight;
         if (m >= 2 || 4 * sum_weight > 3 * total_weight) break;
-        // Reset MVs
-        x->best_mv.as_int = second_best_mv.as_int = INVALID_MV;
       }
-      x->best_mv.as_fullmv = best_mv;
-      bestsme = cur_bestsme;
-      second_best_mv.as_fullmv = second_best_mv0;
     } break;
     case OBMC_CAUSAL:
       bestsme = av1_obmc_full_pixel_search(start_mv, &full_ms_params,
-                                           step_param, &(x->best_mv.as_fullmv));
+                                           step_param, &best_mv->as_fullmv);
       break;
     default: assert(0 && "Invalid motion mode!\n");
   }
@@ -259,9 +254,9 @@
   //     for the other ref_mv.
   if (cpi->sf.inter_sf.skip_repeated_full_newmv &&
       mbmi->motion_mode == SIMPLE_TRANSLATION &&
-      x->best_mv.as_int != INVALID_MV) {
+      best_mv->as_int != INVALID_MV) {
     int_mv this_mv;
-    this_mv.as_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    this_mv.as_mv = get_mv_from_fullmv(&best_mv->as_fullmv);
     const int ref_mv_idx = mbmi->ref_mv_idx;
     const int this_mv_rate =
         av1_mv_bit_cost(&this_mv.as_mv, &ref_mv, x->nmv_vec_cost,
@@ -284,7 +279,7 @@
           // called by handle_new_mv in SIMPLE_TRANSLATION mode, we set the
           // best_mv to INVALID mv to signal that we wish to terminate search
           // for the current mode.
-          x->best_mv.as_int = INVALID_MV;
+          best_mv->as_int = INVALID_MV;
           return;
         }
       }
@@ -292,7 +287,7 @@
   }
 
   if (cpi->common.features.cur_frame_force_integer_mv) {
-    convert_fullmv_to_mv(&x->best_mv);
+    convert_fullmv_to_mv(best_mv);
   }
 
   const int use_fractional_mv =
@@ -305,15 +300,15 @@
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list);
-    MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    MV subpel_start_mv = get_mv_from_fullmv(&best_mv->as_fullmv);
 
     switch (mbmi->motion_mode) {
       case SIMPLE_TRANSLATION:
         if (cpi->sf.mv_sf.use_accurate_subpel_search) {
           const int try_second = second_best_mv.as_int != INVALID_MV &&
-                                 second_best_mv.as_int != x->best_mv.as_int;
+                                 second_best_mv.as_int != best_mv->as_int;
           const int best_mv_var = mv_search_params->find_fractional_mv_step(
-              xd, cm, &ms_params, subpel_start_mv, &x->best_mv.as_mv, &dis,
+              xd, cm, &ms_params, subpel_start_mv, &best_mv->as_mv, &dis,
               &x->pred_sse[ref], fractional_ms_list);
 
           if (try_second) {
@@ -324,29 +319,29 @@
               const int this_var = mv_search_params->find_fractional_mv_step(
                   xd, cm, &ms_params, subpel_start_mv, &this_best_mv, &dis,
                   &x->pred_sse[ref], fractional_ms_list);
-              if (this_var < best_mv_var) x->best_mv.as_mv = this_best_mv;
+              if (this_var < best_mv_var) best_mv->as_mv = this_best_mv;
             }
           }
         } else {
           mv_search_params->find_fractional_mv_step(
-              xd, cm, &ms_params, subpel_start_mv, &x->best_mv.as_mv, &dis,
+              xd, cm, &ms_params, subpel_start_mv, &best_mv->as_mv, &dis,
               &x->pred_sse[ref], NULL);
         }
         break;
       case OBMC_CAUSAL:
         av1_find_best_obmc_sub_pixel_tree_up(xd, cm, &ms_params,
-                                             subpel_start_mv, &x->best_mv.as_mv,
+                                             subpel_start_mv, &best_mv->as_mv,
                                              &dis, &x->pred_sse[ref], NULL);
         break;
       default: assert(0 && "Invalid motion mode!\n");
     }
   }
-  *rate_mv = av1_mv_bit_cost(&x->best_mv.as_mv, &ref_mv, x->nmv_vec_cost,
+  *rate_mv = av1_mv_bit_cost(&best_mv->as_mv, &ref_mv, x->nmv_vec_cost,
                              x->mv_cost_stack, MV_COST_WEIGHT);
 
   if (cpi->sf.mv_sf.adaptive_motion_search &&
       mbmi->motion_mode == SIMPLE_TRANSLATION)
-    x->pred_mv[ref] = x->best_mv.as_mv;
+    x->pred_mv[ref] = best_mv->as_mv;
 }
 
 void av1_joint_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
@@ -386,7 +381,7 @@
   // Prediction buffer from second frame.
   DECLARE_ALIGNED(16, uint8_t, second_pred16[MAX_SB_SQUARE * sizeof(uint16_t)]);
   uint8_t *second_pred = get_buf_by_bd(xd, second_pred16);
-  int_mv *best_int_mv = &x->best_mv;
+  int_mv best_mv;
 
   // Allow joint search multiple times iteratively for each reference frame
   // and break out of the search loop if it couldn't find a better mv.
@@ -465,12 +460,12 @@
 
     // Small-range full-pixel motion search.
     bestsme = av1_refining_search_8p_c(&full_ms_params, start_fullmv,
-                                       &best_int_mv->as_fullmv);
+                                       &best_mv.as_fullmv);
 
     if (bestsme < INT_MAX) {
       bestsme = av1_get_mvpred_compound_var(
-          &full_ms_params.mv_cost_params, best_int_mv->as_fullmv, second_pred,
-          mask, mask_stride, id, &cpi->fn_ptr[bsize], &x->plane[0].src,
+          &full_ms_params.mv_cost_params, best_mv.as_fullmv, second_pred, mask,
+          mask_stride, id, &cpi->fn_ptr[bsize], &x->plane[0].src,
           &ref_yv12[id]);
     }
 
@@ -492,7 +487,7 @@
     if (id) xd->plane[plane].pre[0] = ref_yv12[id];
 
     if (cpi->common.features.cur_frame_force_integer_mv) {
-      convert_fullmv_to_mv(best_int_mv);
+      convert_fullmv_to_mv(&best_mv);
     }
     if (bestsme < INT_MAX &&
         cpi->common.features.cur_frame_force_integer_mv == 0) {
@@ -504,15 +499,15 @@
       av1_set_ms_compound_refs(&ms_params.var_params.ms_buffers, second_pred,
                                mask, mask_stride, id);
       ms_params.forced_stop = EIGHTH_PEL;
-      MV start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+      MV start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
       bestsme = cpi->mv_search_params.find_fractional_mv_step(
-          xd, cm, &ms_params, start_mv, &x->best_mv.as_mv, &dis, &sse, NULL);
+          xd, cm, &ms_params, start_mv, &best_mv.as_mv, &dis, &sse, NULL);
     }
 
     // Restore the pointer to the first prediction buffer.
     if (id) xd->plane[plane].pre[0] = ref_yv12[0];
     if (bestsme < last_besterr[id]) {
-      cur_mv[id] = *best_int_mv;
+      cur_mv[id] = best_mv;
       last_besterr[id] = bestsme;
     } else {
       break;
@@ -574,7 +569,7 @@
   }
 
   int bestsme = INT_MAX;
-  int_mv *best_int_mv = &x->best_mv;
+  int_mv best_mv;
 
   // Make motion search params
   FULLPEL_MOTION_SEARCH_PARAMS full_ms_params;
@@ -588,13 +583,12 @@
 
   // Small-range full-pixel motion search.
   bestsme = av1_refining_search_8p_c(&full_ms_params, start_fullmv,
-                                     &best_int_mv->as_fullmv);
+                                     &best_mv.as_fullmv);
 
   if (bestsme < INT_MAX) {
     bestsme = av1_get_mvpred_compound_var(
-        &full_ms_params.mv_cost_params, best_int_mv->as_fullmv, second_pred,
-        mask, mask_stride, ref_idx, &cpi->fn_ptr[bsize], &x->plane[0].src,
-        &ref_yv12);
+        &full_ms_params.mv_cost_params, best_mv.as_fullmv, second_pred, mask,
+        mask_stride, ref_idx, &cpi->fn_ptr[bsize], &x->plane[0].src, &ref_yv12);
   }
 
   if (scaled_ref_frame) {
@@ -605,7 +599,7 @@
   }
 
   if (cpi->common.features.cur_frame_force_integer_mv) {
-    convert_fullmv_to_mv(best_int_mv);
+    convert_fullmv_to_mv(&best_mv);
   }
   const int use_fractional_mv =
       bestsme < INT_MAX && cpi->common.features.cur_frame_force_integer_mv == 0;
@@ -618,15 +612,15 @@
     av1_set_ms_compound_refs(&ms_params.var_params.ms_buffers, second_pred,
                              mask, mask_stride, ref_idx);
     ms_params.forced_stop = EIGHTH_PEL;
-    MV start_mv = get_mv_from_fullmv(&best_int_mv->as_fullmv);
+    MV start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
     bestsme = cpi->mv_search_params.find_fractional_mv_step(
-        xd, cm, &ms_params, start_mv, &best_int_mv->as_mv, &dis, &sse, NULL);
+        xd, cm, &ms_params, start_mv, &best_mv.as_mv, &dis, &sse, NULL);
   }
 
   // Restore the pointer to the first unscaled prediction buffer.
   if (ref_idx) pd->pre[0] = orig_yv12;
 
-  if (bestsme < INT_MAX) *this_mv = best_int_mv->as_mv;
+  if (bestsme < INT_MAX) *this_mv = best_mv.as_mv;
 
   *rate_mv = 0;
 
@@ -750,10 +744,10 @@
   return tmp_rate_mv;
 }
 
-void av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
-                              int mi_col, BLOCK_SIZE bsize, int ref,
-                              FULLPEL_MV start_mv, int num_planes,
-                              int use_subpixel) {
+int_mv av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
+                                int mi_col, BLOCK_SIZE bsize, int ref,
+                                FULLPEL_MV start_mv, int num_planes,
+                                int use_subpixel) {
   assert(num_planes == 1 &&
          "Currently simple_motion_search only supports luma plane");
   assert(!frame_is_intra_only(&cpi->common) &&
@@ -782,6 +776,7 @@
   int cost_list[5];
   const int ref_idx = 0;
   int var;
+  int_mv best_mv;
 
   av1_setup_pre_planes(xd, ref_idx, yv12, mi_row, mi_col,
                        get_ref_scale_factors(cm, ref), num_planes);
@@ -798,7 +793,7 @@
 
   var = av1_full_pixel_search(start_mv, &full_ms_params, step_param,
                               cond_cost_list(cpi, cost_list),
-                              &x->best_mv.as_fullmv, NULL);
+                              &best_mv.as_fullmv, NULL);
 
   const int use_subpel_search =
       var < INT_MAX && !cpi->common.features.cur_frame_force_integer_mv &&
@@ -812,18 +807,18 @@
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list);
-    MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    MV subpel_start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
 
     cpi->mv_search_params.find_fractional_mv_step(
-        xd, cm, &ms_params, subpel_start_mv, &x->best_mv.as_mv, &not_used,
+        xd, cm, &ms_params, subpel_start_mv, &best_mv.as_mv, &not_used,
         &x->pred_sse[ref], NULL);
   } else {
     // Manually convert from units of pixel to 1/8-pixels if we are not doing
     // subpel search
-    x->best_mv.as_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    convert_fullmv_to_mv(&best_mv);
   }
 
-  mbmi->mv[0] = x->best_mv;
+  mbmi->mv[0] = best_mv;
 
   // Get a copy of the prediction output
   av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
@@ -834,18 +829,20 @@
   if (scaled_ref_frame) {
     xd->plane[AOM_PLANE_Y].pre[ref_idx] = backup_yv12;
   }
+
+  return best_mv;
 }
 
-void av1_simple_motion_sse_var(AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
-                               int mi_col, BLOCK_SIZE bsize,
-                               const FULLPEL_MV start_mv, int use_subpixel,
-                               unsigned int *sse, unsigned int *var) {
+int_mv av1_simple_motion_sse_var(AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
+                                 int mi_col, BLOCK_SIZE bsize,
+                                 const FULLPEL_MV start_mv, int use_subpixel,
+                                 unsigned int *sse, unsigned int *var) {
   MACROBLOCKD *xd = &x->e_mbd;
   const MV_REFERENCE_FRAME ref =
       cpi->rc.is_src_frame_alt_ref ? ALTREF_FRAME : LAST_FRAME;
 
-  av1_simple_motion_search(cpi, x, mi_row, mi_col, bsize, ref, start_mv, 1,
-                           use_subpixel);
+  int_mv best_mv = av1_simple_motion_search(cpi, x, mi_row, mi_col, bsize, ref,
+                                            start_mv, 1, use_subpixel);
 
   const uint8_t *src = x->plane[0].src.buf;
   const int src_stride = x->plane[0].src.stride;
@@ -853,4 +850,6 @@
   const int dst_stride = xd->plane[0].dst.stride;
 
   *var = cpi->fn_ptr[bsize].vf(src, src_stride, dst, dst_stride, sse);
+
+  return best_mv;
 }
diff --git a/av1/encoder/motion_search_facade.h b/av1/encoder/motion_search_facade.h
index bf5d635..3b86e93 100644
--- a/av1/encoder/motion_search_facade.h
+++ b/av1/encoder/motion_search_facade.h
@@ -31,7 +31,8 @@
 
 void av1_single_motion_search(const AV1_COMP *const cpi, MACROBLOCK *x,
                               BLOCK_SIZE bsize, int ref_idx, int *rate_mv,
-                              int search_range, inter_mode_info *mode_info);
+                              int search_range, inter_mode_info *mode_info,
+                              int_mv *best_mv);
 
 void av1_joint_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
                              BLOCK_SIZE bsize, int_mv *cur_mv,
@@ -57,16 +58,16 @@
 // Performs a motion search in SIMPLE_TRANSLATION mode using reference frame
 // ref. Note that this sets the offset of mbmi, so we will need to reset it
 // after calling this function.
-void av1_simple_motion_search(struct AV1_COMP *const cpi, MACROBLOCK *x,
-                              int mi_row, int mi_col, BLOCK_SIZE bsize, int ref,
-                              FULLPEL_MV start_mv, int num_planes,
-                              int use_subpixel);
+int_mv av1_simple_motion_search(struct AV1_COMP *const cpi, MACROBLOCK *x,
+                                int mi_row, int mi_col, BLOCK_SIZE bsize,
+                                int ref, FULLPEL_MV start_mv, int num_planes,
+                                int use_subpixel);
 
 // Performs a simple motion search to calculate the sse and var of the residue
-void av1_simple_motion_sse_var(struct AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
-                               int mi_col, BLOCK_SIZE bsize,
-                               const FULLPEL_MV start_mv, int use_subpixel,
-                               unsigned int *sse, unsigned int *var);
+int_mv av1_simple_motion_sse_var(struct AV1_COMP *cpi, MACROBLOCK *x,
+                                 int mi_row, int mi_col, BLOCK_SIZE bsize,
+                                 const FULLPEL_MV start_mv, int use_subpixel,
+                                 unsigned int *sse, unsigned int *var);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index c93a1b7..884582a 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -160,10 +160,9 @@
                                      src_search_sites);
 
   av1_full_pixel_search(start_mv, &full_ms_params, step_param,
-                        cond_cost_list(cpi, cost_list), &x->best_mv.as_fullmv,
+                        cond_cost_list(cpi, cost_list), &tmp_mv->as_fullmv,
                         NULL);
 
-  *tmp_mv = x->best_mv;
   // calculate the bit cost on motion vector
   MV mvp_full = get_mv_from_fullmv(&tmp_mv->as_fullmv);
 
@@ -177,12 +176,11 @@
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list);
-    MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    MV subpel_start_mv = get_mv_from_fullmv(&tmp_mv->as_fullmv);
     cpi->mv_search_params.find_fractional_mv_step(
-        xd, cm, &ms_params, subpel_start_mv, &x->best_mv.as_mv, &dis,
+        xd, cm, &ms_params, subpel_start_mv, &tmp_mv->as_mv, &dis,
         &x->pred_sse[ref], NULL);
 
-    *tmp_mv = x->best_mv;
     *rate_mv = av1_mv_bit_cost(&tmp_mv->as_mv, &ref_mv, x->nmv_vec_cost,
                                x->mv_cost_stack, MV_COST_WEIGHT);
   }
@@ -220,9 +218,9 @@
     if (tmp_sad + (num_pels_log2_lookup[bsize] << 4) > best_pred_sad) return -1;
 
     frame_mv[NEWMV][ref_frame].as_int = mi->mv[0].as_int;
-    x->best_mv.as_int = mi->mv[0].as_int;
-    x->best_mv.as_mv.row >>= 3;
-    x->best_mv.as_mv.col >>= 3;
+    int_mv best_mv = mi->mv[0];
+    best_mv.as_mv.row >>= 3;
+    best_mv.as_mv.col >>= 3;
     MV ref_mv = av1_get_ref_mv(x, 0).as_mv;
 
     *rate_mv =
@@ -234,11 +232,11 @@
     SUBPEL_MOTION_SEARCH_PARAMS ms_params;
     av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize, &ref_mv,
                                       cost_list);
-    MV start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    MV start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
     cpi->mv_search_params.find_fractional_mv_step(
-        xd, cm, &ms_params, start_mv, &x->best_mv.as_mv, &dis,
+        xd, cm, &ms_params, start_mv, &best_mv.as_mv, &dis,
         &x->pred_sse[ref_frame], NULL);
-    frame_mv[NEWMV][ref_frame].as_int = x->best_mv.as_int;
+    frame_mv[NEWMV][ref_frame].as_int = best_mv.as_int;
   } else if (!combined_motion_search(cpi, x, bsize, mi_row, mi_col,
                                      &frame_mv[NEWMV][ref_frame], rate_mv,
                                      best_rdc->rdcost, 0)) {
diff --git a/av1/encoder/partition_strategy.c b/av1/encoder/partition_strategy.c
index ff5a89c..cc820ba 100644
--- a/av1/encoder/partition_strategy.c
+++ b/av1/encoder/partition_strategy.c
@@ -338,8 +338,9 @@
     if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref]) {
       const FULLPEL_MV *start_mvs = pc_tree->start_mvs;
       unsigned int curr_sse = 0, curr_var = 0;
-      av1_simple_motion_search(cpi, x, mi_row, mi_col, bsize, ref,
-                               start_mvs[ref], num_planes, use_subpixel);
+      int_mv best_mv =
+          av1_simple_motion_search(cpi, x, mi_row, mi_col, bsize, ref,
+                                   start_mvs[ref], num_planes, use_subpixel);
       curr_var = cpi->fn_ptr[bsize].vf(
           x->plane[0].src.buf, x->plane[0].src.stride, xd->plane[0].dst.buf,
           xd->plane[0].dst.stride, &curr_sse);
@@ -350,8 +351,8 @@
       }
 
       if (save_mv) {
-        pc_tree->start_mvs[ref].row = x->best_mv.as_mv.row / 8;
-        pc_tree->start_mvs[ref].col = x->best_mv.as_mv.col / 8;
+        pc_tree->start_mvs[ref].row = best_mv.as_mv.row / 8;
+        pc_tree->start_mvs[ref].col = best_mv.as_mv.col / 8;
 
         if (bsize >= BLOCK_8X8) {
           for (int r_idx = 0; r_idx < 4; r_idx++) {
@@ -661,13 +662,12 @@
       unsigned int sse = 0;
       unsigned int var = 0;
       const FULLPEL_MV start_mv = kZeroFullMv;
-
-      av1_simple_motion_sse_var(cpi, x, this_mi_row, this_mi_col, mb_size,
-                                start_mv, 0, &sse, &var);
+      int_mv best_mv = av1_simple_motion_sse_var(
+          cpi, x, this_mi_row, this_mi_col, mb_size, start_mv, 0, &sse, &var);
 
       aom_clear_system_state();
-      const float mv_row = (float)(x->best_mv.as_mv.row / 8);
-      const float mv_col = (float)(x->best_mv.as_mv.col / 8);
+      const float mv_row = (float)(best_mv.as_mv.row / 8);
+      const float mv_col = (float)(best_mv.as_mv.col / 8);
       const float log_sse = logf(1.0f + (float)sse);
       const float abs_mv_row = fabsf(mv_row);
       const float abs_mv_col = fabsf(mv_col);
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 4fcf43e..f406939 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -1163,15 +1163,15 @@
       }
     }
 
+    int_mv best_mv;
     av1_single_motion_search(cpi, x, bsize, ref_idx, rate_mv, search_range,
-                             mode_info);
-    if (x->best_mv.as_int == INVALID_MV) return INT64_MAX;
+                             mode_info, &best_mv);
+    if (best_mv.as_int == INVALID_MV) return INT64_MAX;
 
-    args->single_newmv[ref_mv_idx][refs[0]] = x->best_mv;
+    args->single_newmv[ref_mv_idx][refs[0]] = best_mv;
     args->single_newmv_rate[ref_mv_idx][refs[0]] = *rate_mv;
     args->single_newmv_valid[ref_mv_idx][refs[0]] = 1;
-
-    cur_mv[0].as_int = x->best_mv.as_int;
+    cur_mv[0].as_int = best_mv.as_int;
   }
 
   return 0;
@@ -1339,8 +1339,8 @@
       const uint32_t cur_mv = mbmi->mv[0].as_int;
       assert(!is_comp_pred);
       if (have_newmv_in_inter_mode(this_mode)) {
-        av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL);
-        mbmi->mv[0].as_int = x->best_mv.as_int;
+        av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL,
+                                 &mbmi->mv[0]);
         tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
       }
       if ((mbmi->mv[0].as_int != cur_mv) || eval_motion_mode) {
@@ -2747,16 +2747,15 @@
 
     const int step_param = cpi->mv_search_params.mv_step_param;
     const FULLPEL_MV start_mv = get_fullmv_from_mv(&dv_ref.as_mv);
-    int cost_list[5];
+    int_mv best_mv;
 
     int bestsme = av1_full_pixel_search(start_mv, &fullms_params, step_param,
-                                        cond_cost_list(cpi, cost_list),
-                                        &x->best_mv.as_fullmv, NULL);
+                                        NULL, &best_mv.as_fullmv, NULL);
     av1_intrabc_hash_search(cpi, x, bsize, &dv_ref.as_mv, &bestsme,
-                            &x->best_mv.as_fullmv);
+                            &best_mv.as_fullmv);
 
     if (bestsme == INT_MAX) continue;
-    const MV dv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+    const MV dv = get_mv_from_fullmv(&best_mv.as_fullmv);
     if (!av1_is_fullmv_in_range(&fullms_params.mv_limits,
                                 get_fullmv_from_mv(&dv)))
       continue;
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index b2b2524..ea4cfb3 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -115,6 +115,7 @@
   // Do motion search.
   // NOTE: In `av1_full_pixel_search()` and `find_fractional_mv_step()`, the
   // searched result will be stored in `mb->best_mv`.
+  int_mv best_mv;
   int block_mse = INT_MAX;
   mb->mv_cost_type = mv_cost_type;
 
@@ -123,35 +124,35 @@
   full_ms_params.run_mesh_search = 1;
   full_ms_params.search_method = full_search_method;
   av1_full_pixel_search(start_mv, &full_ms_params, step_param,
-                        cond_cost_list(cpi, cost_list), &mb->best_mv.as_fullmv,
+                        cond_cost_list(cpi, cost_list), &best_mv.as_fullmv,
                         NULL);
 
   // Since we are merely refining the result from full pixel search, we don't
   // need regularization for subpel search
   mb->mv_cost_type = MV_COST_NONE;
   if (force_integer_mv == 1) {  // Only do full search on the entire block.
-    const int mv_row = mb->best_mv.as_mv.row;
-    const int mv_col = mb->best_mv.as_mv.col;
-    mb->best_mv.as_mv.row = GET_MV_SUBPEL(mv_row);
-    mb->best_mv.as_mv.col = GET_MV_SUBPEL(mv_col);
+    const int mv_row = best_mv.as_mv.row;
+    const int mv_col = best_mv.as_mv.col;
+    best_mv.as_mv.row = GET_MV_SUBPEL(mv_row);
+    best_mv.as_mv.col = GET_MV_SUBPEL(mv_col);
     const int mv_offset = mv_row * y_stride + mv_col;
     error = cpi->fn_ptr[block_size].vf(
         ref_frame->y_buffer + y_offset + mv_offset, y_stride,
         frame_to_filter->y_buffer + y_offset, y_stride, &sse);
     block_mse = DIVIDE_AND_ROUND(error, mb_pels);
-    mb->e_mbd.mi[0]->mv[0] = mb->best_mv;
+    mb->e_mbd.mi[0]->mv[0] = 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);
     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);
+    MV subpel_start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
     error = cpi->mv_search_params.find_fractional_mv_step(
-        &mb->e_mbd, &cpi->common, &ms_params, subpel_start_mv,
-        &mb->best_mv.as_mv, &distortion, &sse, NULL);
+        &mb->e_mbd, &cpi->common, &ms_params, subpel_start_mv, &best_mv.as_mv,
+        &distortion, &sse, NULL);
     block_mse = DIVIDE_AND_ROUND(error, mb_pels);
-    mb->e_mbd.mi[0]->mv[0] = mb->best_mv;
-    *ref_mv = mb->best_mv.as_mv;
+    mb->e_mbd.mi[0]->mv[0] = best_mv;
+    *ref_mv = best_mv.as_mv;
     // On 4 sub-blocks.
     const BLOCK_SIZE subblock_size = ss_size_lookup[block_size][1][1];
     const int subblock_height = block_size_high[subblock_size];
@@ -173,7 +174,7 @@
         full_ms_params.search_method = full_search_method;
         av1_full_pixel_search(start_mv, &full_ms_params, step_param,
                               cond_cost_list(cpi, cost_list),
-                              &mb->best_mv.as_fullmv, NULL);
+                              &best_mv.as_fullmv, NULL);
 
         // Since we are merely refining the result from full pixel search, we
         // don't need regularization for subpel search
@@ -182,12 +183,12 @@
                                           &baseline_mv, cost_list);
         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);
+        subpel_start_mv = get_mv_from_fullmv(&best_mv.as_fullmv);
         error = cpi->mv_search_params.find_fractional_mv_step(
             &mb->e_mbd, &cpi->common, &ms_params, subpel_start_mv,
-            &mb->best_mv.as_mv, &distortion, &sse, NULL);
+            &best_mv.as_mv, &distortion, &sse, NULL);
         subblock_mses[subblock_idx] = DIVIDE_AND_ROUND(error, subblock_pels);
-        subblock_mvs[subblock_idx] = mb->best_mv.as_mv;
+        subblock_mvs[subblock_idx] = best_mv.as_mv;
         ++subblock_idx;
       }
     }
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 1736750..8d214bb 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -122,7 +122,7 @@
                                   uint8_t *cur_frame_buf,
                                   uint8_t *ref_frame_buf, int stride,
                                   int stride_ref, BLOCK_SIZE bsize,
-                                  MV center_mv) {
+                                  MV center_mv, int_mv *best_mv) {
   AV1_COMMON *cm = &cpi->common;
   MACROBLOCKD *const xd = &x->e_mbd;
   TPL_SPEED_FEATURES *tpl_sf = &cpi->sf.tpl_sf;
@@ -153,7 +153,7 @@
                                      ss_cfg);
 
   av1_full_pixel_search(start_mv, &full_ms_params, step_param,
-                        cond_cost_list(cpi, cost_list), &x->best_mv.as_fullmv,
+                        cond_cost_list(cpi, cost_list), &best_mv->as_fullmv,
                         NULL);
 
   SUBPEL_MOTION_SEARCH_PARAMS ms_params;
@@ -162,9 +162,9 @@
   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;
-  MV subpel_start_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
+  MV subpel_start_mv = get_mv_from_fullmv(&best_mv->as_fullmv);
   bestsme = cpi->mv_search_params.find_fractional_mv_step(
-      xd, cm, &ms_params, subpel_start_mv, &x->best_mv.as_mv, &distortion, &sse,
+      xd, cm, &ms_params, subpel_start_mv, &best_mv->as_mv, &distortion, &sse,
       NULL);
 
   return bestsme;
@@ -347,19 +347,18 @@
     }
 
     for (int idx = 0; idx < refmv_count; ++idx) {
+      int_mv this_mv;
       uint32_t thissme =
           motion_estimation(cpi, x, src_mb_buffer, ref_mb, src_stride,
-                            ref_stride, bsize, center_mvs[idx].as_mv);
+                            ref_stride, bsize, center_mvs[idx].as_mv, &this_mv);
 
       if (thissme < bestsme) {
         bestsme = thissme;
-        best_rfidx_mv.as_int = x->best_mv.as_int;
+        best_rfidx_mv = this_mv;
       }
     }
 
-    x->best_mv.as_int = best_rfidx_mv.as_int;
-
-    tpl_stats->mv[rf_idx].as_int = x->best_mv.as_int;
+    tpl_stats->mv[rf_idx].as_int = best_rfidx_mv.as_int;
 
     struct buf_2d ref_buf = { NULL, ref_frame_ptr->y_buffer,
                               ref_frame_ptr->y_width, ref_frame_ptr->y_height,
@@ -370,7 +369,7 @@
                           sf, &ref_buf, kernel);
     inter_pred_params.conv_params = get_conv_params(0, 0, xd->bd);
 
-    av1_build_inter_predictor(predictor, bw, &x->best_mv.as_mv,
+    av1_build_inter_predictor(predictor, bw, &best_rfidx_mv.as_mv,
                               &inter_pred_params);
 
     inter_cost = tpl_get_satd_cost(x, src_diff, bw, src_mb_buffer, src_stride,
@@ -383,7 +382,7 @@
       best_rf_idx = rf_idx;
 
       best_inter_cost = inter_cost;
-      best_mv.as_int = x->best_mv.as_int;
+      best_mv.as_int = best_rfidx_mv.as_int;
       if (best_inter_cost < best_intra_cost) {
         best_mode = NEWMV;
         xd->mi[0]->ref_frame[0] = best_rf_idx + LAST_FRAME;