]> granicus.if.org Git - libvpx/commitdiff
Generalize the dynamic reference motion vector coding mode
authorJingning Han <jingning@google.com>
Wed, 20 Jan 2016 00:36:25 +0000 (16:36 -0800)
committerJingning Han <jingning@google.com>
Wed, 3 Feb 2016 19:57:42 +0000 (11:57 -0800)
This commit generalizes dynamic reference motion vector coding mode
to support multiple candidate modes in the rate-distortion
optimization scheme and to support the selection in the bit-stream
syntax. The maximum number of modes allowed is currently limited to
4. The syntax elements for the dynamic reference motion vector
modes are using binary codes. The scheme supports single reference
frame.

It improves the compression performance
derf   0.135%
hevcmr 0.098%

Change-Id: Id053d6ce76e8365e52727bd0d12d28ce3de2e0e8

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

index 41c2565caf9af19abfb1ecfa17f16ad68618236c..38552e1db7a128b681b59e3b11aea5a5b6df1cd3 100644 (file)
@@ -1028,9 +1028,16 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
 #endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
                                    r, mode_ctx);
 #if CONFIG_REF_MV
-    if (mbmi->mode == NEARMV && !is_compound)
-      if (xd->ref_mv_count[mbmi->ref_frame[0]] > 2)
-        mbmi->ref_mv_idx = vpx_read_bit(r);
+      if (mbmi->mode == NEARMV && !is_compound) {
+        if (xd->ref_mv_count[mbmi->ref_frame[0]] > 2) {
+          if (vpx_read_bit(r)) {
+            mbmi->ref_mv_idx = 1;
+            if (xd->ref_mv_count[mbmi->ref_frame[0]] > 3)
+              if (vpx_read_bit(r))
+                mbmi->ref_mv_idx = 2;
+          }
+        }
+      }
 #endif
     }
   }
@@ -1048,8 +1055,9 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
   }
 
 #if CONFIG_REF_MV
-  if (mbmi->ref_mv_idx == 1) {
-    int_mv cur_mv = xd->ref_mv_stack[mbmi->ref_frame[0]][2].this_mv;
+  if (mbmi->ref_mv_idx > 0) {
+    int_mv cur_mv =
+        xd->ref_mv_stack[mbmi->ref_frame[0]][1 + mbmi->ref_mv_idx].this_mv;
     lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
     nearmv[0] = cur_mv;
   }
index 837fd5bfde62f8eff084653b2f7161dffd9856ac..e0f9bf0330badd5569ebe50d5a9fe9c7578375cc 100644 (file)
@@ -990,9 +990,14 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
                          mode_ctx);
 
 #if CONFIG_REF_MV
-      if (mode == NEARMV && mbmi->ref_frame[1] == NONE)
-        if (mbmi_ext->ref_mv_count[mbmi->ref_frame[0]] > 2)
-          vpx_write_bit(w, mbmi->ref_mv_idx);
+        if (mode == NEARMV && mbmi->ref_frame[1] == NONE) {
+          if (mbmi_ext->ref_mv_count[mbmi->ref_frame[0]] > 2) {
+            vpx_write_bit(w, mbmi->ref_mv_idx != 0);
+            if (mbmi_ext->ref_mv_count[mbmi->ref_frame[0]] > 3 &&
+                mbmi->ref_mv_idx > 0)
+              vpx_write_bit(w, mbmi->ref_mv_idx != 1);
+          }
+        }
 #endif
       }
     }
index 32031ec92719a5e7420874a9c4712b6f6a564f13..cfff06daa4589fb1aca2808a0fe5ebc329359b0e 100644 (file)
@@ -6279,51 +6279,18 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
 #if CONFIG_REF_MV
       mbmi->ref_mv_idx = 0;
 
