]> granicus.if.org Git - libvpx/commitdiff
Changed mv ref to nearestmv always for sub8x8
authorZoe Liu <zoeliu@google.com>
Mon, 9 Feb 2015 23:54:56 +0000 (15:54 -0800)
committerZoe Liu <zoeliu@google.com>
Thu, 5 Mar 2015 19:09:58 +0000 (11:09 -0800)
For all sub8x8 partition, the mv ref has changed to its own nearest_mv
instead of the nearest_mv of the super 8x8 block:

--enable-newmvref-sub8x8: ~0.1% gain for derflr

Besides the above new experiment, code has been cleaned largely for the
sub8x8 motion search, such that the mv ref can be fairly easily changed to
use other options, e.g., the next step's global motion effort.

Change-Id: I8e3f4aaa8553ba8c445369692e079db5ce282593

configure
vp9/common/vp9_blockd.h
vp9/common/vp9_mvref_common.c
vp9/common/vp9_mvref_common.h
vp9/decoder/vp9_decodemv.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodemv.c
vp9/encoder/vp9_rdopt.c

index 52869b6100b2de1b2126bd4e741b4b58a2727c64..3323b3229e512291047199c9ff4b20e1c54f6ca8 100755 (executable)
--- a/configure
+++ b/configure
@@ -293,6 +293,7 @@ EXPERIMENT_LIST="
     compound_modes
     global_motion
     palette
+    newmvref_sub8x8
 "
 CONFIG_LIST="
     external_build
index 237b0f32ad4032306fb2050230bb32857cef4266..3be6ec3db3f6a9d65a4c951a8dd9f0729805427d 100644 (file)
@@ -155,6 +155,9 @@ static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) {
 typedef struct {
   PREDICTION_MODE as_mode;
   int_mv as_mv[2];  // first, second inter predictor motion vectors
+#if CONFIG_NEWMVREF_SUB8X8
+  int_mv ref_mv[2];
+#endif  // CONFIG_NEWMVREF_SUB8X8
 } b_mode_info;
 
 // Note that the rate-distortion optimization loop, bit-stream writer, and
index d18a6e13faed55c428ac0a83ec3434feb7f6e4cf..c0303fcfc58faa4b5f2ba1e288eb7f6fc9b7dba1 100644 (file)
@@ -26,7 +26,9 @@ static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
   const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
   const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
   int different_ref_found = 0;
+#if !CONFIG_NEWMVREF_SUB8X8
   int context_counter = 0;
+#endif  // CONFIG_NEWMVREF_SUB8X8
 
   // Blank the reference vector list
   vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
@@ -41,13 +43,16 @@ static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
                                                    xd->mi_stride].src_mi;
       const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
       // Keep counts for entropy encoding.
+#if !CONFIG_NEWMVREF_SUB8X8
       context_counter += mode_2_counter[candidate->mode];
+#endif  // CONFIG_NEWMVREF_SUB8X8
       different_ref_found = 1;
 
-      if (candidate->ref_frame[0] == ref_frame)
+      if (candidate->ref_frame[0] == ref_frame) {
         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block));
-      else if (candidate->ref_frame[1] == ref_frame)
+      } else if (candidate->ref_frame[1] == ref_frame) {
         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block));
+      }
     }
   }
 
@@ -98,39 +103,77 @@ static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
 
  Done:
 
+#if !CONFIG_NEWMVREF_SUB8X8
   mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
+#endif  // CONFIG_NEWMVREF_SUB8X8
 
   // Clamp vectors
   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
     clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
 }
 
+#if CONFIG_NEWMVREF_SUB8X8
+// This function keeps a mode count for a given MB/SB
+void vp9_update_mv_context(const VP9_COMMON *cm, const MACROBLOCKD *xd,
+                           const TileInfo *const tile,
+                           MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
+                           int_mv *mv_ref_list,
+                           int block, int mi_row, int mi_col) {
+  int i, refmv_count = 0;
+  const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
+  int context_counter = 0;
+
+  // Blank the reference vector list
+  vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
+
+  // The nearest 2 blocks are examined only.
+  // If the size < 8x8, we get the mv from the bmi substructure;
+  for (i = 0; i < 2; ++i) {
+    const POSITION *const mv_ref = &mv_ref_search[i];
+    if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
+      const MODE_INFO *const candidate_mi =
+          xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride].src_mi;
+      const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
+
+      // Keep counts for entropy encoding.
+      context_counter += mode_2_counter[candidate->mode];
+
+      if (candidate->ref_frame[0] == ref_frame) {
+        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block));
+      } else if (candidate->ref_frame[1] == ref_frame) {
+        ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block));
+      }
+    }
+  }
+
+ Done:
+
+  mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
+}
+#endif  // CONFIG_NEWMVREF_SUB8X8
+
 void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
                       const TileInfo *const tile,
                       MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
                       int_mv *mv_ref_list,
                       int mi_row, int mi_col) {
+#if CONFIG_NEWMVREF_SUB8X8
+  vp9_update_mv_context(cm, xd, tile, mi, ref_frame, mv_ref_list, -1,
+                        mi_row, mi_col);
+#endif  // CONFIG_NEWMVREF_SUB8X8
   find_mv_refs_idx(cm, xd, tile, mi, ref_frame, mv_ref_list, -1,
                    mi_row, mi_col);
 }
 
-static void lower_mv_precision(MV *mv, int allow_hp) {
-  const int use_hp = allow_hp && vp9_use_mv_hp(mv);
-  if (!use_hp) {
-    if (mv->row & 1)
-      mv->row += (mv->row > 0 ? -1 : 1);
-    if (mv->col & 1)
-      mv->col += (mv->col > 0 ? -1 : 1);
-  }
-}
-
 void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
                            int_mv *mvlist, int_mv *nearest, int_mv *near) {
   int i;
   // Make sure all the candidates are properly clamped etc
   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
-    lower_mv_precision(&mvlist[i].as_mv, allow_hp);
-    clamp_mv2(&mvlist[i].as_mv, xd);
+    MV *mv = &mvlist[i].as_mv;
+    const int usehp = allow_hp && vp9_use_mv_hp(mv);
+    vp9_lower_mv_precision(mv, usehp);
+    clamp_mv2(mv, xd);
   }
   *nearest = mvlist[0];
   *near = mvlist[1];
