shithub: libvpx

Download patch

ref: 6579720e6aa9e568bd876d2592d52831de1bf7b3
parent: e307e924b5af8555625f6742b2251c316ffc0f34
parent: 31ee193a9ccfccef65dad0fba3462b9f83db97fa
author: Paul Wilkins <paulwilkins@google.com>
date: Wed Apr 24 05:44:48 EDT 2013

Merge "Extension of segmentation to 8 segments." into experimental

--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -23,7 +23,8 @@
 
 // #define MODE_STATS
 
-#define MB_FEATURE_TREE_PROBS   3
+#define MAX_MB_SEGMENTS     8
+#define MB_SEG_TREE_PROBS   (MAX_MB_SEGMENTS-1)
 #define PREDICTION_PROBS 3
 
 #define DEFAULT_PRED_PROB_0 120
@@ -32,8 +33,6 @@
 
 #define MBSKIP_CONTEXTS 3
 
-#define MAX_MB_SEGMENTS         4
-
 #define MAX_REF_LF_DELTAS       4
 #define MAX_MODE_LF_DELTAS      4
 
@@ -398,7 +397,7 @@
   /* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */
 
   // Probability Tree used to code Segment number
-  vp9_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS];
+  vp9_prob mb_segment_tree_probs[MB_SEG_TREE_PROBS];
 
   // Segment features
   signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -36,7 +36,7 @@
                   lim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]);
   DECLARE_ALIGNED(SIMD_WIDTH, unsigned char,
                   hev_thr[4][SIMD_WIDTH]);
-  unsigned char lvl[4][4][4];
+  unsigned char lvl[MAX_MB_SEGMENTS][4][4];
   unsigned char mode_lf_lut[MB_MODE_COUNT];
 } loop_filter_info_n;
 
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -21,6 +21,9 @@
 #include "vpx/vp8cx.h"
 #include "vpx_scale/yv12config.h"
 #include "vp9/common/vp9_ppflags.h"
+
+#define MAX_MB_SEGMENTS 8
+
   typedef int *VP9_PTR;
 
   /* Create/destroy static data structures. */
@@ -225,8 +228,9 @@
 
   int vp9_set_roimap(VP9_PTR comp, unsigned char *map,
                      unsigned int rows, unsigned int cols,
-                     int delta_q[4], int delta_lf[4],
-                     unsigned int threshold[4]);
+                     int delta_q[MAX_MB_SEGMENTS],
+                     int delta_lf[MAX_MB_SEGMENTS],
+                     unsigned int threshold[MAX_MB_SEGMENTS]);
 
   int vp9_set_active_map(VP9_PTR comp, unsigned char *map,
                          unsigned int rows, unsigned int cols);
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -75,8 +75,22 @@
 
 static int read_mb_segid(vp9_reader *r, MACROBLOCKD *xd) {
   const vp9_prob *const p = xd->mb_segment_tree_probs;
-  return vp9_read(r, p[0]) ? 2 + vp9_read(r, p[2])
-                           :     vp9_read(r, p[1]);
+  int ret_val;
+
+  if (vp9_read(r, p[0])) {
+    if (vp9_read(r, p[4])) {
+      ret_val = 6 + vp9_read(r, p[6]);
+    } else {
+      ret_val = 4 + vp9_read(r, p[5]);
+    }
+  } else {
+    if (vp9_read(r, p[1])) {
+      ret_val = 2 + vp9_read(r, p[3]);
+    } else {
+      ret_val = vp9_read(r, p[2]);
+    }
+  }
+  return ret_val;
 }
 
 static void set_segment_id(VP9_COMMON *cm, MB_MODE_INFO *mbmi,
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -1107,7 +1107,7 @@
     xd->allow_implicit_segment_update = vp9_read_bit(r);
 #endif
   if (xd->update_mb_segmentation_map) {
-    for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
+    for (i = 0; i < MB_SEG_TREE_PROBS; i++)
       xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
                                                      : MAX_PROB;
 
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -537,24 +537,49 @@
       case 0:
         vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
         vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
         break;
       case 1:
         vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
-        vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[2]);
         break;
       case 2:
-        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
-        vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[3]);
         break;
       case 3:
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[3]);
+        break;
+      case 4:
         vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
