Commit ff2b8aa2 authored by Jingning Han's avatar Jingning Han

Contextual entropy coding of partition syntax

This commit enables selecting probability models for recursive block
partition information syntax, depending on its above/left partition
information, as well as the current block size. These conditional
probability models are reasonably stationary and consistent across
frames, hence the backward adaptive approach is used to maintain and
update the contextual models.

It achieves coding performance gains (on top of enabling rectangular
block sizes):
derf:   0.242%
yt:     0.391%
hd:     0.376%
stdhd:  0.645%

Change-Id: Ie513d9673337f0d27abd65fb566b711d0844ec2e
parent 41a8a95b
...@@ -57,11 +57,12 @@ void vp9_free_frame_buffers(VP9_COMMON *oci) { ...@@ -57,11 +57,12 @@ void vp9_free_frame_buffers(VP9_COMMON *oci) {
vpx_free(oci->above_context); vpx_free(oci->above_context);
vpx_free(oci->mip); vpx_free(oci->mip);
vpx_free(oci->prev_mip); vpx_free(oci->prev_mip);
vpx_free(oci->above_seg_context);
oci->above_context = 0; oci->above_context = 0;
oci->mip = 0; oci->mip = 0;
oci->prev_mip = 0; oci->prev_mip = 0;
oci->above_seg_context = 0;
} }
int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) { int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
...@@ -130,13 +131,24 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) { ...@@ -130,13 +131,24 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1; oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
oci->above_context = oci->above_context =
vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * (3 + oci->mb_cols), 1); vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * mb_cols_aligned_to_sb(oci), 1);
if (!oci->above_context) { if (!oci->above_context) {
vp9_free_frame_buffers(oci); vp9_free_frame_buffers(oci);
return 1; return 1;
} }
oci->above_seg_context =
vpx_calloc(sizeof(PARTITION_CONTEXT) * mb_cols_aligned_to_sb(oci), 1);
if (!oci->above_seg_context) {
vp9_free_frame_buffers(oci);
return 1;
}
vp9_update_mode_info_border(oci, oci->mip);
vp9_update_mode_info_in_image(oci, oci->mi);
return 0; return 0;
} }
......
...@@ -54,6 +54,8 @@ typedef struct { ...@@ -54,6 +54,8 @@ typedef struct {
ENTROPY_CONTEXT v[2]; ENTROPY_CONTEXT v[2];
} ENTROPY_CONTEXT_PLANES; } ENTROPY_CONTEXT_PLANES;
typedef char PARTITION_CONTEXT;
static INLINE int combine_entropy_contexts(ENTROPY_CONTEXT a, static INLINE int combine_entropy_contexts(ENTROPY_CONTEXT a,
ENTROPY_CONTEXT b) { ENTROPY_CONTEXT b) {
return (a != 0) + (b != 0); return (a != 0) + (b != 0);
...@@ -245,11 +247,6 @@ static INLINE int b_height_log2(BLOCK_SIZE_TYPE sb_type) { ...@@ -245,11 +247,6 @@ static INLINE int b_height_log2(BLOCK_SIZE_TYPE sb_type) {
return mb_height_log2(sb_type) + 2; 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 struct { typedef struct {
MB_PREDICTION_MODE mode, uv_mode; MB_PREDICTION_MODE mode, uv_mode;
#if CONFIG_COMP_INTERINTRA_PRED #if CONFIG_COMP_INTERINTRA_PRED
...@@ -377,6 +374,10 @@ typedef struct macroblockd { ...@@ -377,6 +374,10 @@ typedef struct macroblockd {
ENTROPY_CONTEXT_PLANES *above_context; ENTROPY_CONTEXT_PLANES *above_context;
ENTROPY_CONTEXT_PLANES *left_context; ENTROPY_CONTEXT_PLANES *left_context;
// partition contexts
PARTITION_CONTEXT *above_seg_context;
PARTITION_CONTEXT *left_seg_context;
/* 0 indicates segmentation at MB level is not enabled. Otherwise the individual bits indicate which features are active. */ /* 0 indicates segmentation at MB level is not enabled. Otherwise the individual bits indicate which features are active. */
unsigned char segmentation_enabled; unsigned char segmentation_enabled;
...@@ -449,6 +450,69 @@ typedef struct macroblockd { ...@@ -449,6 +450,69 @@ typedef struct macroblockd {
} MACROBLOCKD; } MACROBLOCKD;
static INLINE void update_partition_context(MACROBLOCKD *xd,
BLOCK_SIZE_TYPE sb_type,
BLOCK_SIZE_TYPE sb_size) {
int bsl = mb_width_log2(sb_size), bs = 1 << bsl;
int bwl = mb_width_log2(sb_type);
int bhl = mb_height_log2(sb_type);
int boffset = mb_width_log2(BLOCK_SIZE_SB64X64) - bsl;
int i;
// skip macroblock partition
if (bsl == 0)
return;
// update the partition context at the end notes. set partition bits
// of block sizes larger than the current one to be one, and partition
// bits of smaller block sizes to be zero.
if ((bwl == bsl) && (bhl == bsl)) {
for (i = 0; i < bs; i++)
xd->left_seg_context[i] = ~(0xf << boffset);
for (i = 0; i < bs; i++)
xd->above_seg_context[i] = ~(0xf << boffset);
#if CONFIG_SBSEGMENT
} else if ((bwl == bsl) && (bhl < bsl)) {
for (i = 0; i < bs; i++)
xd->left_seg_context[i] = ~(0xe << boffset);
for (i = 0; i < bs; i++)
xd->above_seg_context[i] = ~(0xf << boffset);
} else if ((bwl < bsl) && (bhl == bsl)) {
for (i = 0; i < bs; i++)
xd->left_seg_context[i] = ~(0xf << boffset);
for (i = 0; i < bs; i++)
xd->above_seg_context[i] = ~(0xe << boffset);
#endif
} else if ((bwl < bsl) && (bhl < bsl)) {
for (i = 0; i < bs; i++)
xd->left_seg_context[i] = ~(0xe << boffset);
for (i = 0; i < bs; i++)
xd->above_seg_context[i] = ~(0xe << boffset);
} else {
assert(0);
}
}
static INLINE int partition_plane_context(MACROBLOCKD *xd,
BLOCK_SIZE_TYPE sb_type) {
int bsl = mb_width_log2(sb_type), bs = 1 << bsl;
int above = 0, left = 0, i;
int boffset = mb_width_log2(BLOCK_SIZE_SB64X64) - bsl;
assert(mb_width_log2(sb_type) == mb_height_log2(sb_type));
assert(bsl >= 0);
assert(boffset >= 0);
for (i = 0; i < bs; i++)
above |= (xd->above_seg_context[i] & (1 << boffset));
for (i = 0; i < bs; i++)
left |= (xd->left_seg_context[i] & (1 << boffset));
above = (above > 0);
left = (left > 0);
return (left * 2 + above) + (bsl - 1) * PARTITION_PLOFFSET;
}
#define ACTIVE_HT 110 // quantization stepsize threshold #define ACTIVE_HT 110 // quantization stepsize threshold
#define ACTIVE_HT8 300 #define ACTIVE_HT8 300
......
...@@ -152,13 +152,22 @@ const int vp9_mbsplit_count [VP9_NUMMBSPLITS] = { 2, 2, 4, 16}; ...@@ -152,13 +152,22 @@ const int vp9_mbsplit_count [VP9_NUMMBSPLITS] = { 2, 2, 4, 16};
const vp9_prob vp9_mbsplit_probs [VP9_NUMMBSPLITS - 1] = { 110, 111, 150}; const vp9_prob vp9_mbsplit_probs [VP9_NUMMBSPLITS - 1] = { 110, 111, 150};
#if CONFIG_SBSEGMENT #if CONFIG_SBSEGMENT
const vp9_prob vp9_partition_probs[PARTITION_PLANES][PARTITION_TYPES - 1] = { const vp9_prob vp9_partition_probs[NUM_PARTITION_CONTEXTS]
{110, 111, 150}, [PARTITION_TYPES - 1] = {
{110, 111, 150}, {202, 162, 107},
{16, 2, 169},
{3, 246, 19},
{104, 90, 134},
{183, 70, 109},
{30, 14, 162},
{67, 208, 22},
{4, 17, 5},
}; };
#else #else
const vp9_prob vp9_partition_probs[PARTITION_PLANES][PARTITION_TYPES - 1] = { const vp9_prob vp9_partition_probs[NUM_PARTITION_CONTEXTS]
{200}, {200}, [PARTITION_TYPES - 1] = {
{200}, {200}, {200}, {200},
{200}, {200}, {200}, {200},
}; };
#endif #endif
...@@ -660,7 +669,7 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) { ...@@ -660,7 +669,7 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) {
interintra_prob, factor); interintra_prob, factor);
} }
#endif #endif
for (i = 0; i < PARTITION_PLANES; i++) for (i = 0; i < NUM_PARTITION_CONTEXTS; i++)
update_mode_probs(PARTITION_TYPES, vp9_partition_tree, update_mode_probs(PARTITION_TYPES, vp9_partition_tree,
fc->partition_counts[i], fc->pre_partition_prob[i], fc->partition_counts[i], fc->pre_partition_prob[i],
fc->partition_prob[i], 0); fc->partition_prob[i], 0);
......
...@@ -44,6 +44,7 @@ typedef enum PARTITION_TYPE { ...@@ -44,6 +44,7 @@ typedef enum PARTITION_TYPE {
PARTITION_TYPES PARTITION_TYPES
} PARTITION_TYPE; } PARTITION_TYPE;
#define PARTITION_PLANES 2 // number of probability models #define PARTITION_PLOFFSET 4 // number of probability models per block size
#define NUM_PARTITION_CONTEXTS (2 * PARTITION_PLOFFSET)
#endif // VP9_COMMON_VP9_ENUMS_H_ #endif // VP9_COMMON_VP9_ENUMS_H_
...@@ -68,7 +68,7 @@ typedef struct frame_contexts { ...@@ -68,7 +68,7 @@ typedef struct frame_contexts {
vp9_prob i8x8_mode_prob[VP9_I8X8_MODES - 1]; vp9_prob i8x8_mode_prob[VP9_I8X8_MODES - 1];
vp9_prob sub_mv_ref_prob[SUBMVREF_COUNT][VP9_SUBMVREFS - 1]; vp9_prob sub_mv_ref_prob[SUBMVREF_COUNT][VP9_SUBMVREFS - 1];
vp9_prob mbsplit_prob[VP9_NUMMBSPLITS - 1]; vp9_prob mbsplit_prob[VP9_NUMMBSPLITS - 1];
vp9_prob partition_prob[PARTITION_PLANES][PARTITION_TYPES - 1]; vp9_prob partition_prob[NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
vp9_coeff_probs coef_probs_4x4[BLOCK_TYPES]; vp9_coeff_probs coef_probs_4x4[BLOCK_TYPES];
vp9_coeff_probs coef_probs_8x8[BLOCK_TYPES]; vp9_coeff_probs coef_probs_8x8[BLOCK_TYPES];
...@@ -90,7 +90,7 @@ typedef struct frame_contexts { ...@@ -90,7 +90,7 @@ typedef struct frame_contexts {
vp9_prob pre_i8x8_mode_prob[VP9_I8X8_MODES - 1]; 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_sub_mv_ref_prob[SUBMVREF_COUNT][VP9_SUBMVREFS - 1];
vp9_prob pre_mbsplit_prob[VP9_NUMMBSPLITS - 1]; vp9_prob pre_mbsplit_prob[VP9_NUMMBSPLITS - 1];
vp9_prob pre_partition_prob[PARTITION_PLANES][PARTITION_TYPES - 1]; vp9_prob pre_partition_prob[NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
unsigned int bmode_counts[VP9_NKF_BINTRAMODES]; unsigned int bmode_counts[VP9_NKF_BINTRAMODES];
unsigned int ymode_counts[VP9_YMODES]; /* interframe intra mode probs */ unsigned int ymode_counts[VP9_YMODES]; /* interframe intra mode probs */
unsigned int sb_ymode_counts[VP9_I32X32_MODES]; unsigned int sb_ymode_counts[VP9_I32X32_MODES];
...@@ -98,7 +98,7 @@ typedef struct frame_contexts { ...@@ -98,7 +98,7 @@ typedef struct frame_contexts {
unsigned int i8x8_mode_counts[VP9_I8X8_MODES]; /* interframe intra probs */ unsigned int i8x8_mode_counts[VP9_I8X8_MODES]; /* interframe intra probs */
unsigned int sub_mv_ref_counts[SUBMVREF_COUNT][VP9_SUBMVREFS]; unsigned int sub_mv_ref_counts[SUBMVREF_COUNT][VP9_SUBMVREFS];
unsigned int mbsplit_counts[VP9_NUMMBSPLITS]; unsigned int mbsplit_counts[VP9_NUMMBSPLITS];
unsigned int partition_counts[PARTITION_PLANES][PARTITION_TYPES]; unsigned int partition_counts[NUM_PARTITION_CONTEXTS][PARTITION_TYPES];
vp9_coeff_probs pre_coef_probs_4x4[BLOCK_TYPES]; vp9_coeff_probs pre_coef_probs_4x4[BLOCK_TYPES];
vp9_coeff_probs pre_coef_probs_8x8[BLOCK_TYPES]; vp9_coeff_probs pre_coef_probs_8x8[BLOCK_TYPES];
...@@ -251,6 +251,10 @@ typedef struct VP9Common { ...@@ -251,6 +251,10 @@ typedef struct VP9Common {
ENTROPY_CONTEXT_PLANES *above_context; /* row of context for each plane */ ENTROPY_CONTEXT_PLANES *above_context; /* row of context for each plane */
ENTROPY_CONTEXT_PLANES left_context[4]; /* (up to) 4 contexts "" */ ENTROPY_CONTEXT_PLANES left_context[4]; /* (up to) 4 contexts "" */
// partition contexts
PARTITION_CONTEXT *above_seg_context;
PARTITION_CONTEXT left_seg_context[4];
/* keyframe block modes are predicted by their above, left neighbors */ /* keyframe block modes are predicted by their above, left neighbors */
vp9_prob kf_bmode_prob[VP9_KF_BINTRAMODES] vp9_prob kf_bmode_prob[VP9_KF_BINTRAMODES]
...@@ -333,6 +337,10 @@ static void ref_cnt_fb(int *buf, int *idx, int new_idx) { ...@@ -333,6 +337,10 @@ static void ref_cnt_fb(int *buf, int *idx, int new_idx) {
buf[new_idx]++; buf[new_idx]++;
} }
static int mb_cols_aligned_to_sb(VP9_COMMON *cm) {
return (cm->mb_cols + 3) & ~3;
}
// TODO(debargha): merge the two functions // TODO(debargha): merge the two functions
static void set_mb_row(VP9_COMMON *cm, MACROBLOCKD *xd, static void set_mb_row(VP9_COMMON *cm, MACROBLOCKD *xd,
int mb_row, int block_size) { int mb_row, int block_size) {
......
...@@ -479,7 +479,7 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) { ...@@ -479,7 +479,7 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) {
} else { } else {
nmv_context *const nmvc = &pbi->common.fc.nmvc; nmv_context *const nmvc = &pbi->common.fc.nmvc;
MACROBLOCKD *const xd = &pbi->mb; MACROBLOCKD *const xd = &pbi->mb;
int i, j; int i;
if (cm->mcomp_filter_type == SWITCHABLE) if (cm->mcomp_filter_type == SWITCHABLE)
read_switchable_interp_probs(pbi, r); read_switchable_interp_probs(pbi, r);
...@@ -513,11 +513,6 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) { ...@@ -513,11 +513,6 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) {
for (i = 0; i < VP9_I32X32_MODES - 1; ++i) for (i = 0; i < VP9_I32X32_MODES - 1; ++i)
cm->fc.sb_ymode_prob[i] = vp9_read_prob(r); cm->fc.sb_ymode_prob[i] = vp9_read_prob(r);
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); read_nmvprobs(r, nmvc, xd->allow_high_precision_mv);
} }
} }
......
...@@ -796,6 +796,8 @@ static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize, ...@@ -796,6 +796,8 @@ static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize,
xd->prev_mode_info_context = cm->prev_mi + mb_idx; xd->prev_mode_info_context = cm->prev_mi + mb_idx;
xd->above_context = cm->above_context + mb_col; xd->above_context = cm->above_context + mb_col;
xd->left_context = cm->left_context + mb_row % 4; xd->left_context = cm->left_context + mb_row % 4;
xd->above_seg_context = cm->above_seg_context + mb_col;
xd->left_seg_context = cm->left_seg_context + (mb_row & 3);
// Distance of Mb to the various image edges. These are specified to 8th pel // Distance of Mb to the various image edges. These are specified to 8th pel
// as they are always compared to values that are in 1/8th pel units // as they are always compared to values that are in 1/8th pel units
...@@ -865,10 +867,14 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mb_row, int mb_col, ...@@ -865,10 +867,14 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mb_row, int mb_col,
return; return;
if (bsize > BLOCK_SIZE_MB16X16) { if (bsize > BLOCK_SIZE_MB16X16) {
int pl;
// read the partition information // read the partition information
xd->left_seg_context = pc->left_seg_context + (mb_row & 3);
xd->above_seg_context = pc->above_seg_context + mb_col;
pl = partition_plane_context(xd, bsize);
partition = treed_read(r, vp9_partition_tree, partition = treed_read(r, vp9_partition_tree,
pc->fc.partition_prob[bsl - 1]); pc->fc.partition_prob[pl]);
pc->fc.partition_counts[bsl - 1][partition]++; pc->fc.partition_counts[pl][partition]++;
} }
switch (partition) { switch (partition) {
...@@ -907,6 +913,13 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mb_row, int mb_col, ...@@ -907,6 +913,13 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mb_row, int mb_col,
default: default:
assert(0); assert(0);
} }
// update partition context
if ((partition == PARTITION_SPLIT) && (bsize > BLOCK_SIZE_SB32X32))
return;
xd->left_seg_context = pc->left_seg_context + (mb_row & 3);
xd->above_seg_context = pc->above_seg_context + mb_col;
update_partition_context(xd, subsize, bsize);
} }
/* Decode a row of Superblocks (4x4 region of MBs) */ /* Decode a row of Superblocks (4x4 region of MBs) */
...@@ -918,6 +931,7 @@ static void decode_tile(VP9D_COMP *pbi, vp9_reader* r) { ...@@ -918,6 +931,7 @@ static void decode_tile(VP9D_COMP *pbi, vp9_reader* r) {
mb_row < pc->cur_tile_mb_row_end; mb_row += 4) { mb_row < pc->cur_tile_mb_row_end; mb_row += 4) {
// For a SB there are 2 left contexts, each pertaining to a MB row within // For a SB there are 2 left contexts, each pertaining to a MB row within
vpx_memset(pc->left_context, 0, sizeof(pc->left_context)); vpx_memset(pc->left_context, 0, sizeof(pc->left_context));
vpx_memset(pc->left_seg_context, 0, sizeof(pc->left_seg_context));
for (mb_col = pc->cur_tile_mb_col_start; for (mb_col = pc->cur_tile_mb_col_start;
mb_col < pc->cur_tile_mb_col_end; mb_col += 4) { mb_col < pc->cur_tile_mb_col_end; mb_col += 4) {
decode_modes_sb(pbi, mb_row, mb_col, r, BLOCK_SIZE_SB64X64); decode_modes_sb(pbi, mb_row, mb_col, r, BLOCK_SIZE_SB64X64);
...@@ -1359,7 +1373,10 @@ static void decode_tiles(VP9D_COMP *pbi, ...@@ -1359,7 +1373,10 @@ static void decode_tiles(VP9D_COMP *pbi,
pc->tile_rows = 1 << pc->log2_tile_rows; pc->tile_rows = 1 << pc->log2_tile_rows;
vpx_memset(pc->above_context, 0, vpx_memset(pc->above_context, 0,
sizeof(ENTROPY_CONTEXT_PLANES) * pc->mb_cols); sizeof(ENTROPY_CONTEXT_PLANES) * mb_cols_aligned_to_sb(pc));
vpx_memset(pc->above_seg_context, 0, sizeof(PARTITION_CONTEXT) *
mb_cols_aligned_to_sb(pc));
if (pbi->oxcf.inv_tile_order) { if (pbi->oxcf.inv_tile_order) {
const int n_cols = pc->tile_columns; const int n_cols = pc->tile_columns;
......
...@@ -1176,6 +1176,7 @@ static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc, ...@@ -1176,6 +1176,7 @@ static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
int mb_row, int mb_col, int mb_row, int mb_col,
BLOCK_SIZE_TYPE bsize) { BLOCK_SIZE_TYPE bsize) {
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *xd = &cpi->mb.e_mbd;
const int mis = cm->mode_info_stride; const int mis = cm->mode_info_stride;
int bwl, bhl; int bwl, bhl;
#if CONFIG_SBSEGMENT #if CONFIG_SBSEGMENT
...@@ -1210,22 +1211,32 @@ static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc, ...@@ -1210,22 +1211,32 @@ static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
else else
assert(0); assert(0);
if (bsize > BLOCK_SIZE_MB16X16) if (bsize > BLOCK_SIZE_MB16X16) {
int pl;
xd->left_seg_context = cm->left_seg_context + (mb_row & 3);
xd->above_seg_context = cm->above_seg_context + mb_col;
pl = partition_plane_context(xd, bsize);
// encode the partition information // encode the partition information
write_token(bc, vp9_partition_tree, cm->fc.partition_prob[bsl - 1], write_token(bc, vp9_partition_tree, cm->fc.partition_prob[pl],
vp9_partition_encodings + partition); vp9_partition_encodings + partition);
}
switch (partition) { switch (partition) {
case PARTITION_NONE: case PARTITION_NONE:
subsize = bsize;
write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col); write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
break; break;
#if CONFIG_SBSEGMENT #if CONFIG_SBSEGMENT
case PARTITION_HORZ: case PARTITION_HORZ:
subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB64X32 :
BLOCK_SIZE_SB32X16;
write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col); write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
if ((mb_row + bh) < cm->mb_rows) if ((mb_row + bh) < cm->mb_rows)
write_modes_b(cpi, m + bh * mis, bc, tok, tok_end, mb_row + bh, mb_col); write_modes_b(cpi, m + bh * mis, bc, tok, tok_end, mb_row + bh, mb_col);
break; break;
case PARTITION_VERT: case PARTITION_VERT:
subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB32X64 :
BLOCK_SIZE_SB16X32;
write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col); write_modes_b(cpi, m, bc, tok, tok_end, mb_row, mb_col);
if ((mb_col + bw) < cm->mb_cols) if ((mb_col + bw) < cm->mb_cols)
write_modes_b(cpi, m + bw, bc, tok, tok_end, mb_row, mb_col + bw); write_modes_b(cpi, m + bw, bc, tok, tok_end, mb_row, mb_col + bw);
...@@ -1249,6 +1260,14 @@ static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc, ...@@ -1249,6 +1260,14 @@ static void write_modes_sb(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
default: default:
assert(0); assert(0);
} }
// update partition context
if ((partition == PARTITION_SPLIT) && (bsize > BLOCK_SIZE_SB32X32))
return;
xd->left_seg_context = cm->left_seg_context + (mb_row & 3);
xd->above_seg_context = cm->above_seg_context + mb_col;
update_partition_context(xd, subsize, bsize);
} }
static void write_modes(VP9_COMP *cpi, vp9_writer* const bc, static void write_modes(VP9_COMP *cpi, vp9_writer* const bc,
...@@ -1259,9 +1278,13 @@ static void write_modes(VP9_COMP *cpi, vp9_writer* const bc, ...@@ -1259,9 +1278,13 @@ static void write_modes(VP9_COMP *cpi, vp9_writer* const bc,
int mb_row, mb_col; int mb_row, mb_col;
m_ptr += c->cur_tile_mb_col_start + c->cur_tile_mb_row_start * mis; m_ptr += c->cur_tile_mb_col_start + c->cur_tile_mb_row_start * mis;
vpx_memset(c->above_seg_context, 0, sizeof(PARTITION_CONTEXT) *
mb_cols_aligned_to_sb(c));
for (mb_row = c->cur_tile_mb_row_start; for (mb_row = c->cur_tile_mb_row_start;
mb_row < c->cur_tile_mb_row_end; mb_row += 4, m_ptr += 4 * mis) { mb_row < c->cur_tile_mb_row_end; mb_row += 4, m_ptr += 4 * mis) {
m = m_ptr; m = m_ptr;
vpx_memset(c->left_seg_context, 0, sizeof(c->left_seg_context));
for (mb_col = c->cur_tile_mb_col_start; for (mb_col = c->cur_tile_mb_col_start;
mb_col < c->cur_tile_mb_col_end; mb_col += 4, m += 4) 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, write_modes_sb(cpi, m, bc, tok, tok_end, mb_row, mb_col,
...@@ -2253,14 +2276,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, ...@@ -2253,14 +2276,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
} }
update_mbintra_mode_probs(cpi, &header_bc); 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); vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
} }
......
...@@ -163,7 +163,7 @@ struct macroblock { ...@@ -163,7 +163,7 @@ struct macroblock {
PICK_MODE_CONTEXT sb64x32_context[2]; PICK_MODE_CONTEXT sb64x32_context[2];
#endif #endif
PICK_MODE_CONTEXT sb64_context; PICK_MODE_CONTEXT sb64_context;
int partition_cost[PARTITION_PLANES][PARTITION_TYPES]; int partition_cost[NUM_PARTITION_CONTEXTS][PARTITION_TYPES];
void (*fwd_txm4x4)(int16_t *input, int16_t *output, int pitch); void (*fwd_txm4x4)(int16_t *input, int16_t *output, int pitch);
void (*fwd_txm8x4)(int16_t *input, int16_t *output, int pitch); void (*fwd_txm8x4)(int16_t *input, int16_t *output, int pitch);
......
...@@ -551,6 +551,10 @@ static void set_offsets(VP9_COMP *cpi, ...@@ -551,6 +551,10 @@ static void set_offsets(VP9_COMP *cpi,
xd->above_context = cm->above_context + mb_col; xd->above_context = cm->above_context + mb_col;
xd->left_context = cm->left_context + (mb_row & 3); xd->left_context = cm->left_context + (mb_row & 3);
// partition contexts
xd->above_seg_context = cm->above_seg_context + mb_col;
xd->left_seg_context = cm->left_seg_context + (mb_row & 3);
// Activity map pointer // Activity map pointer
x->mb_activity_ptr = &cpi->mb_activity_map[idx_map]; x->mb_activity_ptr = &cpi->mb_activity_map[idx_map];
x->active_ptr = cpi->active_map + idx_map; x->active_ptr = cpi->active_map + idx_map;
...@@ -749,6 +753,11 @@ static void encode_sb(VP9_COMP *cpi, ...@@ -749,6 +753,11 @@ static void encode_sb(VP9_COMP *cpi,
MACROBLOCK *const x = &cpi->mb; MACROBLOCK *const x = &cpi->mb;
MACROBLOCKD *const xd = &x->e_mbd; MACROBLOCKD *const xd = &x->e_mbd;
BLOCK_SIZE_TYPE bsize = BLOCK_SIZE_SB32X32; BLOCK_SIZE_TYPE bsize = BLOCK_SIZE_SB32X32;
int pl;
xd->left_seg_context = cm->left_seg_context + (mb_row & 0x03);
xd->above_seg_context = cm->above_seg_context + mb_col;
pl = partition_plane_context(xd, bsize);
if (is_sb == BLOCK_SIZE_SB32X32) { if (is_sb == BLOCK_SIZE_SB32X32) {
set_offsets(cpi, mb_row, mb_col, bsize); set_offsets(cpi, mb_row, mb_col, bsize);
...@@ -759,7 +768,7 @@ static void encode_sb(VP9_COMP *cpi, ...@@ -759,7 +768,7 @@ static void encode_sb(VP9_COMP *cpi,
output_enabled, mb_row, mb_col, bsize); output_enabled, mb_row, mb_col, bsize);