@@ -139,8 +182,13 @@ void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
                                    const TileInfo *const tile,
                                    int block, int ref, int mi_row, int mi_col,
+#if CONFIG_NEWMVREF_SUB8X8
+                                   int_mv *mv_list,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                                    int_mv *nearest, int_mv *near) {
+#if !CONFIG_NEWMVREF_SUB8X8
   int_mv mv_list[MAX_MV_REF_CANDIDATES];
+#endif  // CONFIG_NEWMVREF_SUB8X8
   MODE_INFO *const mi = xd->mi[0].src_mi;
   b_mode_info *bmi = mi->bmi;
   int n;
index d8b17018ad3d8b8bee1df92a48da786689739ef4..24bfefdb4eb0edf8335c03b3a668261a7a11abfd 100644 (file)
@@ -215,11 +215,29 @@ static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
                xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
 }
 
+#if CONFIG_NEWMVREF_SUB8X8
+// This function keeps a mode count for a given MB/SB
+void vp9_update_mv_context(const VP9_COMMON *cm, const MACROBLOCKD *xd,
+                           const TileInfo *const tile,
+                           MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
+                           int_mv *mv_ref_list,
+                           int block, int mi_row, int mi_col);
+#endif  // CONFIG_NEWMVREF_SUB8X8
+
 void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
                       const TileInfo *const tile,
                       MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
                       int_mv *mv_ref_list, int mi_row, int mi_col);
 
+static INLINE void vp9_lower_mv_precision(MV *mv, const int usehp) {
+  if (!usehp) {
+    if (mv->row & 1)
+      mv->row += (mv->row > 0 ? -1 : 1);
+    if (mv->col & 1)
+      mv->col += (mv->col > 0 ? -1 : 1);
+  }
+}
+
 // check a list of motion vectors by sad score using a number rows of pixels
 // above and a number cols of pixels in the left to select the one with best
 // score to use as ref motion vector
@@ -229,6 +247,9 @@ void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
                                    const TileInfo *const tile,
                                    int block, int ref, int mi_row, int mi_col,
+#if CONFIG_NEWMVREF_SUB8X8
+                                   int_mv *mv_list,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                                    int_mv *nearest, int_mv *near);
 
 #if CONFIG_COPY_MODE
index 3d5a4decd185acfd1ad1b37e2b366f831404ff5d..1d3aaf3e7316e0346ad1ed2c00b18fecc5c52ea2 100644 (file)
@@ -838,7 +838,7 @@ static INLINE int assign_mv(VP9_COMMON *cm, PREDICTION_MODE mode,
       mv[1].as_int = 0;
       break;
     }
-#endif
+#endif  // CONFIG_COMPOUND_MODES
     default: {
       return 0;
     }
@@ -982,6 +982,9 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
     int idx, idy;
     PREDICTION_MODE b_mode;
     int_mv nearest_sub8x8[2], near_sub8x8[2];
