New inter mode context
authorPaul Wilkins <paulwilkins@google.com>
Mon, 12 Nov 2012 15:09:25 +0000 (15:09 +0000)
committerPaul Wilkins <paulwilkins@google.com>
Mon, 12 Nov 2012 15:50:02 +0000 (15:50 +0000)
This change is a fix / extension of the newbestrefmv
experiment. As such it is presented without IFDEF.

The change creates a new context for coding inter modes
in vp9_find_mv_refs(). This replaces the context that
was previously calculated in vp9_find_near_mvs().
The new context is unoptimized and not necessarily
any better at this stage (results pending), but eliminates
the need for a legacy call to vp9_find_near_mvs().
Based on numbers from Scott, this could help decode
speed by several %.

In a later patch I will add support for forward update of
context (assuming this helps) and refine the context as
necessary.

Change-Id: I1cd991b82c8df86cc02237a34185e6d67510698a

vp9/common/blockd.h
vp9/common/entropymode.c
vp9/common/entropymode.h
vp9/common/findnearmv.c
vp9/common/findnearmv.h
vp9/common/modecont.c
vp9/common/mvref_common.c
vp9/common/onyxc_int.h
vp9/decoder/decodemv.c
vp9/encoder/bitstream.c
vp9/encoder/rdopt.c

index 300c01f..0cfa9dc 100644 (file)
@@ -231,6 +231,8 @@ typedef struct {
   int_mv mv[2]; // for each reference frame used
   int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REFS];
 
+  int mb_mode_context[MAX_REF_FRAMES];
+
   SPLITMV_PARTITIONING_TYPE partitioning;
   unsigned char mb_skip_coeff;                                /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */
   unsigned char need_to_clamp_mvs;
