From 90a91cc683a8c52443de8a6720875712978a492e Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Tue, 16 Apr 2013 00:18:02 -0700 Subject: [PATCH] Recursive partition syntax coding 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 --- vp9/common/vp9_blockd.h | 5 ++ vp9/common/vp9_entropymode.c | 34 ++++++++++ vp9/common/vp9_entropymode.h | 4 ++ vp9/common/vp9_enums.h | 12 ++++ vp9/common/vp9_onyxc_int.h | 5 +- vp9/decoder/vp9_decodemv.c | 13 +++- vp9/decoder/vp9_decodframe.c | 133 ++++++++++++++++++++++---------------- vp9/encoder/vp9_bitstream.c | 144 +++++++++++++++++++++++++++--------------- vp9/encoder/vp9_encodeframe.c | 39 +++++++----- vp9/encoder/vp9_onyx_if.c | 3 +- vp9/encoder/vp9_onyx_int.h | 4 +- vp9/encoder/vp9_ratectrl.c | 2 + 12 files changed, 270 insertions(+), 128 deletions(-) diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index 95bfcd3..e034b2d 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -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, diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c index ed3c6a5..f418244 100644 --- a/vp9/common/vp9_entropymode.c +++ b/vp9/common/vp9_entropymode.c @@ -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) { diff --git a/vp9/common/vp9_entropymode.h b/vp9/common/vp9_entropymode.h index fe97f0e..6655695 100644 --- a/vp9/common/vp9_entropymode.h +++ b/vp9/common/vp9_entropymode.h @@ -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; diff --git a/vp9/common/vp9_enums.h b/vp9/common/vp9_enums.h index efa84c4..930a597 100644 --- a/vp9/common/vp9_enums.h +++ b/vp9/common/vp9_enums.h @@ -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_ diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 71a4303..66698f7 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -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]; diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index ab541ec..aaa9b2e 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -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); } } diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 6e32198..47498c1 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -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) { diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 33bc356..8a644d5 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -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); } diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index b76baf5..1170fc1 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -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); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 7499cbe..afc5fb5 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -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 diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index cd03d51..197ede2 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -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]; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index fc22146..96d857f 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -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 -- 2.7.4