+#if CONFIG_NEWMVREF_SUB8X8
+    int_mv ref_mv[2];
+#endif  // CONFIG_NEWMVREF_SUB8X8
     for (idy = 0; idy < 2; idy += num_4x4_h) {
       for (idx = 0; idx < 2; idx += num_4x4_w) {
         int_mv block[2];
@@ -997,19 +1000,59 @@ static void read_inter_block_mode_info(VP9_COMMON *const cm,
 #endif
 #if CONFIG_COMPOUND_MODES
         if (b_mode == NEARESTMV || b_mode == NEARMV ||
+#if CONFIG_NEWMVREF_SUB8X8
+            b_mode == NEWMV || b_mode == NEW_NEWMV ||
+#endif  // CONFIG_NEWMVREF_SUB8X8
             b_mode == NEAREST_NEARESTMV || b_mode == NEAREST_NEARMV ||
             b_mode == NEAR_NEARESTMV || b_mode == NEAREST_NEWMV ||
             b_mode == NEW_NEARESTMV || b_mode == NEAR_NEWMV ||
             b_mode == NEW_NEARMV)
 #else
-        if (b_mode == NEARESTMV || b_mode == NEARMV)
-#endif
-          for (ref = 0; ref < 1 + is_compound; ++ref)
+        if (b_mode == NEARESTMV || b_mode == NEARMV
+#if CONFIG_NEWMVREF_SUB8X8
+            || b_mode == NEWMV
+#endif  // CONFIG_NEWMVREF_SUB8X8
+            )
+#endif  // CONFIG_COMPOUND_MODES
+        {
+          for (ref = 0; ref < 1 + is_compound; ++ref) {
+#if CONFIG_NEWMVREF_SUB8X8
+            int_mv mv_ref_list[MAX_MV_REF_CANDIDATES];
+            int_mv second_ref_mv;
+            vp9_update_mv_context(cm, xd, tile, mi, mbmi->ref_frame[ref],
+                                  mv_ref_list, j, mi_row, mi_col);
+#endif  // CONFIG_NEWMVREF_SUB8X8
             vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col,
+#if CONFIG_NEWMVREF_SUB8X8
+                                          mv_ref_list,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                                           &nearest_sub8x8[ref],
                                           &near_sub8x8[ref]);
+#if CONFIG_NEWMVREF_SUB8X8
+            if (b_mode == NEWMV
+#if CONFIG_COMPOUND_MODES
+                || b_mode == NEW_NEWMV ||
+                b_mode == NEAREST_NEWMV ||
+                b_mode == NEW_NEARESTMV ||
+                b_mode == NEAR_NEWMV ||
+                b_mode == NEW_NEARMV
+#endif  // CONFIG_COMPOUND_MODES
+                ) {
+              mv_ref_list[0].as_int = nearest_sub8x8[ref].as_int;
+              mv_ref_list[1].as_int = near_sub8x8[ref].as_int;
+              vp9_find_best_ref_mvs(xd, allow_hp, mv_ref_list,
+                                    &ref_mv[ref], &second_ref_mv);
+            }
+#endif  // CONFIG_NEWMVREF_SUB8X8
+          }
+        }
 
-        if (!assign_mv(cm, b_mode, block, nearestmv,
+        if (!assign_mv(cm, b_mode, block,
+#if CONFIG_NEWMVREF_SUB8X8
+                       ref_mv,
+#else
+                       nearestmv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                        nearest_sub8x8, near_sub8x8,
                        is_compound, allow_hp, r)) {
           xd->corrupted |= 1;
index 26cb065e9518d36f403ba0eb7594ffa8a624f94c..0e3c1dba44df325db6ab7853be86ecac23c69f40 100644 (file)
@@ -646,22 +646,35 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
 #else
           if (b_mode == NEWMV) {
 #endif
-            for (ref = 0; ref < 1 + is_compound; ++ref)
+            for (ref = 0; ref < 1 + is_compound; ++ref) {
               vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv,
+#if CONFIG_NEWMVREF_SUB8X8
+                            &mi->bmi[j].ref_mv[ref].as_mv,
+#else
                             &mbmi->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                             nmvc, allow_hp);
+            }
           }
 #if CONFIG_COMPOUND_MODES
           else if (b_mode == NEAREST_NEWMV || b_mode == NEAR_NEWMV) {
             vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[1].as_mv,
+#if CONFIG_NEWMVREF_SUB8X8
+                          &mi->bmi[j].ref_mv[1].as_mv,
+#else
                           &mbmi->ref_mvs[mbmi->ref_frame[1]][0].as_mv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                           nmvc, allow_hp);
           } else if (b_mode == NEW_NEARESTMV || b_mode == NEW_NEARMV) {
             vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[0].as_mv,
+#if CONFIG_NEWMVREF_SUB8X8
+                          &mi->bmi[j].ref_mv[0].as_mv,
+#else
                           &mbmi->ref_mvs[mbmi->ref_frame[0]][0].as_mv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                           nmvc, allow_hp);
           }
-#endif
+#endif  // CONFIG_COMPOUND_MODES
         }
       }
     } else {
index 2a7f243b7a0948e3c0fb78e7df2d429c8211cd44..28a9122f4db4f5bb9f34eda239fe8971dff375b2 100644 (file)
@@ -229,26 +229,24 @@ void vp9_build_nmv_cost_table(int *mvjoint, int *mvcost[2],
   build_nmv_component_cost_table(mvcost[1], &ctx->comps[1], usehp);
 }
 
-static void inc_mvs(const MB_MODE_INFO *mbmi, const int_mv mvs[2],
-                    nmv_context_counts *counts) {
+static void inc_mvs(const MB_MODE_INFO *mbmi, const int_mv mv[2],
+                    const int_mv ref_mv[2], nmv_context_counts *counts) {
   int i;
 
   for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
-    const MV *ref = &mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_mv;
-    const MV diff = {mvs[i].as_mv.row - ref->row,
-                     mvs[i].as_mv.col - ref->col};
+    const MV diff = {mv[i].as_mv.row - ref_mv[i].as_mv.row,
+                     mv[i].as_mv.col - ref_mv[i].as_mv.col};
     vp9_inc_mv(&diff, counts);
   }
 }
 
 #if CONFIG_COMPOUND_MODES
-static void inc_compound_single_mv(const MB_MODE_INFO *mbmi,
-                                   int ref_idx,
-                                   const int_mv mvs[2],
+static void inc_compound_single_mv(int ref_idx,
+                                   const int_mv mv[2],
+                                   const int_mv ref_mv[2],
                                    nmv_context_counts *counts) {
-  const MV *ref = &mbmi->ref_mvs[mbmi->ref_frame[ref_idx]][0].as_mv;
-  const MV diff = {mvs[ref_idx].as_mv.row - ref->row,
-                   mvs[ref_idx].as_mv.col - ref->col};
+  const MV diff = {mv[ref_idx].as_mv.row - ref_mv[ref_idx].as_mv.row,
+                   mv[ref_idx].as_mv.col - ref_mv[ref_idx].as_mv.col};
   vp9_inc_mv(&diff, counts);
 }
 #endif
@@ -256,6 +254,11 @@ static void inc_compound_single_mv(const MB_MODE_INFO *mbmi,
 void vp9_update_mv_count(VP9_COMMON *cm, const MACROBLOCKD *xd) {
   const MODE_INFO *mi = xd->mi[0].src_mi;
   const MB_MODE_INFO *const mbmi = &mi->mbmi;
+  int i;
+  int_mv ref_mv[2];
+
+  for (i = 0; i < 1 + has_second_ref(mbmi); ++i)
+    ref_mv[i].as_int = mbmi->ref_mvs[mbmi->ref_frame[i]][0].as_int;
 
   if (mbmi->sb_type < BLOCK_8X8) {
     const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type];
@@ -270,14 +273,32 @@ void vp9_update_mv_count(VP9_COMMON *cm, const MACROBLOCKD *xd) {
 #else
         if (mi->bmi[i].as_mode == NEWMV)
 #endif
-          inc_mvs(mbmi, mi->bmi[i].as_mv, &cm->counts.mv);
+          inc_mvs(mbmi, mi->bmi[i].as_mv,
+#if CONFIG_NEWMVREF_SUB8X8
+                  mi->bmi[i].ref_mv,
+#else
+                  ref_mv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
+                  &cm->counts.mv);
 #if CONFIG_COMPOUND_MODES
         else if (mi->bmi[i].as_mode == NEAREST_NEWMV ||
                  mi->bmi[i].as_mode == NEAR_NEWMV)
-          inc_compound_single_mv(mbmi, 1, mi->bmi[i].as_mv, &cm->counts.mv);
+          inc_compound_single_mv(1, mi->bmi[i].as_mv,
+#if CONFIG_NEWMVREF_SUB8X8
+                                 mi->bmi[i].ref_mv,
+#else
+                                 ref_mv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
+                                 &cm->counts.mv);
         else if (mi->bmi[i].as_mode == NEW_NEARESTMV ||
                  mi->bmi[i].as_mode == NEW_NEARMV)
-          inc_compound_single_mv(mbmi, 0, mi->bmi[i].as_mv, &cm->counts.mv);
+          inc_compound_single_mv(0, mi->bmi[i].as_mv,
+#if CONFIG_NEWMVREF_SUB8X8
+                                 mi->bmi[i].ref_mv,
+#else
+                                 ref_mv,
+#endif  // CONFIG_NEWMVREF_SUB8X8
+                                 &cm->counts.mv);
 #endif
       }
     }
@@ -287,12 +308,12 @@ void vp9_update_mv_count(VP9_COMMON *cm, const MACROBLOCKD *xd) {
 #else
     if (mbmi->mode == NEWMV)
 #endif
-      inc_mvs(mbmi, mbmi->mv, &cm->counts.mv);
+      inc_mvs(mbmi, mbmi->mv, ref_mv, &cm->counts.mv);
 #if CONFIG_COMPOUND_MODES
     else if (mbmi->mode == NEAREST_NEWMV || mbmi->mode == NEAR_NEWMV)
-      inc_compound_single_mv(mbmi, 1, mbmi->mv, &cm->counts.mv);
+      inc_compound_single_mv(1, mbmi->mv, ref_mv, &cm->counts.mv);
     else if (mbmi->mode == NEW_NEARESTMV || mbmi->mode == NEW_NEARMV)
-      inc_compound_single_mv(mbmi, 0, mbmi->mv, &cm->counts.mv);
+      inc_compound_single_mv(0, mbmi->mv, ref_mv, &cm->counts.mv);
 #endif
   }
 }
index ea60bd421983357f69855a35ca88baf126c1ff66..a3fc30170ab335d20633b837b22f9092dd6c85a0 100644 (file)
@@ -1998,6 +1998,7 @@ static int cost_mv_ref(const VP9_COMP *cpi, PREDICTION_MODE mode,
 static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
                                 BLOCK_SIZE bsize,
                                 int_mv *frame_mv,
+                                int_mv *ref_mv,
                                 int mi_row, int mi_col,
                                 int_mv single_newmv[MAX_REF_FRAMES],
                                 int *rate_mv);
@@ -2010,6 +2011,9 @@ static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i,
                                 int *mvcost[2]) {
   MODE_INFO *const mic = xd->mi[0].src_mi;
   const MB_MODE_INFO *const mbmi = &mic->mbmi;
+#if CONFIG_NEWMVREF_SUB8X8
+  int usehp = cpi->common.allow_high_precision_mv;
+#endif  // CONFIG_NEWMVREF_SUB8X8
   int thismvcost = 0;
   int idx, idy;
   const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type];
@@ -2062,6 +2066,11 @@ static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i,
     case NEW_NEARMV:
     case NEW_NEARESTMV:
       this_mv[0].as_int = seg_mvs[mbmi->ref_frame[0]].as_int;
+#if CONFIG_NEWMVREF_SUB8X8
+      usehp = usehp && vp9_use_mv_hp(&best_ref_mv[0]->as_mv);
+      if (!usehp)
+        vp9_lower_mv_precision(&this_mv[0].as_mv, usehp);
+#endif  // CONFIG_NEWMVREF_SUB8X8
       thismvcost += vp9_mv_bit_cost(&this_mv[0].as_mv, &best_ref_mv[0]->as_mv,
                                     mvjcost, mvcost, MV_COST_WEIGHT_SUB);
       this_mv[1].as_int = frame_mv[mbmi->ref_frame[1]].as_int;
@@ -2070,6 +2079,11 @@ static int set_and_cost_bmi_mvs(VP9_COMP *cpi, MACROBLOCKD *xd, int i,
     case NEAREST_NEWMV:
       this_mv[0].as_int = frame_mv[mbmi->ref_frame[0]].as_int;
       this_mv[1].as_int = seg_mvs[mbmi->ref_frame[1]].as_int;
+#if CONFIG_NEWMVREF_SUB8X8
+      usehp = usehp && vp9_use_mv_hp(&best_ref_mv[1]->as_mv);
+      if (!usehp)
+        vp9_lower_mv_precision(&this_mv[1].as_mv, usehp);
+#endif  // CONFIG_NEWMVREF_SUB8X8
       thismvcost += vp9_mv_bit_cost(&this_mv[1].as_mv, &best_ref_mv[1]->as_mv,
                                     mvjcost, mvcost, MV_COST_WEIGHT_SUB);
       break;
@@ -2231,6 +2245,9 @@ typedef struct {
   int64_t bsse;
   int64_t brdcost;
   int_mv mvs[2];
+#if CONFIG_NEWMVREF_SUB8X8
+  int_mv ref_mv[2];
+#endif  // CONFIG_NEWMVREF_SUB8X8
   ENTROPY_CONTEXT ta[2];
   ENTROPY_CONTEXT tl[2];
 } SEG_RDSTAT;
@@ -2372,6 +2389,106 @@ static int check_best_zero_mv(
   return 1;
 }
 
+static void single_motion_search_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
+                                        int i, const BLOCK_SIZE bsize,
+                                        MV *new_mv,
+                                        int_mv *ref_mv, int_mv *mvp) {
+  VP9_COMMON *cm = &cpi->common;
+  MACROBLOCKD *xd = &x->e_mbd;
+  MODE_INFO *mi = xd->mi[0].src_mi;
+  MB_MODE_INFO *mbmi = &mi->mbmi;
+
+  int step_param = 0;
+  int thissme, bestsme = INT_MAX;
+  int sadpb = x->sadperbit4;
+  MV mvp_full;
+  int max_mv;
+  int cost_list[5];
+
+  if (cpi->oxcf.mode != BEST) {
+#if CONFIG_NEWMVREF_SUB8X8
+    mvp->as_int = ref_mv->as_int;
+#else
+    // use previous block's result as next block's MV predictor.
+    if (i > 0) {
+      mvp->as_int = mi->bmi[i - 1].as_mv[0].as_int;
+      if (i == 2)
+        mvp->as_int = mi->bmi[i - 2].as_mv[0].as_int;
+    }
+#endif  // CONFIG_NEWMVREF_SUB8X8
+  }
+  if (i == 0)
+    max_mv = x->max_mv_context[mbmi->ref_frame[0]];
+  else
+    max_mv = MAX(abs(mvp->as_mv.row), abs(mvp->as_mv.col)) >> 3;
+
+  if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
+    // Take wtd average of the step_params based on the last frame's
+    // max mv magnitude and the best ref mvs of the current block for
+    // the given reference.
+    step_param = (vp9_init_search_range(max_mv) +
+                  cpi->mv_step_param) / 2;
+  } else {
+    step_param = cpi->mv_step_param;
+  }
+
+  mvp_full.row = mvp->as_mv.row >> 3;
+  mvp_full.col = mvp->as_mv.col >> 3;
+
+  if (cpi->sf.adaptive_motion_search) {
+    mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3;
+    mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].col >> 3;
+    step_param = MAX(step_param, 8);
+  }
+
+  vp9_set_mv_search_range(x, &ref_mv->as_mv);
+
+  bestsme = vp9_full_pixel_search(
+      cpi, x, bsize, &mvp_full, step_param, sadpb,
+      cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
+      &ref_mv->as_mv, new_mv, INT_MAX, 1);
+
+  // Should we do a full search (best quality only)
+  if (cpi->oxcf.mode == BEST) {
+    int_mv *const best_mv = &mi->bmi[i].as_mv[0];
+    /* Check if mvp_full is within the range. */
+    clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
+             x->mv_row_min, x->mv_row_max);
+    thissme = cpi->full_search_sad(x, &mvp_full,
+                                   sadpb, 16, &cpi->fn_ptr[bsize],
+                                   &ref_mv->as_mv, &best_mv->as_mv);
+    cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] = INT_MAX;
+    if (thissme < bestsme) {
+      bestsme = thissme;
+      *new_mv = best_mv->as_mv;
+    } else {
+      // The full search result is actually worse so re-instate the
+      // previous best vector
+      best_mv->as_mv = *new_mv;
+    }
+  }
+
+  if (bestsme < INT_MAX) {
+    int distortion;
+    cpi->find_fractional_mv_step(
+        x,
+        new_mv,
+        &ref_mv->as_mv,
+        cm->allow_high_precision_mv,
+        x->errorperbit, &cpi->fn_ptr[bsize],
+        cpi->sf.mv.subpel_force_stop,
+        cpi->sf.mv.subpel_iters_per_step,
+        cond_cost_list(cpi, cost_list),
+        x->nmvjointcost, x->mvcost,
+        &distortion,
+        &x->pred_sse[mbmi->ref_frame[0]],
+        NULL, 0, 0);
+  }
+
+  if (cpi->sf.adaptive_motion_search)
+    x->pred_mv[mbmi->ref_frame[0]] = *new_mv;
+}
+
 static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                         const TileInfo * const tile,
                                         int_mv *best_ref_mv,
