shithub: libvpx

Download patch

ref: f6251cc7a8dbbd01d918d3d9fac04276905fab42
parent: f40c00b206ee6b405ce44a46f6e2adf6906bd41b
author: Angie Chiang <angiebird@google.com>
date: Thu Aug 22 13:55:19 EDT 2019

Move motion field from TplDepFrame to MotionField

Replace get_pyramid_mv by vp9_motion_field_mi_get_mv.

The goal is to modularize motion field related operations.

Change-Id: I33084e680567ab106659ba9389cc4b507b893c69

--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -5874,10 +5874,11 @@
 
 #if CONFIG_NON_GREEDY_MV
 static uint32_t full_pixel_motion_search(VP9_COMP *cpi, ThreadData *td,
+                                         MotionField *motion_field,
                                          int frame_idx, uint8_t *cur_frame_buf,
                                          uint8_t *ref_frame_buf, int stride,
                                          BLOCK_SIZE bsize, int mi_row,
-                                         int mi_col, MV *mv, int rf_idx) {
+                                         int mi_col, MV *mv) {
   MACROBLOCK *const x = &td->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
   MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
@@ -5907,8 +5908,8 @@
 
   vp9_set_mv_search_range(&x->mv_limits, &best_ref_mv1);
 
-  nb_full_mv_num = vp9_prepare_nb_full_mvs(&cpi->tpl_stats[frame_idx], mi_row,
-                                           mi_col, rf_idx, bsize, nb_full_mvs);
+  nb_full_mv_num =
+      vp9_prepare_nb_full_mvs(motion_field, mi_row, mi_col, nb_full_mvs);
   vp9_full_pixel_diamond_new(cpi, x, bsize, &best_ref_mv1_full, step_param,
                              lambda, 1, nb_full_mvs, nb_full_mv_num, mv);
 
@@ -6285,12 +6286,16 @@
 
   for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
     int_mv mv;
+#if CONFIG_NON_GREEDY_MV
+    MotionField *motion_field;
+#endif
     if (ref_frame[rf_idx] == NULL) continue;
 
 #if CONFIG_NON_GREEDY_MV
     (void)td;
-    mv.as_int =
-        get_pyramid_mv(tpl_frame, rf_idx, bsize, mi_row, mi_col)->as_int;
+    motion_field = vp9_motion_field_info_get_motion_field(
+        &cpi->motion_field_info, frame_idx, rf_idx, bsize);
+    mv = vp9_motion_field_mi_get_mv(motion_field, mi_row, mi_col);
 #else
     motion_compensated_prediction(cpi, td, xd->cur_buf->y_buffer + mb_y_offset,
                                   ref_frame[rf_idx]->y_buffer + mb_y_offset,
@@ -6436,8 +6441,9 @@
 }
 
 static int_mv get_mv_from_mv_mode(int mv_mode, VP9_COMP *cpi,
-                                  TplDepFrame *tpl_frame, int rf_idx,
-                                  BLOCK_SIZE bsize, int mi_row, int mi_col) {
+                                  MotionField *motion_field,
+                                  TplDepFrame *tpl_frame, BLOCK_SIZE bsize,
+                                  int mi_row, int mi_col) {
   int_mv mv;
   switch (mv_mode) {
     case ZERO_MV_MODE:
@@ -6445,7 +6451,7 @@
       mv.as_mv.col = 0;
       break;
     case NEW_MV_MODE:
-      mv = *get_pyramid_mv(tpl_frame, rf_idx, bsize, mi_row, mi_col);
+      mv = vp9_motion_field_mi_get_mv(motion_field, mi_row, mi_col);
       break;
     case NEAREST_MV_MODE:
       mv = find_ref_mv(mv_mode, cpi, tpl_frame, bsize, mi_row, mi_col);
@@ -6462,15 +6468,16 @@
 }
 
 static double get_mv_dist(int mv_mode, VP9_COMP *cpi, MACROBLOCKD *xd,
-                          GF_PICTURE *gf_picture, int frame_idx,
-                          TplDepFrame *tpl_frame, int rf_idx, BLOCK_SIZE bsize,
-                          int mi_row, int mi_col, int_mv *mv) {
+                          GF_PICTURE *gf_picture, MotionField *motion_field,
+                          int frame_idx, TplDepFrame *tpl_frame, int rf_idx,
+                          BLOCK_SIZE bsize, int mi_row, int mi_col,
+                          int_mv *mv) {
   uint32_t sse;
   struct buf_2d src;
   struct buf_2d pre;
   MV full_mv;
-  *mv = get_mv_from_mv_mode(mv_mode, cpi, tpl_frame, rf_idx, bsize, mi_row,
-                            mi_col);
+  *mv = get_mv_from_mv_mode(mv_mode, cpi, motion_field, tpl_frame, bsize,
+                            mi_row, mi_col);
   full_mv = get_full_mv(&mv->as_mv);
   if (get_block_src_pred_buf(xd, gf_picture, frame_idx, rf_idx, mi_row, mi_col,
                              &src, &pre)) {
@@ -6507,18 +6514,18 @@
   mv_diff_cost *= (1 << VP9_PROB_COST_SHIFT);
   return mv_diff_cost;
 }
-static double get_mv_cost(int mv_mode, VP9_COMP *cpi, TplDepFrame *tpl_frame,
-                          int rf_idx, BLOCK_SIZE bsize, int mi_row,
+static double get_mv_cost(int mv_mode, VP9_COMP *cpi, MotionField *motion_field,
+                          TplDepFrame *tpl_frame, BLOCK_SIZE bsize, int mi_row,
                           int mi_col) {
   double mv_cost = get_mv_mode_cost(mv_mode);
   if (mv_mode == NEW_MV_MODE) {
-    MV new_mv = get_mv_from_mv_mode(mv_mode, cpi, tpl_frame, rf_idx, bsize,
-                                    mi_row, mi_col)
+    MV new_mv = get_mv_from_mv_mode(mv_mode, cpi, motion_field, tpl_frame,
+                                    bsize, mi_row, mi_col)
                     .as_mv;
-    MV nearest_mv = get_mv_from_mv_mode(NEAREST_MV_MODE, cpi, tpl_frame, rf_idx,
-                                        bsize, mi_row, mi_col)
+    MV nearest_mv = get_mv_from_mv_mode(NEAREST_MV_MODE, cpi, motion_field,
+                                        tpl_frame, bsize, mi_row, mi_col)
                         .as_mv;
-    MV near_mv = get_mv_from_mv_mode(NEAR_MV_MODE, cpi, tpl_frame, rf_idx,
+    MV near_mv = get_mv_from_mv_mode(NEAR_MV_MODE, cpi, motion_field, tpl_frame,
                                      bsize, mi_row, mi_col)
                      .as_mv;
     double nearest_cost = get_mv_diff_cost(&new_mv, &nearest_mv);
@@ -6529,14 +6536,16 @@
 }
 
 static double eval_mv_mode(int mv_mode, VP9_COMP *cpi, MACROBLOCK *x,
-                           GF_PICTURE *gf_picture, int frame_idx,
-                           TplDepFrame *tpl_frame, int rf_idx, BLOCK_SIZE bsize,
-                           int mi_row, int mi_col, int_mv *mv) {
+                           GF_PICTURE *gf_picture, MotionField *motion_field,
+                           int frame_idx, TplDepFrame *tpl_frame, int rf_idx,
+                           BLOCK_SIZE bsize, int mi_row, int mi_col,
+                           int_mv *mv) {
   MACROBLOCKD *xd = &x->e_mbd;
-  double mv_dist = get_mv_dist(mv_mode, cpi, xd, gf_picture, frame_idx,
-                               tpl_frame, rf_idx, bsize, mi_row, mi_col, mv);
+  double mv_dist =
+      get_mv_dist(mv_mode, cpi, xd, gf_picture, motion_field, frame_idx,
+                  tpl_frame, rf_idx, bsize, mi_row, mi_col, mv);
   double mv_cost =
-      get_mv_cost(mv_mode, cpi, tpl_frame, rf_idx, bsize, mi_row, mi_col);
+      get_mv_cost(mv_mode, cpi, motion_field, tpl_frame, bsize, mi_row, mi_col);
   double mult = 180;
 
   return mv_cost + mult * log2f(1 + mv_dist);
@@ -6543,7 +6552,8 @@
 }
 
 static int find_best_ref_mv_mode(VP9_COMP *cpi, MACROBLOCK *x,
-                                 GF_PICTURE *gf_picture, int frame_idx,
+                                 GF_PICTURE *gf_picture,
+                                 MotionField *motion_field, int frame_idx,
                                  TplDepFrame *tpl_frame, int rf_idx,
                                  BLOCK_SIZE bsize, int mi_row, int mi_col,
                                  double *rd, int_mv *mv) {
@@ -6557,8 +6567,8 @@
     if (mv_mode == NEW_MV_MODE) {
       continue;
     }
-    this_rd = eval_mv_mode(mv_mode, cpi, x, gf_picture, frame_idx, tpl_frame,
-                           rf_idx, bsize, mi_row, mi_col, &this_mv);
+    this_rd = eval_mv_mode(mv_mode, cpi, x, gf_picture, motion_field, frame_idx,
+                           tpl_frame, rf_idx, bsize, mi_row, mi_col, &this_mv);
     if (update == 0) {
       *rd = this_rd;
       *mv = this_mv;
@@ -6576,8 +6586,8 @@
 }
 
 static void predict_mv_mode(VP9_COMP *cpi, MACROBLOCK *x,
-                            GF_PICTURE *gf_picture, int frame_idx,
-                            TplDepFrame *tpl_frame, int rf_idx,
+                            GF_PICTURE *gf_picture, MotionField *motion_field,
+                            int frame_idx, TplDepFrame *tpl_frame, int rf_idx,
                             BLOCK_SIZE bsize, int mi_row, int mi_col) {
   const int mi_height = num_8x8_blocks_high_lookup[bsize];
   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
@@ -6607,9 +6617,9 @@
       if (nb_row < tpl_frame->mi_rows && nb_col < tpl_frame->mi_cols) {
         double this_rd;
         int_mv *mv = &select_mv_arr[nb_row * stride + nb_col];
-        mv_mode_arr[nb_row * stride + nb_col] =
-            find_best_ref_mv_mode(cpi, x, gf_picture, frame_idx, tpl_frame,
-                                  rf_idx, bsize, nb_row, nb_col, &this_rd, mv);
+        mv_mode_arr[nb_row * stride + nb_col] = find_best_ref_mv_mode(
+            cpi, x, gf_picture, motion_field, frame_idx, tpl_frame, rf_idx,
+            bsize, nb_row, nb_col, &this_rd, mv);
         if (r == 0 && c == 0) {
           this_no_new_mv_rd = this_rd;
         }
@@ -6623,9 +6633,9 @@
 
   // new mv
   mv_mode_arr[mi_row * stride + mi_col] = NEW_MV_MODE;
-  this_new_mv_rd = eval_mv_mode(NEW_MV_MODE, cpi, x, gf_picture, frame_idx,
-                                tpl_frame, rf_idx, bsize, mi_row, mi_col,
-                                &select_mv_arr[mi_row * stride + mi_col]);
+  this_new_mv_rd = eval_mv_mode(
+      NEW_MV_MODE, cpi, x, gf_picture, motion_field, frame_idx, tpl_frame,
+      rf_idx, bsize, mi_row, mi_col, &select_mv_arr[mi_row * stride + mi_col]);
   new_mv_rd = this_new_mv_rd;
   // We start from idx = 1 because idx = 0 is evaluated as NEW_MV_MODE
   // beforehand.
@@ -6638,9 +6648,9 @@
       if (nb_row < tpl_frame->mi_rows && nb_col < tpl_frame->mi_cols) {
         double this_rd;
         int_mv *mv = &select_mv_arr[nb_row * stride + nb_col];
-        mv_mode_arr[nb_row * stride + nb_col] =
-            find_best_ref_mv_mode(cpi, x, gf_picture, frame_idx, tpl_frame,
-                                  rf_idx, bsize, nb_row, nb_col, &this_rd, mv);
+        mv_mode_arr[nb_row * stride + nb_col] = find_best_ref_mv_mode(
+            cpi, x, gf_picture, motion_field, frame_idx, tpl_frame, rf_idx,
+            bsize, nb_row, nb_col, &this_rd, mv);
         new_mv_rd += this_rd;
       }
     }
@@ -6670,7 +6680,8 @@
 }
 
 static void predict_mv_mode_arr(VP9_COMP *cpi, MACROBLOCK *x,
-                                GF_PICTURE *gf_picture, int frame_idx,
+                                GF_PICTURE *gf_picture,
+                                MotionField *motion_field, int frame_idx,
                                 TplDepFrame *tpl_frame, int rf_idx,
                                 BLOCK_SIZE bsize) {
   const int mi_height = num_8x8_blocks_high_lookup[bsize];
@@ -6689,8 +6700,8 @@
       assert(c >= 0 && c < unit_cols);
       assert(mi_row >= 0 && mi_row < tpl_frame->mi_rows);
       assert(mi_col >= 0 && mi_col < tpl_frame->mi_cols);
-      predict_mv_mode(cpi, x, gf_picture, frame_idx, tpl_frame, rf_idx, bsize,
-                      mi_row, mi_col);
+      predict_mv_mode(cpi, x, gf_picture, motion_field, frame_idx, tpl_frame,
+                      rf_idx, bsize, mi_row, mi_col);
     }
   }
 }
@@ -6731,29 +6742,28 @@
   }
 }
 
-static void do_motion_search(VP9_COMP *cpi, ThreadData *td, int frame_idx,
+static void do_motion_search(VP9_COMP *cpi, ThreadData *td,
+                             MotionField *motion_field, int frame_idx,
                              YV12_BUFFER_CONFIG *ref_frame, BLOCK_SIZE bsize,
-                             int mi_row, int mi_col, int rf_idx) {
+                             int mi_row, int mi_col) {
   VP9_COMMON *cm = &cpi->common;
   MACROBLOCK *x = &td->mb;
   MACROBLOCKD *xd = &x->e_mbd;
-  TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
-  TplDepStats *tpl_stats =
-      &tpl_frame->tpl_stats_ptr[mi_row * tpl_frame->stride + mi_col];
   const int mb_y_offset =
       mi_row * MI_SIZE * xd->cur_buf->y_stride + mi_col * MI_SIZE;
   assert(ref_frame != NULL);
   set_mv_limits(cm, x, mi_row, mi_col);
-  tpl_stats->ready[rf_idx] = 1;
   {
-    int_mv *mv = get_pyramid_mv(tpl_frame, rf_idx, bsize, mi_row, mi_col);
+    int_mv mv = vp9_motion_field_mi_get_mv(motion_field, mi_row, mi_col);
     uint8_t *cur_frame_buf = xd->cur_buf->y_buffer + mb_y_offset;
     uint8_t *ref_frame_buf = ref_frame->y_buffer + mb_y_offset;
     const int stride = xd->cur_buf->y_stride;
-    full_pixel_motion_search(cpi, td, frame_idx, cur_frame_buf, ref_frame_buf,
-                             stride, bsize, mi_row, mi_col, &mv->as_mv, rf_idx);
+    full_pixel_motion_search(cpi, td, motion_field, frame_idx, cur_frame_buf,
+                             ref_frame_buf, stride, bsize, mi_row, mi_col,
+                             &mv.as_mv);
     sub_pixel_motion_search(cpi, td, cur_frame_buf, ref_frame_buf, stride,
-                            bsize, &mv->as_mv);
+                            bsize, &mv.as_mv);
+    vp9_motion_field_mi_set_mv(motion_field, mi_row, mi_col, mv);
   }
 }
 
@@ -6861,14 +6871,11 @@
           mi_row * MI_SIZE * xd->cur_buf->y_stride + mi_col * MI_SIZE;
       const int bw = 4 << b_width_log2_lookup[bsize];
       const int bh = 4 << b_height_log2_lookup[bsize];
-      TplDepStats *tpl_stats =
-          &tpl_frame->tpl_stats_ptr[mi_row * tpl_frame->stride + mi_col];
       FEATURE_SCORE_LOC *fs_loc =
           &cpi->feature_score_loc_arr[mi_row * tpl_frame->stride + mi_col];
-      tpl_stats->feature_score = get_feature_score(
+      fs_loc->feature_score = get_feature_score(
           xd->cur_buf->y_buffer + mb_y_offset, xd->cur_buf->y_stride, bw, bh);
       fs_loc->visited = 0;
-      fs_loc->feature_score = tpl_stats->feature_score;
       fs_loc->mi_row = mi_row;
       fs_loc->mi_col = mi_col;
       cpi->feature_score_loc_sort[fs_loc_sort_size] = fs_loc;
@@ -6879,28 +6886,21 @@
   qsort(cpi->feature_score_loc_sort, fs_loc_sort_size,
         sizeof(*cpi->feature_score_loc_sort), compare_feature_score);
 
-  for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
-    for (mi_row = 0; mi_row < cm->mi_rows; mi_row += mi_height) {
-      for (mi_col = 0; mi_col < cm->mi_cols; mi_col += mi_width) {
-        TplDepStats *tpl_stats =
-            &tpl_frame->tpl_stats_ptr[mi_row * tpl_frame->stride + mi_col];
-        tpl_stats->ready[rf_idx] = 0;
-      }
-    }
-  }
-
   // TODO(angiebird): Clean up this part.
   for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
     int i;
+    MotionField *motion_field = vp9_motion_field_info_get_motion_field(
+        &cpi->motion_field_info, frame_idx, rf_idx, bsize);
     if (ref_frame[rf_idx] == NULL) {
       continue;
     }
+    vp9_motion_field_reset_mvs(motion_field);
 #if CHANGE_MV_SEARCH_ORDER
 #if !USE_PQSORT
     for (i = 0; i < fs_loc_sort_size; ++i) {
       FEATURE_SCORE_LOC *fs_loc = cpi->feature_score_loc_sort[i];
-      do_motion_search(cpi, td, frame_idx, ref_frame[rf_idx], bsize,
-                       fs_loc->mi_row, fs_loc->mi_col, rf_idx);
+      do_motion_search(cpi, td, motion_field, frame_idx, ref_frame[rf_idx],
+                       bsize, fs_loc->mi_row, fs_loc->mi_col);
     }
 #else   // !USE_PQSORT
     fs_loc_heap_size = 0;
@@ -6915,8 +6915,8 @@
       FEATURE_SCORE_LOC *fs_loc;
       max_heap_pop(cpi->feature_score_loc_heap, &fs_loc_heap_size, &fs_loc);
 
-      do_motion_search(cpi, td, frame_idx, ref_frame[rf_idx], bsize,
-                       fs_loc->mi_row, fs_loc->mi_col, rf_idx);
+      do_motion_search(cpi, td, motion_field, frame_idx, ref_frame[rf_idx],
+                       bsize, fs_loc->mi_row, fs_loc->mi_col);
 
       add_nb_blocks_to_heap(cpi, tpl_frame, bsize, fs_loc->mi_row,
                             fs_loc->mi_col, &fs_loc_heap_size);
@@ -6925,8 +6925,8 @@
 #else   // CHANGE_MV_SEARCH_ORDER
     for (mi_row = 0; mi_row < cm->mi_rows; mi_row += mi_height) {
       for (mi_col = 0; mi_col < cm->mi_cols; mi_col += mi_width) {
-        do_motion_search(cpi, td, frame_idx, ref_frame[rf_idx], bsize, mi_row,
-                         mi_col, rf_idx);
+        do_motion_search(cpi, td, motion_field, frame_idx, ref_frame[rf_idx],
+                         bsize, mi_row, mi_col);
       }
     }
 #endif  // CHANGE_MV_SEARCH_ORDER
@@ -7016,8 +7016,10 @@
   for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
     int ref_frame_idx = gf_picture[frame_idx].ref_frame[rf_idx];
     if (ref_frame_idx != -1) {
-      predict_mv_mode_arr(cpi, x, gf_picture, frame_idx, tpl_frame, rf_idx,
-                          bsize);
+      MotionField *motion_field = vp9_motion_field_info_get_motion_field(
+          &cpi->motion_field_info, frame_idx, rf_idx, bsize);
+      predict_mv_mode_arr(cpi, x, gf_picture, motion_field, frame_idx,
+                          tpl_frame, rf_idx, bsize);
     }
   }
 #endif
@@ -7088,8 +7090,9 @@
         for (mi_row = 0; mi_row < cm->mi_rows; ++mi_row) {
           for (mi_col = 0; mi_col < cm->mi_cols; ++mi_col) {
             if ((mi_row % mi_height) == 0 && (mi_col % mi_width) == 0) {
-              int_mv mv =
-                  *get_pyramid_mv(tpl_frame, rf_idx, bsize, mi_row, mi_col);
+              int_mv mv = vp9_motion_field_info_get_mv(&cpi->motion_field_info,
+                                                       frame_idx, rf_idx, bsize,
+                                                       mi_row, mi_col);
               printf("%d %d %d %d\n", mi_row, mi_col, mv.as_mv.row,
                      mv.as_mv.col);
             }
@@ -7133,7 +7136,6 @@
   const int mi_cols = mi_cols_aligned_to_sb(cm->mi_cols);
   const int mi_rows = mi_cols_aligned_to_sb(cm->mi_rows);
 #if CONFIG_NON_GREEDY_MV
-  int sqr_bsize;
   int rf_idx;
 
   // TODO(angiebird): This probably needs further modifications to support
@@ -7170,15 +7172,6 @@
 
 #if CONFIG_NON_GREEDY_MV
     for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
-      for (sqr_bsize = 0; sqr_bsize < SQUARE_BLOCK_SIZES; ++sqr_bsize) {
-        vpx_free(cpi->tpl_stats[frame].pyramid_mv_arr[rf_idx][sqr_bsize]);
-        CHECK_MEM_ERROR(
-            cm, cpi->tpl_stats[frame].pyramid_mv_arr[rf_idx][sqr_bsize],
-            vpx_calloc(
-                mi_rows * mi_cols * 4,
-                sizeof(
-                    *cpi->tpl_stats[frame].pyramid_mv_arr[rf_idx][sqr_bsize])));
-      }
       vpx_free(cpi->tpl_stats[frame].mv_mode_arr[rf_idx]);
       CHECK_MEM_ERROR(
           cm, cpi->tpl_stats[frame].mv_mode_arr[rf_idx],
@@ -7222,10 +7215,6 @@
 #if CONFIG_NON_GREEDY_MV
     int rf_idx;
     for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
-      int sqr_bsize;
-      for (sqr_bsize = 0; sqr_bsize < SQUARE_BLOCK_SIZES; ++sqr_bsize) {
-        vpx_free(cpi->tpl_stats[frame].pyramid_mv_arr[rf_idx][sqr_bsize]);
-      }
       vpx_free(cpi->tpl_stats[frame].mv_mode_arr[rf_idx]);
       vpx_free(cpi->tpl_stats[frame].rd_diff_arr[rf_idx]);
     }
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -293,12 +293,6 @@
 
   int ref_frame_index;
   int_mv mv;
-
-#if CONFIG_NON_GREEDY_MV
-  int ready[3];
-  int64_t sse_arr[3];
-  double feature_score;
-#endif
 } TplDepStats;
 
 #if CONFIG_NON_GREEDY_MV
@@ -321,19 +315,10 @@
   int base_qindex;
 #if CONFIG_NON_GREEDY_MV
   int lambda;
-  int_mv *pyramid_mv_arr[3][SQUARE_BLOCK_SIZES];
   int *mv_mode_arr[3];
   double *rd_diff_arr[3];
 #endif
 } TplDepFrame;
-
-#if CONFIG_NON_GREEDY_MV
-static INLINE int_mv *get_pyramid_mv(const TplDepFrame *tpl_frame, int rf_idx,
-                                     BLOCK_SIZE bsize, int mi_row, int mi_col) {
-  return &tpl_frame->pyramid_mv_arr[rf_idx][get_square_block_idx(bsize)]
-                                   [mi_row * tpl_frame->stride + mi_col];
-}
-#endif
 
 #define TPL_DEP_COST_SCALE_LOG2 4
 
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -2055,26 +2055,25 @@
   return bestsad;
 }
 
-int vp9_prepare_nb_full_mvs(const TplDepFrame *tpl_frame, int mi_row,
-                            int mi_col, int rf_idx, BLOCK_SIZE bsize,
-                            int_mv *nb_full_mvs) {
-  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
-  const int mi_height = num_8x8_blocks_high_lookup[bsize];
+int vp9_prepare_nb_full_mvs(const MotionField *motion_field, int mi_row,
+                            int mi_col, int_mv *nb_full_mvs) {
+  const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
+  const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
   const int dirs[NB_MVS_NUM][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
   int nb_full_mv_num = 0;
   int i;
+  assert(mi_row % mi_height == 0);
+  assert(mi_col % mi_width == 0);
   for (i = 0; i < NB_MVS_NUM; ++i) {
-    int r = dirs[i][0] * mi_height;
-    int c = dirs[i][1] * mi_width;
-    if (mi_row + r >= 0 && mi_row + r < tpl_frame->mi_rows && mi_col + c >= 0 &&
-        mi_col + c < tpl_frame->mi_cols) {
-      const TplDepStats *tpl_ptr =
-          &tpl_frame
-               ->tpl_stats_ptr[(mi_row + r) * tpl_frame->stride + mi_col + c];
-      if (tpl_ptr->ready[rf_idx]) {
-        int_mv *mv =
-            get_pyramid_mv(tpl_frame, rf_idx, bsize, mi_row + r, mi_col + c);
-        nb_full_mvs[nb_full_mv_num].as_mv = get_full_mv(&mv->as_mv);
+    int r = dirs[i][0];
+    int c = dirs[i][1];
+    int brow = mi_row / mi_height + r;
+    int bcol = mi_col / mi_width + c;
+    if (brow >= 0 && brow < motion_field->block_rows && bcol >= 0 &&
+        bcol < motion_field->block_cols) {
+      if (vp9_motion_field_is_mv_set(motion_field, brow, bcol)) {
+        int_mv mv = vp9_motion_field_get_mv(motion_field, brow, bcol);
+        nb_full_mvs[nb_full_mv_num].as_mv = get_full_mv(&mv.as_mv);
         ++nb_full_mv_num;
       }
     }
--- a/vp9/encoder/vp9_mcomp.h
+++ b/vp9/encoder/vp9_mcomp.h
@@ -148,9 +148,8 @@
   return out_mv;
 }
 struct TplDepFrame;
-int vp9_prepare_nb_full_mvs(const struct TplDepFrame *tpl_frame, int mi_row,
-                            int mi_col, int rf_idx, BLOCK_SIZE bsize,
-                            int_mv *nb_full_mvs);
+int vp9_prepare_nb_full_mvs(const struct MotionField *motion_field, int mi_row,
+                            int mi_col, int_mv *nb_full_mvs);
 
 static INLINE BLOCK_SIZE get_square_block_size(BLOCK_SIZE bsize) {
   BLOCK_SIZE square_bsize;
--- a/vp9/encoder/vp9_non_greedy_mv.c
+++ b/vp9/encoder/vp9_non_greedy_mv.c
@@ -171,7 +171,7 @@
 Status vp9_alloc_motion_field_info(MotionFieldInfo *motion_field_info,
                                    int frame_num, int mi_rows, int mi_cols) {
   int frame_idx, rf_idx, square_block_idx;
-  if (motion_field_info->allocated == 1) {
+  if (motion_field_info->allocated) {
     // TODO(angiebird): Avoid re-allocate buffer if possible
     vp9_free_motion_field_info(motion_field_info);
   }
@@ -210,14 +210,21 @@
   motion_field->bsize = bsize;
   motion_field->block_rows = block_rows;
   motion_field->block_cols = block_cols;
+  motion_field->block_num = block_rows * block_cols;
   motion_field->mf =
-      vpx_calloc(block_rows * block_cols, sizeof(*motion_field->mf));
+      vpx_calloc(motion_field->block_num, sizeof(*motion_field->mf));
   if (motion_field->mf == NULL) {
     assert(0);
     status = STATUS_FAILED;
   }
+  motion_field->set_mv =
+      vpx_calloc(motion_field->block_num, sizeof(*motion_field->set_mv));
+  if (motion_field->set_mv == NULL) {
+    assert(0);
+    status = STATUS_FAILED;
+  }
   motion_field->local_structure = vpx_calloc(
-      block_rows * block_cols, sizeof(*motion_field->local_structure));
+      motion_field->block_num, sizeof(*motion_field->local_structure));
   if (motion_field->local_structure == NULL) {
     assert(0);
     status = STATUS_FAILED;
@@ -250,6 +257,60 @@
     motion_field_info->frame_num = 0;
     motion_field_info->allocated = 0;
   }
+}
+
+MotionField *vp9_motion_field_info_get_motion_field(
+    MotionFieldInfo *motion_field_info, int frame_idx, int rf_idx,
+    BLOCK_SIZE bsize) {
+  int square_block_idx = get_square_block_idx(bsize);
+  assert(frame_idx < motion_field_info->frame_num);
+  assert(motion_field_info->allocated == 1);
+  return &motion_field_info
+              ->motion_field_array[frame_idx][rf_idx][square_block_idx];
+}
+
+int vp9_motion_field_is_mv_set(const MotionField *motion_field, int brow,
+                               int bcol) {
+  assert(brow >= 0 && brow < motion_field->block_rows);
+  assert(bcol >= 0 && bcol < motion_field->block_cols);
+  return motion_field->set_mv[brow * motion_field->block_cols + bcol];
+}
+
+int_mv vp9_motion_field_get_mv(const MotionField *motion_field, int brow,
+                               int bcol) {
+  assert(brow >= 0 && brow < motion_field->block_rows);
+  assert(bcol >= 0 && bcol < motion_field->block_cols);
+  return motion_field->mf[brow * motion_field->block_cols + bcol];
+}
+
+int_mv vp9_motion_field_mi_get_mv(const MotionField *motion_field, int mi_row,
+                                  int mi_col) {
+  const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
+  const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
+  const int brow = mi_row / mi_height;
+  const int bcol = mi_col / mi_width;
+  assert(mi_row % mi_height == 0);
+  assert(mi_col % mi_width == 0);
+  return vp9_motion_field_get_mv(motion_field, brow, bcol);
+}
+
+void vp9_motion_field_mi_set_mv(MotionField *motion_field, int mi_row,
+                                int mi_col, int_mv mv) {
+  const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
+  const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
+  const int brow = mi_row / mi_height;
+  const int bcol = mi_col / mi_width;
+  assert(mi_row % mi_height == 0);
+  assert(mi_col % mi_width == 0);
+  assert(brow >= 0 && brow < motion_field->block_rows);
+  assert(bcol >= 0 && bcol < motion_field->block_cols);
+  motion_field->mf[brow * motion_field->block_cols + bcol] = mv;
+  motion_field->set_mv[brow * motion_field->block_cols + bcol] = 1;
+}
+
+void vp9_motion_field_reset_mvs(MotionField *motion_field) {
+  memset(motion_field->set_mv, 0,
+         motion_field->block_num * sizeof(*motion_field->set_mv));
 }
 
 static int64_t log2_approximation(int64_t v) {
--- a/vp9/encoder/vp9_non_greedy_mv.h
+++ b/vp9/encoder/vp9_non_greedy_mv.h
@@ -31,8 +31,10 @@
   BLOCK_SIZE bsize;
   int block_rows;
   int block_cols;
+  int block_num;  // block_num == block_rows * block_cols
   int (*local_structure)[MF_LOCAL_STRUCTURE_SIZE];
-  MV *mf;
+  int_mv *mf;
+  int *set_mv;
   int mv_log_scale;
 } MotionField;
 
@@ -104,6 +106,23 @@
                              const vp9_variance_fn_ptr_t *fn_ptr, int rows,
                              int cols, BLOCK_SIZE bsize,
                              int (*M)[MF_LOCAL_STRUCTURE_SIZE]);
+
+MotionField *vp9_motion_field_info_get_motion_field(
+    MotionFieldInfo *motion_field_info, int frame_idx, int rf_idx,
+    BLOCK_SIZE bsize);
+
+void vp9_motion_field_mi_set_mv(MotionField *motion_field, int mi_row,
+                                int mi_col, int_mv mv);
+
+void vp9_motion_field_reset_mvs(MotionField *motion_field);
+
+int_mv vp9_motion_field_get_mv(const MotionField *motion_field, int brow,
+                               int bcol);
+int_mv vp9_motion_field_mi_get_mv(const MotionField *motion_field, int mi_row,
+                                  int mi_col);
+int vp9_motion_field_is_mv_set(const MotionField *motion_field, int brow,
+                               int bcol);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -2500,9 +2500,10 @@
   int gf_rf_idx = ref_frame_to_gf_rf_idx(ref);
   BLOCK_SIZE square_bsize = get_square_block_size(bsize);
   int_mv nb_full_mvs[NB_MVS_NUM];
+  MotionField *motion_field = vp9_motion_field_info_get_motion_field(
+      &cpi->motion_field_info, gf_group_idx, gf_rf_idx, square_bsize);
   const int nb_full_mv_num =
-      vp9_prepare_nb_full_mvs(&cpi->tpl_stats[gf_group_idx], mi_row, mi_col,
-                              gf_rf_idx, square_bsize, nb_full_mvs);
+      vp9_prepare_nb_full_mvs(motion_field, mi_row, mi_col, nb_full_mvs);
   const int lambda = (pw * ph) / 4;
   assert(pw * ph == lambda << 2);
 #else   // CONFIG_NON_GREEDY_MV
@@ -2673,8 +2674,7 @@
 // However, once established that vector may be usable through the nearest and
 // near mv modes to reduce distortion in subsequent blocks and also improve
 // visual quality.
-static int discount_newmv_test(const VP9_COMP *cpi, int this_mode,
-                               int_mv this_mv,
+static int discount_newmv_test(VP9_COMP *cpi, int this_mode, int_mv this_mv,
                                int_mv (*mode_mv)[MAX_REF_FRAMES], int ref_frame,
                                int mi_row, int mi_col, BLOCK_SIZE bsize) {
 #if CONFIG_NON_GREEDY_MV
@@ -2684,6 +2684,8 @@
     const int gf_group_idx = cpi->twopass.gf_group.index;
     const int gf_rf_idx = ref_frame_to_gf_rf_idx(ref_frame);
     const TplDepFrame tpl_frame = cpi->tpl_stats[gf_group_idx];
+    const MotionField *motion_field = vp9_motion_field_info_get_motion_field(
+        &cpi->motion_field_info, gf_group_idx, gf_rf_idx, cpi->tpl_bsize);
     const int tpl_block_mi_h = num_8x8_blocks_high_lookup[cpi->tpl_bsize];
     const int tpl_block_mi_w = num_8x8_blocks_wide_lookup[cpi->tpl_bsize];
     const int tpl_mi_row = mi_row - (mi_row % tpl_block_mi_h);
@@ -2692,8 +2694,8 @@
         tpl_frame
             .mv_mode_arr[gf_rf_idx][tpl_mi_row * tpl_frame.stride + tpl_mi_col];
     if (mv_mode == NEW_MV_MODE) {
-      int_mv tpl_new_mv = *get_pyramid_mv(&tpl_frame, gf_rf_idx, cpi->tpl_bsize,
-                                          tpl_mi_row, tpl_mi_col);
+      int_mv tpl_new_mv =
+          vp9_motion_field_mi_get_mv(motion_field, tpl_mi_row, tpl_mi_col);
       int row_diff = abs(tpl_new_mv.as_mv.row - this_mv.as_mv.row);
       int col_diff = abs(tpl_new_mv.as_mv.col - this_mv.as_mv.col);
       if (VPXMAX(row_diff, col_diff) <= 8) {