]> granicus.if.org Git - libvpx/commitdiff
Rework the predicted motion vector for sub8x8 block
authorJingning Han <jingning@google.com>
Tue, 22 Mar 2016 23:38:27 +0000 (16:38 -0700)
committerJingning Han <jingning@google.com>
Mon, 28 Mar 2016 21:58:17 +0000 (14:58 -0700)
This commit makes the sub8x8 block to use its nearest neighbor's
motion vector as predicted motion vector for NEWMV mode. It improves
the coding performance by 0.12%.

Change-Id: I99e56715b327573ce7e8a26e3515a4984dadfd98

vp10/decoder/decodemv.c
vp10/encoder/rdopt.c

index a76d5d8698425947a7feba140b7a84f065b18f03..8035e063d2fa0ea1686a2cef3e5c291dd31e7bbf 100644 (file)
@@ -1390,7 +1390,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
 
         if (b_mode != ZEROMV && b_mode != ZERO_ZEROMV) {
 #else
-        if (b_mode == NEARESTMV || b_mode == NEARMV) {
+        if (b_mode != ZEROMV) {
 #endif  // CONFIG_EXT_INTER
 #if CONFIG_REF_MV
           CANDIDATE_MV ref_mv_stack[2][MAX_REF_MV_STACK_SIZE];
@@ -1411,8 +1411,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
 #if CONFIG_EXT_INTER
                                            mv_ref_list,
 #endif  // CONFIG_EXT_INTER
-                                          &nearest_sub8x8[ref],
-                                          &near_sub8x8[ref]);
+                                           &nearest_sub8x8[ref],
+                                           &near_sub8x8[ref]);
 #if CONFIG_EXT_INTER
             if (have_newmv_in_inter_mode(b_mode)) {
               mv_ref_list[0].as_int = nearest_sub8x8[ref].as_int;
@@ -1424,8 +1424,13 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
 #endif  // CONFIG_EXT_INTER
         }
 
-        for (ref = 0; ref < 2; ++ref) {
+        for (ref = 0; ref < 1 + is_compound && b_mode != ZEROMV; ++ref) {
+#if CONFIG_REF_MV
+          ref_mv_s8[ref] = nearest_sub8x8[ref];
+          lower_mv_precision(&ref_mv_s8[ref].as_mv, allow_hp);
+#else
           ref_mv_s8[ref] = nearestmv[ref];
+#endif
         }
 #if CONFIG_EXT_INTER
         (void)ref_mv_s8;
index 3939e698c043900ef9fa8fef6ac85f55b0142d54..b73e05db0a9ae166725166954162db8611c985c6 100644 (file)
@@ -4772,8 +4772,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
 #endif  // CONFIG_EXT_INTER
                                         BEST_SEG_INFO *bsi_buf, int filter_idx,
                                         int mi_row, int mi_col) {
-  int i;
   BEST_SEG_INFO *bsi = bsi_buf + filter_idx;
+#if CONFIG_REF_MV
+  int_mv tmp_ref_mv[2];
+#endif
   MACROBLOCKD *xd = &x->e_mbd;
   MODE_INFO *mi = xd->mi[0];
   MB_MODE_INFO *mbmi = &mi->mbmi;
@@ -4805,8 +4807,20 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
   bsi->mvp.as_int = best_ref_mv->as_int;
   bsi->mvthresh = mvthresh;
 
-  for (i = 0; i < 4; i++)
-    bsi->modes[i] = ZEROMV;
+  for (idx = 0; idx < 4; ++idx)
+    bsi->modes[idx] = ZEROMV;
+
+#if CONFIG_REFMV
+  for (idx = 0; idx < 4; ++idx) {
+    for (k = NEARESTMV; k <= NEWMV; ++k) {
+      bsi->rdstat[idx][INTER_OFFSET(k)].pred_mv[0].as_int = INVALID_MV;
+      bsi->rdstat[idx][INTER_OFFSET(k)].pred_mv[1].as_int = INVALID_MV;
+
+      bsi->rdstat[idx][INTER_OFFSET(k)].mvs[0].as_int = INVALID_MV;
+      bsi->rdstat[idx][INTER_OFFSET(k)].mvs[1].as_int = INVALID_MV;
+    }
+  }
+#endif
 
   memcpy(t_above, pd->above_context, sizeof(t_above));
   memcpy(t_left, pd->left_context, sizeof(t_left));
@@ -4856,6 +4870,13 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
                                       &frame_mv[NEARESTMV][frame],
                                       &frame_mv[NEARMV][frame]);
 
+#if CONFIG_REF_MV
+        tmp_ref_mv[ref] = frame_mv[NEARESTMV][mbmi->ref_frame[ref]];
+        lower_mv_precision(&tmp_ref_mv[ref].as_mv, cm->allow_high_precision_mv);
+        bsi->ref_mv[ref] = &tmp_ref_mv[ref];
+        mbmi_ext->ref_mvs[frame][0] = tmp_ref_mv[ref];
+#endif
+
 #if CONFIG_EXT_INTER
         mv_ref_list[0].as_int = frame_mv[NEARESTMV][frame].as_int;
         mv_ref_list[1].as_int = frame_mv[NEARMV][frame].as_int;
@@ -4900,6 +4921,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
 #endif  // CONFIG_EXT_INTER
         const struct buf_2d orig_src = x->plane[0].src;
         struct buf_2d orig_pre[2];
+        int run_rd_check = 0;
 
         mode_idx = INTER_OFFSET(this_mode);
 #if CONFIG_EXT_INTER
@@ -4912,6 +4934,55 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
         if (!(inter_mode_mask & (1 << this_mode)))
           continue;
 
+#if CONFIG_REF_MV
+        run_rd_check = 2;
+#if !CONFIG_EXT_INTER
+        if (filter_idx > 0) {
+          BEST_SEG_INFO* ref_bsi = bsi_buf;
+          if (seg_mvs[i][mbmi->ref_frame[0]].as_int ==
+              ref_bsi->rdstat[i][mode_idx].mvs[0].as_int &&
+              ref_bsi->rdstat[i][mode_idx].mvs[0].as_int != INVALID_MV)
+            if (bsi->ref_mv[0]->as_int ==
+                ref_bsi->rdstat[i][mode_idx].pred_mv[0].as_int)
+              --run_rd_check;
+
+          if (!has_second_rf) {
+            --run_rd_check;
+          } else {
+            if (seg_mvs[i][mbmi->ref_frame[1]].as_int ==
+                ref_bsi->rdstat[i][mode_idx].mvs[1].as_int &&
+                ref_bsi->rdstat[i][mode_idx].mvs[1].as_int != INVALID_MV)
+              if (bsi->ref_mv[1]->as_int ==
+                  ref_bsi->rdstat[i][mode_idx].pred_mv[1].as_int)
+                --run_rd_check;
+          }
+
+          if (run_rd_check != 0 && filter_idx > 1) {
+            ref_bsi = bsi_buf + 1;
+            run_rd_check = 2;
+
+            if (seg_mvs[i][mbmi->ref_frame[0]].as_int ==
+                ref_bsi->rdstat[i][mode_idx].mvs[0].as_int &&
+                ref_bsi->rdstat[i][mode_idx].mvs[0].as_int != INVALID_MV)
+              if (bsi->ref_mv[0]->as_int ==
+                  ref_bsi->rdstat[i][mode_idx].pred_mv[0].as_int)
+                --run_rd_check;
+
+            if (!has_second_rf) {
+              --run_rd_check;
+            } else {
+              if (seg_mvs[i][mbmi->ref_frame[1]].as_int ==
+                  ref_bsi->rdstat[i][mode_idx].mvs[1].as_int &&
+                  ref_bsi->rdstat[i][mode_idx].mvs[1].as_int != INVALID_MV)
+                if (bsi->ref_mv[1]->as_int ==
+                    ref_bsi->rdstat[i][mode_idx].pred_mv[1].as_int)
+                  --run_rd_check;
+            }
+          }
+        }
+#endif  // CONFIG_EXT_INTER
+#endif  // CONFIG_REF_MV
+
         if (!check_best_zero_mv(cpi, mbmi_ext->mode_context,
 #if CONFIG_REF_MV && CONFIG_EXT_INTER
                                 mbmi_ext->compound_mode_context,
@@ -4933,7 +5004,8 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
             seg_mvs[i][mv_idx][mbmi->ref_frame[0]].as_int == INVALID_MV
 #else
             this_mode == NEWMV &&
-            seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV
+            (seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV ||
+                run_rd_check)
 #endif  // CONFIG_EXT_INTER
             ) {
 #if CONFIG_EXT_INTER
@@ -4958,11 +5030,13 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
             bsi->mvp.as_int = bsi->ref_mv[0]->as_int;
 #else
             // use previous block's result as next block's MV predictor.
+#if !CONFIG_REF_MV
             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;
             }
+#endif
 #endif  // CONFIG_EXT_INTER
           }
           if (i == 0)
@@ -4981,8 +5055,13 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
             step_param = cpi->mv_step_param;
           }
 