-        vp9_write(bc, 1, xd->mb_segment_tree_probs[2]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[5]);
         break;
+      case 5:
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[5]);
+        break;
+      case 6:
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[6]);
+        break;
+      case 7:
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[6]);
+        break;
 
         // TRAP.. This should not happen
       default:
         vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
         vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
         break;
     }
   }
@@ -1977,7 +2002,7 @@
       vp9_choose_segmap_coding_method(cpi);
       // Send the tree probabilities used to decode unpredicted
       // macro-block segments
-      for (i = 0; i < MB_FEATURE_TREE_PROBS; i++) {
+      for (i = 0; i < MB_SEG_TREE_PROBS; i++) {
         const int prob = xd->mb_segment_tree_probs[i];
         if (prob != 255) {
           vp9_write_bit(&header_bc, 1);
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -594,7 +594,7 @@
       mbmi->segment_id = find_seg_id(cm->last_frame_seg_map, bsize,
                                      mb_row, cm->mb_rows, mb_col, cm->mb_cols);
     }
-    assert(mbmi->segment_id <= 3);
+    assert(mbmi->segment_id <= (MAX_MB_SEGMENTS-1));
     vp9_mb_init_quantizer(cpi, x);
 
     if (xd->segmentation_enabled && cpi->seg0_cnt > 0 &&
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -4204,8 +4204,9 @@
 }
 
 int vp9_set_roimap(VP9_PTR comp, unsigned char *map, unsigned int rows,
-                   unsigned int cols, int delta_q[4], int delta_lf[4],
-                   unsigned int threshold[4]) {
+                   unsigned int cols, int delta_q[MAX_MB_SEGMENTS],
+                   int delta_lf[MAX_MB_SEGMENTS],
+                   unsigned int threshold[MAX_MB_SEGMENTS]) {
   VP9_COMP *cpi = (VP9_COMP *) comp;
   signed char feature_data[SEG_LVL_MAX][MAX_MB_SEGMENTS];
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
@@ -4225,25 +4226,15 @@
   // Activate segmentation.
   vp9_enable_segmentation((VP9_PTR)cpi);
 
-  // Set up the quant segment data
-  feature_data[SEG_LVL_ALT_Q][0] = delta_q[0];
-  feature_data[SEG_LVL_ALT_Q][1] = delta_q[1];
-  feature_data[SEG_LVL_ALT_Q][2] = delta_q[2];
-  feature_data[SEG_LVL_ALT_Q][3] = delta_q[3];
+  // Set up the quan, LF and breakout threshold segment data
+  for (i = 0; i < MAX_MB_SEGMENTS; i++) {
+    feature_data[SEG_LVL_ALT_Q][i] = delta_q[i];
+    feature_data[SEG_LVL_ALT_LF][i] = delta_lf[i];
+    cpi->segment_encode_breakout[i] = threshold[i];
+  }
 
-  // Set up the loop segment data s
-  feature_data[SEG_LVL_ALT_LF][0] = delta_lf[0];
-  feature_data[SEG_LVL_ALT_LF][1] = delta_lf[1];
-  feature_data[SEG_LVL_ALT_LF][2] = delta_lf[2];
-  feature_data[SEG_LVL_ALT_LF][3] = delta_lf[3];
-
-  cpi->segment_encode_breakout[0] = threshold[0];
-  cpi->segment_encode_breakout[1] = threshold[1];
-  cpi->segment_encode_breakout[2] = threshold[2];
-  cpi->segment_encode_breakout[3] = threshold[3];
-
   // Enable the loop and quant changes in the feature mask
-  for (i = 0; i < 4; i++) {
+  for (i = 0; i < MAX_MB_SEGMENTS; i++) {
     if (delta_q[i])
       vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q);
     else
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -63,16 +63,18 @@
 static void calc_segtree_probs(MACROBLOCKD *xd,
                                int *segcounts,
                                vp9_prob *segment_tree_probs) {
-  int count1, count2;
-
-  // Total count for all segments
-  count1 = segcounts[0] + segcounts[1];
-  count2 = segcounts[2] + segcounts[3];
-
   // Work out probabilities of each segment
-  segment_tree_probs[0] = get_binary_prob(count1, count2);
-  segment_tree_probs[1] = get_prob(segcounts[0], count1);
-  segment_tree_probs[2] = get_prob(segcounts[2], count2);
+  segment_tree_probs[0] =
+    get_binary_prob(segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3],
+                    segcounts[4] + segcounts[5] + segcounts[6] + segcounts[7]);
+  segment_tree_probs[1] =
+    get_binary_prob(segcounts[0] + segcounts[1], segcounts[2] + segcounts[3]);
+  segment_tree_probs[2] = get_binary_prob(segcounts[0], segcounts[1]);
+  segment_tree_probs[3] = get_binary_prob(segcounts[2], segcounts[3]);
+  segment_tree_probs[4] =
+    get_binary_prob(segcounts[4] + segcounts[5], segcounts[6] + segcounts[7]);
+  segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]);
+  segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]);
 }
 
 // Based on set of segment counts and probabilities calculate a cost estimate