@@ -2410,16 +2527,20 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
 #if CONFIG_COMPOUND_MODES
   int_mv newnew_seg_mvs[4][MAX_REF_FRAMES];
 #endif
-
+  int_mv ref_mv_sub8x8[2];
 
   vp9_zero(*bsi);
 
   bsi->segment_rd = best_rd;
-  bsi->ref_mv[0] = best_ref_mv;
-  bsi->ref_mv[1] = second_best_ref_mv;
   bsi->mvp.as_int = best_ref_mv->as_int;
   bsi->mvthresh = mvthresh;
 
+  ref_mv_sub8x8[0].as_int = best_ref_mv->as_int;
+  ref_mv_sub8x8[1].as_int =
+      second_best_ref_mv ? second_best_ref_mv->as_int : 0;
+  bsi->ref_mv[0] = &ref_mv_sub8x8[0];
+  bsi->ref_mv[1] = &ref_mv_sub8x8[1];
+
   for (i = 0; i < 4; i++)
     bsi->modes[i] = ZEROMV;
 
@@ -2446,10 +2567,25 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
 
       for (ref = 0; ref < 1 + has_second_rf; ++ref) {
         const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
+#if CONFIG_NEWMVREF_SUB8X8
+        int_mv mv_ref_list[MAX_MV_REF_CANDIDATES];
+        int_mv second_ref_mv;
+        vp9_update_mv_context(cm, xd, tile, mi, frame, mv_ref_list,
+                              i, mi_row, mi_col);
+#endif  // CONFIG_NEWMVREF_SUB8X8
         frame_mv[ZEROMV][frame].as_int = 0;
         vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, i, ref, mi_row, mi_col,
+#if CONFIG_NEWMVREF_SUB8X8
+                                      mv_ref_list,
+#endif  // CONFIG_NEWMVREF_SUB8X8
                                       &frame_mv[NEARESTMV][frame],
                                       &frame_mv[NEARMV][frame]);