+      // TODO(jingning): This needs some refactoring to improve code quality
+      // and reduce redundant steps.
       if (!comp_pred && mbmi->mode == NEARMV &&
           mbmi_ext->ref_mv_count[ref_frame] > 2) {
         int_mv backup_mv = frame_mv[NEARMV][ref_frame];
         int_mv cur_mv = mbmi_ext->ref_mv_stack[ref_frame][2].this_mv;
         MB_MODE_INFO backup_mbmi = *mbmi;
 
-        int64_t tmp_alt_rd = INT64_MAX, tmp_ref_rd = this_rd;
-        int tmp_rate = 0, tmp_rate_y = 0, tmp_rate_uv = 0;
-        int tmp_skip = 1;
-        int64_t tmp_dist = 0, tmp_sse = 0;
-
-        lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
-        clamp_mv2(&cur_mv.as_mv, xd);
-
-        if (!mv_check_bounds(x, &cur_mv.as_mv)) {
-          int64_t dummy_filter_cache[SWITCHABLE_FILTER_CONTEXTS];
-          INTERP_FILTER dummy_single_inter_filter[MB_MODE_COUNT]
-                                                 [MAX_REF_FRAMES];
-          int dummy_single_skippable[MB_MODE_COUNT][MAX_REF_FRAMES];
-          int dummy_disable_skip = 0;
-          int64_t dummy_mask_filter = 0;
-#if CONFIG_EXT_INTER
-          int_mv dummy_single_newmvs[2][MAX_REF_FRAMES] =
-                                        { { { 0 } },  { { 0 } } };
-#else
-          int_mv dummy_single_newmv[MAX_REF_FRAMES] = { { 0 } };
-#endif
-
-          frame_mv[NEARMV][ref_frame] = cur_mv;
-          tmp_alt_rd = handle_inter_mode(cpi, x, bsize,
-                                         &tmp_rate, &tmp_dist, &tmp_skip,
-                                         &tmp_rate_y, &tmp_rate_uv,
-                                         &dummy_disable_skip, frame_mv,
-                                         mi_row, mi_col,
-#if CONFIG_EXT_INTER
-                                         dummy_single_newmvs,
-#else
-                                         dummy_single_newmv,
-#endif
-                                         dummy_single_inter_filter,
-                                         dummy_single_skippable,
-                                         &tmp_sse, best_rd,
-                                         &dummy_mask_filter,
-                                         dummy_filter_cache);
-        }
+        int64_t tmp_ref_rd = this_rd;
+        int ref_idx;
+        int ref_set = VPXMIN(2, mbmi_ext->ref_mv_count[ref_frame] - 2);
+        rate2 += vp10_cost_bit(128, 0);
 
         if (this_rd < INT64_MAX) {
           if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) <
@@ -6338,37 +6305,86 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
                 total_sse);
         }
 