@@ -83,68 +85,38 @@
   int count1, count2;
 
   // Cost the top node of the tree
-  count1 = segcounts[0] + segcounts[1];
-  count2 = segcounts[2] + segcounts[3];
+  count1 = segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3];
+  count2 = segcounts[3] + segcounts[4] + segcounts[5] + segcounts[6];
   cost = count1 * vp9_cost_zero(probs[0]) +
          count2 * vp9_cost_one(probs[0]);
 
-  // Now add the cost of each individual segment branch
-  if (count1 > 0)
-    cost += segcounts[0] * vp9_cost_zero(probs[1]) +
-            segcounts[1] * vp9_cost_one(probs[1]);
+  // Cost subsequent levels
+  if (count1 > 0) {
+    count1 = segcounts[0] + segcounts[1];
+    count2 = segcounts[2] + segcounts[3];
+    cost += count1 * vp9_cost_zero(probs[1]) +
+            count2 * vp9_cost_one(probs[1]);
 
-  if (count2 > 0)
-    cost += segcounts[2] * vp9_cost_zero(probs[2]) +
-            segcounts[3] * vp9_cost_one(probs[2]);
+    if (count1 > 0)
+      cost += segcounts[0] * vp9_cost_zero(probs[2]) +
+              segcounts[1] * vp9_cost_one(probs[2]);
+    if (count2 > 0)
+      cost += segcounts[2] * vp9_cost_zero(probs[3]) +
+              segcounts[3] * vp9_cost_one(probs[3]);
+  }
 
-  return cost;
-}
+  if (count2 > 0) {
+    count1 = segcounts[4] + segcounts[5];
+    count2 = segcounts[6] + segcounts[7];
+    cost += count1 * vp9_cost_zero(probs[4]) +
+            count2 * vp9_cost_one(probs[4]);
 
-// Based on set of segment counts calculate a probability tree
-static void calc_segtree_probs_pred(MACROBLOCKD *xd,
-                                    int (*segcounts)[MAX_MB_SEGMENTS],
-                                    vp9_prob *segment_tree_probs) {
-  int count[4];
-
-  assert(!segcounts[0][0] && !segcounts[1][1] &&
-         !segcounts[2][2] && !segcounts[3][3]);
-
-  // Total count for all segments
-  count[0] = segcounts[3][0] + segcounts[1][0] + segcounts[2][0];
-  count[1] = segcounts[2][1] + segcounts[0][1] + segcounts[3][1];
-  count[2] = segcounts[0][2] + segcounts[3][2] + segcounts[1][2];
-  count[3] = segcounts[1][3] + segcounts[2][3] + segcounts[0][3];
-
-  // Work out probabilities of each segment
-  segment_tree_probs[0] = get_binary_prob(count[0] + count[1],
-                                          count[2] + count[3]);
-  segment_tree_probs[1] = get_binary_prob(count[0], count[1]);
-  segment_tree_probs[2] = get_binary_prob(count[2], count[3]);
-}
-
-// Based on set of segment counts and probabilities calculate a cost estimate
-static int cost_segmap_pred(MACROBLOCKD *xd,
-                            int (*segcounts)[MAX_MB_SEGMENTS],
-                            vp9_prob *probs) {
-  int pred_seg, cost = 0;
-
-  for (pred_seg = 0; pred_seg < MAX_MB_SEGMENTS; pred_seg++) {
-    int count1, count2;
-
-    // Cost the top node of the tree
-    count1 = segcounts[pred_seg][0] + segcounts[pred_seg][1];
-    count2 = segcounts[pred_seg][2] + segcounts[pred_seg][3];
-    cost += count1 * vp9_cost_zero(probs[0]) +
-            count2 * vp9_cost_one(probs[0]);
-
-    // Now add the cost of each individual segment branch
-    if (pred_seg >= 2 && count1) {
-      cost += segcounts[pred_seg][0] * vp9_cost_zero(probs[1]) +
-              segcounts[pred_seg][1] * vp9_cost_one(probs[1]);
-    } else if (pred_seg < 2 && count2 > 0) {
-      cost += segcounts[pred_seg][2] * vp9_cost_zero(probs[2]) +
-              segcounts[pred_seg][3] * vp9_cost_one(probs[2]);
-    }
+    if (count1 > 0)
+      cost += segcounts[4] * vp9_cost_zero(probs[5]) +
+              segcounts[5] * vp9_cost_one(probs[5]);
+    if (count2 > 0)
+      cost += segcounts[6] * vp9_cost_zero(probs[6]) +
+              segcounts[7] * vp9_cost_one(probs[6]);
   }
 
   return cost;
@@ -154,7 +126,7 @@
                        MODE_INFO *mi,
                        int *no_pred_segcounts,
                        int (*temporal_predictor_count)[2],
-                       int (*t_unpred_seg_counts)[MAX_MB_SEGMENTS],
+                       int *t_unpred_seg_counts,
                        int bw, int bh, int mb_row, int mb_col) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &cpi->mb.e_mbd;
@@ -184,7 +156,7 @@
 
     if (!seg_predicted)
       // Update the "unpredicted" segment count
-      t_unpred_seg_counts[pred_seg_id][segment_id]++;
+      t_unpred_seg_counts[segment_id]++;
   }
 }
 