index 37d09db..d0e83ec 100644 (file)
@@ -451,7 +451,7 @@ void vp9_init_mode_contexts(VP9_COMMON *pc) {
 
 void vp9_accum_mv_refs(VP9_COMMON *pc,
                        MB_PREDICTION_MODE m,
-                       const int ct[4]) {
+                       const int context) {
   int (*mv_ref_ct)[4][2];
 
   if (pc->refresh_alt_ref_frame)
@@ -460,21 +460,21 @@ void vp9_accum_mv_refs(VP9_COMMON *pc,
     mv_ref_ct = pc->fc.mv_ref_ct;
 
   if (m == ZEROMV) {
-    ++mv_ref_ct [ct[0]] [0] [0];
+    ++mv_ref_ct[context][0][0];
   } else {
-    ++mv_ref_ct [ct[0]] [0] [1];
+    ++mv_ref_ct[context][0][1];
     if (m == NEARESTMV) {
-      ++mv_ref_ct [ct[1]] [1] [0];
+      ++mv_ref_ct[context][1][0];
     } else {
-      ++mv_ref_ct [ct[1]] [1] [1];
+      ++mv_ref_ct[context][1][1];
       if (m == NEARMV) {
-        ++mv_ref_ct [ct[2]] [2] [0];
+        ++mv_ref_ct[context][2][0];
       } else {
-        ++mv_ref_ct [ct[2]] [2] [1];
+        ++mv_ref_ct[context][2][1];
         if (m == NEWMV) {
-          ++mv_ref_ct [ct[3]] [3] [0];
+          ++mv_ref_ct[context][3][0];
         } else {
-          ++mv_ref_ct [ct[3]] [3] [1];
+          ++mv_ref_ct[context][3][1];
         }
       }
     }
@@ -496,7 +496,7 @@ void vp9_update_mode_context(VP9_COMMON *pc) {
     mode_context = pc->fc.mode_context;
   }
 
-  for (j = 0; j < 6; j++) {
+  for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
     for (i = 0; i < 4; i++) {
       int this_prob;
       int count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
index 0297591..34a2bea 100644 (file)
@@ -79,7 +79,7 @@ extern void vp9_update_mode_context(struct VP9Common *pc);
 
 extern void vp9_accum_mv_refs(struct VP9Common *pc,
                               MB_PREDICTION_MODE m,
-                              const int ct[4]);
+                              const int context);
 
 void vp9_default_bmode_probs(vp9_prob dest[VP9_NKF_BINTRAMODES - 1]);
 
index 84a377e..8cc0474 100644 (file)
@@ -31,140 +31,13 @@ static void lower_mv_precision(int_mv *mv, int usehp)
   }
 }
 
-/* Predict motion vectors using those from already-decoded nearby blocks.
-   Note that we only consider one 4x4 subblock from each candidate 16x16
-   macroblock.   */
-
-void vp9_find_near_mvs
-(
-  MACROBLOCKD *xd,
-  const MODE_INFO *here,
-  const MODE_INFO *lf_here,
-  int_mv *nearest,
-  int_mv *nearby,
-  int_mv *best_mv,
-  int cnt[4],
-  int refframe,
-  int *ref_frame_sign_bias) {
-  const MODE_INFO *above = here - xd->mode_info_stride;
-  const MODE_INFO *left = here - 1;
-  const MODE_INFO *aboveleft = above - 1;
-  const MODE_INFO *third = NULL;
-  int_mv            near_mvs[4];
-  int_mv           *mv = near_mvs;
-  int             *cntx = cnt;
-  enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
-
-  /* Zero accumulators */
-  mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
-  cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
-
-  /* Process above */
-  if (above->mbmi.ref_frame != INTRA_FRAME) {
-    if (above->mbmi.mv[0].as_int) {
-      ++ mv;
-      mv->as_int = above->mbmi.mv[0].as_int;
-      mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
-              refframe, mv, ref_frame_sign_bias);
-      ++cntx;
-    }
-    *cntx += 2;
-  }
-
-  /* Process left */
-  if (left->mbmi.ref_frame != INTRA_FRAME) {
-    if (left->mbmi.mv[0].as_int) {
-      int_mv this_mv;
-      this_mv.as_int = left->mbmi.mv[0].as_int;
-      mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
-              refframe, &this_mv, ref_frame_sign_bias);
-
-      if (this_mv.as_int != mv->as_int) {
-        ++ mv;
-        mv->as_int = this_mv.as_int;
-        ++ cntx;
-      }
-      *cntx += 2;
-    } else
-      cnt[CNT_INTRA] += 2;
-  }
-  /* Process above left or the one from last frame */
-  if (aboveleft->mbmi.ref_frame != INTRA_FRAME ||
-      (lf_here->mbmi.ref_frame == LAST_FRAME && refframe == LAST_FRAME)) {
-    if (aboveleft->mbmi.mv[0].as_int) {
-      third = aboveleft;
-    } else if (lf_here->mbmi.mv[0].as_int) {
-      third = lf_here;
-    }
-    if (third) {
-      int_mv this_mv;
-      this_mv.as_int = third->mbmi.mv[0].as_int;
-      mv_bias(ref_frame_sign_bias[third->mbmi.ref_frame],
-              refframe, &this_mv, ref_frame_sign_bias);
-
-      if (this_mv.as_int != mv->as_int) {
-        ++ mv;
-        mv->as_int = this_mv.as_int;
-        ++ cntx;
-      }
-      *cntx += 1;
-    } else
-      cnt[CNT_INTRA] += 1;
-  }
-
-  /* If we have three distinct MV's ... */
-  if (cnt[CNT_SPLITMV]) {
-    /* See if the third MV can be merged with NEAREST */
-    if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
-      cnt[CNT_NEAREST] += 1;
-  }
-
-  cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
-                      + (left->mbmi.mode == SPLITMV)) * 2
-                     + (
-                       lf_here->mbmi.mode == SPLITMV ||
-                       aboveleft->mbmi.mode == SPLITMV);
-
-  /* Swap near and nearest if necessary */
-  if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
-    int tmp;
-    tmp = cnt[CNT_NEAREST];
-    cnt[CNT_NEAREST] = cnt[CNT_NEAR];
-    cnt[CNT_NEAR] = tmp;
-    tmp = near_mvs[CNT_NEAREST].as_int;
-    near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
-    near_mvs[CNT_NEAR].as_int = tmp;
-  }
-
-  /* Use near_mvs[0] to store the "best" MV */
-  if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA])
-    near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];
-
-  /* Set up return values */
-  best_mv->as_int = near_mvs[0].as_int;
-  nearest->as_int = near_mvs[CNT_NEAREST].as_int;
-  nearby->as_int = near_mvs[CNT_NEAR].as_int;
-
-  /* Make sure that the 1/8th bits of the Mvs are zero if high_precision
-   * is not being used, by truncating the last bit towards 0
-   */
-  lower_mv_precision(best_mv, xd->allow_high_precision_mv);
-  lower_mv_precision(nearest, xd->allow_high_precision_mv);
-  lower_mv_precision(nearby, xd->allow_high_precision_mv);
-
-  // TODO: move clamp outside findnearmv
-  clamp_mv2(nearest, xd);
-  clamp_mv2(nearby, xd);
-  clamp_mv2(best_mv, xd);
-}
-
 vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc,