+#if CONFIG_NEWMVREF_SUB8X8
+        mv_ref_list[0].as_int = frame_mv[NEARESTMV][frame].as_int;
+        mv_ref_list[1].as_int = frame_mv[NEARMV][frame].as_int;
+        vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv, mv_ref_list,
+                              &ref_mv_sub8x8[ref], &second_ref_mv);
+#endif  // CONFIG_NEWMVREF_SUB8X8
 #if CONFIG_COMPOUND_MODES
         frame_mv[ZERO_ZEROMV][frame].as_int = 0;
         frame_mv[NEAREST_NEARESTMV][frame].as_int =
@@ -2502,10 +2638,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
         if (is_inter_compound_mode(this_mode)) {
           mode_idx = INTER_COMPOUND_OFFSET(this_mode) + INTER_OFFSET(NEWMV) + 1;
         } else {
-          mode_idx = INTER_OFFSET(this_mode);
-        }
-#else
+#endif
         mode_idx = INTER_OFFSET(this_mode);
+#if CONFIG_COMPOUND_MODES
+        }
 #endif
 
         bsi->rdstat[i][mode_idx].brdcost = INT64_MAX;
@@ -2523,108 +2659,29 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
                    sizeof(bsi->rdstat[i][mode_idx].tl));
 
         // motion search for newmv (single predictor case only)