-        if (tmp_alt_rd < INT64_MAX) {
-          if (RDCOST(x->rdmult, x->rddiv, tmp_rate_y + tmp_rate_uv, tmp_dist) <
-              RDCOST(x->rdmult, x->rddiv, 0, tmp_sse))
-            tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
-                tmp_rate + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 0),
-                tmp_dist);
-          else
-            tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
-                tmp_rate + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 1) -
-                tmp_rate_y - tmp_rate_uv,
-                tmp_sse);
-        }
+        for (ref_idx = 0; ref_idx < ref_set; ++ref_idx) {
+          int64_t tmp_alt_rd = INT64_MAX;
+          int tmp_rate = 0, tmp_rate_y = 0, tmp_rate_uv = 0;
+          int tmp_skip = 1;
+          int64_t tmp_dist = 0, tmp_sse = 0;
+
+          cur_mv = mbmi_ext->ref_mv_stack[ref_frame][2 + ref_idx].this_mv;
+          lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
+          clamp_mv2(&cur_mv.as_mv, xd);
+
+          if (!mv_check_bounds(x, &cur_mv.as_mv)) {
+            int64_t dummy_filter_cache[SWITCHABLE_FILTER_CONTEXTS];
+            INTERP_FILTER dummy_single_inter_filter[MB_MODE_COUNT]
+                                                   [MAX_REF_FRAMES];
+            int dummy_single_skippable[MB_MODE_COUNT][MAX_REF_FRAMES];
+            int dummy_disable_skip = 0;
+            int64_t dummy_mask_filter = 0;
+#if CONFIG_EXT_INTER
+            int_mv dummy_single_newmvs[2][MAX_REF_FRAMES] =
+                                          { { { 0 } },  { { 0 } } };
+#else
+            int_mv dummy_single_newmv[MAX_REF_FRAMES] = { { 0 } };
+#endif
 
-        if (tmp_ref_rd > tmp_alt_rd) {
-          rate2 = tmp_rate;
-          distortion2 = tmp_dist;
-          skippable = tmp_skip;
-          rate_y = tmp_rate_y;
-          rate_uv = tmp_rate_uv;
-          total_sse = tmp_sse;
-          this_rd = tmp_alt_rd;
-          mbmi->ref_mv_idx = 1;
-          // Indicator of the effective nearmv reference motion vector.
-          best_ref_mv_idx[ref_frame] = 1;
-        } else {
-          *mbmi = backup_mbmi;
+
+            frame_mv[NEARMV][ref_frame] = cur_mv;
+            tmp_alt_rd = handle_inter_mode(cpi, x, bsize,
+                                           &tmp_rate, &tmp_dist, &tmp_skip,
+                                           &tmp_rate_y, &tmp_rate_uv,
+                                           &dummy_disable_skip, frame_mv,
+                                           mi_row, mi_col,
+#if CONFIG_EXT_INTER
+                                           dummy_single_newmvs,
+#else
+                                           dummy_single_newmv,
+#endif
+                                           dummy_single_inter_filter,
+                                           dummy_single_skippable,
+                                           &tmp_sse, best_rd,
+                                           &dummy_mask_filter,
+                                           dummy_filter_cache);
+          }
+
+          tmp_rate += vp10_cost_bit(128, 1);
+          if (mbmi_ext->ref_mv_count[ref_frame] > 3)
+            tmp_rate += vp10_cost_bit(128, ref_idx);
+
+          if (tmp_alt_rd < INT64_MAX) {
+            if (RDCOST(x->rdmult, x->rddiv,
+                       tmp_rate_y + tmp_rate_uv, tmp_dist) <
+                RDCOST(x->rdmult, x->rddiv, 0, tmp_sse))
+              tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
+                  tmp_rate + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 0),
+                  tmp_dist);
+            else
+              tmp_alt_rd = RDCOST(x->rdmult, x->rddiv,
+                  tmp_rate + vp10_cost_bit(vp10_get_skip_prob(cm, xd), 1) -
+                  tmp_rate_y - tmp_rate_uv,
+                  tmp_sse);
+          }
+
+          if (tmp_ref_rd > tmp_alt_rd) {
+            rate2 = tmp_rate;
+            distortion2 = tmp_dist;
+            skippable = tmp_skip;
+            rate_y = tmp_rate_y;
+            rate_uv = tmp_rate_uv;
+            total_sse = tmp_sse;
+            this_rd = tmp_alt_rd;
+            mbmi->ref_mv_idx = 1 + ref_idx;
+            // Indicator of the effective nearmv reference motion vector.
+            best_ref_mv_idx[ref_frame] = 1 + ref_idx;
+            tmp_ref_rd = tmp_alt_rd;
+            backup_mbmi = *mbmi;
+          } else {
+            *mbmi = backup_mbmi;
+          }
         }
 
         frame_mv[NEARMV][ref_frame] = backup_mv;
-
-        rate2 += vp10_cost_bit(128, mbmi->ref_mv_idx);
       }
 #endif
 
@@ -6581,10 +6597,11 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
     int comp_pred_mode = refs[1] > INTRA_FRAME;
 #if CONFIG_REF_MV
     if (!comp_pred_mode) {
-      if (best_ref_mv_idx[best_mbmode.ref_frame[0]] == 1 &&
+      if (best_ref_mv_idx[best_mbmode.ref_frame[0]] > 0 &&
           best_mbmode.ref_frame[1] == NONE) {
+        int idx = best_ref_mv_idx[best_mbmode.ref_frame[0]] + 1;
         int_mv cur_mv =
-            mbmi_ext->ref_mv_stack[best_mbmode.ref_frame[0]][2].this_mv;
+            mbmi_ext->ref_mv_stack[best_mbmode.ref_frame[0]][idx].this_mv;
         lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
         frame_mv[NEARMV][refs[0]] = cur_mv;
       }