@@ -200,10 +172,10 @@
 
   int temporal_predictor_count[PREDICTION_PROBS][2];
   int no_pred_segcounts[MAX_MB_SEGMENTS];
-  int t_unpred_seg_counts[MAX_MB_SEGMENTS][MAX_MB_SEGMENTS];
+  int t_unpred_seg_counts[MAX_MB_SEGMENTS];
 
-  vp9_prob no_pred_tree[MB_FEATURE_TREE_PROBS];
-  vp9_prob t_pred_tree[MB_FEATURE_TREE_PROBS];
+  vp9_prob no_pred_tree[MB_SEG_TREE_PROBS];
+  vp9_prob t_pred_tree[MB_SEG_TREE_PROBS];
   vp9_prob t_nopred_prob[PREDICTION_PROBS];
 
   const int mis = cm->mode_info_stride;
@@ -318,8 +290,8 @@
   if (cm->frame_type != KEY_FRAME) {
     // Work out probability tree for coding those segments not
     // predicted using the temporal method and the cost.
-    calc_segtree_probs_pred(xd, t_unpred_seg_counts, t_pred_tree);
-    t_pred_cost = cost_segmap_pred(xd, t_unpred_seg_counts, t_pred_tree);
+    calc_segtree_probs(xd, t_unpred_seg_counts, t_pred_tree);
+    t_pred_cost = cost_segmap(xd, t_unpred_seg_counts, t_pred_tree);
 
     // Add in the cost of the signalling for each prediction context
     for (i = 0; i < PREDICTION_PROBS; i++) {
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -215,9 +215,13 @@
   unsigned char *roi_map;      /**< specify an id between 0 and 3 for each 16x16 region within a frame */
   unsigned int   rows;         /**< number of rows */
   unsigned int   cols;         /**< number of cols */
-  int     delta_q[4];          /**< quantizer delta [-63, 63] off baseline for regions with id between 0 and 3*/
-  int     delta_lf[4];         /**< loop filter strength delta [-63, 63] for regions with id between 0 and 3 */
-  unsigned int   static_threshold[4];/**< threshold for region to be treated as static */
+  // TODO(paulwilkins): broken for VP9 which has 8 segments
+  // q and loop filter deltas for each segment
+  // (see MAX_MB_SEGMENTS)
+  int     delta_q[4];
+  int     delta_lf[4];
+  // Static breakout threshold for each segment
+  unsigned int   static_threshold[4];
 } vpx_roi_map_t;
 
 /*!\brief  vpx active region map