]> granicus.if.org Git - libvpx/commitdiff
New inter mode context.
authorPaul Wilkins <paulwilkins@google.com>
Thu, 16 May 2013 10:27:12 +0000 (11:27 +0100)
committerPaul Wilkins <paulwilkins@google.com>
Thu, 16 May 2013 11:09:19 +0000 (12:09 +0100)
This patch creates a new inter mode contest that avoids
a dependence on the reconstructed motion vectors from
neighboring blocks. This was a change requested by
a hardware vendor to improve decode performance.

As part of this change I have also made some modifications
to stats output code (under a flag) to allow accumulation of
inter mode context flags over multiple clips

Some further changes will be required to accommodate the
deprecation of the split mv mode over the next few days.

Performance as stands is around -0.25% on derf and
std-hd but up on the YT and YT-HD sets. With further tuning
or some adjustment to the context criteria it should be
possible to make this change broadly neutral.

Change-Id: Ia15cb4470969b9e87332a59c546ae0bd40676f6c

vp9/common/vp9_modecont.c
vp9/common/vp9_mvref_common.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_mcomp.c
vp9/encoder/vp9_mcomp.h
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_onyx_int.h

index 73cb5e15e39ec97459588a05741cfacbacc85b53..86a8fb85013b4431e57ab51d474002802c1b104b 100644 (file)
 #include "vp9/common/vp9_entropy.h"
 
 const int vp9_default_mode_contexts[INTER_MODE_CONTEXTS][4] = {
-  {1,       223,   1,    237},  // 0,0 best: Only candidate
-  {87,      166,   26,   219},  // 0,0 best: non zero candidates
-  {89,      67,    18,   125},  // 0,0 best: non zero candidates, split
-  {16,      141,   69,   226},  // strong nz candidate(s), no split
-  {35,      122,   14,   227},  // weak nz candidate(s), no split
-  {14,      122,   22,   164},  // strong nz candidate(s), split
-  {16,      70,    9,    183},  // weak nz candidate(s), split
+  {2,       173,   34,   229},  // 0 = both zero mv
+  {7,       145,   85,   225},  // 1 = one zero mv + one a predicted mv
+  {7,       166,   63,   231},  // 2 = two predicted mvs
+  {7,       94,    66,   219},  // 3 = one predicted/zero and one new mv
+  {8,       64,    46,   213},  // 4 = two new mvs
+  {17,      81,    31,   231},  // 5 = one intra neighbour + x
+  {25,      29,    30,   246},  // 6 = two intra neighbours
 };
index 3f18c6961fafda22e74f8b172be43bd979e57d7d..fa84ce6bd47a07b989e0c459b212f99713cbc94f 100644 (file)
@@ -165,6 +165,10 @@ void vp9_find_mv_refs(VP9_COMMON *cm, MACROBLOCKD *xd, MODE_INFO *here,
   int split_count = 0;
   int (*mv_ref_search)[2];
   const int mi_col = get_mi_col(xd);
+  int intra_count = 0;
+  int zero_count = 0;
+  int newmv_count = 0;
+
   // Blank the reference vector lists and other local structures.
   vpx_memset(mv_ref_list, 0, sizeof(int_mv) * MAX_MV_REF_CANDIDATES);
   vpx_memset(candidate_scores, 0, sizeof(candidate_scores));
@@ -196,9 +200,24 @@ void vp9_find_mv_refs(VP9_COMMON *cm, MACROBLOCKD *xd, MODE_INFO *here,
                          &refmv_count, c_refmv, 16);
       }
       split_count += (candidate_mi->mbmi.mode == SPLITMV);
+
+      // Count number of neihgbours coded intra and zeromv
+      intra_count += (candidate_mi->mbmi.mode < NEARESTMV);
+      zero_count += (candidate_mi->mbmi.mode == ZEROMV);
+      newmv_count += (candidate_mi->mbmi.mode >= NEWMV);
     }
   }
 