-                           vp9_prob p[VP9_MVREFS - 1],
-                           const int near_mv_ref_ct[4]) {
-  p[0] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[0]][0];
-  p[1] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[1]][1];
-  p[2] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[2]][2];
-  p[3] = pc->fc.vp9_mode_contexts[near_mv_ref_ct[3]][3];
+                           vp9_prob p[4], const int context
+                          ) {
+  p[0] = pc->fc.vp9_mode_contexts[context][0];
+  p[1] = pc->fc.vp9_mode_contexts[context][1];
+  p[2] = pc->fc.vp9_mode_contexts[context][2];
+  p[3] = pc->fc.vp9_mode_contexts[context][3];
   return p;
 }
 
index c53575e..64233ec 100644 (file)
@@ -79,17 +79,9 @@ static unsigned int check_mv_bounds(int_mv *mv,
          (mv->as_mv.row > mb_to_bottom_edge);
 }
 
-void vp9_find_near_mvs(MACROBLOCKD *xd,
-                       const MODE_INFO *here,
-                       const MODE_INFO *lfhere,
-                       int_mv *nearest, int_mv *nearby, int_mv *best,
-                       int near_mv_ref_cts[4],
-                       int refframe,
-                       int *ref_frame_sign_bias);
-
 vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc,
                            vp9_prob p[VP9_MVREFS - 1],
-                           const int near_mv_ref_ct[4]);
+                           const int context);
 
 extern const unsigned char vp9_mbsplit_offset[4][16];
 
index 023d201..ac6719a 100644 (file)
 
 
 #include "entropy.h"
+
 const int vp9_default_mode_contexts[6][4] = {
-  {
-    /* 0 */
-    7,     1,     1,   183
-  },
-  {
-    /* 1 */
-    14,    18,    14,   147
-  },
-  {
-    /* 2 */
-    135,    64,    57,    68
-  },
-  {
-    /* 3 */
-    60,    56,   128,   65
-  },
-  {
-    /* 4 */
-    159,   134,   128,   34
-  },
-  {
-    /* 5 */
-    234,   188,   128,   28
-  },
+  {117,     1,     1,    141},
+  {234,     1,     1,    213},
+  {128,     90,    22,   145},
+  {30,      104,   61,   159},
+  {13,      169,   18,   206},
+  {15,      76,    24,   166}
 };
 const int vp9_default_mode_contexts_a[6][4] = {
-  {
-    /* 0 */
-    4,     1,    1,   143
-  },
-  {
-    /* 1 */
-    7,     9,    7,   107
-  },
-  {
-    /* 2 */
-    95,    34,   57,    68
-  },
-  {
-    /* 3 */
-    95,    56,   128,   65
-  },
-  {
-    /* 4 */
-    159,   67,   128,   34
-  },
-  {
-    /* 5 */
-    234,   94,   128,   28
-  },
+  {117,     1,     1,    141},
+  {234,     1,     1,    213},
+  {128,     90,    22,   145},
+  {30,      104,   61,   159},
+  {13,      169,   18,   206},
+  {15,      76,    24,   166}
 };
