vp10: allow forward updates for keyframe y intra mode probabilities.

See issue 1040 point 5.

Change-Id: I51a70b9eade39efba392a1457bd70a3c515525cb
This commit is contained in:
Ronald S. Bultje 2015-10-13 14:08:24 -04:00
parent d8f3bb1837
commit 1eb51a2010
7 changed files with 69 additions and 24 deletions

View File

@ -282,15 +282,6 @@ static INLINE void reset_skip_context(MACROBLOCKD *xd, BLOCK_SIZE bsize) {
} }
} }
static INLINE const vpx_prob *get_y_mode_probs(const MODE_INFO *mi,
const MODE_INFO *above_mi,
const MODE_INFO *left_mi,
int block) {
const PREDICTION_MODE above = vp10_above_block_mode(mi, above_mi, block);
const PREDICTION_MODE left = vp10_left_block_mode(mi, left_mi, block);
return vp10_kf_y_mode_prob[above][left];
}
typedef void (*foreach_transformed_block_visitor)(int plane, int block, typedef void (*foreach_transformed_block_visitor)(int plane, int block,
BLOCK_SIZE plane_bsize, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, TX_SIZE tx_size,

View File

@ -76,6 +76,7 @@ typedef struct frame_contexts {
} FRAME_CONTEXT; } FRAME_CONTEXT;
typedef struct FRAME_COUNTS { typedef struct FRAME_COUNTS {
unsigned int kf_y_mode[INTRA_MODES][INTRA_MODES][INTRA_MODES];
unsigned int y_mode[BLOCK_SIZE_GROUPS][INTRA_MODES]; unsigned int y_mode[BLOCK_SIZE_GROUPS][INTRA_MODES];
unsigned int uv_mode[INTRA_MODES][INTRA_MODES]; unsigned int uv_mode[INTRA_MODES][INTRA_MODES];
unsigned int partition[PARTITION_CONTEXTS][PARTITION_TYPES]; unsigned int partition[PARTITION_CONTEXTS][PARTITION_TYPES];

View File

@ -302,6 +302,11 @@ typedef struct VP10Common {
PARTITION_CONTEXT *above_seg_context; PARTITION_CONTEXT *above_seg_context;
ENTROPY_CONTEXT *above_context; ENTROPY_CONTEXT *above_context;
int above_context_alloc_cols; int above_context_alloc_cols;
// scratch memory for intraonly/keyframe forward updates from default tables
// - this is intentionally not placed in FRAME_CONTEXT since it's reset upon
// each keyframe and not used afterwards
vpx_prob kf_y_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1];
} VP10_COMMON; } VP10_COMMON;
// TODO(hkuang): Don't need to lock the whole pool after implementing atomic // TODO(hkuang): Don't need to lock the whole pool after implementing atomic
@ -443,6 +448,16 @@ static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
} }
} }
static INLINE const vpx_prob *get_y_mode_probs(const VP10_COMMON *cm,
const MODE_INFO *mi,
const MODE_INFO *above_mi,
const MODE_INFO *left_mi,
int block) {
const PREDICTION_MODE above = vp10_above_block_mode(mi, above_mi, block);
const PREDICTION_MODE left = vp10_left_block_mode(mi, left_mi, block);
return cm->kf_y_prob[above][left];
}
static INLINE void update_partition_context(MACROBLOCKD *xd, static INLINE void update_partition_context(MACROBLOCKD *xd,
int mi_row, int mi_col, int mi_row, int mi_col,
BLOCK_SIZE subsize, BLOCK_SIZE subsize,

View File

@ -2156,7 +2156,15 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data,
vp10_diff_update_prob(&r, &fc->partition_prob[j][i]); vp10_diff_update_prob(&r, &fc->partition_prob[j][i]);
#endif #endif
if (!frame_is_intra_only(cm)) { if (frame_is_intra_only(cm)) {
vp10_copy(cm->kf_y_prob, vp10_kf_y_mode_prob);
#if CONFIG_MISC_FIXES
for (k = 0; k < INTRA_MODES; k++)
for (j = 0; j < INTRA_MODES; j++)
for (i = 0; i < INTRA_MODES - 1; ++i)
vp10_diff_update_prob(&r, &cm->kf_y_prob[k][j][i]);
#endif
} else {
nmv_context *const nmvc = &fc->nmvc; nmv_context *const nmvc = &fc->nmvc;
read_inter_mode_probs(fc, &r); read_inter_mode_probs(fc, &r);

View File

@ -305,24 +305,24 @@ static void read_intra_frame_mode_info(VP10_COMMON *const cm,
case BLOCK_4X4: case BLOCK_4X4:
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
mi->bmi[i].as_mode = mi->bmi[i].as_mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, i)); read_intra_mode(r, get_y_mode_probs(cm, mi, above_mi, left_mi, i));
mbmi->mode = mi->bmi[3].as_mode; mbmi->mode = mi->bmi[3].as_mode;
break; break;
case BLOCK_4X8: case BLOCK_4X8:
mi->bmi[0].as_mode = mi->bmi[2].as_mode = mi->bmi[0].as_mode = mi->bmi[2].as_mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0)); read_intra_mode(r, get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode = mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 1)); read_intra_mode(r, get_y_mode_probs(cm, mi, above_mi, left_mi, 1));
break; break;
case BLOCK_8X4: case BLOCK_8X4:
mi->bmi[0].as_mode = mi->bmi[1].as_mode = mi->bmi[0].as_mode = mi->bmi[1].as_mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0)); read_intra_mode(r, get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode = mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 2)); read_intra_mode(r, get_y_mode_probs(cm, mi, above_mi, left_mi, 2));
break; break;
default: default:
mbmi->mode = read_intra_mode(r, mbmi->mode = read_intra_mode(r,
get_y_mode_probs(mi, above_mi, left_mi, 0)); get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
} }
mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode); mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode);