+  // If at this stage wwe have a 0 vector and a non zero vector from the
+  // correct reference frame then make sure that the non zero one is given
+  // precedence as we have other options for coding 0,0
+  /* if (refmv_count == MAX_MV_REF_CANDIDATES) {
+    if (mv_ref_list[1].as_int && !mv_ref_list[0].as_int) {
+      mv_ref_list[0].as_int = mv_ref_list[1].as_int;
+      mv_ref_list[1].as_int = 0;
+    }
+  } */
+
   // More distant neigbours
   for (i = 2; (i < MVREF_NEIGHBOURS) &&
               (refmv_count < MAX_MV_REF_CANDIDATES); ++i) {
@@ -278,24 +297,21 @@ void vp9_find_mv_refs(VP9_COMMON *cm, MACROBLOCKD *xd, MODE_INFO *here,
     }
   }
 
-  // Define inter mode coding context.
-  // 0,0 was best
-  if (mv_ref_list[0].as_int == 0) {
-    // 0,0 is only candidate
-    if (refmv_count <= 1) {
-      mbmi->mb_mode_context[ref_frame] = 0;
-    // non zero candidates candidates available
-    } else if (split_count == 0) {
-      mbmi->mb_mode_context[ref_frame] = 1;
+  if (!intra_count) {
+    if (!newmv_count) {
+      // 0 = both zero mv
+      // 1 = one zero mv + one a predicted mv
+      // 2 = two predicted mvs
+      mbmi->mb_mode_context[ref_frame] = 2 - zero_count;
     } else {
-      mbmi->mb_mode_context[ref_frame] = 2;
+      // 3 = one predicted/zero and one new mv
+      // 4 = two new mvs
+      mbmi->mb_mode_context[ref_frame] = 2 + newmv_count;
     }
-  } else if (split_count == 0) {
-    // Non zero best, No Split MV cases
-    mbmi->mb_mode_context[ref_frame] = candidate_scores[0] >= 16 ? 3 : 4;
   } else {
-    // Non zero best, some split mv
-    mbmi->mb_mode_context[ref_frame] = candidate_scores[0] >= 16 ? 5 : 6;
+    // 5 = one intra neighbour + x
+    // 6 = two intra neighbours
+    mbmi->mb_mode_context[ref_frame] = 4 + intra_count;
   }
 
   // Clamp vectors
index 39854513606e9eda8a9025907a3ff0ca0b7aeae3..fbdee35f95154b1a54d2e5bc5b11a0d971e2c775 100644 (file)
@@ -826,9 +826,9 @@ static void write_mb_modes_kf(const VP9_COMP *cpi,
                                   left_block_mode(m, i) : B_DC_PRED;
       const int bm = m->bmi[i].as_mode.first;
 
-#ifdef ENTROPY_STATS
+/*#ifdef ENTROPY_STATS
       ++intra_mode_stats [A] [L] [bm];
-#endif
+#endif*/
       write_kf_bmode(bc, bm, c->kf_bmode_prob[a][l]);
     } while (++i < 4);
   }
index aff5637e1d61f936d24390f557a86d6424336fe2..75e6e6757e8b948c8864b3fd307c1444b226a7c7 100644 (file)
@@ -2430,32 +2430,3 @@ int vp9_refining_search_8p_c(MACROBLOCK *x,
   }
 }
 #endif  // CONFIG_COMP_INTER_JOINT_SEARCH
-
-#ifdef ENTROPY_STATS
-void print_mode_context(VP9_COMMON *pc) {
-  FILE *f = fopen("vp9_modecont.c", "a");
-  int i, j;
-
-  fprintf(f, "#include \"vp9_entropy.h\"\n");
-  fprintf(f, "const int vp9_mode_contexts[INTER_MODE_CONTEXTS][4] =");
-  fprintf(f, "{\n");
-  for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
-    fprintf(f, "  {/* %d */ ", j);
-    fprintf(f, "    ");
-    for (i = 0; i < 4; i++) {
-      int this_prob;
-
-      // context probs
-      this_prob = get_binary_prob(pc->fc.mv_ref_ct[j][i][0],
-                                  pc->fc.mv_ref_ct[j][i][1]);
-
-      fprintf(f, "%5d, ", this_prob);
-    }
-    fprintf(f, "  },\n");
-  }
-
-  fprintf(f, "};\n");
-  fclose(f);
-}
-
-#endif/* END MV ref count ENTROPY_STATS stats code */
index cdbd29aa5d1414fd838c41a90e47c5087baedae7..33e688b973dd6f5a864dbed2c6922bbbf3e0691c 100644 (file)
 #include "vp9/encoder/vp9_block.h"
 #include "vp9/encoder/vp9_variance.h"
 
