Clean up mcomp.c

This CL contains the following changes:
  - MV is now split into two structs: MV and FULLPEL_MV. MV is used to
    hold motion vectors in 1/8-pel precision. FULLPEL_MV is used to hold
    motion vectors in fullpel precision.
  - To facilitate the containment of MV and FULLPEL_MV, int_mv is now a
    union of int, MV, and FULLPEL_MV
  - The names of functional parameters is now more consistent. For
    instance, the starting point of the motion search is now always
    called start_mv. The mv with respect to which we calculate the mv
    cost is now always called ref_mv.
  - Some typos are fixed.

Change-Id: Iad00a8e2f3bc26aa770449332d182610ac86f291
diff --git a/av1/common/mv.h b/av1/common/mv.h
index fe821ee..adbe779 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -21,17 +21,28 @@
 #endif
 
 #define INVALID_MV 0x80008000
+#define GET_MV_RAWPEL(x) ((x) >> 3)
+#define GET_MV_SUBPEL(x) ((x)*8)
 
+// The motion vector in units of full pixel
+typedef struct fullpel_mv {
+  int16_t row;
+  int16_t col;
+} FULLPEL_MV;
+
+// The motion vector in units of 1/8-pel
 typedef struct mv {
   int16_t row;
   int16_t col;
 } MV;
 
 static const MV kZeroMv = { 0, 0 };
+static const FULLPEL_MV kZeroFullMv = { 0, 0 };
 
 typedef union int_mv {
   uint32_t as_int;
   MV as_mv;
+  FULLPEL_MV as_fullmv;
 } int_mv; /* facilitates faster equality tests and copies */
 
 typedef struct mv32 {
@@ -39,6 +50,18 @@
   int32_t col;
 } MV32;
 
+static AOM_INLINE FULLPEL_MV get_fullmv_from_mv(const MV *subpel_mv) {
+  const FULLPEL_MV full_mv = { (int16_t)GET_MV_RAWPEL(subpel_mv->row),
+                               (int16_t)GET_MV_RAWPEL(subpel_mv->col) };
+  return full_mv;
+}
+
+static AOM_INLINE MV get_mv_from_fullmv(const FULLPEL_MV *full_mv) {
+  const MV subpel_mv = { (int16_t)GET_MV_SUBPEL(full_mv->row),
+                         (int16_t)GET_MV_SUBPEL(full_mv->col) };
+  return subpel_mv;
+}
+
 // Bits of precision used for the model
 #define WARPEDMODEL_PREC_BITS 16
 #define WARPEDMODEL_ROW3HOMO_PREC_BITS 16
@@ -293,6 +316,12 @@
   mv->row = clamp(mv->row, min_row, max_row);
 }
 
+static INLINE void clamp_fullmv(FULLPEL_MV *mv, int min_col, int max_col,
+                                int min_row, int max_row) {
+  mv->col = clamp(mv->col, min_col, max_col);
+  mv->row = clamp(mv->row, min_row, max_row);
+}
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/encoder/context_tree.h b/av1/encoder/context_tree.h
index ca311cc..24f002a 100644
--- a/av1/encoder/context_tree.h
+++ b/av1/encoder/context_tree.h
@@ -77,7 +77,7 @@
   int index;
 
   // Simple motion search_features
