Recursive partition syntax coding
authorJingning Han <jingning@google.com>
Tue, 16 Apr 2013 07:18:02 +0000 (00:18 -0700)
committerJingning Han <jingning@google.com>
Wed, 17 Apr 2013 01:41:26 +0000 (18:41 -0700)
Enable recursive partition information coding from SB64X64 down to
MB16X16. The bit-stream syntax is now supporting rectangular block
sizes. It starts from SB64X64 and recursively describes the partition
type of the current block. If the partition type is PARTITION_NONE,
the block is coded as a single unit; if it is PARTITION_HORZ or
PARTITION_VERT, the block is segmented into two independently coded
rectangular units, with no further partition needed; otherwise, the
block is segmented into 4 square blocks. i.e., PARTITION_SPLIT case,
each can be potentially further partitioned.

Forward adaptive probability modeling is used for the partition
information coding, conditioned on the current block size.

Change-Id: I499365fb547839d555498e3bcc0387d8a3587d87

12 files changed:
vp9/common/vp9_blockd.h
vp9/common/vp9_entropymode.c
vp9/common/vp9_entropymode.h
vp9/common/vp9_enums.h
vp9/common/vp9_onyxc_int.h
vp9/decoder/vp9_decodemv.c
vp9/decoder/vp9_decodframe.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_onyx_int.h
vp9/encoder/vp9_ratectrl.c

index 95bfcd3..e034b2d 100644 (file)
@@ -240,6 +240,11 @@ static INLINE int b_height_log2(BLOCK_SIZE_TYPE sb_type) {
   return mb_height_log2(sb_type) + 2;
 }
 
+static INLINE int partition_plane(BLOCK_SIZE_TYPE sb_type) {
+  assert(mb_width_log2(sb_type) == mb_height_log2(sb_type));
+  return (mb_width_log2(sb_type) - 1);
+}
+
 typedef enum {
   BLOCK_4X4_LG2 = 0,
   BLOCK_8X8_LG2 = 2,
index ed3c6a5..f418244 100644 (file)
@@ -151,6 +151,17 @@ const int vp9_mbsplit_count [VP9_NUMMBSPLITS] = { 2, 2, 4, 16};
 
 const vp9_prob vp9_mbsplit_probs [VP9_NUMMBSPLITS - 1] = { 110, 111, 150};
 
+#if CONFIG_SBSEGMENT
+const vp9_prob vp9_partition_probs[PARTITION_PLANES][PARTITION_TYPES - 1] = {
+  {110, 111, 150},
+  {110, 111, 150},
+};
+#else
+const vp9_prob vp9_partition_probs[PARTITION_PLANES][PARTITION_TYPES - 1] = {
+  {200}, {200},
+};
+#endif
+
 /* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
 
 const vp9_tree_index vp9_kf_bmode_tree[VP9_KF_BINTRAMODES * 2 - 2] = {
@@ -283,6 +294,18 @@ const vp9_tree_index vp9_sub_mv_ref_tree[6] = {
   -ZERO4X4, -NEW4X4
 };
 
+#if CONFIG_SBSEGMENT
+const vp9_tree_index vp9_partition_tree[6] = {
+  -PARTITION_NONE, 2,
+  -PARTITION_HORZ, 4,
+  -PARTITION_VERT, -PARTITION_SPLIT
+};
+#else
+const vp9_tree_index vp9_partition_tree[2] = {
+  -PARTITION_NONE, -PARTITION_SPLIT
+};
+#endif
+
 struct vp9_token vp9_bmode_encodings[VP9_NKF_BINTRAMODES];
 struct vp9_token vp9_kf_bmode_encodings[VP9_KF_BINTRAMODES];
 struct vp9_token vp9_ymode_encodings[VP9_YMODES];
@@ -297,6 +320,8 @@ struct vp9_token vp9_mv_ref_encoding_array[VP9_MVREFS];
 struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_MVREFS];
 struct vp9_token vp9_sub_mv_ref_encoding_array[VP9_SUBMVREFS];
 
+struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
+
 void vp9_init_mbmode_probs(VP9_COMMON *x) {
   unsigned int bct [VP9_YMODES] [2];      /* num Ymodes > num UV modes */
 
@@ -332,6 +357,10 @@ void vp9_init_mbmode_probs(VP9_COMMON *x) {
   vpx_memcpy(x->fc.mbsplit_prob, vp9_mbsplit_probs, sizeof(vp9_mbsplit_probs));
   vpx_memcpy(x->fc.switchable_interp_prob, vp9_switchable_interp_prob,
              sizeof(vp9_switchable_interp_prob));
+
+  vpx_memcpy(x->fc.partition_prob, vp9_partition_probs,
+             sizeof(vp9_partition_probs));
+
 #if CONFIG_COMP_INTERINTRA_PRED
   x->fc.interintra_prob = VP9_DEF_INTERINTRA_PROB;
 #endif
@@ -433,6 +462,7 @@ void vp9_entropy_mode_init() {
   vp9_tokens_from_tree(vp9_mbsplit_encodings, vp9_mbsplit_tree);
   vp9_tokens_from_tree(vp9_switchable_interp_encodings,
                        vp9_switchable_interp_tree);
+  vp9_tokens_from_tree(vp9_partition_encodings, vp9_partition_tree);
 
   vp9_tokens_from_tree_offset(vp9_mv_ref_encoding_array,
                               vp9_mv_ref_tree, NEARESTMV);
@@ -631,6 +661,10 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) {
                                            interintra_prob, factor);
   }
 #endif
+  for (i = 0; i < PARTITION_PLANES; i++)
+    update_mode_probs(PARTITION_TYPES, vp9_partition_tree,
+                      cm->fc.partition_counts[i], cm->fc.pre_partition_prob[i],
+                      cm->fc.partition_prob[i], 0);
 }
 
 static void set_default_lf_deltas(MACROBLOCKD *xd) {
index fe97f0e..6655695 100644 (file)
@@ -70,6 +70,10 @@ extern struct vp9_token vp9_mv_ref_encoding_array[VP9_MVREFS];
 extern struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_MVREFS];
 extern struct vp9_token vp9_sub_mv_ref_encoding_array[VP9_SUBMVREFS];
 