-        if (!has_second_rf && this_mode == NEWMV &&
-            seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV) {
-          MV *const new_mv = &mode_mv[NEWMV][0].as_mv;
-          int step_param = 0;
-          int thissme, bestsme = INT_MAX;
-          int sadpb = x->sadperbit4;
-          MV mvp_full;
-          int max_mv;
-          int cost_list[5];
-
+        // Note: Need to check new mvs for every iteration as the mv ref has
+        //       changed in the NEWMVREF_SUB8X8 experiment.
+        if (!has_second_rf && this_mode == NEWMV
+#if !CONFIG_NEWMVREF_SUB8X8
+            && seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV
+#endif  // CONFIG_NEWMVREF_SUB8X8
+            ) {
           /* Is the best so far sufficiently good that we cant justify doing
            * and new motion search. */
           if (best_rd < label_mv_thresh)
             break;
 
-          if (cpi->oxcf.mode != BEST) {
-            // use previous block's result as next block's MV predictor.
-            if (i > 0) {
-              bsi->mvp.as_int = mi->bmi[i - 1].as_mv[0].as_int;
-              if (i == 2)
-                bsi->mvp.as_int = mi->bmi[i - 2].as_mv[0].as_int;
-            }
-          }
-          if (i == 0)
-            max_mv = x->max_mv_context[mbmi->ref_frame[0]];
-          else
-            max_mv = MAX(abs(bsi->mvp.as_mv.row), abs(bsi->mvp.as_mv.col)) >> 3;
-
-          if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
-            // Take wtd average of the step_params based on the last frame's
-            // max mv magnitude and the best ref mvs of the current block for
-            // the given reference.
-            step_param = (vp9_init_search_range(max_mv) +
-                          cpi->mv_step_param) / 2;
-          } else {
-            step_param = cpi->mv_step_param;
-          }
-
-          mvp_full.row = bsi->mvp.as_mv.row >> 3;
-          mvp_full.col = bsi->mvp.as_mv.col >> 3;
-
-          if (cpi->sf.adaptive_motion_search) {
-            mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3;
-            mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].col >> 3;
-            step_param = MAX(step_param, 8);
-          }
-
           // adjust src pointer for this block
           mi_buf_shift(x, i);
-
-          vp9_set_mv_search_range(x, &bsi->ref_mv[0]->as_mv);
-
-          bestsme = vp9_full_pixel_search(
-              cpi, x, bsize, &mvp_full, step_param, sadpb,
-              cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
-              &bsi->ref_mv[0]->as_mv, new_mv,
-              INT_MAX, 1);
-
-          // Should we do a full search (best quality only)
-          if (cpi->oxcf.mode == BEST) {
-            int_mv *const best_mv = &mi->bmi[i].as_mv[0];
-            /* Check if mvp_full is within the range. */
-            clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
-                     x->mv_row_min, x->mv_row_max);
-            thissme = cpi->full_search_sad(x, &mvp_full,
-                                           sadpb, 16, &cpi->fn_ptr[bsize],
-                                           &bsi->ref_mv[0]->as_mv,
-                                           &best_mv->as_mv);
-            cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] = INT_MAX;
-            if (thissme < bestsme) {
-              bestsme = thissme;
-              *new_mv = best_mv->as_mv;
-            } else {
-              // The full search result is actually worse so re-instate the
-              // previous best vector
-              best_mv->as_mv = *new_mv;
-            }
-          }
-
-          if (bestsme < INT_MAX) {
-            int distortion;
-            cpi->find_fractional_mv_step(
-                x,
-                new_mv,
-                &bsi->ref_mv[0]->as_mv,
-                cm->allow_high_precision_mv,
-                x->errorperbit, &cpi->fn_ptr[bsize],
-                cpi->sf.mv.subpel_force_stop,
-                cpi->sf.mv.subpel_iters_per_step,
-                cond_cost_list(cpi, cost_list),
-                x->nmvjointcost, x->mvcost,
-                &distortion,
-                &x->pred_sse[mbmi->ref_frame[0]],
-                NULL, 0, 0);
-
-            // save motion search result for use in compound prediction
-            seg_mvs[i][mbmi->ref_frame[0]].as_mv = *new_mv;
-          }
-
-          if (cpi->sf.adaptive_motion_search)
-            x->pred_mv[mbmi->ref_frame[0]] = *new_mv;
-
+          frame_mv[this_mode][mbmi->ref_frame[0]].as_int = INVALID_MV;
+          single_motion_search_sub8x8(
+              cpi, x, i, bsize,
+              &frame_mv[this_mode][mbmi->ref_frame[0]].as_mv,
+              &ref_mv_sub8x8[0],
+              &bsi->mvp);
+          // save motion search result for use in compound prediction
+          seg_mvs[i][mbmi->ref_frame[0]].as_int =
+              frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
           // restore src pointers
           mi_buf_restore(x, orig_src, orig_pre);
         }