index 67f2fb0..a412a6c 100644 (file)
@@ -214,6 +214,7 @@ void vp9_find_mv_refs(
 
   int i;
   MODE_INFO *candidate_mi;
+  MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
   int_mv candidate_mvs[MAX_MV_REFS];
   int_mv c_refmv;
   MV_REFERENCE_FRAME c_ref_frame;
@@ -328,6 +329,31 @@ void vp9_find_mv_refs(
     index = (MAX_MV_REFS - 1);
   }
 
+  if (candidate_mvs[0].as_int == 0) {
+    // 0,0 was best
+    if (index == 0) {
+      // No reference candidates
+      mbmi->mb_mode_context[ref_frame] = 0;
+    } else if (index == 1) {
+      // 0,0 was only candidate
+      mbmi->mb_mode_context[ref_frame] = 1;
+    } else {
+      // Other candidates available
+      mbmi->mb_mode_context[ref_frame] = 2;
+    }
+  } else if (candidate_scores[0] >= 32) {
+    if (candidate_scores[1] >= 16) {
+      // Strong primary and strong or moderate secondary candidate
+      mbmi->mb_mode_context[ref_frame] = 3;
+    } else {
+      // Strong primary but weak secondary candidate
+      mbmi->mb_mode_context[ref_frame] = 4;
+    }
+  } else {
+    // Weak or moderate candidates
+    mbmi->mb_mode_context[ref_frame] = 5;
+  }
+
   // 0,0 is always a valid reference.
   for (i = 0; i < index; ++i)
     if (candidate_mvs[i].as_int == 0)
index de81470..516bea3 100644 (file)
@@ -42,6 +42,7 @@ void vp9_initialize_common(void);
 #define NUM_YV12_BUFFERS 4
 
 #define COMP_PRED_CONTEXTS   2
+#define INTER_MODE_CONTEXTS 6
 
 typedef struct frame_contexts {
   vp9_prob bmode_prob[VP9_NKF_BINTRAMODES - 1];
@@ -106,11 +107,11 @@ typedef struct frame_contexts {
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
 
-  int mode_context[6][4];
-  int mode_context_a[6][4];
-  int vp9_mode_contexts[6][4];
-  int mv_ref_ct[6][4][2];
-  int mv_ref_ct_a[6][4][2];
+  int mode_context[INTER_MODE_CONTEXTS][4];
+  int mode_context_a[INTER_MODE_CONTEXTS][4];
+  int vp9_mode_contexts[INTER_MODE_CONTEXTS][4];
+  int mv_ref_ct[INTER_MODE_CONTEXTS][4][2];
+  int mv_ref_ct_a[INTER_MODE_CONTEXTS][4][2];
 } FRAME_CONTEXT;
 
 typedef enum {
index 7d4d6a7..52032bc 100644 (file)
@@ -720,10 +720,6 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
     int recon_y_stride, recon_yoffset;
     int recon_uv_stride, recon_uvoffset;
 
-    vp9_find_near_mvs(xd, mi,
-                      prev_mi,
-                      &nearest, &nearby, &best_mv, rct,
-                      mbmi->ref_frame, cm->ref_frame_sign_bias);
     {
       int ref_fb_idx;
       MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame;
@@ -755,9 +751,10 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
                             recon_y_stride,
                             mbmi->ref_mvs[ref_frame],
                             &best_mv, &nearest, &nearby);
-    }
 
-    vp9_mv_ref_probs(&pbi->common, mv_ref_p, rct);
+      vp9_mv_ref_probs(&pbi->common, mv_ref_p,
+                       mbmi->mb_mode_context[ref_frame]);
+    }
 
     // Is the segment level mode feature enabled for this segment
     if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_MODE)) {
@@ -771,7 +768,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
 #endif
       mbmi->mode = read_mv_ref(bc, mv_ref_p);
 
-      vp9_accum_mv_refs(&pbi->common, mbmi->mode, rct);
+      vp9_accum_mv_refs(&pbi->common, mbmi->mode,
+                        mbmi->mb_mode_context[mbmi->ref_frame]);
     }
 
 #if CONFIG_PRED_FILTER
@@ -825,11 +823,6 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
           cm->yv12_fb[second_ref_fb_idx].u_buffer + recon_uvoffset;
         xd->second_pre.v_buffer =
           cm->yv12_fb[second_ref_fb_idx].v_buffer + recon_uvoffset;