-#ifdef ENTROPY_STATS
-void print_mode_context(VP9_COMMON *pc);
-#endif
-
 // The maximum number of steps in a step search given the largest
 // allowed initial step
 #define MAX_MVSEARCH_STEPS 11
index 67d1b67fcec174cb2f1be0296df0e44fd495a58d..86d32ea2fe4233a5addea0ab64c7089b0d963904 100644 (file)
@@ -533,6 +533,66 @@ static void configure_implicit_segmentation(VP9_COMP *cpi, int frame_qindex) {
 }
 #endif
 
+#ifdef ENTROPY_STATS
+void vp9_update_mode_context_stats(VP9_COMP *cpi) {
+  VP9_COMMON *cm = &cpi->common;
+  int i, j;
+  unsigned int (*mv_ref_ct)[4][2] = cm->fc.mv_ref_ct;
+  int64_t (*mv_ref_stats)[4][2] = cpi->mv_ref_stats;
+  FILE *f;
+
+  // Read the past stats counters
+  f = fopen("mode_context.bin",  "rb");
+  if (!f) {
+    vpx_memset(cpi->mv_ref_stats, 0, sizeof(cpi->mv_ref_stats));
+  } else {
+    fread(cpi->mv_ref_stats, sizeof(cpi->mv_ref_stats), 1, f);
+    fclose(f);
+  }
+
+  // Add in the values for this frame
+  for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
+    for (j = 0; j < 4; j++) {
+      mv_ref_stats[i][j][0] += (int64_t)mv_ref_ct[i][j][0];
+      mv_ref_stats[i][j][1] += (int64_t)mv_ref_ct[i][j][1];
+    }
+  }
+
+  // Write back the accumulated stats
+  f = fopen("mode_context.bin",  "wb");
+  fwrite(cpi->mv_ref_stats, sizeof(cpi->mv_ref_stats), 1, f);
+  fclose(f);
+}
+
+void print_mode_context(VP9_COMP *cpi) {
+  FILE *f = fopen("vp9_modecont.c", "a");
+  int i, j;
+
+  fprintf(f, "#include \"vp9_entropy.h\"\n");
+  fprintf(f, "const int vp9_mode_contexts[INTER_MODE_CONTEXTS][4] =");
+  fprintf(f, "{\n");
+  for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
+    fprintf(f, "  {/* %d */ ", j);
+    fprintf(f, "    ");
+    for (i = 0; i < 4; i++) {
+      int this_prob;
+      int64_t count = cpi->mv_ref_stats[j][i][0] + cpi->mv_ref_stats[j][i][1];
+      if (count)
+        this_prob = ((cpi->mv_ref_stats[j][i][0] * 256) + (count >> 1)) / count;
+      else
+        this_prob = 128;
+
+      // context probs
+      fprintf(f, "%5d, ", this_prob);
+    }
+    fprintf(f, "  },\n");
+  }
+
+  fprintf(f, "};\n");
+  fclose(f);
+}
+#endif  // ENTROPY_STATS
+
 // DEBUG: Print out the segment id of each MB in the current frame.
 static void print_seg_map(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
@@ -1646,7 +1706,7 @@ void vp9_remove_compressor(VP9_PTR *ptr) {
     if (cpi->pass != 1) {
       print_context_counters();
       print_tree_update_probs();
-      print_mode_context(&cpi->common);
+      print_mode_context(cpi);
     }
 #endif
 #ifdef NMV_STATS
@@ -3239,6 +3299,10 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
     }
   }
 
+#ifdef ENTROPY_STATS
+  vp9_update_mode_context_stats(cpi);
+#endif
+
   /* Move storing frame_type out of the above loop since it is also
    * needed in motion search besides loopfilter */
   cm->last_frame_type = cm->frame_type;
index aba4c0e64d6f2322edcc8d0e89e1452d4a5b1346..9a94f3be5f18673bf02889cfe8e3e9015c07780e 100644 (file)
@@ -621,6 +621,10 @@ typedef struct VP9_COMP {
   int this_frame_weight;
   int max_arf_level;
 #endif
+
+#ifdef ENTROPY_STATS
+  int64_t mv_ref_stats[INTER_MODE_CONTEXTS][4][2];
+#endif
 } VP9_COMP;
 
 void vp9_encode_frame(VP9_COMP *cpi);