@@ -2634,18 +2691,27 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
               seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV)
             continue;
         }
+        // Note: Need to check new mvs for every iteration as the mv ref has
+        //       changed in the NEWMVREF_SUB8X8 experiment.
+        // TODO(zoeliu): Further optimization work may be done for:
+        // NEW_NEARESTMV, NEW_NEARMV, NEAREST_NEWMV, and NEAR_NEWMV, as the mv
+        // ref may have changed in the compound mode as opposed to single ref.
+        if (has_second_rf
 #if CONFIG_COMPOUND_MODES
-        if (has_second_rf &&
-            this_mode == NEW_NEWMV &&
-            mbmi->interp_filter == EIGHTTAP) {
+            && this_mode == NEW_NEWMV
 #else
-        if (has_second_rf && this_mode == NEWMV &&
-            mbmi->interp_filter == EIGHTTAP) {
-#endif
+            && this_mode == NEWMV
+#endif  // CONFIG_COMPOUND_MODES
+#if !CONFIG_NEWMVREF_SUB8X8
+            && mbmi->interp_filter == EIGHTTAP
+#endif  // CONFIG_NEWMVREF_SUB8X8
+            ) {
           mi_buf_shift(x, i);
           if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
             int rate_mv;
-            joint_motion_search(cpi, x, bsize, frame_mv[this_mode],
+            joint_motion_search(cpi, x, bsize,
+                                frame_mv[this_mode],
+                                ref_mv_sub8x8,
                                 mi_row, mi_col, seg_mvs[i],
                                 &rate_mv);
 #if CONFIG_COMPOUND_MODES
@@ -2655,9 +2721,9 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
                 frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
 #else
             seg_mvs[i][mbmi->ref_frame[0]].as_int =
-              frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
+                frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
             seg_mvs[i][mbmi->ref_frame[1]].as_int =
-              frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
+                frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
 #endif
           }
           // restore src pointers
@@ -2689,6 +2755,17 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
           if (num_4x4_blocks_high > 1)
             bsi->rdstat[i + 2][mode_idx].mvs[ref].as_int =
                 mode_mv[this_mode][ref].as_int;
+#if CONFIG_NEWMVREF_SUB8X8
+          // Save the mv refs for the best mvs.
+          bsi->rdstat[i][mode_idx].ref_mv[ref].as_int =
+              bsi->ref_mv[ref]->as_int;
+          if (num_4x4_blocks_wide > 1)
+            bsi->rdstat[i + 1][mode_idx].ref_mv[ref].as_int =
+                bsi->ref_mv[ref]->as_int;
+          if (num_4x4_blocks_high > 1)
+            bsi->rdstat[i + 2][mode_idx].ref_mv[ref].as_int =
+                bsi->ref_mv[ref]->as_int;
+#endif  // CONFIG_NEWMVREF_SUB8X8
         }
 
         // Trap vectors that reach beyond the UMV borders
@@ -2704,6 +2781,23 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
 
           for (ref = 0; ref < 1 + has_second_rf; ++ref) {
             subpelmv |= mv_has_subpel(&mode_mv[this_mode][ref].as_mv);
+#if CONFIG_NEWMVREF_SUB8X8
+            if (this_mode == NEWMV
+#if CONFIG_COMPOUND_MODES
+                || this_mode == NEW_NEWMV ||
+                this_mode == NEAREST_NEWMV ||
+                this_mode == NEW_NEARESTMV ||
+                this_mode == NEAR_NEWMV ||
+                this_mode == NEW_NEARMV
+#endif  // CONFIG_COMPOUND_MODES
+                )
+              have_ref &= (
+                  (mode_mv[this_mode][ref].as_int ==
+                   ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int) &&
+                  (bsi->ref_mv[ref]->as_int ==
+                   ref_bsi->rdstat[i][mode_idx].ref_mv[ref].as_int) );
+            else
+#endif  // CONFIG_NEWMVREF_SUB8X8
             have_ref &= mode_mv[this_mode][ref].as_int ==
                 ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int;
           }
@@ -2712,6 +2806,23 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
             ref_bsi = bsi_buf + 1;
             have_ref = 1;
             for (ref = 0; ref < 1 + has_second_rf; ++ref)
+#if CONFIG_NEWMVREF_SUB8X8
+              if (this_mode == NEWMV
+#if CONFIG_COMPOUND_MODES
+                  || this_mode == NEW_NEWMV ||
+                  this_mode == NEAREST_NEWMV ||
+                  this_mode == NEW_NEARESTMV ||
+                  this_mode == NEAR_NEWMV ||
+                  this_mode == NEW_NEARMV
+#endif  // CONFIG_COMPOUND_MODES
+                  )
+                have_ref &= (
+                    (mode_mv[this_mode][ref].as_int ==
+                     ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int) &&
+                    (bsi->ref_mv[ref]->as_int ==
+                     ref_bsi->rdstat[i][mode_idx].ref_mv[ref].as_int) );
+              else
+#endif  // CONFIG_NEWMVREF_SUB8X8
               have_ref &= mode_mv[this_mode][ref].as_int ==
                   ref_bsi->rdstat[i][mode_idx].mvs[ref].as_int;
           }
@@ -2759,7 +2870,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
           mode_selected = this_mode;
           best_rd = bsi->rdstat[i][mode_idx].brdcost;
         }
-      } /*for each 4x4 mode*/
+      } /*for each sub 8x8 mode*/
 
       if (best_rd == INT64_MAX) {
         int iy, midx;
@@ -2778,10 +2889,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
         mode_idx = INTER_COMPOUND_OFFSET(mode_selected)
                    + INTER_OFFSET(NEWMV) + 1;
       } else {
-        mode_idx = INTER_OFFSET(mode_selected);
-      }
-#else
+#endif
       mode_idx = INTER_OFFSET(mode_selected);
