]> granicus.if.org Git - libvpx/commitdiff
Enable adaptive motion vector referencing mode
authorJingning Han <jingning@google.com>
Fri, 15 Jan 2016 17:05:51 +0000 (09:05 -0800)
committerJingning Han <jingning@google.com>
Tue, 2 Feb 2016 23:15:40 +0000 (15:15 -0800)
This commit allows an adaptive motion vector referencing mode
approach. It checks the available reference motion vector candidate
list and decides the amount of motion vector referencing modes. The
current implementation assumes simple binary coding for the syntax.

The compression performance is improved by
derf   0.11%
hevcmr 0.38%
stdhd  0.09%
hevchr 0.23%

The coding gains due to the new reference motion vector system are
derf   1.0%
hevcmr 1.7%
stdhd  1.4%
hevchr 1.3%

Change-Id: Idf932fc373546fe59c8741f1b933ff656e8dbc3f

vp10/common/blockd.h
vp10/decoder/decodemv.c
vp10/encoder/bitstream.c
vp10/encoder/rdopt.c

index 27e33bafa6a1fc46ed7db1342f8ac0ee800284ca..5e41b6b07a8223e9b60e684b212427a7b6a516a9 100644 (file)
@@ -167,6 +167,9 @@ typedef struct {
 
   int_mv mv[2];
   int_mv pred_mv[2];
+#if CONFIG_REF_MV
+  uint8_t ref_mv_idx;
+#endif
 } MB_MODE_INFO;
 
 typedef struct MODE_INFO {
index 44b0fc7eca1db5b7c233141b7c488b66e99725d6..41c2565caf9af19abfb1ecfa17f16ad68618236c 100644 (file)
@@ -1003,6 +1003,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
 #endif  // CONFIG_EXT_INTER
   mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx,
                                         mbmi->ref_frame, bsize, -1);
+  mbmi->ref_mv_idx = 0;
 #else
   mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]];
 #endif
@@ -1015,9 +1016,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
         return;
     }
   } else {
-    if (bsize >= BLOCK_8X8)
+    if (bsize >= BLOCK_8X8) {
 #if CONFIG_EXT_INTER
-    {
       if (is_compound)
         mbmi->mode = read_inter_compound_mode(cm, xd, r, mode_ctx);
       else
@@ -1027,9 +1027,12 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
                                    mbmi,
 #endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
                                    r, mode_ctx);
-#if CONFIG_EXT_INTER
+#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);
+#endif
     }
-#endif  // CONFIG_EXT_INTER
   }
 
 #if CONFIG_EXT_INTER
@@ -1045,6 +1048,12 @@ 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;
+    lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
+    nearmv[0] = cur_mv;
+  }
+
 #if CONFIG_EXT_INTER
   if (is_compound && bsize >= BLOCK_8X8 && mbmi->mode != ZERO_ZEROMV) {
 #else
index db2e8ee1050b8ea9422d80994de62d27ea1d65d6..60e168b06c9b9df05664562c1d666b7c4d248ef8 100644 (file)
@@ -988,6 +988,12 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
                          has_second_ref(mbmi),
 #endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
                          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);
+#endif
       }
     }
 
index 1a6e6c541d2309e998a7a4e052a70dbbef213bce..eb0a1bc2e65a0905ce93b342e71d84b7f869847f 100644 (file)
@@ -5715,6 +5715,9 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
   int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
   int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
   MB_MODE_INFO best_mbmode;
+#if CONFIG_REF_MV
+  uint8_t best_ref_mv_idx[MAX_REF_FRAMES] = { 0 };
+#endif
   int best_mode_skippable = 0;
   int midx, best_mode_index = -1;
   unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
@@ -6273,6 +6276,78 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
                                   single_skippable, &total_sse, best_rd,
                                   &mask_filter, filter_cache);
 
+#if CONFIG_REF_MV
+      mbmi->ref_mv_idx = 0;
+
+      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;
+        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);
+        }
+
+        if (RDCOST(x->rdmult, x->rddiv, rate2, distortion2) >
+            RDCOST(x->rdmult, x->rddiv, tmp_rate, tmp_dist) &&
+            tmp_alt_rd != INT64_MAX) {
+          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] = backup_mv;
+
+        rate2 += 256;
+      }
+#endif
+
       if (this_rd == INT64_MAX)
         continue;
 
@@ -6482,6 +6557,14 @@ 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 &&
+          best_mbmode.ref_frame[1] == NONE) {
+        int_mv cur_mv =
+            mbmi_ext->ref_mv_stack[best_mbmode.ref_frame[0]][2].this_mv;
+        lower_mv_precision(&cur_mv.as_mv, cm->allow_high_precision_mv);
+        frame_mv[NEARMV][refs[0]] = cur_mv;
+      }
+
       if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
         best_mbmode.mode = NEARESTMV;
       else if (frame_mv[NEARMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
@@ -6593,6 +6676,9 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
     if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET))
       best_mbmode.mode = ZEROMV;
   }
+
+  if (best_mbmode.mode == NEARMV && best_mbmode.ref_frame[1] == NONE)
+    best_mbmode.ref_mv_idx = best_ref_mv_idx[best_mbmode.ref_frame[0]];
 #endif
 
   if (best_mode_index < 0 || best_rd >= best_rd_so_far) {