-        vp9_find_near_mvs(xd, mi, prev_mi,
-                          &nearest_second, &nearby_second, &best_mv_second,
-                          rct,
-                          mbmi->second_ref_frame,
-                          cm->ref_frame_sign_bias);
 
         vp9_find_mv_refs(xd, mi, prev_mi,
                          mbmi->second_ref_frame,
index a80532e..d568e78 100644 (file)
@@ -1053,13 +1053,9 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) {
           {
             int_mv n1, n2;
 
-            // Only used for context just now and soon to be deprecated.
-            vp9_find_near_mvs(xd, m, prev_m, &n1, &n2, &best_mv, ct,
-                              rf, cpi->common.ref_frame_sign_bias);
-
             best_mv.as_int = mi->ref_mvs[rf][0].as_int;
 
-            vp9_mv_ref_probs(&cpi->common, mv_ref_p, ct);
+            vp9_mv_ref_probs(&cpi->common, mv_ref_p, mi->mb_mode_context[rf]);
 
 #ifdef ENTROPY_STATS
             accum_mv_refs(mode, ct);
@@ -1080,7 +1076,7 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) {
             {
               write_mv_ref(bc, mode, mv_ref_p);
             }
-            vp9_accum_mv_refs(&cpi->common, mode, ct);
+            vp9_accum_mv_refs(&cpi->common, mode, mi->mb_mode_context[rf]);
           }
 
 #if CONFIG_PRED_FILTER
@@ -1112,12 +1108,6 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) {
               (mode == NEWMV || mode == SPLITMV)) {
             int_mv n1, n2;
 
-            // Only used for context just now and soon to be deprecated.
-            vp9_find_near_mvs(xd, m, prev_m,
-                              &n1, &n2, &best_second_mv, ct,
-                              mi->second_ref_frame,
-                              cpi->common.ref_frame_sign_bias);
-
             best_second_mv.as_int =
               mi->ref_mvs[mi->second_ref_frame][0].as_int;
           }
@@ -2287,11 +2277,9 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
     vp9_update_mode_context(&cpi->common);
   }
 
-
   vp9_stop_encode(&residual_bc);
 
   *size += residual_bc.pos;
-
 }
 
 #ifdef ENTROPY_STATS
index 4637db0..2a08ae8 100644 (file)
@@ -1897,7 +1897,7 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi,
 
 int vp9_cost_mv_ref(VP9_COMP *cpi,
                     MB_PREDICTION_MODE m,
-                    const int near_mv_ref_ct[4]) {
+                    const int mode_context) {
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
   int segment_id = xd->mode_info_context->mbmi.segment_id;
 
@@ -1911,7 +1911,7 @@ int vp9_cost_mv_ref(VP9_COMP *cpi,
 
     vp9_prob p [VP9_MVREFS - 1];
     assert(NEARESTMV <= m  &&  m <= SPLITMV);
-    vp9_mv_ref_probs(pc, p, near_mv_ref_ct);
+    vp9_mv_ref_probs(pc, p, mode_context);
     return cost_token(vp9_mv_ref_tree, p,
                       vp9_mv_ref_encoding_array - NEARESTMV + m);
   } else
@@ -2253,7 +2253,8 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x,
   // Segmentation method overheads
   rate = cost_token(vp9_mbsplit_tree, vp9_mbsplit_probs,
                     vp9_mbsplit_encodings + segmentation);
-  rate += vp9_cost_mv_ref(cpi, SPLITMV, bsi->mdcounts);
+  rate += vp9_cost_mv_ref(cpi, SPLITMV,
+                          mbmi->mb_mode_context[mbmi->ref_frame]);
   this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
   br += rate;
   other_segment_rd = this_segment_rd;
@@ -3207,12 +3208,6 @@ static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x,
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
 
-  vp9_find_near_mvs(xd, xd->mode_info_context,
-                    xd->prev_mode_info_context,
-                    &frame_nearest_mv[frame_type], &frame_near_mv[frame_type],
-                    &frame_best_ref_mv[frame_type], frame_mdcounts[frame_type],
-                    frame_type, cpi->common.ref_frame_sign_bias);
-
   y_buffer[frame_type] = yv12->y_buffer + recon_yoffset;
   u_buffer[frame_type] = yv12->u_buffer + recon_uvoffset;
   v_buffer[frame_type] = yv12->v_buffer + recon_uvoffset;
@@ -3371,7 +3366,8 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
    * if the first is known */
   *compmode_cost = vp9_cost_bit(vp9_get_pred_prob(cm, xd, PRED_COMP),
                                 is_comp_pred);
-  *rate2 += vp9_cost_mv_ref(cpi, this_mode, mdcounts);
+  *rate2 += vp9_cost_mv_ref(cpi, this_mode,
+                            mbmi->mb_mode_context[mbmi->ref_frame]);
 
   if (block_size == BLOCK_16X16) {
     vp9_build_1st_inter16x16_predictors_mby(xd, xd->predictor, 16, 0);