+#if CONFIG_COMPOUND_MODES
+      }
 #endif
       vpx_memcpy(t_above, bsi->rdstat[i][mode_idx].ta, sizeof(t_above));
       vpx_memcpy(t_left, bsi->rdstat[i][mode_idx].tl, sizeof(t_left));
@@ -2789,19 +2900,17 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
 #if CONFIG_COMPOUND_MODES
       if (mode_selected == NEW_NEWMV) {
         set_and_cost_bmi_mvs(cpi, xd, i, mode_selected, mode_mv[mode_selected],
-                                   frame_mv[mode_selected], newnew_seg_mvs[i],
-                                   bsi->ref_mv,
-                                   x->nmvjointcost, x->mvcost);
+                             frame_mv[mode_selected], newnew_seg_mvs[i],
+                             bsi->ref_mv, x->nmvjointcost, x->mvcost);
       } else {
 #endif
       set_and_cost_bmi_mvs(cpi, xd, i, mode_selected, mode_mv[mode_selected],
-                                 frame_mv[mode_selected], seg_mvs[i],
-                                 bsi->ref_mv, x->nmvjointcost, x->mvcost);
+                           frame_mv[mode_selected], seg_mvs[i],
+                           bsi->ref_mv, x->nmvjointcost, x->mvcost);
 #if CONFIG_COMPOUND_MODES
       }
 #endif
 
-
       br += bsi->rdstat[i][mode_idx].brate;
       bd += bsi->rdstat[i][mode_idx].bdist;
       block_sse += bsi->rdstat[i][mode_idx].bsse;
@@ -2842,14 +2951,19 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
     if (is_inter_compound_mode(bsi->modes[i])) {
       mode_idx = INTER_COMPOUND_OFFSET(bsi->modes[i]) + INTER_OFFSET(NEWMV) + 1;
     } else {
-      mode_idx = INTER_OFFSET(bsi->modes[i]);
-    }
-#else
+#endif
     mode_idx = INTER_OFFSET(bsi->modes[i]);
+#if CONFIG_COMPOUND_MODES
+    }
 #endif
     mi->bmi[i].as_mv[0].as_int = bsi->rdstat[i][mode_idx].mvs[0].as_int;
     if (has_second_ref(mbmi))
       mi->bmi[i].as_mv[1].as_int = bsi->rdstat[i][mode_idx].mvs[1].as_int;
+#if CONFIG_NEWMVREF_SUB8X8
+    mi->bmi[i].ref_mv[0].as_int = bsi->rdstat[i][mode_idx].ref_mv[0].as_int;
+    if (has_second_ref(mbmi))
+      mi->bmi[i].ref_mv[1].as_int = bsi->rdstat[i][mode_idx].ref_mv[1].as_int;
+#endif  // CONFIG_NEWMVREF_SUB8X8
     x->plane[0].eobs[i] = bsi->rdstat[i][mode_idx].eobs;
     mi->bmi[i].as_mode = bsi->modes[i];
   }
@@ -3121,6 +3235,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
 static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
                                 BLOCK_SIZE bsize,
                                 int_mv *frame_mv,
+                                int_mv *ref_mv,
                                 int mi_row, int mi_col,
                                 int_mv single_newmv[MAX_REF_FRAMES],
                                 int *rate_mv) {
@@ -3130,7 +3245,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
   MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
   const int refs[2] = { mbmi->ref_frame[0],
                         mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
-  int_mv ref_mv[2];
   int ite, ref;
   // Prediction buffer from second frame.
 #if CONFIG_VP9_HIGHBITDEPTH
@@ -3160,8 +3274,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
 #endif  // CONFIG_VP9_HIGHBITDEPTH
 
   for (ref = 0; ref < 2; ++ref) {
-    ref_mv[ref] = mbmi->ref_mvs[refs[ref]][0];
-
     if (scaled_ref_frame[ref]) {
       int i;
       // Swap out the reference frame for a version that's been scaled to
@@ -3172,7 +3284,6 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
       vp9_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col,
                            NULL);
     }
-
     frame_mv[refs[ref]].as_int = single_newmv[refs[ref]].as_int;
   }
 
@@ -3291,7 +3402,7 @@ static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
     }
 
     *rate_mv += vp9_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
-                                &mbmi->ref_mvs[refs[ref]][0].as_mv,
+                                &ref_mv[ref].as_mv,
                                 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
   }
 
@@ -3507,6 +3618,8 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
   int i;
   int refs[2] = { mbmi->ref_frame[0],
     (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
+  int_mv ref_mv[2] =
+    { mbmi->ref_mvs[refs[0]][0], mbmi->ref_mvs[refs[1]][0] };
   int_mv cur_mv[2];
 #if CONFIG_VP9_HIGHBITDEPTH
   DECLARE_ALIGNED_ARRAY(16, uint16_t, tmp_buf16, MAX_MB_PLANE * 64 * 64);
@@ -3654,7 +3767,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 #if CONFIG_COMPOUND_MODES
       if (this_mode == NEW_NEWMV) {
         if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
-          joint_motion_search(cpi, x, bsize, frame_mv,
+          joint_motion_search(cpi, x, bsize, frame_mv, ref_mv,
                               mi_row, mi_col, single_newmv, &rate_mv);
         } else {
           // Initialize mv using single prediction mode result.
@@ -3679,7 +3792,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
 #else
       // Initialize mv using single prediction mode result.
       if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
-        joint_motion_search(cpi, x, bsize, frame_mv,
+        joint_motion_search(cpi, x, bsize, frame_mv, ref_mv,
                             mi_row, mi_col, single_newmv, &rate_mv);
       } else {
         rate_mv  = vp9_mv_bit_cost(&frame_mv[refs[0]].as_mv,