View File

@ -455,7 +455,8 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
write_selected_tx_size(cm, xd, w); write_selected_tx_size(cm, xd, w);
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
write_intra_mode(w, mbmi->mode, get_y_mode_probs(mi, above_mi, left_mi, 0)); write_intra_mode(w, mbmi->mode,
get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
} else { } else {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
@ -465,7 +466,7 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
for (idx = 0; idx < 2; idx += num_4x4_w) { for (idx = 0; idx < 2; idx += num_4x4_w) {
const int block = idy * 2 + idx; const int block = idy * 2 + idx;
write_intra_mode(w, mi->bmi[block].as_mode, write_intra_mode(w, mi->bmi[block].as_mode,
get_y_mode_probs(mi, above_mi, left_mi, block)); get_y_mode_probs(cm, mi, above_mi, left_mi, block));
} }
} }
} }
@ -1348,6 +1349,9 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) {
FRAME_COUNTS *counts = cpi->td.counts; FRAME_COUNTS *counts = cpi->td.counts;
vpx_writer header_bc; vpx_writer header_bc;
int i; int i;
#if CONFIG_MISC_FIXES
int j;
#endif
vpx_start_encode(&header_bc, data); vpx_start_encode(&header_bc, data);
@ -1373,7 +1377,15 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) {
counts->partition[i], PARTITION_TYPES, &header_bc); counts->partition[i], PARTITION_TYPES, &header_bc);
#endif #endif
if (!frame_is_intra_only(cm)) { if (frame_is_intra_only(cm)) {
vp10_copy(cm->kf_y_prob, vp10_kf_y_mode_prob);
#if CONFIG_MISC_FIXES
for (i = 0; i < INTRA_MODES; ++i)
for (j = 0; j < INTRA_MODES; ++j)
prob_diff_update(vp10_intra_mode_tree, cm->kf_y_prob[i][j],
counts->kf_y_mode[i][j], INTRA_MODES, &header_bc);
#endif
} else {
for (i = 0; i < INTER_MODE_CONTEXTS; ++i) for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
prob_diff_update(vp10_inter_mode_tree, cm->fc->inter_mode_probs[i], prob_diff_update(vp10_inter_mode_tree, cm->fc->inter_mode_probs[i],
counts->inter_mode[i], INTER_MODES, &header_bc); counts->inter_mode[i], INTER_MODES, &header_bc);

View File

@ -2900,7 +2900,9 @@ void vp10_encode_frame(VP10_COMP *cpi) {
} }
} }
static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) { static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi,
const MODE_INFO *above_mi, const MODE_INFO *left_mi,
const int intraonly) {
const PREDICTION_MODE y_mode = mi->mbmi.mode; const PREDICTION_MODE y_mode = mi->mbmi.mode;
const PREDICTION_MODE uv_mode = mi->mbmi.uv_mode; const PREDICTION_MODE uv_mode = mi->mbmi.uv_mode;
const BLOCK_SIZE bsize = mi->mbmi.sb_type; const BLOCK_SIZE bsize = mi->mbmi.sb_type;
@ -2910,10 +2912,25 @@ static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
for (idy = 0; idy < 2; idy += num_4x4_h) for (idy = 0; idy < 2; idy += num_4x4_h)
for (idx = 0; idx < 2; idx += num_4x4_w) for (idx = 0; idx < 2; idx += num_4x4_w) {
++counts->y_mode[0][mi->bmi[idy * 2 + idx].as_mode]; const int bidx = idy * 2 + idx;
const PREDICTION_MODE bmode = mi->bmi[bidx].as_mode;
if (intraonly) {
const PREDICTION_MODE a = vp10_above_block_mode(mi, above_mi, bidx);
const PREDICTION_MODE l = vp10_left_block_mode(mi, left_mi, bidx);
++counts->kf_y_mode[a][l][bmode];
} else {
++counts->y_mode[0][bmode];
}
}
} else { } else {
++counts->y_mode[size_group_lookup[bsize]][y_mode]; if (intraonly) {
const PREDICTION_MODE above = vp10_above_block_mode(mi, above_mi, 0);
const PREDICTION_MODE left = vp10_left_block_mode(mi, left_mi, 0);
++counts->kf_y_mode[above][left][y_mode];
} else {
++counts->y_mode[size_group_lookup[bsize]][y_mode];
}
} }
++counts->uv_mode[y_mode][uv_mode]; ++counts->uv_mode[y_mode][uv_mode];
@ -2953,7 +2970,8 @@ static void encode_superblock(VP10_COMP *cpi, ThreadData *td,
for (plane = 0; plane < MAX_MB_PLANE; ++plane) for (plane = 0; plane < MAX_MB_PLANE; ++plane)
vp10_encode_intra_block_plane(x, VPXMAX(bsize, BLOCK_8X8), plane); vp10_encode_intra_block_plane(x, VPXMAX(bsize, BLOCK_8X8), plane);
if (output_enabled) if (output_enabled)
sum_intra_stats(td->counts, mi); sum_intra_stats(td->counts, mi, xd->above_mi, xd->left_mi,
frame_is_intra_only(cm));
if (bsize >= BLOCK_8X8 && output_enabled) { if (bsize >= BLOCK_8X8 && output_enabled) {
if (mbmi->palette_mode_info.palette_size[0] > 0) { if (mbmi->palette_mode_info.palette_size[0] > 0) {