+// probability models for partition information
+extern const vp9_tree_index  vp9_partition_tree[];
+extern struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
+
 void vp9_entropy_mode_init(void);
 
 struct VP9Common;
index efa84c4..930a597 100644 (file)
@@ -27,4 +27,16 @@ typedef enum BLOCK_SIZE_TYPE {
   BLOCK_SIZE_SB64X64,
 } BLOCK_SIZE_TYPE;
 
+typedef enum PARTITION_TYPE {
+  PARTITION_NONE,
+#if CONFIG_SBSEGMENT
+  PARTITION_HORZ,
+  PARTITION_VERT,
+#endif
+  PARTITION_SPLIT,
+  PARTITION_TYPES
+} PARTITION_TYPE;
+
+#define PARTITION_PLANES 2  // number of probability models
+
 #endif  // VP9_COMMON_VP9_ENUMS_H_
index 71a4303..66698f7 100644 (file)
@@ -68,6 +68,7 @@ typedef struct frame_contexts {
   vp9_prob i8x8_mode_prob[VP9_I8X8_MODES - 1];
   vp9_prob sub_mv_ref_prob[SUBMVREF_COUNT][VP9_SUBMVREFS - 1];
   vp9_prob mbsplit_prob[VP9_NUMMBSPLITS - 1];
+  vp9_prob partition_prob[PARTITION_PLANES][PARTITION_TYPES - 1];
 
   vp9_coeff_probs coef_probs_4x4[BLOCK_TYPES];
   vp9_coeff_probs coef_probs_8x8[BLOCK_TYPES];
@@ -95,6 +96,7 @@ typedef struct frame_contexts {
   vp9_prob pre_i8x8_mode_prob[VP9_I8X8_MODES - 1];
   vp9_prob pre_sub_mv_ref_prob[SUBMVREF_COUNT][VP9_SUBMVREFS - 1];
   vp9_prob pre_mbsplit_prob[VP9_NUMMBSPLITS - 1];
+  vp9_prob pre_partition_prob[PARTITION_PLANES][PARTITION_TYPES - 1];
   unsigned int bmode_counts[VP9_NKF_BINTRAMODES];
   unsigned int ymode_counts[VP9_YMODES];   /* interframe intra mode probs */
   unsigned int sb_ymode_counts[VP9_I32X32_MODES];
@@ -102,6 +104,7 @@ typedef struct frame_contexts {
   unsigned int i8x8_mode_counts[VP9_I8X8_MODES];   /* interframe intra probs */
   unsigned int sub_mv_ref_counts[SUBMVREF_COUNT][VP9_SUBMVREFS];
   unsigned int mbsplit_counts[VP9_NUMMBSPLITS];
+  unsigned int partition_counts[PARTITION_PLANES][PARTITION_TYPES];
 
   vp9_coeff_probs pre_coef_probs_4x4[BLOCK_TYPES];
   vp9_coeff_probs pre_coef_probs_8x8[BLOCK_TYPES];
@@ -279,8 +282,6 @@ typedef struct VP9Common {
   vp9_prob prob_intra_coded;
   vp9_prob prob_last_coded;
   vp9_prob prob_gf_coded;
-  vp9_prob prob_sb32_coded;
-  vp9_prob prob_sb64_coded;
 
   // Context probabilities when using predictive coding of segment id
   vp9_prob segment_pred_probs[PREDICTION_PROBS];
index ab541ec..aaa9b2e 100644 (file)
@@ -483,7 +483,9 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) {
     if (!cm->kf_ymode_probs_update)
       cm->kf_ymode_probs_index = vp9_read_literal(r, 3);
   } else {
-    int i;
+    nmv_context *const nmvc = &pbi->common.fc.nmvc;
+    MACROBLOCKD *const xd = &pbi->mb;
+    int i, j;
 
     if (cm->mcomp_filter_type == SWITCHABLE)
       read_switchable_interp_probs(pbi, r);
@@ -517,7 +519,14 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) {
       for (i = 0; i < VP9_I32X32_MODES - 1; ++i)
         cm->fc.sb_ymode_prob[i] = vp9_read_prob(r);
 
-    read_nmvprobs(r, &cm->fc.nmvc, pbi->mb.allow_high_precision_mv);
+    for (j = 0; j < PARTITION_PLANES; j++) {
+      if (vp9_read_bit(r)) {
+        for (i = 0; i < PARTITION_TYPES - 1; i++)
+          cm->fc.partition_prob[j][i] = vp9_read_prob(r);
+      }
+    }
+
+    read_nmvprobs(r, nmvc, xd->allow_high_precision_mv);
   }
 }
 
index 6e32198..47498c1 100644 (file)
@@ -815,10 +815,83 @@ static void set_refs(VP9D_COMP *pbi, int mb_row, int mb_col) {
   }
 }
 
-/* Decode a row of Superblocks (2x2 region of MBs) */
-static void decode_sb_row(VP9D_COMP *pbi, int mb_row, vp9_reader* r) {
+static void decode_modes_b(VP9D_COMP *pbi, int mb_row, int mb_col,
+                           vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
+  MACROBLOCKD *const xd = &pbi->mb;
+
+  set_offsets(pbi, bsize, mb_row, mb_col);
+  vp9_decode_mb_mode_mv(pbi, xd, mb_row, mb_col, r);
+  set_refs(pbi, mb_row, mb_col);
+
+  // TODO(jingning): merge decode_sb_ and decode_mb_
+  if (bsize > BLOCK_SIZE_MB16X16)
+    decode_sb(pbi, xd, mb_row, mb_col, r, bsize);
+  else
+    decode_mb(pbi, xd, mb_row, mb_col, r);
+
+  xd->corrupted |= bool_error(r);
+}
+
+static void decode_modes_sb(VP9D_COMP *pbi, int mb_row, int mb_col,
+                            vp9_reader* r, BLOCK_SIZE_TYPE bsize) {
   VP9_COMMON *const pc = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
+  int bsl = mb_width_log2(bsize), bs = (1 << bsl) / 2;
+  int n;
+  PARTITION_TYPE partition = PARTITION_NONE;
+  BLOCK_SIZE_TYPE subsize;
+
+  if (mb_row >= pc->mb_rows || mb_col >= pc->mb_cols)
+    return;
+
+  if (bsize > BLOCK_SIZE_MB16X16) {
+    // read the partition information
+    partition = treed_read(r, vp9_partition_tree,
+                           pc->fc.partition_prob[bsl - 1]);
+    pc->fc.partition_counts[bsl - 1][partition]++;
+  }
+
+  switch (partition) {
+    case PARTITION_NONE:
+      subsize = bsize;
+      decode_modes_b(pbi, mb_row, mb_col, r, subsize);
+      break;
+#if CONFIG_SBSEGMENT
+    case PARTITION_HORZ:
+      subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB64X32 :
+                                                BLOCK_SIZE_SB32X16;
+      decode_modes_b(pbi, mb_row, mb_col, r, subsize);
+      if ((mb_row + bs) < pc->mb_rows)
+        decode_modes_b(pbi, mb_row + bs, mb_col, r, subsize);
+      break;
+    case PARTITION_VERT:
+      subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB32X64 :
+                                                BLOCK_SIZE_SB16X32;
+      decode_modes_b(pbi, mb_row, mb_col, r, subsize);
+      if ((mb_col + bs) < pc->mb_cols)
+        decode_modes_b(pbi, mb_row, mb_col + bs, r, subsize);
+      break;
+#endif
+    case PARTITION_SPLIT:
+      subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB32X32 :
+                                                BLOCK_SIZE_MB16X16;
+      for (n = 0; n < 4; n++) {
+        int j = n >> 1, i = n & 0x01;
+        if (subsize == BLOCK_SIZE_SB32X32)
+          xd->sb_index = n;
+        else
+          xd->mb_index = n;
+        decode_modes_sb(pbi, mb_row + j * bs, mb_col + i * bs, r, subsize);
+      }
+      break;
+    default:
+      assert(0);
+  }
+}
+
+/* Decode a row of Superblocks (4x4 region of MBs) */
+static void decode_sb_row(VP9D_COMP *pbi, int mb_row, vp9_reader* r) {
+  VP9_COMMON *const pc = &pbi->common;
   int mb_col;
 
   // For a SB there are 2 left contexts, each pertaining to a MB row within
@@ -826,60 +899,10 @@ static void decode_sb_row(VP9D_COMP *pbi, int mb_row, vp9_reader* r) {
 
   for (mb_col = pc->cur_tile_mb_col_start;
        mb_col < pc->cur_tile_mb_col_end; mb_col += 4) {
-    if (vp9_read(r, pc->prob_sb64_coded)) {
-      // SB64 decoding
-      set_offsets(pbi, BLOCK_SIZE_SB64X64, mb_row, mb_col);
-      vp9_decode_mb_mode_mv(pbi, xd, mb_row, mb_col, r);
-      set_refs(pbi, mb_row, mb_col);
-      decode_sb(pbi, xd, mb_row, mb_col, r, BLOCK_SIZE_SB64X64);
-      xd->corrupted |= bool_error(r);
-    } else {
-      // not SB64
-      int j;
-      for (j = 0; j < 4; j++) {
-        const int x_idx_sb = mb_col + 2 * (j % 2);
-        const int y_idx_sb = mb_row + 2 * (j / 2);
-
-        if (y_idx_sb >= pc->mb_rows || x_idx_sb >= pc->mb_cols)
-          continue;  // MB lies outside frame, skip on to next
-
-        xd->sb_index = j;
-
-        if (vp9_read(r, pc->prob_sb32_coded)) {
-          // SB32 decoding
-          set_offsets(pbi, BLOCK_SIZE_SB32X32, y_idx_sb, x_idx_sb);
-          vp9_decode_mb_mode_mv(pbi, xd, y_idx_sb, x_idx_sb, r);
-          set_refs(pbi, y_idx_sb, x_idx_sb);
-          decode_sb(pbi, xd, y_idx_sb, x_idx_sb, r, BLOCK_SIZE_SB32X32);
-          xd->corrupted |= bool_error(r);
-        } else {
-          // not SB32
-          // Process the 4 MBs within the SB in the order:
-          // top-left, top-right, bottom-left, bottom-right
-          int i;
-          for (i = 0; i < 4; i++) {
-            const int x_idx_mb = x_idx_sb + (i % 2);
-            const int y_idx_mb = y_idx_sb + (i / 2);
-
-            if (y_idx_mb >= pc->mb_rows || x_idx_mb >= pc->mb_cols)
-              continue;  // MB lies outside frame, skip on to next
-
-            xd->mb_index = i;
-
-            // MB decoding
-            set_offsets(pbi, BLOCK_SIZE_MB16X16, y_idx_mb, x_idx_mb);
-            vp9_decode_mb_mode_mv(pbi, xd, y_idx_mb, x_idx_mb, r);
-            set_refs(pbi, y_idx_mb, x_idx_mb);
-            decode_mb(pbi, xd, y_idx_mb, x_idx_mb, r);
-            xd->corrupted |= bool_error(r);
-          }
-        }
-      }
-    }
+    decode_modes_sb(pbi, mb_row, mb_col, r, BLOCK_SIZE_SB64X64);
   }
 }
 
-
 static void setup_token_decoder(VP9D_COMP *pbi,
                                 const uint8_t *data,
                                 vp9_reader *r) {
@@ -1290,6 +1313,7 @@ static void update_frame_context(VP9D_COMP *pbi, vp9_reader *r) {
   vp9_copy(fc->pre_i8x8_mode_prob, fc->i8x8_mode_prob);
   vp9_copy(fc->pre_sub_mv_ref_prob, fc->sub_mv_ref_prob);
   vp9_copy(fc->pre_mbsplit_prob, fc->mbsplit_prob);
+  vp9_copy(fc->pre_partition_prob, fc->partition_prob);
   fc->pre_nmvc = fc->nmvc;
 
   vp9_zero(fc->coef_counts_4x4);
@@ -1306,6 +1330,7 @@ static void update_frame_context(VP9D_COMP *pbi, vp9_reader *r) {
   vp9_zero(fc->mbsplit_counts);
   vp9_zero(fc->NMVcount);
   vp9_zero(fc->mv_ref_ct);
+  vp9_zero(fc->partition_counts);
 
 #if CONFIG_COMP_INTERINTRA_PRED
   fc->pre_interintra_prob = fc->interintra_prob;
@@ -1497,8 +1522,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
 
   setup_pred_probs(pc, &header_bc);
 
-  pc->prob_sb64_coded = vp9_read_prob(&header_bc);
-  pc->prob_sb32_coded = vp9_read_prob(&header_bc);
   xd->lossless = vp9_read_bit(&header_bc);
   pc->txfm_mode = xd->lossless ? ONLY_4X4 : read_txfm_mode(&header_bc);
   if (pc->txfm_mode == TX_MODE_SELECT) {
index 33bc356..8a644d5 100644 (file)
@@ -1673,64 +1673,104 @@ static void write_modes_b(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
   pack_mb_tokens(bc, tok, tok_end);
 }
 
+static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
+                           TOKENEXTRA **tok, TOKENEXTRA *tok_end,
+                           int mb_row, int mb_col,
+                           BLOCK_SIZE_TYPE bsize) {
+  VP9_COMMON *const cm = &cpi->common;
+  const int mis = cm->mode_info_stride;
+  int bwl, bhl;
+#if CONFIG_SBSEGMENT
+  int bw, bh;
+#endif
+  int bsl = mb_width_log2(bsize), bs = (1 << bsl) / 2;
+  int n;
+  PARTITION_TYPE partition;
+  BLOCK_SIZE_TYPE subsize;
+
+  if (mb_row >= cm->mb_rows || mb_col >= cm->mb_cols)
+    return;
+
+  bwl = mb_width_log2(m->mbmi.sb_type);
+  bhl = mb_height_log2(m->mbmi.sb_type);
+#if CONFIG_SBSEGMENT
+  bw = 1 << bwl;
+  bh = 1 << bhl;
+#endif
+
+  // parse the partition type
+  if ((bwl == bsl) && (bhl == bsl))
+    partition = PARTITION_NONE;
+#if CONFIG_SBSEGMENT
+  else if ((bwl == bsl) && (bhl < bsl))
+    partition = PARTITION_HORZ;
+  else if ((bwl < bsl) && (bhl == bsl))
+    partition = PARTITION_VERT;
+#endif
+  else if ((bwl < bsl) && (bhl < bsl))
+    partition = PARTITION_SPLIT;
+  else
+    assert(0);
+
+  if (bsize > BLOCK_SIZE_MB16X16)
+    // encode the partition information
+    write_token(bc, vp9_partition_tree, cm->fc.partition_prob[bsl - 1],
+                vp9_partition_encodings + partition);
+
+  switch (partition) {
+    case PARTITION_NONE:
+      write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
+      break;
+#if CONFIG_SBSEGMENT
+    case PARTITION_HORZ:
+      write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
+      if ((mb_row + bh) < cm->mb_rows)
+        write_modes_b(cpi, m + bh * mis, bc, tok, tok_end, mb_row + bh, mb_col);
+      break;
+    case PARTITION_VERT:
+      write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
+      if ((mb_col + bw) < cm->mb_cols)
+        write_modes_b(cpi, m + bw, bc, tok, tok_end, mb_row, mb_col + bw);
+      break;
+#endif
+    case PARTITION_SPLIT:
+      // TODO(jingning): support recursive partitioning down to 16x16 as for
+      // now. need to merge in 16x8, 8x16, 8x8, and smaller partitions.
+      if (bsize == BLOCK_SIZE_SB64X64)
+        subsize = BLOCK_SIZE_SB32X32;
+      else if (bsize == BLOCK_SIZE_SB32X32)
+        subsize = BLOCK_SIZE_MB16X16;
+      else
+        assert(0);
+      for (n = 0; n < 4; n++) {
+        int j = n >> 1, i = n & 0x01;
+        write_modes_sb(cpi, m + j * bs * mis + i * bs, bc, tok, tok_end,
+                       mb_row + j * bs, mb_col + i * bs, subsize);
+      }
+      break;
+    default:
+      assert(0);
+  }
+}
+
 static void write_modes(VP9_COMP *cpi, vp9_writer* const bc,
                         TOKENEXTRA **tok, TOKENEXTRA *tok_end) {
   VP9_COMMON *const c = &cpi->common;
   const int mis = c->mode_info_stride;
   MODE_INFO *m, *m_ptr = c->mi;
-  int i, mb_row, mb_col;
+  int mb_row, mb_col;
 
   m_ptr += c->cur_tile_mb_col_start + c->cur_tile_mb_row_start * mis;
   for (mb_row = c->cur_tile_mb_row_start;
        mb_row < c->cur_tile_mb_row_end; mb_row += 4, m_ptr += 4 * mis) {
     m = m_ptr;
     for (mb_col = c->cur_tile_mb_col_start;
-         mb_col < c->cur_tile_mb_col_end; mb_col += 4, m += 4) {
-      vp9_write(bc, m->mbmi.sb_type == BLOCK_SIZE_SB64X64, c->prob_sb64_coded);
-      if (m->mbmi.sb_type == BLOCK_SIZE_SB64X64) {
-        write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
-      } else {
-        int j;
-
-        for (j = 0; j < 4; j++) {
-          const int x_idx_sb = (j & 1) << 1, y_idx_sb = j & 2;
-          MODE_INFO *sb_m = m + y_idx_sb * mis + x_idx_sb;
-
-          if (mb_col + x_idx_sb >= c->mb_cols ||
-              mb_row + y_idx_sb >= c->mb_rows)
-            continue;
-
-          vp9_write(bc, sb_m->mbmi.sb_type == BLOCK_SIZE_SB32X32,
-                    c->prob_sb32_coded);
-          if (sb_m->mbmi.sb_type) {
-            assert(sb_m->mbmi.sb_type == BLOCK_SIZE_SB32X32);
-            write_modes_b(cpi, sb_m, bc, tok, tok_end,
-                          mb_row + y_idx_sb, mb_col + x_idx_sb);
-          } else {
-            // Process the 4 MBs in the order:
-            // top-left, top-right, bottom-left, bottom-right
-            for (i = 0; i < 4; i++) {
-              const int x_idx = x_idx_sb + (i & 1), y_idx = y_idx_sb + (i >> 1);
-              MODE_INFO *mb_m = m + x_idx + y_idx * mis;
-
-              if (mb_row + y_idx >= c->mb_rows ||
-                  mb_col + x_idx >= c->mb_cols) {
-                // MB lies outside frame, move on
-                continue;
-              }
-
-              assert(mb_m->mbmi.sb_type == BLOCK_SIZE_MB16X16);
-              write_modes_b(cpi, mb_m, bc, tok, tok_end,
-                            mb_row + y_idx, mb_col + x_idx);
-            }
-          }
-        }
-      }
-    }
+         mb_col < c->cur_tile_mb_col_end; mb_col += 4, m += 4)
+      write_modes_sb(cpi, m, bc, tok, tok_end, mb_row, mb_col,
+                     BLOCK_SIZE_SB64X64);
   }
 }
 
-
 /* This function is used for debugging probability trees. */
 static void print_prob_tree(vp9_coeff_probs *coef_probs, int block_types) {
   /* print coef probability tree */
@@ -2468,11 +2508,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
     }
   }
 
-  pc->prob_sb64_coded = get_binary_prob(cpi->sb64_count[0], cpi->sb64_count[1]);
-  vp9_write_prob(&header_bc, pc->prob_sb64_coded);
-  pc->prob_sb32_coded = get_binary_prob(cpi->sb32_count[0], cpi->sb32_count[1]);
-  vp9_write_prob(&header_bc, pc->prob_sb32_coded);
-
   vp9_write_bit(&header_bc, cpi->mb.e_mbd.lossless);
   if (cpi->mb.e_mbd.lossless) {
     pc->txfm_mode = ONLY_4X4;
@@ -2791,13 +2826,14 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
   vp9_copy(cpi->common.fc.pre_sub_mv_ref_prob, cpi->common.fc.sub_mv_ref_prob);
   vp9_copy(cpi->common.fc.pre_mbsplit_prob, cpi->common.fc.mbsplit_prob);
   vp9_copy(cpi->common.fc.pre_i8x8_mode_prob, cpi->common.fc.i8x8_mode_prob);
+  vp9_copy(cpi->common.fc.pre_partition_prob, cpi->common.fc.partition_prob);
   cpi->common.fc.pre_nmvc = cpi->common.fc.nmvc;
 #if CONFIG_COMP_INTERINTRA_PRED
   cpi->common.fc.pre_interintra_prob = cpi->common.fc.interintra_prob;
 #endif
   vp9_zero(cpi->sub_mv_ref_count);
   vp9_zero(cpi->mbsplit_count);
-  vp9_zero(cpi->common.fc.mv_ref_ct)
+  vp9_zero(cpi->common.fc.mv_ref_ct);
 
   update_coef_probs(cpi, &header_bc);
 #if CONFIG_CODE_NONZEROCOUNT
@@ -2863,6 +2899,14 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
     }
     update_mbintra_mode_probs(cpi, &header_bc);
 
+    for (i = 0; i < PARTITION_PLANES; i++) {
+      vp9_prob Pnew[PARTITION_TYPES - 1];
+      unsigned int bct[PARTITION_TYPES - 1][2];
+      update_mode(&header_bc, PARTITION_TYPES, vp9_partition_encodings,
+                  vp9_partition_tree, Pnew, pc->fc.partition_prob[i], bct,
+                  (unsigned int *)cpi->partition_count[i]);
+    }
+
     vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
   }
 
index b76baf5..1170fc1 100644 (file)
@@ -857,17 +857,18 @@ static void encode_sb(VP9_COMP *cpi,
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
+  BLOCK_SIZE_TYPE bsize = BLOCK_SIZE_SB32X32;
 
-  cpi->sb32_count[is_sb]++;
   if (is_sb) {
-    set_offsets(cpi, mb_row, mb_col, BLOCK_SIZE_SB32X32);
+    set_offsets(cpi, mb_row, mb_col, bsize);
     update_state(cpi, &x->sb32_context[xd->sb_index],
-                 BLOCK_SIZE_SB32X32, output_enabled);
+                 bsize, output_enabled);
 
     encode_superblock(cpi, tp,
-                      output_enabled, mb_row, mb_col, BLOCK_SIZE_SB32X32);
+                      output_enabled, mb_row, mb_col, bsize);
     if (output_enabled) {
       update_stats(cpi, mb_row, mb_col);
+      cpi->partition_count[partition_plane(bsize)][PARTITION_NONE]++;
     }
 
     if (output_enabled) {
@@ -876,6 +877,8 @@ static void encode_sb(VP9_COMP *cpi,
     }
   } else {
     int i;
+    if (output_enabled)
+      cpi->partition_count[partition_plane(bsize)][PARTITION_SPLIT]++;
 
     for (i = 0; i < 4; i++) {
       const int x_idx = i & 1, y_idx = i >> 1;
@@ -924,20 +927,21 @@ static void encode_sb64(VP9_COMP *cpi,
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
+  BLOCK_SIZE_TYPE bsize = BLOCK_SIZE_SB64X64;
 
-  cpi->sb64_count[is_sb[0] == 2]++;
   if (is_sb[0] == 2) {
-    set_offsets(cpi, mb_row, mb_col, BLOCK_SIZE_SB64X64);
-    update_state(cpi, &x->sb64_context, BLOCK_SIZE_SB64X64, 1);
+    set_offsets(cpi, mb_row, mb_col, bsize);
+    update_state(cpi, &x->sb64_context, bsize, 1);
     encode_superblock(cpi, tp,
-                      1, mb_row, mb_col, BLOCK_SIZE_SB64X64);
+                      1, mb_row, mb_col, bsize);
     update_stats(cpi, mb_row, mb_col);
 
     (*tp)->Token = EOSB_TOKEN;
     (*tp)++;
+    cpi->partition_count[partition_plane(bsize)][PARTITION_NONE]++;
   } else {
     int i;
-
+    cpi->partition_count[partition_plane(bsize)][PARTITION_SPLIT]++;
     for (i = 0; i < 4; i++) {
       const int x_idx = i & 1, y_idx = i >> 1;
 
@@ -1024,7 +1028,9 @@ static void encode_sb_row(VP9_COMP *cpi,
       vpx_memcpy(cm->left_context + y_idx, l2, sizeof(l2));
       vpx_memcpy(cm->above_context + mb_col + x_idx, a2, sizeof(a2));
 
-      mb_rate += vp9_cost_bit(cm->prob_sb32_coded, 0);
+      // TODO(jingning): pre-calculate the overhead costs
+      mb_rate += vp9_cost_bit(cm->fc.partition_prob
+               [partition_plane(BLOCK_SIZE_SB32X32)][0], 0);
 
       if (cpi->sf.splitmode_breakout) {
         sb32_skip = splitmodes_used;
@@ -1037,7 +1043,8 @@ static void encode_sb_row(VP9_COMP *cpi,
         pick_sb_modes(cpi, mb_row + y_idx, mb_col + x_idx,
                       tp, &sb_rate, &sb_dist, BLOCK_SIZE_SB32X32,
                       &x->sb32_context[xd->sb_index]);
-        sb_rate += vp9_cost_bit(cm->prob_sb32_coded, 1);
+        sb_rate += vp9_cost_bit(cm->fc.partition_prob
+                 [partition_plane(BLOCK_SIZE_SB32X32)][0], 1);
       }
 
       /* Decide whether to encode as a SB or 4xMBs */
@@ -1069,13 +1076,15 @@ static void encode_sb_row(VP9_COMP *cpi,
 
     memcpy(cm->above_context + mb_col, &a, sizeof(a));
     memcpy(cm->left_context, &l, sizeof(l));
-    sb32_rate += vp9_cost_bit(cm->prob_sb64_coded, 0);
+    sb32_rate += vp9_cost_bit(cm->fc.partition_prob
+               [partition_plane(BLOCK_SIZE_SB64X64)][0], 0);
 
     if (!sb64_skip && !(mb_col + 3 >= cm->mb_cols ||
                         mb_row + 3 >= cm->mb_rows)) {
       pick_sb_modes(cpi, mb_row, mb_col, tp, &sb64_rate, &sb64_dist,
                     BLOCK_SIZE_SB64X64, &x->sb64_context);
-      sb64_rate += vp9_cost_bit(cm->prob_sb64_coded, 1);
+      sb64_rate += vp9_cost_bit(cm->fc.partition_prob
+                 [partition_plane(BLOCK_SIZE_SB64X64)][0], 1);
     }
 
     /* Decide whether to encode as a SB or 4xMBs */
@@ -1139,8 +1148,8 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
   vp9_zero(cpi->mbsplit_count)
   vp9_zero(cpi->common.fc.mv_ref_ct)
   vp9_zero(cpi->sb_ymode_count)
-  vp9_zero(cpi->sb32_count);
-  vp9_zero(cpi->sb64_count);
+  vp9_zero(cpi->partition_count);
+
 #if CONFIG_COMP_INTERINTRA_PRED
   vp9_zero(cpi->interintra_count);
   vp9_zero(cpi->interintra_select_count);
index 7499cbe..afc5fb5 100644 (file)
@@ -1380,8 +1380,6 @@ VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) {
   cm->prob_last_coded               = 128;
   cm->prob_gf_coded                 = 128;
   cm->prob_intra_coded              = 63;
-  cm->prob_sb32_coded               = 200;
-  cm->prob_sb64_coded               = 200;
   for (i = 0; i < COMP_PRED_CONTEXTS; i++)
     cm->prob_comppred[i]         = 128;
   for (i = 0; i < TX_SIZE_MAX_SB - 1; i++)
@@ -3351,6 +3349,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
     vp9_copy(cpi->common.fc.i8x8_mode_counts, cpi->i8x8_mode_count);
     vp9_copy(cpi->common.fc.sub_mv_ref_counts, cpi->sub_mv_ref_count);
     vp9_copy(cpi->common.fc.mbsplit_counts, cpi->mbsplit_count);
+    vp9_copy(cpi->common.fc.partition_counts, cpi->partition_count);
 #if CONFIG_COMP_INTERINTRA_PRED
     vp9_copy(cpi->common.fc.interintra_counts, cpi->interintra_count);
 #endif
index cd03d51..197ede2 100644 (file)
@@ -103,6 +103,7 @@ typedef struct {
   vp9_prob i8x8_mode_prob[VP9_I8X8_MODES - 1];
   vp9_prob sub_mv_ref_prob[SUBMVREF_COUNT][VP9_SUBMVREFS - 1];
   vp9_prob mbsplit_prob[VP9_NUMMBSPLITS - 1];
+  vp9_prob partition_prob[PARTITION_PLANES][PARTITION_TYPES - 1];
 
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
@@ -455,8 +456,6 @@ typedef struct VP9_COMP {
 
   int cq_target_quality;
 
-  int sb32_count[2];
-  int sb64_count[2];
   int sb_ymode_count [VP9_I32X32_MODES];
   int ymode_count[VP9_YMODES];        /* intra MB type cts this frame */
   int bmode_count[VP9_NKF_BINTRAMODES];
@@ -464,6 +463,7 @@ typedef struct VP9_COMP {
   int sub_mv_ref_count[SUBMVREF_COUNT][VP9_SUBMVREFS];
   int mbsplit_count[VP9_NUMMBSPLITS];
   int y_uv_mode_count[VP9_YMODES][VP9_UV_MODES];
+  unsigned int partition_count[PARTITION_PLANES][PARTITION_TYPES];
 #if CONFIG_COMP_INTERINTRA_PRED
   unsigned int interintra_count[2];
   unsigned int interintra_select_count[2];
index fc22146..96d857f 100644 (file)
@@ -141,6 +141,7 @@ void vp9_save_coding_context(VP9_COMP *cpi) {
   vp9_copy(cc->i8x8_mode_prob, cm->fc.i8x8_mode_prob);
   vp9_copy(cc->sub_mv_ref_prob, cm->fc.sub_mv_ref_prob);
   vp9_copy(cc->mbsplit_prob, cm->fc.mbsplit_prob);
+  vp9_copy(cc->partition_prob, cm->fc.partition_prob);
 
   // Stats
 #ifdef MODE_STATS
@@ -202,6 +203,7 @@ void vp9_restore_coding_context(VP9_COMP *cpi) {
   vp9_copy(cm->fc.uv_mode_prob, cc->uv_mode_prob);
   vp9_copy(cm->fc.sub_mv_ref_prob, cc->sub_mv_ref_prob);
   vp9_copy(cm->fc.mbsplit_prob, cc->mbsplit_prob);
+  vp9_copy(cm->fc.partition_prob, cc->partition_prob);
 
   // Stats
 #ifdef MODE_STATS