+#if CONFIG_REF_MV
+          mvp_full.row = best_ref_mv->as_mv.row >> 3;
+          mvp_full.col = best_ref_mv->as_mv.col >> 3;
+#else
           mvp_full.row = bsi->mvp.as_mv.row >> 3;
           mvp_full.col = bsi->mvp.as_mv.col >> 3;
+#endif
 
           if (cpi->sf.adaptive_motion_search) {
             mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3;
@@ -5090,7 +5169,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
 #else
             this_mode == NEWMV &&
 #endif  // CONFIG_EXT_INTER
-            mbmi->interp_filter == EIGHTTAP_REGULAR) {
+            (mbmi->interp_filter == EIGHTTAP_REGULAR || run_rd_check)) {
           // adjust src pointers
           mi_buf_shift(x, i);
           if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
@@ -5208,8 +5287,34 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
 
           if (!subpelmv && have_ref &&
               ref_bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) {
+#if CONFIG_REF_MV
+            bsi->rdstat[i][mode_idx].pred_mv[0].as_int =
+                bsi->ref_mv[0]->as_int;
+
+            if (has_second_rf)
+              bsi->rdstat[i][mode_idx].pred_mv[1].as_int =
+                  bsi->ref_mv[1]->as_int;
+
+            bsi->rdstat[i][mode_idx].byrate =
+                ref_bsi->rdstat[i][mode_idx].byrate;
+            bsi->rdstat[i][mode_idx].bdist =
+                ref_bsi->rdstat[i][mode_idx].bdist;
+            bsi->rdstat[i][mode_idx].bsse =
+                ref_bsi->rdstat[i][mode_idx].bsse;
+            bsi->rdstat[i][mode_idx].brate +=
+                ref_bsi->rdstat[i][mode_idx].byrate;
+            bsi->rdstat[i][mode_idx].eobs =
+                ref_bsi->rdstat[i][mode_idx].eobs;
+            memcpy(bsi->rdstat[i][mode_idx].ta,
+                   ref_bsi->rdstat[i][mode_idx].ta,
+                   sizeof(bsi->rdstat[i][mode_idx].ta));
+            memcpy(bsi->rdstat[i][mode_idx].tl,
+                   ref_bsi->rdstat[i][mode_idx].tl,
+                   sizeof(bsi->rdstat[i][mode_idx].tl));
+#else
             memcpy(&bsi->rdstat[i][mode_idx], &ref_bsi->rdstat[i][mode_idx],
                    sizeof(SEG_RDSTAT));
+#endif
             if (num_4x4_blocks_wide > 1)
               bsi->rdstat[i + 1][mode_idx].eobs =
                   ref_bsi->rdstat[i + 1][mode_idx].eobs;
@@ -5320,23 +5425,24 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
   if (bsi->segment_rd > best_rd)
     return INT64_MAX;
   /* set it to the best */
-  for (i = 0; i < 4; i++) {
-    mode_idx = INTER_OFFSET(bsi->modes[i]);
-    mi->bmi[i].as_mv[0].as_int = bsi->rdstat[i][mode_idx].mvs[0].as_int;
+  for (idx = 0; idx < 4; idx++) {
+    mode_idx = INTER_OFFSET(bsi->modes[idx]);
+    mi->bmi[idx].as_mv[0].as_int = bsi->rdstat[idx][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;
+      mi->bmi[idx].as_mv[1].as_int = bsi->rdstat[idx][mode_idx].mvs[1].as_int;
 #if CONFIG_REF_MV
-    mi->bmi[i].pred_mv_s8[0] = bsi->rdstat[i][mode_idx].pred_mv[0];
+    mi->bmi[idx].pred_mv_s8[0] = bsi->rdstat[idx][mode_idx].pred_mv[0];
     if (has_second_ref(mbmi))
-      mi->bmi[i].pred_mv_s8[1] = bsi->rdstat[i][mode_idx].pred_mv[1];
+      mi->bmi[idx].pred_mv_s8[1] = bsi->rdstat[idx][mode_idx].pred_mv[1];
 #endif
 #if CONFIG_EXT_INTER
-    mi->bmi[i].ref_mv[0].as_int = bsi->rdstat[i][mode_idx].ref_mv[0].as_int;
+    mi->bmi[idx].ref_mv[0].as_int = bsi->rdstat[idx][mode_idx].ref_mv[0].as_int;
     if (has_second_rf)
-      mi->bmi[i].ref_mv[1].as_int = bsi->rdstat[i][mode_idx].ref_mv[1].as_int;
+      mi->bmi[idx].ref_mv[1].as_int =
+          bsi->rdstat[idx][mode_idx].ref_mv[1].as_int;
 #endif  // CONFIG_EXT_INTER
-    x->plane[0].eobs[i] = bsi->rdstat[i][mode_idx].eobs;
-    mi->bmi[i].as_mode = bsi->modes[i];
+    x->plane[0].eobs[idx] = bsi->rdstat[idx][mode_idx].eobs;
+    mi->bmi[idx].as_mode = bsi->modes[idx];
   }
 
   /*