-  MV mv_ref_fulls[REF_FRAMES];
+  FULLPEL_MV start_mvs[REF_FRAMES];
   unsigned int sms_none_feat[2];
   unsigned int sms_rect_feat[8];
   int sms_none_valid;
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 6c8d307..9881a25 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -804,9 +804,9 @@
         av1_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
   }
   if (use_pb_simple_motion_pred_sse(cpi)) {
-    const MV ref_mv_full = { .row = 0, .col = 0 };
+    const FULLPEL_MV start_mv = kZeroFullMv;
     unsigned int var = 0;
-    av1_simple_motion_sse_var(cpi, x, mi_row, mi_col, bsize, ref_mv_full, 0,
+    av1_simple_motion_sse_var(cpi, x, mi_row, mi_col, bsize, start_mv, 0,
                               &x->simple_motion_pred_sse, &var);
   }
 
@@ -3244,10 +3244,10 @@
 
   if (use_pb_simple_motion_pred_sse(cpi) &&
       pb_simple_motion_pred_sse == UINT_MAX) {
-    const MV ref_mv_full = { .row = 0, .col = 0 };
+    const FULLPEL_MV start_mv = kZeroFullMv;
     unsigned int var = 0;
 
-    av1_simple_motion_sse_var(cpi, x, mi_row, mi_col, bsize, ref_mv_full, 0,
+    av1_simple_motion_sse_var(cpi, x, mi_row, mi_col, bsize, start_mv, 0,
                               &pb_simple_motion_pred_sse, &var);
   }
 
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 8a1be0e..d747bf0 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -17,13 +17,13 @@
 #include "config/aom_scale_rtcd.h"
 
 #include "aom_dsp/aom_dsp_common.h"
+#include "aom_dsp/variance.h"
 #include "aom_mem/aom_mem.h"
 #include "aom_ports/mem.h"
 #include "aom_ports/system_state.h"
 #include "aom_scale/aom_scale.h"
 #include "aom_scale/yv12config.h"
 
-#include "aom_dsp/variance.h"
 #include "av1/common/entropymv.h"
 #include "av1/common/quant_common.h"
 #include "av1/common/reconinter.h"  // av1_setup_dst_planes()
@@ -222,7 +222,7 @@
                                                 const MV *ref_mv, MV *best_mv,
                                                 int *best_motion_err) {
   MACROBLOCKD *const xd = &x->e_mbd;
-  MV ref_mv_full = { ref_mv->row >> 3, ref_mv->col >> 3 };
+  FULLPEL_MV start_mv = get_fullmv_from_mv(ref_mv);
   int tmp_err;
   const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
   aom_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
@@ -232,14 +232,15 @@
   int cost_list[5];
 
   tmp_err = av1_full_pixel_search(
-      cpi, x, bsize, &ref_mv_full, step_param, 0, NSTEP, 0, x->sadperbit16,
+      cpi, x, bsize, &start_mv, step_param, 0, NSTEP, 0, x->sadperbit16,
       cond_cost_list(cpi, cost_list), ref_mv, INT_MAX, 0,
       (MI_SIZE * xd->mi_col), (MI_SIZE * xd->mi_row), 0,
       &cpi->ss_cfg[SS_CFG_FPF], 0);
 
   if (tmp_err < INT_MAX)
-    tmp_err = av1_get_mvpred_var(x, &x->best_mv.as_mv, ref_mv, &v_fn_ptr, 0) +
-              new_mv_mode_penalty;
+    tmp_err =
+        av1_get_mvpred_var(x, &x->best_mv.as_fullmv, ref_mv, &v_fn_ptr, 0) +
+        new_mv_mode_penalty;
 
   if (tmp_err < *best_motion_err) {
     *best_motion_err = tmp_err;
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 7ef27e9..980c0bb 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -51,20 +51,22 @@
 #define SAD_LAMBDA_HDRES 8  // Used by mvsad_err_cost during full pixel search
 
 static INLINE const uint8_t *get_buf_from_mv(const struct buf_2d *buf,
-                                             const MV *mv) {
+                                             const FULLPEL_MV *mv) {
   return &buf->buf[mv->row * buf->stride + mv->col];
 }
 
 void av1_set_mv_search_range(MvLimits *mv_limits, const MV *mv) {
-  int col_min = (mv->col >> 3) - MAX_FULL_PEL_VAL + (mv->col & 7 ? 1 : 0);
-  int row_min = (mv->row >> 3) - MAX_FULL_PEL_VAL + (mv->row & 7 ? 1 : 0);
-  int col_max = (mv->col >> 3) + MAX_FULL_PEL_VAL;
-  int row_max = (mv->row >> 3) + MAX_FULL_PEL_VAL;
+  int col_min =
+      GET_MV_RAWPEL(mv->col) - MAX_FULL_PEL_VAL + (mv->col & 7 ? 1 : 0);
+  int row_min =
+      GET_MV_RAWPEL(mv->row) - MAX_FULL_PEL_VAL + (mv->row & 7 ? 1 : 0);
+  int col_max = GET_MV_RAWPEL(mv->col) + MAX_FULL_PEL_VAL;
+  int row_max = GET_MV_RAWPEL(mv->row) + MAX_FULL_PEL_VAL;
 
-  col_min = AOMMAX(col_min, (MV_LOW >> 3) + 1);
-  row_min = AOMMAX(row_min, (MV_LOW >> 3) + 1);
-  col_max = AOMMIN(col_max, (MV_UPP >> 3) - 1);
-  row_max = AOMMIN(row_max, (MV_UPP >> 3) - 1);
+  col_min = AOMMAX(col_min, GET_MV_RAWPEL(MV_LOW) + 1);
+  row_min = AOMMAX(row_min, GET_MV_RAWPEL(MV_LOW) + 1);
+  col_max = AOMMIN(col_max, GET_MV_RAWPEL(MV_UPP) - 1);
+  row_max = AOMMIN(row_max, GET_MV_RAWPEL(MV_UPP) - 1);
 
   // Get intersection of UMV window and valid MV window to reduce # of checks
   // in diamond search.
@@ -99,19 +101,19 @@
 // is defined as the rate required to encode diff * weight, rounded to the
 // nearest 2 ** 7.
 // This is NOT used during motion compensation.
-int av1_mv_bit_cost(const MV *mv, const MV *ref, const int *mvjcost,
+int av1_mv_bit_cost(const MV *mv, const MV *ref_mv, const int *mvjcost,
                     int *mvcost[2], int weight) {
-  const MV diff = { mv->row - ref->row, mv->col - ref->col };
+  const MV diff = { mv->row - ref_mv->row, mv->col - ref_mv->col };
   return ROUND_POWER_OF_TWO(mv_cost(&diff, mvjcost, mvcost) * weight, 7);
 }
 
 // Returns the cost of using the current mv during the motion search. This is
 // used when var is used as the error metric.
 #define PIXEL_TRANSFORM_ERROR_SCALE 4
-static int mv_err_cost(const MV *mv, const MV *ref, const int *mvjcost,
+static int mv_err_cost(const MV *mv, const MV *ref_mv, const int *mvjcost,
                        int *mvcost[2], int error_per_bit,
                        MV_COST_TYPE mv_cost_type) {
-  const MV diff = { mv->row - ref->row, mv->col - ref->col };
+  const MV diff = { mv->row - ref_mv->row, mv->col - ref_mv->col };
   const MV abs_diff = { abs(diff.row), abs(diff.col) };
 
   switch (mv_cost_type) {
@@ -137,9 +139,10 @@
 // Returns the cost of using the current mv during the motion search. This is
 // only used during full pixel motion search when sad is used as the error
 // metric.
-static int mvsad_err_cost(const MACROBLOCK *x, const MV *mv, const MV *ref,
-                          int sad_per_bit) {
-  const MV diff = { (mv->row - ref->row) * 8, (mv->col - ref->col) * 8 };
+static int mvsad_err_cost(const MACROBLOCK *x, const FULLPEL_MV *mv,
+                          const FULLPEL_MV *ref_mv, int sad_per_bit) {
+  const MV diff = { GET_MV_SUBPEL(mv->row - ref_mv->row),
+                    GET_MV_SUBPEL(mv->col - ref_mv->col) };
   const MV_COST_TYPE mv_cost_type = x->mv_cost_type;
   switch (mv_cost_type) {
     case MV_COST_ENTROPY:
@@ -169,7 +172,7 @@
   for (int radius = MAX_FIRST_STEP; radius > 0; radius /= 2) {
     int num_search_pts = 8;
 
-    const MV ss_mvs[13] = {
+    const FULLPEL_MV ss_mvs[13] = {
       { 0, 0 },           { -radius, 0 },      { radius, 0 },
       { 0, -radius },     { 0, radius },       { -radius, -radius },
       { radius, radius }, { -radius, radius }, { radius, -radius },
@@ -203,7 +206,7 @@
     int num_search_pts = 12;
     if (radius == 1) num_search_pts = 8;
 
-    const MV ss_mvs[13] = {
+    const FULLPEL_MV ss_mvs[13] = {
       { 0, 0 },
       { -radius, 0 },
       { radius, 0 },
@@ -245,7 +248,7 @@
       tan_radius = radius;
       num_search_pts = 8;
     }
-    const MV ss_mvs[13] = {
+    const FULLPEL_MV ss_mvs[13] = {
       { 0, 0 },
       { -radius, 0 },
       { radius, 0 },
@@ -1155,36 +1158,37 @@
          ((col + range) <= mv_limits->col_max);
 }
 
-static INLINE int is_mv_in(const MvLimits *mv_limits, const MV *mv) {
+static INLINE int is_mv_in(const MvLimits *mv_limits, const FULLPEL_MV *mv) {
   return (mv->col >= mv_limits->col_min) && (mv->col <= mv_limits->col_max) &&
          (mv->row >= mv_limits->row_min) && (mv->row <= mv_limits->row_max);
 }
 
-#define CHECK_BETTER                                                      \
-  {                                                                       \
-    if (thissad < bestsad) {                                              \
-      if (use_mvcost)                                                     \
-        thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit); \
-      if (thissad < bestsad) {                                            \
-        bestsad = thissad;                                                \
-        best_site = i;                                                    \
-      }                                                                   \
-    }                                                                     \
+#define CHECK_BETTER                                                       \
+  {                                                                        \
+    if (thissad < bestsad) {                                               \
+      if (use_mvcost)                                                      \
+        thissad += mvsad_err_cost(x, &this_mv, &full_ref_mv, sad_per_bit); \
+      if (thissad < bestsad) {                                             \
+        bestsad = thissad;                                                 \
+        best_site = i;                                                     \
+      }                                                                    \
+    }                                                                      \
   }
 
 #define MAX_PATTERN_SCALES 11
-#define MAX_PATTERN_CANDIDATES 8  // max number of canddiates per scale
+#define MAX_PATTERN_CANDIDATES 8  // max number of candidates per scale
 #define PATTERN_CANDIDATES_REF 3  // number of refinement candidates
 
 // Calculate and return a sad+mvcost list around an integer best pel.
 static INLINE void calc_int_cost_list(const MACROBLOCK *x,
                                       const MV *const ref_mv, int sadpb,
                                       const aom_variance_fn_ptr_t *fn_ptr,
-                                      const MV *best_mv, int *cost_list) {
+                                      const FULLPEL_MV *best_mv,
+                                      int *cost_list) {
   static const MV neighbors[4] = { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } };
   const struct buf_2d *const what = &x->plane[0].src;
   const struct buf_2d *const in_what = &x->e_mbd.plane[0].pre[0];
-  const MV fcenter_mv = { ref_mv->row >> 3, ref_mv->col >> 3 };
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
   const int br = best_mv->row;
   const int bc = best_mv->col;
   const MV_COST_TYPE mv_cost_type = x->mv_cost_type;
@@ -1193,32 +1197,32 @@
   cost_list[0] =
       fn_ptr->vf(what->buf, what->stride, get_buf_from_mv(in_what, best_mv),
                  in_what->stride, &sse) +
-      mvsad_err_cost(x, best_mv, &fcenter_mv, sadpb);
+      mvsad_err_cost(x, best_mv, &full_ref_mv, sadpb);
   if (check_bounds(&x->mv_limits, br, bc, 1)) {
     for (int i = 0; i < 4; i++) {
-      const MV neighbor_mv = { br + neighbors[i].row, bc + neighbors[i].col };
-      const MV neighbor_mv_subpel = { neighbor_mv.row * 8,
-                                      neighbor_mv.col * 8 };
+      const FULLPEL_MV neighbor_mv = { br + neighbors[i].row,
+                                       bc + neighbors[i].col };
+      const MV sub_neighbor_mv = get_mv_from_fullmv(&neighbor_mv);
       cost_list[i + 1] =
           fn_ptr->vf(what->buf, what->stride,
                      get_buf_from_mv(in_what, &neighbor_mv), in_what->stride,
                      &sse) +
-          mv_err_cost(&neighbor_mv_subpel, ref_mv, x->nmv_vec_cost,
+          mv_err_cost(&sub_neighbor_mv, ref_mv, x->nmv_vec_cost,
                       x->mv_cost_stack, x->errorperbit, mv_cost_type);
     }
   } else {
     for (int i = 0; i < 4; i++) {
-      const MV neighbor_mv = { br + neighbors[i].row, bc + neighbors[i].col };
+      const FULLPEL_MV neighbor_mv = { br + neighbors[i].row,
+                                       bc + neighbors[i].col };
       if (!is_mv_in(&x->mv_limits, &neighbor_mv)) {
         cost_list[i + 1] = INT_MAX;
       } else {
-        const MV neighbor_mv_subpel = { neighbor_mv.row * 8,
-                                        neighbor_mv.col * 8 };
+        const MV sub_neighbor_mv = get_mv_from_fullmv(&neighbor_mv);
         cost_list[i + 1] =
             fn_ptr->vf(what->buf, what->stride,
                        get_buf_from_mv(in_what, &neighbor_mv), in_what->stride,
                        &sse) +
-            mv_err_cost(&neighbor_mv_subpel, ref_mv, x->nmv_vec_cost,
+            mv_err_cost(&sub_neighbor_mv, ref_mv, x->nmv_vec_cost,
                         x->mv_cost_stack, x->errorperbit, mv_cost_type);
       }
     }
@@ -1228,27 +1232,29 @@
 static INLINE void calc_int_sad_list(const MACROBLOCK *x,
                                      const MV *const ref_mv, int sadpb,
                                      const aom_variance_fn_ptr_t *fn_ptr,
-                                     const MV *best_mv, int *cost_list,
+                                     const FULLPEL_MV *best_mv, int *cost_list,
                                      const int use_mvcost, const int bestsad) {
   static const MV neighbors[4] = { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } };
   const struct buf_2d *const what = &x->plane[0].src;
   const struct buf_2d *const in_what = &x->e_mbd.plane[0].pre[0];
   const int br = best_mv->row;
   const int bc = best_mv->col;
-  const MV ref_mv_fullpel = { ref_mv->row >> 3, ref_mv->col >> 3 };
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
 
   if (cost_list[0] == INT_MAX) {
     cost_list[0] = bestsad;
     if (check_bounds(&x->mv_limits, br, bc, 1)) {
       for (int i = 0; i < 4; i++) {
-        const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
+        const FULLPEL_MV this_mv = { br + neighbors[i].row,
+                                     bc + neighbors[i].col };
         cost_list[i + 1] =
             fn_ptr->sdf(what->buf, what->stride,
                         get_buf_from_mv(in_what, &this_mv), in_what->stride);
       }
     } else {
       for (int i = 0; i < 4; i++) {
-        const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
+        const FULLPEL_MV this_mv = { br + neighbors[i].row,
+                                     bc + neighbors[i].col };
         if (!is_mv_in(&x->mv_limits, &this_mv))
           cost_list[i + 1] = INT_MAX;
         else
@@ -1260,10 +1266,10 @@
   } else {
     if (use_mvcost) {
       for (int i = 0; i < 4; i++) {
-        const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
+        const FULLPEL_MV this_mv = { br + neighbors[i].row,
+                                     bc + neighbors[i].col };
         if (cost_list[i + 1] != INT_MAX) {
-          cost_list[i + 1] +=
-              mvsad_err_cost(x, &this_mv, &ref_mv_fullpel, sadpb);
+          cost_list[i + 1] += mvsad_err_cost(x, &this_mv, &full_ref_mv, sadpb);
         }
       }
     }
@@ -1274,11 +1280,10 @@
 // Each scale can have a different number of candidates and shape of
 // candidates as indicated in the num_candidates and candidates arrays
 // passed into this function
-//
 static int pattern_search(
-    MACROBLOCK *x, MV *start_mv, int search_param, int sad_per_bit,
+    MACROBLOCK *x, FULLPEL_MV *start_mv, int search_param, int sad_per_bit,
     int do_init_search, int *cost_list, const aom_variance_fn_ptr_t *vfp,
-    int use_mvcost, const MV *center_mv,
+    int use_mvcost, const MV *ref_mv,
     const int num_candidates[MAX_PATTERN_SCALES],
     const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES]) {
   const MACROBLOCKD *const xd = &x->e_mbd;
@@ -1293,12 +1298,12 @@
   int bestsad = INT_MAX;
   int thissad;
   int k = -1;
-  const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
   assert(search_param < MAX_MVSEARCH_STEPS);
   int best_init_s = search_param_to_steps[search_param];
   // adjust ref_mv to make sure it is within MV range
-  clamp_mv(start_mv, x->mv_limits.col_min, x->mv_limits.col_max,
-           x->mv_limits.row_min, x->mv_limits.row_max);
+  clamp_fullmv(start_mv, x->mv_limits.col_min, x->mv_limits.col_max,
+               x->mv_limits.row_min, x->mv_limits.row_max);
   br = start_mv->row;
   bc = start_mv->col;
   if (cost_list != NULL) {
@@ -1309,9 +1314,9 @@
   // Work out the start point for the search
   bestsad = vfp->sdf(what->buf, what->stride,
                      get_buf_from_mv(in_what, start_mv), in_what->stride) +
-            mvsad_err_cost(x, start_mv, &fcenter_mv, sad_per_bit);
+            mvsad_err_cost(x, start_mv, &full_ref_mv, sad_per_bit);
 
-  // Search all possible scales upto the search param around the center point
+  // Search all possible scales up to the search param around the center point
   // pick the scale of the point that is best as the starting scale of
   // further steps around it.
   if (do_init_search) {
@@ -1321,8 +1326,8 @@
       int best_site = -1;
       if (check_bounds(&x->mv_limits, br, bc, 1 << t)) {
         for (i = 0; i < num_candidates[t]; i++) {
-          const MV this_mv = { br + candidates[t][i].row,
-                               bc + candidates[t][i].col };
+          const FULLPEL_MV this_mv = { br + candidates[t][i].row,
+                                       bc + candidates[t][i].col };
           thissad =
               vfp->sdf(what->buf, what->stride,
                        get_buf_from_mv(in_what, &this_mv), in_what->stride);
@@ -1330,8 +1335,8 @@
         }
       } else {
         for (i = 0; i < num_candidates[t]; i++) {
-          const MV this_mv = { br + candidates[t][i].row,
-                               bc + candidates[t][i].col };
+          const FULLPEL_MV this_mv = { br + candidates[t][i].row,
+                                       bc + candidates[t][i].col };
           if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
           thissad =
               vfp->sdf(what->buf, what->stride,
@@ -1364,8 +1369,8 @@
       if (!do_init_search || s != best_init_s) {
         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
           for (i = 0; i < num_candidates[s]; i++) {
-            const MV this_mv = { br + candidates[s][i].row,
-                                 bc + candidates[s][i].col };
+            const FULLPEL_MV this_mv = { br + candidates[s][i].row,
+                                         bc + candidates[s][i].col };
             thissad =
                 vfp->sdf(what->buf, what->stride,
                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
@@ -1373,8 +1378,8 @@
           }
         } else {
           for (i = 0; i < num_candidates[s]; i++) {
-            const MV this_mv = { br + candidates[s][i].row,
-                                 bc + candidates[s][i].col };
+            const FULLPEL_MV this_mv = { br + candidates[s][i].row,
+                                         bc + candidates[s][i].col };
             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
             thissad =
                 vfp->sdf(what->buf, what->stride,
@@ -1401,7 +1406,7 @@
 
         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
-            const MV this_mv = {
+            const FULLPEL_MV this_mv = {
               br + candidates[s][next_chkpts_indices[i]].row,
               bc + candidates[s][next_chkpts_indices[i]].col
             };
@@ -1412,7 +1417,7 @@
           }
         } else {
           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
-            const MV this_mv = {
+            const FULLPEL_MV this_mv = {
               br + candidates[s][next_chkpts_indices[i]].row,
               bc + candidates[s][next_chkpts_indices[i]].col
             };
@@ -1438,8 +1443,8 @@
       if (!do_init_search || s != best_init_s) {
         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
           for (i = 0; i < num_candidates[s]; i++) {
-            const MV this_mv = { br + candidates[s][i].row,
-                                 bc + candidates[s][i].col };
+            const FULLPEL_MV this_mv = { br + candidates[s][i].row,
+                                         bc + candidates[s][i].col };
             cost_list[i + 1] = thissad =
                 vfp->sdf(what->buf, what->stride,
                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
@@ -1447,8 +1452,8 @@
           }
         } else {
           for (i = 0; i < num_candidates[s]; i++) {
-            const MV this_mv = { br + candidates[s][i].row,
-                                 bc + candidates[s][i].col };
+            const FULLPEL_MV this_mv = { br + candidates[s][i].row,
+                                         bc + candidates[s][i].col };
             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
             cost_list[i + 1] = thissad =
                 vfp->sdf(what->buf, what->stride,
@@ -1475,7 +1480,7 @@
 
         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
-            const MV this_mv = {
+            const FULLPEL_MV this_mv = {
               br + candidates[s][next_chkpts_indices[i]].row,
               bc + candidates[s][next_chkpts_indices[i]].col
             };
@@ -1486,7 +1491,7 @@
           }
         } else {
           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
-            const MV this_mv = {
+            const FULLPEL_MV this_mv = {
               br + candidates[s][next_chkpts_indices[i]].row,
               bc + candidates[s][next_chkpts_indices[i]].col
             };
@@ -1517,13 +1522,12 @@
   // cost_list[3]: cost/sad at delta { 0, 1} (right)  from the best integer pel
   // cost_list[4]: cost/sad at delta {-1, 0} (top)    from the best integer pel
   if (cost_list) {
-    const MV best_int_mv = { br, bc };
+    const FULLPEL_MV best_int_mv = { br, bc };
     if (last_is_4) {
-      calc_int_sad_list(x, center_mv, sad_per_bit, vfp, &best_int_mv, cost_list,
+      calc_int_sad_list(x, ref_mv, sad_per_bit, vfp, &best_int_mv, cost_list,
                         use_mvcost, bestsad);
     } else {
-      calc_int_cost_list(x, center_mv, sad_per_bit, vfp, &best_int_mv,
-                         cost_list);
+      calc_int_cost_list(x, ref_mv, sad_per_bit, vfp, &best_int_mv, cost_list);
     }
   }
   x->best_mv.as_mv.row = br;
@@ -1531,13 +1535,13 @@
   return bestsad;
 }
 
-int av1_get_mvpred_var(const MACROBLOCK *x, const MV *best_mv,
-                       const MV *center_mv, const aom_variance_fn_ptr_t *vfp,
+int av1_get_mvpred_var(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
+                       const MV *ref_mv, const aom_variance_fn_ptr_t *vfp,
                        int use_var) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const struct buf_2d *const what = &x->plane[0].src;
   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
-  const MV mv = { best_mv->row * 8, best_mv->col * 8 };
+  const MV mv = get_mv_from_fullmv(best_mv);
   const MV_COST_TYPE mv_cost_type = x->mv_cost_type;
   unsigned int sse, var;
 
@@ -1546,38 +1550,38 @@
 
   if (!use_var) var = sse;
 
-  return var + mv_err_cost(&mv, center_mv, x->nmv_vec_cost, x->mv_cost_stack,
+  return var + mv_err_cost(&mv, ref_mv, x->nmv_vec_cost, x->mv_cost_stack,
                            x->errorperbit, mv_cost_type);
 }
 
-int av1_get_mvpred_av_var(const MACROBLOCK *x, const MV *best_mv,
-                          const MV *center_mv, const uint8_t *second_pred,
+int av1_get_mvpred_av_var(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
+                          const MV *ref_mv, const uint8_t *second_pred,
                           const aom_variance_fn_ptr_t *vfp,
                           const struct buf_2d *src, const struct buf_2d *pre,
                           int use_mvcost) {
   const struct buf_2d *const what = src;
   const struct buf_2d *const in_what = pre;
-  const MV mv = { best_mv->row * 8, best_mv->col * 8 };
+  const MV mv = get_mv_from_fullmv(best_mv);
   const MV_COST_TYPE mv_cost_type = x->mv_cost_type;
   unsigned int unused;
 
   return vfp->svaf(get_buf_from_mv(in_what, best_mv), in_what->stride, 0, 0,
                    what->buf, what->stride, &unused, second_pred) +
          (use_mvcost
-              ? mv_err_cost(&mv, center_mv, x->nmv_vec_cost, x->mv_cost_stack,
+              ? mv_err_cost(&mv, ref_mv, x->nmv_vec_cost, x->mv_cost_stack,
                             x->errorperbit, mv_cost_type)
               : 0);
 }
 
-int av1_get_mvpred_mask_var(const MACROBLOCK *x, const MV *best_mv,
-                            const MV *center_mv, const uint8_t *second_pred,
+int av1_get_mvpred_mask_var(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
+                            const MV *ref_mv, const uint8_t *second_pred,
                             const uint8_t *mask, int mask_stride,
                             int invert_mask, const aom_variance_fn_ptr_t *vfp,
                             const struct buf_2d *src, const struct buf_2d *pre,
                             int use_mvcost) {
   const struct buf_2d *const what = src;
   const struct buf_2d *const in_what = pre;
-  const MV mv = { best_mv->row * 8, best_mv->col * 8 };
+  const MV mv = get_mv_from_fullmv(best_mv);
   const MV_COST_TYPE mv_cost_type = x->mv_cost_type;
   unsigned int unused;
 
@@ -1585,15 +1589,30 @@
                    get_buf_from_mv(in_what, best_mv), in_what->stride,
                    second_pred, mask, mask_stride, invert_mask, &unused) +
          (use_mvcost
-              ? mv_err_cost(&mv, center_mv, x->nmv_vec_cost, x->mv_cost_stack,
+              ? mv_err_cost(&mv, ref_mv, x->nmv_vec_cost, x->mv_cost_stack,
                             x->errorperbit, mv_cost_type)
               : 0);
 }
 
-int av1_hex_search(MACROBLOCK *x, MV *start_mv, int search_param,
+// For the following foo_search, the input arguments are:
+// x: The struct used to hold a bunch of random configs.
+// start_mv: where we are starting our motion search
+// search_param: how many steps to skip in our motion search. For example,
+//   a value 3 suggests that 3 search steps have already taken place prior to
+//   this function call, so we jump directly to step 4 of the search process
+// sad_per_bit: a multiplier used to convert rate to sad cost
+// do_init_search: if on, do an initial search of all possible scales around the
+//   start_mv, and then pick the best scale.
+// cond_list: used to hold the cost around the best full mv so we can use it to
+//   speed up subpel search later.
+// vfp: a function pointer to the simd function so we can compute the cost
+//   efficiently
+// use_mv_cost: whether we want include the cost of encoding a mv in our search.
+// ref_mf: the reference mv used to compute the mv cost
+int av1_hex_search(MACROBLOCK *x, FULLPEL_MV *start_mv, int search_param,
                    int sad_per_bit, int do_init_search, int *cost_list,
                    const aom_variance_fn_ptr_t *vfp, int use_mvcost,
-                   const MV *center_mv) {
+                   const MV *ref_mv) {
   // First scale has 8-closest points, the rest have 6 points in hex shape
   // at increasing scales
   static const int hex_num_candidates[MAX_PATTERN_SCALES] = { 8, 6, 6, 6, 6, 6,
@@ -1622,14 +1641,14 @@
   };
   /* clang-format on */
   return pattern_search(x, start_mv, search_param, sad_per_bit, do_init_search,
-                        cost_list, vfp, use_mvcost, center_mv,
-                        hex_num_candidates, hex_candidates);
+                        cost_list, vfp, use_mvcost, ref_mv, hex_num_candidates,
+                        hex_candidates);
 }
 
-static int bigdia_search(MACROBLOCK *x, MV *start_mv, int search_param,
+static int bigdia_search(MACROBLOCK *x, FULLPEL_MV *start_mv, int search_param,
                          int sad_per_bit, int do_init_search, int *cost_list,
                          const aom_variance_fn_ptr_t *vfp, int use_mvcost,
-                         const MV *center_mv) {
+                         const MV *ref_mv) {
   // First scale has 4-closest points, the rest have 8 points in diamond
   // shape at increasing scales
   static const int bigdia_num_candidates[MAX_PATTERN_SCALES] = {
@@ -1663,14 +1682,14 @@
       };
   /* clang-format on */
   return pattern_search(x, start_mv, search_param, sad_per_bit, do_init_search,
-                        cost_list, vfp, use_mvcost, center_mv,
+                        cost_list, vfp, use_mvcost, ref_mv,
                         bigdia_num_candidates, bigdia_candidates);
 }
 
-static int square_search(MACROBLOCK *x, MV *start_mv, int search_param,
+static int square_search(MACROBLOCK *x, FULLPEL_MV *start_mv, int search_param,
                          int sad_per_bit, int do_init_search, int *cost_list,
                          const aom_variance_fn_ptr_t *vfp, int use_mvcost,
-                         const MV *center_mv) {
+                         const MV *ref_mv) {
   // All scales have 8 closest points in square shape
   static const int square_num_candidates[MAX_PATTERN_SCALES] = {
     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
@@ -1704,41 +1723,43 @@
       };
   /* clang-format on */
   return pattern_search(x, start_mv, search_param, sad_per_bit, do_init_search,
-                        cost_list, vfp, use_mvcost, center_mv,
+                        cost_list, vfp, use_mvcost, ref_mv,
                         square_num_candidates, square_candidates);
 }
 
-static int fast_hex_search(MACROBLOCK *x, MV *ref_mv, int search_param,
-                           int sad_per_bit,
+static int fast_hex_search(MACROBLOCK *x, FULLPEL_MV *start_mv,
+                           int search_param, int sad_per_bit,
                            int do_init_search,  // must be zero for fast_hex
                            int *cost_list, const aom_variance_fn_ptr_t *vfp,
-                           int use_mvcost, const MV *center_mv) {
-  return av1_hex_search(x, ref_mv, AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param),
-                        sad_per_bit, do_init_search, cost_list, vfp, use_mvcost,
-                        center_mv);
+                           int use_mvcost, const MV *ref_mv) {
+  return av1_hex_search(
+      x, start_mv, AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param), sad_per_bit,
+      do_init_search, cost_list, vfp, use_mvcost, ref_mv);
 }
 
-static int fast_dia_search(MACROBLOCK *x, MV *ref_mv, int search_param,
-                           int sad_per_bit, int do_init_search, int *cost_list,
+static int fast_dia_search(MACROBLOCK *x, FULLPEL_MV *start_mv,
+                           int search_param, int sad_per_bit,
+                           int do_init_search, int *cost_list,
                            const aom_variance_fn_ptr_t *vfp, int use_mvcost,
-                           const MV *center_mv) {
-  return bigdia_search(x, ref_mv, AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param),
-                       sad_per_bit, do_init_search, cost_list, vfp, use_mvcost,
-                       center_mv);
+                           const MV *ref_mv) {
+  return bigdia_search(
+      x, start_mv, AOMMAX(MAX_MVSEARCH_STEPS - 2, search_param), sad_per_bit,
+      do_init_search, cost_list, vfp, use_mvcost, ref_mv);
 }
 
 #undef CHECK_BETTER
 
-// Exhuastive motion search around a given centre position with a given
+// Exhaustive motion search around a given centre position with a given
 // step size.
-static int exhuastive_mesh_search(MACROBLOCK *x, MV *ref_mv, MV *best_mv,
-                                  int range, int step, int sad_per_bit,
+static int exhuastive_mesh_search(MACROBLOCK *x, FULLPEL_MV *ref_mv,
+                                  FULLPEL_MV *best_mv, int range, int step,
+                                  int sad_per_bit,
                                   const aom_variance_fn_ptr_t *fn_ptr,
-                                  const MV *center_mv) {
+                                  const FULLPEL_MV *start_mv) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const struct buf_2d *const what = &x->plane[0].src;
   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
-  MV fcenter_mv = { center_mv->row, center_mv->col };
+  FULLPEL_MV start_mv_ = *start_mv;
   unsigned int best_sad = INT_MAX;
   int r, c, i;
   int start_col, end_col, start_row, end_row;
@@ -1746,23 +1767,23 @@
 
   assert(step >= 1);
 
-  clamp_mv(&fcenter_mv, x->mv_limits.col_min, x->mv_limits.col_max,
-           x->mv_limits.row_min, x->mv_limits.row_max);
-  *best_mv = fcenter_mv;
+  clamp_fullmv(&start_mv_, x->mv_limits.col_min, x->mv_limits.col_max,
+               x->mv_limits.row_min, x->mv_limits.row_max);
+  *best_mv = start_mv_;
   best_sad =
-      fn_ptr->sdf(what->buf, what->stride,
-                  get_buf_from_mv(in_what, &fcenter_mv), in_what->stride) +
-      mvsad_err_cost(x, &fcenter_mv, ref_mv, sad_per_bit);
-  start_row = AOMMAX(-range, x->mv_limits.row_min - fcenter_mv.row);
-  start_col = AOMMAX(-range, x->mv_limits.col_min - fcenter_mv.col);
-  end_row = AOMMIN(range, x->mv_limits.row_max - fcenter_mv.row);
-  end_col = AOMMIN(range, x->mv_limits.col_max - fcenter_mv.col);
+      fn_ptr->sdf(what->buf, what->stride, get_buf_from_mv(in_what, &start_mv_),
+                  in_what->stride) +
+      mvsad_err_cost(x, &start_mv_, ref_mv, sad_per_bit);
+  start_row = AOMMAX(-range, x->mv_limits.row_min - start_mv_.row);
+  start_col = AOMMAX(-range, x->mv_limits.col_min - start_mv_.col);
+  end_row = AOMMIN(range, x->mv_limits.row_max - start_mv_.row);
+  end_col = AOMMIN(range, x->mv_limits.col_max - start_mv_.col);
 
   for (r = start_row; r <= end_row; r += step) {
     for (c = start_col; c <= end_col; c += col_step) {
       // Step > 1 means we are not checking every location in this pass.
       if (step > 1) {
-        const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c };
+        const FULLPEL_MV mv = { start_mv_.row + r, start_mv_.col + c };
         unsigned int sad =
             fn_ptr->sdf(what->buf, what->stride, get_buf_from_mv(in_what, &mv),
                         in_what->stride);
@@ -1770,7 +1791,7 @@
           sad += mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
           if (sad < best_sad) {
             best_sad = sad;
-            x->second_best_mv.as_mv = *best_mv;
+            x->second_best_mv.as_fullmv = *best_mv;
             *best_mv = mv;
           }
         }
@@ -1780,26 +1801,27 @@
           unsigned int sads[4];
           const uint8_t *addrs[4];
           for (i = 0; i < 4; ++i) {
-            const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
+            const FULLPEL_MV mv = { start_mv_.row + r, start_mv_.col + c + i };
             addrs[i] = get_buf_from_mv(in_what, &mv);
           }
           fn_ptr->sdx4df(what->buf, what->stride, addrs, in_what->stride, sads);
 
           for (i = 0; i < 4; ++i) {
             if (sads[i] < best_sad) {
-              const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
+              const FULLPEL_MV mv = { start_mv_.row + r,
+                                      start_mv_.col + c + i };
               const unsigned int sad =
                   sads[i] + mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
               if (sad < best_sad) {
                 best_sad = sad;
-                x->second_best_mv.as_mv = *best_mv;
+                x->second_best_mv.as_fullmv = *best_mv;
                 *best_mv = mv;
               }
             }
           }
         } else {
           for (i = 0; i < end_col - c; ++i) {
-            const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
+            const FULLPEL_MV mv = { start_mv_.row + r, start_mv_.col + c + i };
             unsigned int sad =
                 fn_ptr->sdf(what->buf, what->stride,
                             get_buf_from_mv(in_what, &mv), in_what->stride);
@@ -1807,7 +1829,7 @@
               sad += mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
               if (sad < best_sad) {
                 best_sad = sad;
-                x->second_best_mv.as_mv = *best_mv;
+                x->second_best_mv.as_fullmv = *best_mv;
                 *best_mv = mv;
               }
             }
@@ -1821,10 +1843,10 @@
 }
 
 int av1_diamond_search_sad_c(MACROBLOCK *x, const search_site_config *cfg,
-                             MV *ref_mv, MV *best_mv, int search_param,
-                             int sad_per_bit, int *num00,
+                             FULLPEL_MV *start_mv, FULLPEL_MV *best_mv,
+                             int search_param, int sad_per_bit, int *num00,
                              const aom_variance_fn_ptr_t *fn_ptr,
-                             const MV *center_mv, uint8_t *second_pred,
+                             const MV *ref_mv, uint8_t *second_pred,
                              uint8_t *mask, int mask_stride, int inv_mask) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   uint8_t *what = x->plane[0].src.buf;
@@ -1837,24 +1859,19 @@
   int best_site = 0;
   int is_off_center = 0;
 
-  int ref_row;
-  int ref_col;
-
   // search_param determines the length of the initial step and hence the number
   // of iterations.
   const int tot_steps = cfg->ss_count - search_param;
 
-  const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
-  clamp_mv(ref_mv, x->mv_limits.col_min, x->mv_limits.col_max,
-           x->mv_limits.row_min, x->mv_limits.row_max);
-  ref_row = ref_mv->row;
-  ref_col = ref_mv->col;
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
+  clamp_fullmv(start_mv, x->mv_limits.col_min, x->mv_limits.col_max,
+               x->mv_limits.row_min, x->mv_limits.row_max);
   *num00 = 0;
-  best_mv->row = ref_row;
-  best_mv->col = ref_col;
+  best_mv->row = start_mv->row;
+  best_mv->col = start_mv->col;
 
   // Work out the start point for the search
-  in_what = xd->plane[0].pre[0].buf + ref_row * in_what_stride + ref_col;
+  in_what = get_buf_from_mv(&xd->plane[0].pre[0], start_mv);
   best_address = in_what;
 
   // Check the starting position
@@ -1869,7 +1886,7 @@
   else
     bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride);
 
-  bestsad += mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit);
+  bestsad += mvsad_err_cost(x, best_mv, &full_ref_mv, sad_per_bit);
 
   int next_step_size = tot_steps > 2 ? cfg->radius[tot_steps - 2] : 1;
   for (int step = tot_steps - 1; step >= 0; --step) {
@@ -1896,10 +1913,11 @@
         fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride, sads);
         for (j = 0; j < 4; j++) {
           if (sads[j] < bestsad) {
-            const MV this_mv = { best_mv->row + ss[idx + j].mv.row,
-                                 best_mv->col + ss[idx + j].mv.col };
+            const FULLPEL_MV this_mv = { best_mv->row + ss[idx + j].mv.row,
+                                         best_mv->col + ss[idx + j].mv.col };
             unsigned int thissad =
-                sads[j] + mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
+                sads[j] +
+                mvsad_err_cost(x, &this_mv, &full_ref_mv, sad_per_bit);
             if (thissad < bestsad) {
               bestsad = thissad;
               best_site = idx + j;
@@ -1909,8 +1927,8 @@
       }
     } else {
       for (int idx = 1; idx <= cfg->searches_per_step[step]; idx++) {
-        const MV this_mv = { best_mv->row + ss[idx].mv.row,
-                             best_mv->col + ss[idx].mv.col };
+        const FULLPEL_MV this_mv = { best_mv->row + ss[idx].mv.row,
+                                     best_mv->col + ss[idx].mv.col };
 
         if (is_mv_in(&x->mv_limits, &this_mv)) {
           const uint8_t *const check_here = ss[idx].offset + best_address;
@@ -1928,7 +1946,7 @@
                 fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
 
           if (thissad < bestsad) {
-            thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
+            thissad += mvsad_err_cost(x, &this_mv, &full_ref_mv, sad_per_bit);
             if (thissad < bestsad) {
               bestsad = thissad;
               best_site = idx;
@@ -1939,7 +1957,7 @@
     }
 
     if (best_site != 0) {
-      x->second_best_mv.as_mv = *best_mv;
+      x->second_best_mv.as_fullmv = *best_mv;
       best_mv->row += ss[best_site].mv.row;
       best_mv->col += ss[best_site].mv.col;
       best_address += ss[best_site].offset;
@@ -1963,32 +1981,33 @@
 /* do_refine: If last step (1-away) of n-step search doesn't pick the center
               point as the best match, we will do a final 1-away diamond
               refining search  */
-static int full_pixel_diamond(MACROBLOCK *x, MV *mvp_full, int step_param,
-                              int use_var, int sadpb, int *cost_list,
+static int full_pixel_diamond(MACROBLOCK *x, FULLPEL_MV *start_mv,
+                              int step_param, int use_var, int sadpb,
+                              int *cost_list,
                               const aom_variance_fn_ptr_t *fn_ptr,
                               const MV *ref_mv, const search_site_config *cfg,
                               uint8_t *second_pred, uint8_t *mask,
                               int mask_stride, int inv_mask) {
-  MV temp_mv;
+  FULLPEL_MV best_mv;
   int thissme, n, num00 = 0;
-  int bestsme = av1_diamond_search_sad_c(x, cfg, mvp_full, &temp_mv, step_param,
+  int bestsme = av1_diamond_search_sad_c(x, cfg, start_mv, &best_mv, step_param,
                                          sadpb, &n, fn_ptr, ref_mv, second_pred,
                                          mask, mask_stride, inv_mask);
 
   if (bestsme < INT_MAX) {
     if (mask)
       bestsme = av1_get_mvpred_mask_var(
-          x, &temp_mv, ref_mv, second_pred, mask, mask_stride, inv_mask, fn_ptr,
+          x, &best_mv, ref_mv, second_pred, mask, mask_stride, inv_mask, fn_ptr,
           &x->plane[0].src, &x->e_mbd.plane[0].pre[0], use_var);
     else if (second_pred)
-      bestsme = av1_get_mvpred_av_var(x, &temp_mv, ref_mv, second_pred, fn_ptr,
+      bestsme = av1_get_mvpred_av_var(x, &best_mv, ref_mv, second_pred, fn_ptr,
                                       &x->plane[0].src,
                                       &x->e_mbd.plane[0].pre[0], use_var);
     else
-      bestsme = av1_get_mvpred_var(x, &temp_mv, ref_mv, fn_ptr, use_var);
+      bestsme = av1_get_mvpred_var(x, &best_mv, ref_mv, fn_ptr, use_var);
   }
 
-  x->best_mv.as_mv = temp_mv;
+  x->best_mv.as_fullmv = best_mv;
 
   // If there won't be more n-step search, check to see if refining search is
   // needed.
@@ -2000,32 +2019,33 @@
       num00--;
     } else {
       thissme = av1_diamond_search_sad_c(
-          x, cfg, mvp_full, &temp_mv, step_param + n, sadpb, &num00, fn_ptr,
+          x, cfg, start_mv, &best_mv, step_param + n, sadpb, &num00, fn_ptr,
           ref_mv, second_pred, mask, mask_stride, inv_mask);
 
       if (thissme < INT_MAX) {
         if (mask)
           thissme = av1_get_mvpred_mask_var(
-              x, &temp_mv, ref_mv, second_pred, mask, mask_stride, inv_mask,
+              x, &best_mv, ref_mv, second_pred, mask, mask_stride, inv_mask,
               fn_ptr, &x->plane[0].src, &x->e_mbd.plane[0].pre[0], use_var);
         else if (second_pred)
-          thissme = av1_get_mvpred_av_var(x, &temp_mv, ref_mv, second_pred,
+          thissme = av1_get_mvpred_av_var(x, &best_mv, ref_mv, second_pred,
                                           fn_ptr, &x->plane[0].src,
                                           &x->e_mbd.plane[0].pre[0], use_var);
         else
-          thissme = av1_get_mvpred_var(x, &temp_mv, ref_mv, fn_ptr, use_var);
+          thissme = av1_get_mvpred_var(x, &best_mv, ref_mv, fn_ptr, use_var);
       }
 
       if (thissme < bestsme) {
         bestsme = thissme;
-        x->best_mv.as_mv = temp_mv;
+        x->best_mv.as_fullmv = best_mv;
       }
     }
   }
 
   // Return cost list.
   if (cost_list) {
-    calc_int_cost_list(x, ref_mv, sadpb, fn_ptr, &x->best_mv.as_mv, cost_list);
+    calc_int_cost_list(x, ref_mv, sadpb, fn_ptr, &x->best_mv.as_fullmv,
+                       cost_list);
   }
   return bestsme;
 }
@@ -2036,17 +2056,18 @@
 // Runs an limited range exhaustive mesh search using a pattern set
 // according to the encode speed profile.
 static int full_pixel_exhaustive(
-    MACROBLOCK *x, const MV *centre_mv_full, int sadpb, int *cost_list,
-    const aom_variance_fn_ptr_t *fn_ptr, const MV *ref_mv, MV *dst_mv,
+    MACROBLOCK *x, const FULLPEL_MV *start_mv, int sadpb, int *cost_list,
+    const aom_variance_fn_ptr_t *fn_ptr, const MV *ref_mv, FULLPEL_MV *best_mv,
     const struct MESH_PATTERN *const mesh_patterns) {
-  MV temp_mv = { centre_mv_full->row, centre_mv_full->col };
-  MV f_ref_mv = { ref_mv->row >> 3, ref_mv->col >> 3 };
+  FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
   int bestsme;
   int i;
   int interval = mesh_patterns[0].interval;
   int range = mesh_patterns[0].range;
   int baseline_interval_divisor;
 
+  *best_mv = *start_mv;
+
   // Keep track of number of exhaustive calls (this frame in this thread).
   if (x->ex_search_count_ptr != NULL) ++(*x->ex_search_count_ptr);
 
@@ -2059,13 +2080,13 @@
 
   // Check size of proposed first range against magnitude of the centre
   // value used as a starting point.
-  range = AOMMAX(range, (5 * AOMMAX(abs(temp_mv.row), abs(temp_mv.col))) / 4);
+  range = AOMMAX(range, (5 * AOMMAX(abs(best_mv->row), abs(best_mv->col))) / 4);
   range = AOMMIN(range, MAX_RANGE);
   interval = AOMMAX(interval, range / baseline_interval_divisor);
 
   // initial search
-  bestsme = exhuastive_mesh_search(x, &f_ref_mv, &temp_mv, range, interval,
-                                   sadpb, fn_ptr, &temp_mv);
+  bestsme = exhuastive_mesh_search(x, &full_ref_mv, best_mv, range, interval,
+                                   sadpb, fn_ptr, best_mv);
 
   if ((interval > MIN_INTERVAL) && (range > MIN_RANGE)) {
     // Progressive searches with range and step size decreasing each time
@@ -2073,20 +2094,19 @@
     for (i = 1; i < MAX_MESH_STEP; ++i) {
       // First pass with coarser step and longer range
       bestsme = exhuastive_mesh_search(
-          x, &f_ref_mv, &temp_mv, mesh_patterns[i].range,
-          mesh_patterns[i].interval, sadpb, fn_ptr, &temp_mv);
+          x, &full_ref_mv, best_mv, mesh_patterns[i].range,
+          mesh_patterns[i].interval, sadpb, fn_ptr, best_mv);
 
       if (mesh_patterns[i].interval == 1) break;
     }
   }
 
   if (bestsme < INT_MAX)
-    bestsme = av1_get_mvpred_var(x, &temp_mv, ref_mv, fn_ptr, 1);
-  *dst_mv = temp_mv;
+    bestsme = av1_get_mvpred_var(x, best_mv, ref_mv, fn_ptr, 1);
 
   // Return cost list.
   if (cost_list) {
-    calc_int_cost_list(x, ref_mv, sadpb, fn_ptr, dst_mv, cost_list);
+    calc_int_cost_list(x, ref_mv, sadpb, fn_ptr, best_mv, cost_list);
   }
   return bestsme;
 }
@@ -2096,7 +2116,7 @@
 int av1_refining_search_8p_c(MACROBLOCK *x, int error_per_bit, int search_range,
                              const aom_variance_fn_ptr_t *fn_ptr,
                              const uint8_t *mask, int mask_stride,
-                             int invert_mask, const MV *center_mv,
+                             int invert_mask, const MV *ref_mv,
                              const uint8_t *second_pred,
                              const struct buf_2d *src,
                              const struct buf_2d *pre) {
@@ -2112,8 +2132,8 @@
   };
   const struct buf_2d *const what = src;
   const struct buf_2d *const in_what = pre;
-  const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
-  MV *best_mv = &x->best_mv.as_mv;
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
+  FULLPEL_MV *best_mv = &x->best_mv.as_fullmv;
   unsigned int best_sad = INT_MAX;
   int i, j;
   uint8_t do_refine_search_grid[SEARCH_GRID_STRIDE_8P *
@@ -2121,18 +2141,18 @@
   int grid_center = SEARCH_GRID_CENTER_8P;
   int grid_coord = grid_center;
 
-  clamp_mv(best_mv, x->mv_limits.col_min, x->mv_limits.col_max,
-           x->mv_limits.row_min, x->mv_limits.row_max);
+  clamp_fullmv(best_mv, x->mv_limits.col_min, x->mv_limits.col_max,
+               x->mv_limits.row_min, x->mv_limits.row_max);
   if (mask) {
     best_sad = fn_ptr->msdf(what->buf, what->stride,
                             get_buf_from_mv(in_what, best_mv), in_what->stride,
                             second_pred, mask, mask_stride, invert_mask) +
-               mvsad_err_cost(x, best_mv, &fcenter_mv, error_per_bit);
+               mvsad_err_cost(x, best_mv, &full_ref_mv, error_per_bit);
   } else {
     best_sad =
         fn_ptr->sdaf(what->buf, what->stride, get_buf_from_mv(in_what, best_mv),
                      in_what->stride, second_pred) +
-        mvsad_err_cost(x, best_mv, &fcenter_mv, error_per_bit);
+        mvsad_err_cost(x, best_mv, &full_ref_mv, error_per_bit);
   }
 
   do_refine_search_grid[grid_coord] = 1;
@@ -2145,8 +2165,8 @@
       if (do_refine_search_grid[grid_coord] == 1) {
         continue;
       }
-      const MV mv = { best_mv->row + neighbors[j].coord.row,
-                      best_mv->col + neighbors[j].coord.col };
+      const FULLPEL_MV mv = { best_mv->row + neighbors[j].coord.row,
+                              best_mv->col + neighbors[j].coord.col };
 
       do_refine_search_grid[grid_coord] = 1;
       if (is_mv_in(&x->mv_limits, &mv)) {
@@ -2161,7 +2181,7 @@
                              second_pred);
         }
         if (sad < best_sad) {
-          sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
+          sad += mvsad_err_cost(x, &mv, &full_ref_mv, error_per_bit);
           if (sad < best_sad) {
             best_sad = sad;
             best_site = j;
@@ -2286,9 +2306,8 @@
   const int src_stride = x->plane[0].src.stride;
   const int ref_stride = xd->plane[0].pre[0].stride;
   uint8_t const *ref_buf, *src_buf;
-  MV *tmp_mv = &xd->mi[0]->mv[0].as_mv;
+  int_mv *best_int_mv = &xd->mi[0]->mv[0];
   unsigned int best_sad, tmp_sad, this_sad[4];
-  MV this_mv;
   const int norm_factor = 3 + (bw >> 5);
   const YV12_BUFFER_CONFIG *scaled_ref_frame =
       av1_get_scaled_ref_frame(cpi, mi->ref_frame[0]);
@@ -2306,8 +2325,7 @@
 
   if (xd->bd != 8) {
     unsigned int sad;
-    tmp_mv->row = 0;
-    tmp_mv->col = 0;
+    best_int_mv->as_fullmv = kZeroFullMv;
     sad = cpi->fn_ptr[bsize].sdf(x->plane[0].src.buf, src_stride,
                                  xd->plane[0].pre[0].buf, ref_stride);
 
@@ -2344,12 +2362,14 @@
   }
 
   // Find the best match per 1-D search
-  tmp_mv->col = vector_match(hbuf, src_hbuf, mi_size_wide_log2[bsize]);
-  tmp_mv->row = vector_match(vbuf, src_vbuf, mi_size_high_log2[bsize]);
+  best_int_mv->as_fullmv.col =
+      vector_match(hbuf, src_hbuf, mi_size_wide_log2[bsize]);
+  best_int_mv->as_fullmv.row =
+      vector_match(vbuf, src_vbuf, mi_size_high_log2[bsize]);
 
-  this_mv = *tmp_mv;
+  FULLPEL_MV this_mv = best_int_mv->as_fullmv;
   src_buf = x->plane[0].src.buf;
-  ref_buf = xd->plane[0].pre[0].buf + this_mv.row * ref_stride + this_mv.col;
+  ref_buf = get_buf_from_mv(&xd->plane[0].pre[0], &this_mv);
   best_sad = cpi->fn_ptr[bsize].sdf(src_buf, src_stride, ref_buf, ref_stride);
 
   {
@@ -2366,8 +2386,8 @@
   for (idx = 0; idx < 4; ++idx) {
     if (this_sad[idx] < best_sad) {
       best_sad = this_sad[idx];
-      tmp_mv->row = search_pos[idx].row + this_mv.row;
-      tmp_mv->col = search_pos[idx].col + this_mv.col;
+      best_int_mv->as_fullmv.row = search_pos[idx].row + this_mv.row;
+      best_int_mv->as_fullmv.col = search_pos[idx].col + this_mv.col;
     }
   }
 
@@ -2381,22 +2401,22 @@
   else
     this_mv.col += 1;
 
-  ref_buf = xd->plane[0].pre[0].buf + this_mv.row * ref_stride + this_mv.col;
+  ref_buf = get_buf_from_mv(&xd->plane[0].pre[0], &this_mv);
 
   tmp_sad = cpi->fn_ptr[bsize].sdf(src_buf, src_stride, ref_buf, ref_stride);
   if (best_sad > tmp_sad) {
-    *tmp_mv = this_mv;
+    best_int_mv->as_fullmv = this_mv;
     best_sad = tmp_sad;
   }
 
-  tmp_mv->row *= 8;
-  tmp_mv->col *= 8;
+  best_int_mv->as_mv = get_mv_from_fullmv(&best_int_mv->as_fullmv);
 
   set_subpel_mv_search_range(
       &x->mv_limits, &subpel_mv_limits.col_min, &subpel_mv_limits.col_max,
       &subpel_mv_limits.row_min, &subpel_mv_limits.row_max, ref_mv);
-  clamp_mv(tmp_mv, subpel_mv_limits.col_min, subpel_mv_limits.col_max,
-           subpel_mv_limits.row_min, subpel_mv_limits.row_max);
+  clamp_mv(&best_int_mv->as_mv, subpel_mv_limits.col_min,
+           subpel_mv_limits.col_max, subpel_mv_limits.row_min,
+           subpel_mv_limits.row_max);
 
   if (scaled_ref_frame) {
     int i;
@@ -2407,8 +2427,8 @@
 }
 
 int av1_full_pixel_search(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
-                          MV *mvp_full, int step_param, int use_var, int method,
-                          int run_mesh_search, int error_per_bit,
+                          FULLPEL_MV *start_mv, int step_param, int use_var,
+                          int method, int run_mesh_search, int error_per_bit,
                           int *cost_list, const MV *ref_mv, int var_max, int rd,
                           int x_pos, int y_pos, int intra,
                           const search_site_config *cfg,
@@ -2430,29 +2450,29 @@
 
   switch (method) {
     case FAST_DIAMOND:
-      var = fast_dia_search(x, mvp_full, step_param, error_per_bit, 0,
+      var = fast_dia_search(x, start_mv, step_param, error_per_bit, 0,
                             cost_list, fn_ptr, 1, ref_mv);
       break;
     case FAST_HEX:
-      var = fast_hex_search(x, mvp_full, step_param, error_per_bit, 0,
+      var = fast_hex_search(x, start_mv, step_param, error_per_bit, 0,
                             cost_list, fn_ptr, 1, ref_mv);
       break;
     case HEX:
-      var = av1_hex_search(x, mvp_full, step_param, error_per_bit, 1, cost_list,
+      var = av1_hex_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
                            fn_ptr, 1, ref_mv);
       break;
     case SQUARE:
-      var = square_search(x, mvp_full, step_param, error_per_bit, 1, cost_list,
+      var = square_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
                           fn_ptr, 1, ref_mv);
       break;
     case BIGDIA:
-      var = bigdia_search(x, mvp_full, step_param, error_per_bit, 1, cost_list,
+      var = bigdia_search(x, start_mv, step_param, error_per_bit, 1, cost_list,
                           fn_ptr, 1, ref_mv);
       break;
     case NSTEP:
     case DIAMOND:
       var =
-          full_pixel_diamond(x, mvp_full, step_param, use_var, error_per_bit,
+          full_pixel_diamond(x, start_mv, step_param, use_var, error_per_bit,
                              cost_list, fn_ptr, ref_mv, cfg, NULL, NULL, 0, 0);
       break;
     default: assert(0 && "Invalid search method.");
@@ -2477,8 +2497,8 @@
   // filtering. Can extend it to intrabc.
   if (!use_intrabc_mesh_pattern && sf->mv_sf.prune_mesh_search) {
     const int full_pel_mv_diff =
-        AOMMAX(abs(mvp_full->row - x->best_mv.as_mv.row),
-               abs(mvp_full->col - x->best_mv.as_mv.col));
+        AOMMAX(abs(start_mv->row - x->best_mv.as_fullmv.row),
+               abs(start_mv->col - x->best_mv.as_fullmv.col));
     if (full_pel_mv_diff <= 4) {
       run_mesh_search = 0;
     }
@@ -2486,23 +2506,23 @@
 
   if (run_mesh_search) {
     int var_ex;
-    MV tmp_mv_ex;
+    FULLPEL_MV tmp_mv_ex;
     // Pick the mesh pattern for exhaustive search based on the toolset (intraBC
     // or non-intraBC)
     const MESH_PATTERN *const mesh_patterns =
         use_intrabc_mesh_pattern ? sf->mv_sf.intrabc_mesh_patterns
                                  : sf->mv_sf.mesh_patterns;
-    var_ex =
-        full_pixel_exhaustive(x, &x->best_mv.as_mv, error_per_bit, cost_list,
-                              fn_ptr, ref_mv, &tmp_mv_ex, mesh_patterns);
+    var_ex = full_pixel_exhaustive(x, &x->best_mv.as_fullmv, error_per_bit,
+                                   cost_list, fn_ptr, ref_mv, &tmp_mv_ex,
+                                   mesh_patterns);
     if (var_ex < var) {
       var = var_ex;
-      x->best_mv.as_mv = tmp_mv_ex;
+      x->best_mv.as_fullmv = tmp_mv_ex;
     }
   }
 
   if (method != NSTEP && rd && var < var_max)
-    var = av1_get_mvpred_var(x, &x->best_mv.as_mv, ref_mv, fn_ptr, 1);
+    var = av1_get_mvpred_var(x, &x->best_mv.as_fullmv, ref_mv, fn_ptr, 1);
 
   // Use hash-me for intrablock copy
   do {
@@ -2518,7 +2538,7 @@
         uint8_t *what = x->plane[0].src.buf;
         const int what_stride = x->plane[0].src.stride;
         uint32_t hash_value1, hash_value2;
-        MV best_hash_mv;
+        FULLPEL_MV best_hash_mv;
         int best_hash_cost = INT_MAX;
 
         // for the hashMap
@@ -2549,7 +2569,7 @@
                                    bsize, cpi->common.seq_params.mib_size_log2))
                 continue;
             }
-            MV hash_mv;
+            FULLPEL_MV hash_mv;
             hash_mv.col = ref_block_hash.x - x_pos;
             hash_mv.row = ref_block_hash.y - y_pos;
             if (!is_mv_in(&x->mv_limits, &hash_mv)) continue;
@@ -2563,7 +2583,7 @@
         }
         if (best_hash_cost < var) {
           x->second_best_mv = x->best_mv;
-          x->best_mv.as_mv = best_hash_mv;
+          x->best_mv.as_fullmv = best_hash_mv;
           var = best_hash_cost;
         }
       }
@@ -2850,49 +2870,50 @@
 #undef CHECK_BETTER
 
 static int get_obmc_mvpred_var(const MACROBLOCK *x, const int32_t *wsrc,
-                               const int32_t *mask, const MV *best_mv,
-                               const MV *center_mv,
+                               const int32_t *mask, const FULLPEL_MV *best_mv,
+                               const MV *ref_mv,
                                const aom_variance_fn_ptr_t *vfp, int use_mvcost,
                                int is_second) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
-  const MV mv = { best_mv->row * 8, best_mv->col * 8 };
+  const MV mv = get_mv_from_fullmv(best_mv);
   const MV_COST_TYPE mv_cost_type = x->mv_cost_type;
   unsigned int unused;
 
   return vfp->ovf(get_buf_from_mv(in_what, best_mv), in_what->stride, wsrc,
                   mask, &unused) +
          (use_mvcost
-              ? mv_err_cost(&mv, center_mv, x->nmv_vec_cost, x->mv_cost_stack,
+              ? mv_err_cost(&mv, ref_mv, x->nmv_vec_cost, x->mv_cost_stack,
                             x->errorperbit, mv_cost_type)
               : 0);
 }
 
 static int obmc_refining_search_sad(const MACROBLOCK *x, const int32_t *wsrc,
-                                    const int32_t *mask, MV *ref_mv,
+                                    const int32_t *mask, FULLPEL_MV *start_mv,
                                     int error_per_bit, int search_range,
                                     const aom_variance_fn_ptr_t *fn_ptr,
-                                    const MV *center_mv, int is_second) {
+                                    const MV *ref_mv, int is_second) {
   const MV neighbors[4] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
   const MACROBLOCKD *const xd = &x->e_mbd;
   const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
-  const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
-  unsigned int best_sad = fn_ptr->osdf(get_buf_from_mv(in_what, ref_mv),
-                                       in_what->stride, wsrc, mask) +
-                          mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
+  unsigned int best_sad =
+      fn_ptr->osdf(get_buf_from_mv(in_what, start_mv), in_what->stride, wsrc,
+                   mask) +
+      mvsad_err_cost(x, start_mv, &full_ref_mv, error_per_bit);
   int i, j;
 
   for (i = 0; i < search_range; i++) {
     int best_site = -1;
 
     for (j = 0; j < 4; j++) {
-      const MV mv = { ref_mv->row + neighbors[j].row,
-                      ref_mv->col + neighbors[j].col };
+      const FULLPEL_MV mv = { start_mv->row + neighbors[j].row,
+                              start_mv->col + neighbors[j].col };
       if (is_mv_in(&x->mv_limits, &mv)) {
         unsigned int sad = fn_ptr->osdf(get_buf_from_mv(in_what, &mv),
                                         in_what->stride, wsrc, mask);
         if (sad < best_sad) {
-          sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
+          sad += mvsad_err_cost(x, &mv, &full_ref_mv, error_per_bit);
           if (sad < best_sad) {
             best_sad = sad;
             best_site = j;
@@ -2904,20 +2925,18 @@
     if (best_site == -1) {
       break;
     } else {
-      ref_mv->row += neighbors[best_site].row;
-      ref_mv->col += neighbors[best_site].col;
+      start_mv->row += neighbors[best_site].row;
+      start_mv->col += neighbors[best_site].col;
     }
   }
   return best_sad;
 }
 
-static int obmc_diamond_search_sad(const MACROBLOCK *x,
-                                   const search_site_config *cfg,
-                                   const int32_t *wsrc, const int32_t *mask,
-                                   MV *ref_mv, MV *best_mv, int search_param,
-                                   int sad_per_bit, int *num00,
-                                   const aom_variance_fn_ptr_t *fn_ptr,
-                                   const MV *center_mv, int is_second) {
+static int obmc_diamond_search_sad(
+    const MACROBLOCK *x, const search_site_config *cfg, const int32_t *wsrc,
+    const int32_t *mask, FULLPEL_MV *start_mv, FULLPEL_MV *best_mv,
+    int search_param, int sad_per_bit, int *num00,
+    const aom_variance_fn_ptr_t *fn_ptr, const MV *ref_mv, int is_second) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
   // search_param determines the length of the initial step and hence the number
@@ -2926,34 +2945,34 @@
   // (MAX_FIRST_STEP/4) pel... etc.
 
   const int tot_steps = MAX_MVSEARCH_STEPS - 1 - search_param;
-  const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
+  const FULLPEL_MV full_ref_mv = get_fullmv_from_mv(ref_mv);
   const uint8_t *best_address, *in_what_ref;
   int best_sad = INT_MAX;
   int best_site = 0;
   int step;
 
-  clamp_mv(ref_mv, x->mv_limits.col_min, x->mv_limits.col_max,
-           x->mv_limits.row_min, x->mv_limits.row_max);
-  in_what_ref = in_what->buf + ref_mv->row * in_what->stride + ref_mv->col;
+  clamp_fullmv(start_mv, x->mv_limits.col_min, x->mv_limits.col_max,
+               x->mv_limits.row_min, x->mv_limits.row_max);
+  in_what_ref = get_buf_from_mv(in_what, start_mv);
   best_address = in_what_ref;
   *num00 = 0;
-  *best_mv = *ref_mv;
+  *best_mv = *start_mv;
 
   // Check the starting position
   best_sad = fn_ptr->osdf(best_address, in_what->stride, wsrc, mask) +
-             mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit);
+             mvsad_err_cost(x, best_mv, &full_ref_mv, sad_per_bit);
 
   for (step = tot_steps; step >= 0; --step) {
     const search_site *const ss = cfg->ss[step];
     best_site = 0;
     for (int idx = 1; idx <= cfg->searches_per_step[step]; ++idx) {
-      const MV mv = { best_mv->row + ss[idx].mv.row,
-                      best_mv->col + ss[idx].mv.col };
+      const FULLPEL_MV mv = { best_mv->row + ss[idx].mv.row,
+                              best_mv->col + ss[idx].mv.col };
       if (is_mv_in(&x->mv_limits, &mv)) {
         int sad = fn_ptr->osdf(best_address + ss[idx].offset, in_what->stride,
                                wsrc, mask);
         if (sad < best_sad) {
-          sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit);
+          sad += mvsad_err_cost(x, &mv, &full_ref_mv, sad_per_bit);
           if (sad < best_sad) {
             best_sad = sad;
             best_site = idx;
@@ -2974,23 +2993,24 @@
 }
 
 static int obmc_full_pixel_diamond(const AV1_COMP *cpi, MACROBLOCK *x,
-                                   MV *mvp_full, int step_param, int sadpb,
-                                   int further_steps, int do_refine,
+                                   FULLPEL_MV *start_mv, int step_param,
+                                   int sadpb, int further_steps, int do_refine,
                                    const aom_variance_fn_ptr_t *fn_ptr,
-                                   const MV *ref_mv, MV *dst_mv, int is_second,
+                                   const MV *ref_mv, FULLPEL_MV *best_mv,
+                                   int is_second,
                                    const search_site_config *cfg) {
   (void)cpi;  // to silence compiler warning
   const int32_t *wsrc = x->wsrc_buf;
   const int32_t *mask = x->mask_buf;
-  MV temp_mv;
+  FULLPEL_MV tmp_mv;
   int thissme, n, num00 = 0;
   int bestsme =
-      obmc_diamond_search_sad(x, cfg, wsrc, mask, mvp_full, &temp_mv,
-                              step_param, sadpb, &n, fn_ptr, ref_mv, is_second);
+      obmc_diamond_search_sad(x, cfg, wsrc, mask, start_mv, &tmp_mv, step_param,
+                              sadpb, &n, fn_ptr, ref_mv, is_second);
   if (bestsme < INT_MAX)
-    bestsme = get_obmc_mvpred_var(x, wsrc, mask, &temp_mv, ref_mv, fn_ptr, 1,
+    bestsme = get_obmc_mvpred_var(x, wsrc, mask, &tmp_mv, ref_mv, fn_ptr, 1,
                                   is_second);
-  *dst_mv = temp_mv;
+  *best_mv = tmp_mv;
 
   // If there won't be more n-step search, check to see if refining search is
   // needed.
@@ -3002,19 +3022,19 @@
     if (num00) {
       num00--;
     } else {
-      thissme = obmc_diamond_search_sad(x, cfg, wsrc, mask, mvp_full, &temp_mv,
+      thissme = obmc_diamond_search_sad(x, cfg, wsrc, mask, start_mv, &tmp_mv,
                                         step_param + n, sadpb, &num00, fn_ptr,
                                         ref_mv, is_second);
       if (thissme < INT_MAX)
-        thissme = get_obmc_mvpred_var(x, wsrc, mask, &temp_mv, ref_mv, fn_ptr,
-                                      1, is_second);
+        thissme = get_obmc_mvpred_var(x, wsrc, mask, &tmp_mv, ref_mv, fn_ptr, 1,
+                                      is_second);
 
       // check to see if refining search is needed.
       if (num00 > further_steps - n) do_refine = 0;
 
       if (thissme < bestsme) {
         bestsme = thissme;
-        *dst_mv = temp_mv;
+        *best_mv = tmp_mv;
       }
     }
   }
@@ -3022,41 +3042,42 @@
   // final 1-away diamond refining search
   if (do_refine) {
     const int search_range = 8;
-    MV best_mv = *dst_mv;
-    thissme = obmc_refining_search_sad(x, wsrc, mask, &best_mv, sadpb,
+    tmp_mv = *best_mv;
+    thissme = obmc_refining_search_sad(x, wsrc, mask, &tmp_mv, sadpb,
                                        search_range, fn_ptr, ref_mv, is_second);
     if (thissme < INT_MAX)
-      thissme = get_obmc_mvpred_var(x, wsrc, mask, &best_mv, ref_mv, fn_ptr, 1,
+      thissme = get_obmc_mvpred_var(x, wsrc, mask, &tmp_mv, ref_mv, fn_ptr, 1,
                                     is_second);
     if (thissme < bestsme) {
       bestsme = thissme;
-      *dst_mv = best_mv;
+      *best_mv = tmp_mv;
     }
   }
   return bestsme;
 }
 
-int av1_obmc_full_pixel_search(const AV1_COMP *cpi, MACROBLOCK *x, MV *mvp_full,
-                               int step_param, int sadpb, int further_steps,
-                               int do_refine,
+int av1_obmc_full_pixel_search(const AV1_COMP *cpi, MACROBLOCK *x,
+                               FULLPEL_MV *start_mv, int step_param, int sadpb,
+                               int further_steps, int do_refine,
                                const aom_variance_fn_ptr_t *fn_ptr,
-                               const MV *ref_mv, MV *dst_mv, int is_second,
-                               const search_site_config *cfg) {
+                               const MV *ref_mv, FULLPEL_MV *best_mv,
+                               int is_second, const search_site_config *cfg) {
   if (cpi->sf.inter_sf.obmc_full_pixel_search_level == 0) {
-    return obmc_full_pixel_diamond(cpi, x, mvp_full, step_param, sadpb,
-                                   further_steps, do_refine, fn_ptr, ref_mv,
-                                   dst_mv, is_second, cfg);
+    const int bestsme = obmc_full_pixel_diamond(
+        cpi, x, start_mv, step_param, sadpb, further_steps, do_refine, fn_ptr,
+        ref_mv, best_mv, is_second, cfg);
+    return bestsme;
   } else {
     const int32_t *wsrc = x->wsrc_buf;
     const int32_t *mask = x->mask_buf;
     const int search_range = 8;
-    *dst_mv = *mvp_full;
-    clamp_mv(dst_mv, x->mv_limits.col_min, x->mv_limits.col_max,
-             x->mv_limits.row_min, x->mv_limits.row_max);
+    *best_mv = *start_mv;
+    clamp_fullmv(best_mv, x->mv_limits.col_min, x->mv_limits.col_max,
+                 x->mv_limits.row_min, x->mv_limits.row_max);
     int thissme = obmc_refining_search_sad(
-        x, wsrc, mask, dst_mv, sadpb, search_range, fn_ptr, ref_mv, is_second);
+        x, wsrc, mask, best_mv, sadpb, search_range, fn_ptr, ref_mv, is_second);
     if (thissme < INT_MAX)
-      thissme = get_obmc_mvpred_var(x, wsrc, mask, dst_mv, ref_mv, fn_ptr, 1,
+      thissme = get_obmc_mvpred_var(x, wsrc, mask, best_mv, ref_mv, fn_ptr, 1,
                                     is_second);
     return thissme;
   }
@@ -3159,7 +3180,7 @@
 
 void av1_simple_motion_search(AV1_COMP *const cpi, MACROBLOCK *x, int mi_row,
                               int mi_col, BLOCK_SIZE bsize, int ref,
-                              MV ref_mv_full, int num_planes,
+                              FULLPEL_MV start_mv, int num_planes,
                               int use_subpixel) {
   assert(num_planes == 1 &&
          "Currently simple_motion_search only supports luma plane");
@@ -3181,9 +3202,8 @@
   const YV12_BUFFER_CONFIG *scaled_ref_frame =
       av1_get_scaled_ref_frame(cpi, ref);
   struct buf_2d backup_yv12;
-  // ref_mv is used to code the motion vector. ref_mv_full is the initial point.
-  // ref_mv is in units of 1/8 pel whereas ref_mv_full is in units of pel.
-  MV ref_mv = { 0, 0 };
+  // ref_mv is used to calculate the cost of the motion vector
+  const MV ref_mv = kZeroMv;
   const int step_param = cpi->mv_step_param;
   const MvLimits tmp_mv_limits = x->mv_limits;
   const SEARCH_METHODS search_methods = cpi->sf.mv_sf.search_method;
@@ -3205,9 +3225,9 @@
   // This overwrites the mv_limits so we will need to restore it later.
   av1_set_mv_search_range(&x->mv_limits, &ref_mv);
   var = av1_full_pixel_search(
-      cpi, x, bsize, &ref_mv_full, step_param, 1, search_methods,
-      do_mesh_search, sadpb, cond_cost_list(cpi, cost_list), &ref_mv, INT_MAX,
-      1, mi_col * MI_SIZE, mi_row * MI_SIZE, 0, &cpi->ss_cfg[SS_CFG_SRC], 0);
+      cpi, x, bsize, &start_mv, step_param, 1, search_methods, do_mesh_search,
+      sadpb, cond_cost_list(cpi, cost_list), &ref_mv, INT_MAX, 1,
+      mi_col * MI_SIZE, mi_row * MI_SIZE, 0, &cpi->ss_cfg[SS_CFG_SRC], 0);
   // Restore
   x->mv_limits = tmp_mv_limits;
 
@@ -3238,11 +3258,10 @@
   } else {
     // Manually convert from units of pixel to 1/8-pixels if we are not doing
     // subpel search
-    x->best_mv.as_mv.row *= 8;
-    x->best_mv.as_mv.col *= 8;
+    x->best_mv.as_mv = get_mv_from_fullmv(&x->best_mv.as_fullmv);
   }
 
-  mbmi->mv[0].as_mv = x->best_mv.as_mv;
+  mbmi->mv[0] = x->best_mv;
 
   // Get a copy of the prediction output
   av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
@@ -3257,13 +3276,13 @@
 
 void av1_simple_motion_sse_var(AV1_COMP *cpi, MACROBLOCK *x, int mi_row,
                                int mi_col, BLOCK_SIZE bsize,
-                               const MV ref_mv_full, int use_subpixel,
+                               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, ref_mv_full, 1,
+  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;
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index 7e95289..cdd92a7 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -20,6 +20,16 @@
 extern "C" {
 #endif
 
+// In this file, the following variables always have the same meaning:
+// start_mv: the motion vector where we start the motion search
+// ref_mv: the motion vector with respect to which we calculate the mv_cost
+// best_mv: when it is not const, it is the destination where to store the
+//   best motion vector
+// full_*: a prefix of full indicates that the mv is a FULLPEL_MV
+//
+// When a mv needs to both act as a fullpel_mv and subpel_mv, it is stored as an
+// int_mv, which is a union of int, FULLPEL_MV, and MV
+
 // The maximum number of steps in a step search given the largest
 // allowed initial step
 #define MAX_MVSEARCH_STEPS 11
@@ -39,7 +49,7 @@
 
 // motion search site
 typedef struct search_site {
-  MV mv;
+  FULLPEL_MV mv;
   int offset;
 } search_site;
 
@@ -62,20 +72,20 @@
 
 void av1_set_mv_search_range(MvLimits *mv_limits, const MV *mv);
 
-int av1_mv_bit_cost(const MV *mv, const MV *ref, const int *mvjcost,
+int av1_mv_bit_cost(const MV *mv, const MV *ref_mv, const int *mvjcost,
                     int *mvcost[2], int weight);
 
 // Utility to compute variance + MV rate cost for a given MV
-int av1_get_mvpred_var(const MACROBLOCK *x, const MV *best_mv,
-                       const MV *center_mv, const aom_variance_fn_ptr_t *vfp,
+int av1_get_mvpred_var(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
+                       const MV *ref_mv, const aom_variance_fn_ptr_t *vfp,
                        int use_var);
-int av1_get_mvpred_av_var(const MACROBLOCK *x, const MV *best_mv,
-                          const MV *center_mv, const uint8_t *second_pred,
+int av1_get_mvpred_av_var(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
+                          const MV *ref_mv, const uint8_t *second_pred,
                           const aom_variance_fn_ptr_t *vfp,
                           const struct buf_2d *src, const struct buf_2d *pre,
                           int use_mvcost);
-int av1_get_mvpred_mask_var(const MACROBLOCK *x, const MV *best_mv,
-                            const MV *center_mv, const uint8_t *second_pred,
+int av1_get_mvpred_mask_var(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
+                            const MV *ref_mv, const uint8_t *second_pred,
                             const uint8_t *mask, int mask_stride,
                             int invert_mask, const aom_variance_fn_ptr_t *vfp,
                             const struct buf_2d *src, const struct buf_2d *pre,
@@ -92,16 +102,10 @@
                                            const MV *ref_mv);
 
 // Runs sequence of diamond searches in smaller steps for RD.
-int av1_full_pixel_diamond(const struct AV1_COMP *cpi, MACROBLOCK *x,
-                           MV *mvp_full, int step_param, int sadpb,
-                           int further_steps, int do_refine, int *cost_list,
-                           const aom_variance_fn_ptr_t *fn_ptr,
-                           const MV *ref_mv, MV *dst_mv);
-
-int av1_hex_search(MACROBLOCK *x, MV *start_mv, int search_param,
+int av1_hex_search(MACROBLOCK *x, FULLPEL_MV *start_mv, int search_param,
                    int sad_per_bit, int do_init_search, int *cost_list,
                    const aom_variance_fn_ptr_t *vfp, int use_mvcost,
-                   const MV *center_mv);
+                   const MV *ref_mv);
 
 typedef int(fractional_mv_step_fp)(
     MACROBLOCK *x, const AV1_COMMON *const cm, int mi_row, int mi_col,
@@ -123,32 +127,33 @@
 int av1_refining_search_8p_c(MACROBLOCK *x, int error_per_bit, int search_range,
                              const aom_variance_fn_ptr_t *fn_ptr,
                              const uint8_t *mask, int mask_stride,
-                             int invert_mask, const MV *center_mv,
+                             int invert_mask, const MV *ref_mv,
                              const uint8_t *second_pred,
                              const struct buf_2d *src,
                              const struct buf_2d *pre);
 
 int av1_diamond_search_sad_c(MACROBLOCK *x, const search_site_config *cfg,
-                             MV *ref_mv, MV *best_mv, int search_param,
-                             int sad_per_bit, int *num00,
+                             FULLPEL_MV *start_mv, FULLPEL_MV *best_mv,
+                             int search_param, int sad_per_bit, int *num00,
                              const aom_variance_fn_ptr_t *fn_ptr,
-                             const MV *center_mv, uint8_t *second_pred,
+                             const MV *ref_mv, uint8_t *second_pred,
                              uint8_t *mask, int mask_stride, int inv_mask);
 
 int av1_full_pixel_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
-                          BLOCK_SIZE bsize, MV *mvp_full, int step_param,
-                          int use_var, int method, int run_mesh_search,
-                          int error_per_bit, int *cost_list, const MV *ref_mv,
-                          int var_max, int rd, int x_pos, int y_pos, int intra,
+                          BLOCK_SIZE bsize, FULLPEL_MV *start_mv,
+                          int step_param, int use_var, int method,
+                          int run_mesh_search, int error_per_bit,
+                          int *cost_list, const MV *ref_mv, int var_max, int rd,
+                          int x_pos, int y_pos, int intra,
                           const search_site_config *cfg,
                           int use_intrabc_mesh_pattern);
 
 int av1_obmc_full_pixel_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
-                               MV *mvp_full, int step_param, int sadpb,
+                               FULLPEL_MV *start_mv, int step_param, int sadpb,
                                int further_steps, int do_refine,
                                const aom_variance_fn_ptr_t *fn_ptr,
-                               const MV *ref_mv, MV *dst_mv, int is_second,
-                               const search_site_config *cfg);
+                               const MV *ref_mv, FULLPEL_MV *dst_mv,
+                               int is_second, const search_site_config *cfg);
 int av1_find_best_obmc_sub_pixel_tree_up(
     MACROBLOCK *x, const AV1_COMMON *const cm, int mi_row, int mi_col,
     MV *bestmv, const MV *ref_mv, int allow_hp, int error_per_bit,
@@ -169,12 +174,13 @@
 // 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,
-                              MV ref_mv_full, int num_planes, int use_subpixel);
+                              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 MV ref_mv_full, int use_subpixel,
+                               const FULLPEL_MV start_mv, int use_subpixel,
                                unsigned int *sse, unsigned int *var);
 
 static INLINE void av1_set_fractional_mv(int_mv *fractional_best_mv) {
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index 0063ac1..1c9008c 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -113,14 +113,11 @@
   // after full-pixel motion search.
   av1_set_mv_search_range(&x->mv_limits, &ref_mv);
 
-  MV mvp_full;
+  FULLPEL_MV start_mv;
   if (mbmi->motion_mode != SIMPLE_TRANSLATION)
-    mvp_full = mbmi->mv[0].as_mv;
+    start_mv = get_fullmv_from_mv(&mbmi->mv[0].as_mv);
   else
-    mvp_full = ref_mv;
-
-  mvp_full.col >>= 3;
-  mvp_full.row >>= 3;
+    start_mv = get_fullmv_from_mv(&ref_mv);
 
   const int sadpb = x->sadperbit16;
   int cost_list[5];
@@ -128,16 +125,16 @@
   switch (mbmi->motion_mode) {
     case SIMPLE_TRANSLATION:
       bestsme = av1_full_pixel_search(
-          cpi, x, bsize, &mvp_full, step_param, 1, cpi->sf.mv_sf.search_method,
+          cpi, x, bsize, &start_mv, step_param, 1, cpi->sf.mv_sf.search_method,
           0, sadpb, cond_cost_list(cpi, cost_list), &ref_mv, INT_MAX, 1,
           (MI_SIZE * mi_col), (MI_SIZE * mi_row), 0, &cpi->ss_cfg[SS_CFG_SRC],
           0);
       break;
     case OBMC_CAUSAL:
       bestsme = av1_obmc_full_pixel_search(
-          cpi, x, &mvp_full, step_param, sadpb,
+          cpi, x, &start_mv, step_param, sadpb,
           MAX_MVSEARCH_STEPS - 1 - step_param, 1, &cpi->fn_ptr[bsize], &ref_mv,
-          &(x->best_mv.as_mv), 0, &cpi->ss_cfg[SS_CFG_SRC]);
+          &(x->best_mv.as_fullmv), 0, &cpi->ss_cfg[SS_CFG_SRC]);
       break;
     default: assert(0 && "Invalid motion mode!\n");
   }
@@ -270,8 +267,8 @@
   // 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;
 
-  MV *const best_mv = &x->best_mv.as_mv;
   const int search_range = SEARCH_RANGE_8P;
   const int sadpb = x->sadperbit16;
   // Allow joint search multiple times iteratively for each reference frame
@@ -342,10 +339,7 @@
     av1_set_mv_search_range(&x->mv_limits, &ref_mv[id].as_mv);
 
     // Use the mv result from the single mode as mv predictor.
-    *best_mv = cur_mv[id].as_mv;
-
-    best_mv->col >>= 3;
-    best_mv->row >>= 3;
+    best_int_mv->as_fullmv = get_fullmv_from_mv(&cur_mv[id].as_mv);
 
     // Small-range full-pixel motion search.
     bestsme = av1_refining_search_8p_c(
@@ -353,13 +347,14 @@
         &ref_mv[id].as_mv, second_pred, &x->plane[0].src, &ref_yv12[id]);
     if (bestsme < INT_MAX) {
       if (mask)
-        bestsme = av1_get_mvpred_mask_var(
-            x, best_mv, &ref_mv[id].as_mv, second_pred, mask, mask_stride, id,
-            &cpi->fn_ptr[bsize], &x->plane[0].src, &ref_yv12[id], 1);
+        bestsme = av1_get_mvpred_mask_var(x, &best_int_mv->as_fullmv,
+                                          &ref_mv[id].as_mv, second_pred, mask,
+                                          mask_stride, id, &cpi->fn_ptr[bsize],
+                                          &x->plane[0].src, &ref_yv12[id], 1);
       else
-        bestsme = av1_get_mvpred_av_var(x, best_mv, &ref_mv[id].as_mv,
-                                        second_pred, &cpi->fn_ptr[bsize],
-                                        &x->plane[0].src, &ref_yv12[id], 1);
+        bestsme = av1_get_mvpred_av_var(
+            x, &best_int_mv->as_fullmv, &ref_mv[id].as_mv, second_pred,
+            &cpi->fn_ptr[bsize], &x->plane[0].src, &ref_yv12[id], 1);
     }
 
     x->mv_limits = tmp_mv_limits;
@@ -382,8 +377,7 @@
     if (id) xd->plane[plane].pre[0] = ref_yv12[id];
 
     if (cpi->common.cur_frame_force_integer_mv) {
-      x->best_mv.as_mv.row *= 8;
-      x->best_mv.as_mv.col *= 8;
+      best_int_mv->as_mv = get_mv_from_fullmv(&best_int_mv->as_fullmv);
     }
     if (bestsme < INT_MAX && cpi->common.cur_frame_force_integer_mv == 0) {
       int dis; /* TODO: use dis in distortion calculation later. */
@@ -399,7 +393,7 @@
     // 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].as_mv = *best_mv;
+      cur_mv[id] = *best_int_mv;
       last_besterr[id] = bestsme;
     } else {
       break;
@@ -464,7 +458,7 @@
 
   int bestsme = INT_MAX;
   int sadpb = x->sadperbit16;
-  MV *const best_mv = &x->best_mv.as_mv;
+  int_mv *best_int_mv = &x->best_mv;
   int search_range = SEARCH_RANGE_8P;
 
   MvLimits tmp_mv_limits = x->mv_limits;
@@ -473,10 +467,7 @@
   av1_set_mv_search_range(&x->mv_limits, &ref_mv.as_mv);
 
   // Use the mv result from the single mode as mv predictor.
-  *best_mv = *this_mv;
-
-  best_mv->col >>= 3;
-  best_mv->row >>= 3;
+  best_int_mv->as_fullmv = get_fullmv_from_mv(this_mv);
 
   // Small-range full-pixel motion search.
   bestsme = av1_refining_search_8p_c(
@@ -485,12 +476,13 @@
   if (bestsme < INT_MAX) {
     if (mask)
       bestsme = av1_get_mvpred_mask_var(
-          x, best_mv, &ref_mv.as_mv, second_pred, mask, mask_stride, ref_idx,
-          &cpi->fn_ptr[bsize], &x->plane[0].src, &ref_yv12, 1);
+          x, &best_int_mv->as_fullmv, &ref_mv.as_mv, second_pred, mask,
+          mask_stride, ref_idx, &cpi->fn_ptr[bsize], &x->plane[0].src,
+          &ref_yv12, 1);
     else
-      bestsme = av1_get_mvpred_av_var(x, best_mv, &ref_mv.as_mv, second_pred,
-                                      &cpi->fn_ptr[bsize], &x->plane[0].src,
-                                      &ref_yv12, 1);
+      bestsme = av1_get_mvpred_av_var(x, &best_int_mv->as_fullmv, &ref_mv.as_mv,
+                                      second_pred, &cpi->fn_ptr[bsize],
+                                      &x->plane[0].src, &ref_yv12, 1);
   }
 
   x->mv_limits = tmp_mv_limits;
@@ -503,8 +495,7 @@
   }
 
   if (cpi->common.cur_frame_force_integer_mv) {
-    x->best_mv.as_mv.row *= 8;
-    x->best_mv.as_mv.col *= 8;
+    best_int_mv->as_mv = get_mv_from_fullmv(&best_int_mv->as_fullmv);
   }
   const int use_fractional_mv =
       bestsme < INT_MAX && cpi->common.cur_frame_force_integer_mv == 0;
@@ -525,7 +516,7 @@
   // Restore the pointer to the first unscaled prediction buffer.
   if (ref_idx) pd->pre[0] = orig_yv12;
 
-  if (bestsme < INT_MAX) *this_mv = *best_mv;
+  if (bestsme < INT_MAX) *this_mv = best_int_mv->as_mv;
 
   *rate_mv = 0;
 
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 11f3132..750d285 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -121,7 +121,7 @@
   struct buf_2d backup_yv12[MAX_MB_PLANE] = { { 0, 0, 0, 0, 0 } };
   int step_param = cpi->mv_step_param;
   const int sadpb = x->sadperbit16;
-  MV mvp_full;
+  FULLPEL_MV start_mv;
   const int ref = mi->ref_frame[0];
   const MV ref_mv = av1_get_ref_mv(x, mi->ref_mv_idx).as_mv;
   MV center_mv;
@@ -144,10 +144,7 @@
   }
   av1_set_mv_search_range(&x->mv_limits, &ref_mv);
 
-  mvp_full = ref_mv;
-
-  mvp_full.col >>= 3;
-  mvp_full.row >>= 3;
+  start_mv = get_fullmv_from_mv(&ref_mv);
 
   if (!use_base_mv)
     center_mv = ref_mv;
@@ -155,13 +152,14 @@
     center_mv = tmp_mv->as_mv;
 
   av1_full_pixel_search(
-      cpi, x, bsize, &mvp_full, step_param, 1, cpi->sf.mv_sf.search_method, 0,
+      cpi, x, bsize, &start_mv, step_param, 1, cpi->sf.mv_sf.search_method, 0,
       sadpb, cond_cost_list(cpi, cost_list), &center_mv, INT_MAX, 0,
       (MI_SIZE * mi_col), (MI_SIZE * mi_row), 0, &cpi->ss_cfg[SS_CFG_SRC], 0);
 
   x->mv_limits = tmp_mv_limits;
   *tmp_mv = x->best_mv;
   // calculate the bit cost on motion vector
+  MV mvp_full;
   mvp_full.row = tmp_mv->as_mv.row * 8;
   mvp_full.col = tmp_mv->as_mv.col * 8;
 
diff --git a/av1/encoder/partition_strategy.c b/av1/encoder/partition_strategy.c
index 8d91210..8832944 100644
--- a/av1/encoder/partition_strategy.c
+++ b/av1/encoder/partition_strategy.c
@@ -326,7 +326,6 @@
   // Otherwise do loop through the reference frames and find the one with the
   // minimum SSE
   const MACROBLOCKD *xd = &x->e_mbd;
-  const MV *mv_ref_fulls = pc_tree->mv_ref_fulls;
 
   const int num_planes = 1;
 
@@ -336,9 +335,10 @@
     const int ref = refs[ref_idx];
 
     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,
-                               mv_ref_fulls[ref], num_planes, use_subpixel);
+                               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);
@@ -349,18 +349,14 @@
       }
 
       if (save_mv) {
-        const int new_mv_row = x->best_mv.as_mv.row / 8;
-        const int new_mv_col = x->best_mv.as_mv.col / 8;
-
-        pc_tree->mv_ref_fulls[ref].row = new_mv_row;
-        pc_tree->mv_ref_fulls[ref].col = new_mv_col;
+        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;
 
         if (bsize >= BLOCK_8X8) {
           for (int r_idx = 0; r_idx < 4; r_idx++) {
             // Propagate the new motion vectors to a lower level
             PC_TREE *sub_tree = pc_tree->split[r_idx];
-            sub_tree->mv_ref_fulls[ref].row = new_mv_row;
-            sub_tree->mv_ref_fulls[ref].col = new_mv_col;
+            sub_tree->start_mvs[ref] = pc_tree->start_mvs[ref];
           }
         }
       }
@@ -663,10 +659,10 @@
       const int this_mi_col = mi_col + (mb_col << mb_in_mi_size_wide_log2);
       unsigned int sse = 0;
       unsigned int var = 0;
-      const MV ref_mv_full = { .row = 0, .col = 0 };
+      const FULLPEL_MV start_mv = kZeroFullMv;
 
       av1_simple_motion_sse_var(cpi, x, this_mi_row, this_mi_col, mb_size,
-                                ref_mv_full, 0, &sse, &var);
+                                start_mv, 0, &sse, &var);
 
       aom_clear_system_state();
       const float mv_row = (float)(x->best_mv.as_mv.row / 8);
diff --git a/av1/encoder/partition_strategy.h b/av1/encoder/partition_strategy.h
index 3b6c50a..ee1d475 100644
--- a/av1/encoder/partition_strategy.h
+++ b/av1/encoder/partition_strategy.h
@@ -173,7 +173,7 @@
 }
 
 static INLINE void init_simple_motion_search_mvs(PC_TREE *pc_tree) {
-  av1_zero(pc_tree->mv_ref_fulls);
+  av1_zero(pc_tree->start_mvs);
 
   av1_zero(pc_tree->sms_none_feat);
   av1_zero(pc_tree->sms_rect_feat);
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index fcf40eb..33553b5 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -2492,21 +2492,19 @@
     }
 
     int step_param = cpi->mv_step_param;
-    MV mvp_full = dv_ref.as_mv;
-    mvp_full.col >>= 3;
-    mvp_full.row >>= 3;
+    FULLPEL_MV start_mv = get_fullmv_from_mv(&dv_ref.as_mv);
     const int sadpb = x->sadperbit16;
     int cost_list[5];
     const int bestsme = av1_full_pixel_search(
-        cpi, x, bsize, &mvp_full, step_param, 1, cpi->sf.mv_sf.search_method, 0,
+        cpi, x, bsize, &start_mv, step_param, 1, cpi->sf.mv_sf.search_method, 0,
         sadpb, cond_cost_list(cpi, cost_list), &dv_ref.as_mv, INT_MAX, 1,
         (MI_SIZE * mi_col), (MI_SIZE * mi_row), 1,
         &cpi->ss_cfg[SS_CFG_LOOKAHEAD], 1);
 
     x->mv_limits = tmp_mv_limits;
     if (bestsme == INT_MAX) continue;
-    mvp_full = x->best_mv.as_mv;
-    const MV dv = { .row = mvp_full.row * 8, .col = mvp_full.col * 8 };
+    const MV dv = { .row = x->best_mv.as_mv.row * 8,
+                    .col = x->best_mv.as_mv.col * 8 };
     if (mv_check_bounds(&x->mv_limits, &dv)) continue;
     if (!av1_is_dv_valid(dv, cm, xd, mi_row, mi_col, bsize,
                          cm->seq_params.mib_size_log2))
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index 970c6a5..c44c426 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -37,10 +37,6 @@
 
 // NOTE: All `tf` in this file means `temporal filtering`.
 
-// Motion search supports 1/8 precision for sub-pixel.
-#define GET_MV_SUBPEL(x) ((x) << 3)
-#define GET_MV_RAWPEL(x) ((x) >> 3)
-
 // Does motion search for blocks in temporal filtering. This is the first step
 // for temporal filtering. More specifically, given a frame to be filtered and
 // another frame as reference, this function searches the reference frame to
@@ -104,7 +100,7 @@
           : (min_frame_size >= 480 ? MV_COST_L1_MIDRES : MV_COST_L1_LOWRES);
 
   // Starting position for motion search.
-  MV start_mv = { GET_MV_RAWPEL(ref_mv->row), GET_MV_RAWPEL(ref_mv->col) };
+  FULLPEL_MV start_mv = get_fullmv_from_mv(ref_mv);
   // Baseline position for motion search (used for rate distortion comparison).
   const MV baseline_mv = kZeroMv;
 
@@ -153,8 +149,8 @@
     const BLOCK_SIZE subblock_size = ss_size_lookup[block_size][1][1];
     const int subblock_height = block_size_high[subblock_size];
     const int subblock_width = block_size_wide[subblock_size];
-    start_mv.row = GET_MV_RAWPEL(ref_mv->row);
-    start_mv.col = GET_MV_RAWPEL(ref_mv->col);
+    start_mv = get_fullmv_from_mv(ref_mv);
+
     int subblock_idx = 0;
     for (int i = 0; i < mb_height; i += subblock_height) {
       for (int j = 0; j < mb_width; j += subblock_width) {
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c
index 49d7d3b..2d656b1 100644
--- a/av1/encoder/tpl_model.c
+++ b/av1/encoder/tpl_model.c
@@ -135,10 +135,7 @@
   uint32_t sse;
   int cost_list[5];
   const MvLimits tmp_mv_limits = x->mv_limits;
-  MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
-
-  best_ref_mv1_full.col = center_mv.col >> 3;
-  best_ref_mv1_full.row = center_mv.row >> 3;
+  FULLPEL_MV start_mv = get_fullmv_from_mv(&center_mv);
 
   // Setup frame pointers
   x->plane[0].src.buf = cur_frame_buf;
@@ -156,10 +153,10 @@
 
   assert(ss_cfg->stride == stride_ref);
 
-  av1_full_pixel_search(cpi, x, bsize, &best_ref_mv1_full, step_param, 1,
-                        search_method, 0, sadpb, cond_cost_list(cpi, cost_list),
-                        &center_mv, INT_MAX, 0, (MI_SIZE * mi_col),
-                        (MI_SIZE * mi_row), 0, ss_cfg, 0);
+  av1_full_pixel_search(cpi, x, bsize, &start_mv, step_param, 1, search_method,
+                        0, sadpb, cond_cost_list(cpi, cost_list), &center_mv,
+                        INT_MAX, 0, (MI_SIZE * mi_col), (MI_SIZE * mi_row), 0,
+                        ss_cfg, 0);
 
   /* restore UMV window */
   x->mv_limits = tmp_mv_limits;