Commit 8ba92a0b authored by Yaowu Xu's avatar Yaowu Xu Committed by Paul Wilkins

changes intra coding to be based on txfm block

This commit changed the encoding and decoding of intra blocks to be
based on transform block. In each prediction block, the intra coding
iterates thorough each transform block based on raster scan order.

This commit also fixed a bug in D135 prediction code.

TODO next:
The RD mode/txfm_size selection should take this into account when
computing RD values.

Change-Id: I6d1be2faa4c4948a52e830b6a9a84a6b2b6850f6
parent 232d90d8
......@@ -192,6 +192,7 @@ static INLINE int b_width_log2(BLOCK_SIZE_TYPE sb_type) {
case BLOCK_SIZE_SB64X32:
case BLOCK_SIZE_SB64X64: return 4;
default: assert(0);
return -1;
}
}
......@@ -215,6 +216,7 @@ static INLINE int b_height_log2(BLOCK_SIZE_TYPE sb_type) {
case BLOCK_SIZE_SB32X64:
case BLOCK_SIZE_SB64X64: return 4;
default: assert(0);
return -1;
}
}
......
......@@ -138,14 +138,10 @@ static void d135_predictor(uint8_t *ypred_ptr, int y_stride,
ypred_ptr[y_stride] = ROUND_POWER_OF_TWO(yabove_row[-1] +
yleft_col[0] * 2 +
yleft_col[1], 2);
for (r = 2; r < bh - 1; ++r)
for (r = 2; r < bh; ++r)
ypred_ptr[r * y_stride] = ROUND_POWER_OF_TWO(yleft_col[r - 2] +
yleft_col[r - 1] * 2 +
yleft_col[r + 1], 2);
ypred_ptr[(bh - 1) * y_stride] = ROUND_POWER_OF_TWO(yleft_col[bh - 2] +
yleft_col[bh - 1] * 3,
2);
yleft_col[r], 2);
ypred_ptr += y_stride;
for (r = 1; r < bh; ++r) {
......@@ -396,11 +392,11 @@ void vp9_build_intra_predictors_sbuv_s(MACROBLOCKD *xd,
void vp9_predict_intra_block(MACROBLOCKD *xd,
int block_idx,
BLOCK_SIZE_TYPE bsize,
int bwl_in,
TX_SIZE tx_size,
int mode,
uint8_t *predictor, int pre_stride) {
const int bwl = b_width_log2(bsize) - tx_size;
const int bwl = bwl_in - tx_size;
const int wmask = (1 << bwl) - 1;
const int have_top =
(block_idx >> bwl) || xd->up_available;
......@@ -424,6 +420,6 @@ void vp9_intra4x4_predict(MACROBLOCKD *xd,
BLOCK_SIZE_TYPE bsize,
int mode,
uint8_t *predictor, int pre_stride) {
vp9_predict_intra_block(xd, block_idx, bsize, TX_4X4,
vp9_predict_intra_block(xd, block_idx, b_width_log2(bsize), TX_4X4,
mode, predictor, pre_stride);
}
......@@ -23,7 +23,7 @@ B_PREDICTION_MODE vp9_find_bpred_context(MACROBLOCKD *xd, int block,
void vp9_predict_intra_block(MACROBLOCKD *xd,
int block_idx,
BLOCK_SIZE_TYPE bsize,
int bwl_in,
TX_SIZE tx_size,
int mode,
uint8_t *predictor, int pre_stride);
......
......@@ -154,11 +154,11 @@ static void kfread_modes(VP9D_COMP *pbi, MODE_INFO *m,
m->mbmi.uv_mode = read_uv_mode(r, cm->kf_uv_mode_prob[m->mbmi.mode]);
if (cm->txfm_mode == TX_MODE_SELECT &&
!m->mbmi.mb_skip_coeff &&
!(m->mbmi.mb_skip_coeff && m->mbmi.ref_frame != INTRA_FRAME)
#if CONFIG_AB4X4
m->mbmi.sb_type >= BLOCK_SIZE_SB8X8
&& m->mbmi.sb_type >= BLOCK_SIZE_SB8X8
#else
m->mbmi.mode != I4X4_PRED
&& m->mbmi.mode != I4X4_PRED
#endif
) {
const int allow_16x16 = m->mbmi.sb_type >= BLOCK_SIZE_MB16X16;
......@@ -880,7 +880,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
if (cm->txfm_mode == TX_MODE_SELECT && mbmi->mb_skip_coeff == 0 &&
bsize >= BLOCK_SIZE_SB8X8) {
#else
if (cm->txfm_mode == TX_MODE_SELECT && mbmi->mb_skip_coeff == 0 &&
if (cm->txfm_mode == TX_MODE_SELECT &&
(mbmi->mb_skip_coeff == 0 || mbmi->ref_frame == INTRA_FRAME) &&
((mbmi->ref_frame == INTRA_FRAME && mbmi->mode != I4X4_PRED) ||
(mbmi->ref_frame != INTRA_FRAME && mbmi->mode != SPLITMV))) {
#endif
......
......@@ -239,6 +239,59 @@ static void decode_block(int plane, int block, BLOCK_SIZE_TYPE bsize,
}
}
static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
int ss_txfrm_size, void *arg) {
MACROBLOCKD* const xd = arg;
int16_t* const qcoeff = BLOCK_OFFSET(xd->plane[plane].qcoeff, block, 16);
const int stride = xd->plane[plane].dst.stride;
const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane,
block, ss_txfrm_size);
uint8_t* const dst = raster_block_offset_uint8(xd, bsize, plane,
raster_block,
xd->plane[plane].dst.buf,
stride);
const TX_SIZE tx_size = (TX_SIZE)(ss_txfrm_size / 2);
TX_TYPE tx_type;
int mode, b_mode;
int plane_b_size;
int tx_ib = raster_block >> tx_size;
mode = plane == 0? xd->mode_info_context->mbmi.mode:
xd->mode_info_context->mbmi.uv_mode;
if (bsize <= BLOCK_SIZE_SB8X8 && mode == I4X4_PRED && plane == 0)
b_mode = xd->mode_info_context->bmi[raster_block].as_mode.first;
else
b_mode = mode;
plane_b_size = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size,
b_mode, dst, xd->plane[plane].dst.stride);
switch (ss_txfrm_size / 2) {
case TX_4X4:
tx_type = plane == 0 ? get_tx_type_4x4(xd, raster_block) : DCT_DCT;
if (tx_type == DCT_DCT)
xd->itxm_add(qcoeff, dst, stride, xd->plane[plane].eobs[block]);
else
vp9_iht_add_c(tx_type, qcoeff, dst, stride,
xd->plane[plane].eobs[block]);
break;
case TX_8X8:
tx_type = plane == 0 ? get_tx_type_8x8(xd, raster_block) : DCT_DCT;
vp9_iht_add_8x8_c(tx_type, qcoeff, dst, stride,
xd->plane[plane].eobs[block]);
break;
case TX_16X16:
tx_type = plane == 0 ? get_tx_type_16x16(xd, raster_block) : DCT_DCT;
vp9_iht_add_16x16_c(tx_type, qcoeff, dst, stride,
xd->plane[plane].eobs[block]);
break;
case TX_32X32:
vp9_idct_add_32x32(qcoeff, dst, stride, xd->plane[plane].eobs[block]);
break;
}
}
static void decode_atom_intra(VP9D_COMP *pbi, MACROBLOCKD *xd,
vp9_reader *r,
BLOCK_SIZE_TYPE bsize) {
......@@ -295,6 +348,26 @@ static void decode_atom(VP9D_COMP *pbi, MACROBLOCKD *xd,
foreach_transformed_block(xd, bsize, decode_block, xd);
}
static void decode_sb_intra(VP9D_COMP *pbi, MACROBLOCKD *xd,
int mi_row, int mi_col,
vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
if (mbmi->mb_skip_coeff) {
vp9_reset_sb_tokens_context(xd, bsize);
} else {
// re-initialize macroblock dequantizer before detokenization
if (xd->segmentation_enabled)
mb_init_dequantizer(&pbi->common, xd);
if (!vp9_reader_has_error(r)) {
vp9_decode_tokens(pbi, xd, r, bsize);
}
}
foreach_transformed_block(xd, bsize, decode_block_intra, xd);
}
static void decode_sb(VP9D_COMP *pbi, MACROBLOCKD *xd, int mi_row, int mi_col,
vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
const int bwl = mi_width_log2(bsize), bhl = mi_height_log2(bsize);
......@@ -422,12 +495,13 @@ static void decode_modes_b(VP9D_COMP *pbi, int mi_row, int mi_col,
vp9_decode_mb_mode_mv(pbi, xd, mi_row, mi_col, r);
set_refs(pbi, mi_row, mi_col);
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
decode_sb_intra(pbi, xd, mi_row, mi_col, r, bsize);
#if CONFIG_AB4X4
if (bsize < BLOCK_SIZE_SB8X8)
else if (bsize < BLOCK_SIZE_SB8X8)
#else
if (bsize == BLOCK_SIZE_SB8X8 &&
(xd->mode_info_context->mbmi.mode == SPLITMV ||
xd->mode_info_context->mbmi.mode == I4X4_PRED))
else if (bsize == BLOCK_SIZE_SB8X8 &&
xd->mode_info_context->mbmi.mode == SPLITMV)
#endif
decode_atom(pbi, xd, mi_row, mi_col, r, BLOCK_SIZE_SB8X8);
else
......
......@@ -352,6 +352,16 @@ int vp9_receive_compressed_data(VP9D_PTR ptr,
vp9_loop_filter_frame(cm, &pbi->mb, cm->filter_level, 0,
cm->dering_enabled);
}
#if WRITE_RECON_BUFFER == 2
if (cm->show_frame)
write_dx_frame_to_file(cm->frame_to_show,
cm->current_video_frame + 2000);
else
write_dx_frame_to_file(cm->frame_to_show,
cm->current_video_frame + 3000);
#endif
vp9_extend_frame_borders(cm->frame_to_show,
cm->subsampling_x, cm->subsampling_y);
}
......
......@@ -871,8 +871,9 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m,
if (((rf == INTRA_FRAME && mode != I4X4_PRED) ||
(rf != INTRA_FRAME && mode != SPLITMV)) &&
pc->txfm_mode == TX_MODE_SELECT &&
!(skip_coeff || vp9_segfeature_active(xd, segment_id,
SEG_LVL_SKIP)))
!(rf != INTRA_FRAME &&
(skip_coeff || vp9_segfeature_active(xd, segment_id,
SEG_LVL_SKIP))))
#endif
{
TX_SIZE sz = mi->txfm_size;
......@@ -941,7 +942,8 @@ static void write_mb_modes_kf(const VP9_COMP *cpi,
!(skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
#else
if (ym != I4X4_PRED && c->txfm_mode == TX_MODE_SELECT &&
!(skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
!(m->mbmi.ref_frame != INTRA_FRAME && (skip_coeff ||
vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
#endif
TX_SIZE sz = m->mbmi.txfm_size;
// FIXME(rbultje) code ternary symbol once all experiments are merged
......
......@@ -1703,19 +1703,14 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t,
#if CONFIG_AB4X4
if (mbmi->ref_frame == INTRA_FRAME &&
bsize < BLOCK_SIZE_SB8X8) {
#else
if (mbmi->mode == I4X4_PRED) {
assert(bsize == BLOCK_SIZE_SB8X8 && mbmi->txfm_size == TX_4X4);
#endif
vp9_encode_intra4x4mby(cm, x, BLOCK_SIZE_SB8X8);
vp9_encode_intra_block_y(cm, x, BLOCK_SIZE_SB8X8);
vp9_build_intra_predictors_sbuv_s(xd, BLOCK_SIZE_SB8X8);
vp9_encode_sbuv(cm, x, BLOCK_SIZE_SB8X8);
if (output_enabled)
sum_intra_stats(cpi, x);
} else if (mbmi->ref_frame == INTRA_FRAME) {
vp9_build_intra_predictors_sby_s(xd, bsize);
vp9_build_intra_predictors_sbuv_s(xd, bsize);
#else
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
vp9_encode_intra_block_y(cm, x, bsize);
vp9_encode_intra_block_uv(cm, x, bsize);
#endif
if (output_enabled)
sum_intra_stats(cpi, x);
} else {
......@@ -1741,10 +1736,10 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t,
if (mbmi->ref_frame == INTRA_FRAME &&
bsize < BLOCK_SIZE_SB8X8) {
#else
if (mbmi->mode == I4X4_PRED) {
assert(bsize == BLOCK_SIZE_SB8X8);
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
#endif
vp9_tokenize_sb(cpi, xd, t, !output_enabled, BLOCK_SIZE_SB8X8);
vp9_tokenize_sb(cpi, xd, t, !output_enabled,
(bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : bsize);
} else if (!x->skip) {
vp9_encode_sb(cm, x, (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : bsize);
vp9_tokenize_sb(cpi, xd, t, !output_enabled,
......@@ -1771,8 +1766,9 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t,
if (output_enabled) {
if (cm->txfm_mode == TX_MODE_SELECT &&
(mbmi->ref_frame == INTRA_FRAME ||
!(mbmi->mb_skip_coeff ||
vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))) {
vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
if (bsize >= BLOCK_SIZE_SB32X32) {
cpi->txfm_count_32x32p[mbmi->txfm_size]++;
} else if (bsize >= BLOCK_SIZE_MB16X16) {
......@@ -1783,18 +1779,23 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t,
} else {
int x, y;
TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_32X32 : cm->txfm_mode;
if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
sz = TX_16X16;
if (sz == TX_16X16 && bsize < BLOCK_SIZE_MB16X16)
sz = TX_8X8;
// The new intra coding scheme requires no change of transform size
if (mi->mbmi.ref_frame != INTRA_FRAME) {
if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
sz = TX_16X16;
if (sz == TX_16X16 && bsize < BLOCK_SIZE_MB16X16)
sz = TX_8X8;
#if CONFIG_AB4X4
if (sz == TX_8X8 && bsize < BLOCK_SIZE_SB8X8)
if (sz == TX_8X8 && bsize < BLOCK_SIZE_SB8X8)
#else
if (sz == TX_8X8 && (mbmi->mode == SPLITMV ||
mbmi->mode == I4X4_PRED))
if (sz == TX_8X8 && mbmi->mode == SPLITMV)
#endif
sz = TX_4X4;
} else if (mbmi->mode != I4X4_PRED) {
sz = mbmi->txfm_size;
} else {
sz = TX_4X4;
}
for (y = 0; y < bh; y++) {
for (x = 0; x < bw; x++) {
......
......@@ -16,6 +16,9 @@
int vp9_encode_intra(VP9_COMP *cpi, MACROBLOCK *x, int use_16x16_pred);
void vp9_encode_intra16x16mby(VP9_COMMON *const cm, MACROBLOCK *x);
void vp9_encode_intra16x16mbuv(VP9_COMMON *const cm, MACROBLOCK *x);
void vp9_encode_intra4x4mby(VP9_COMMON *const cm, MACROBLOCK *mb,
BLOCK_SIZE_TYPE bs);
void vp9_encode_intra_block_y(VP9_COMMON *const cm, MACROBLOCK *mb,
BLOCK_SIZE_TYPE bs);
void vp9_encode_intra_block_uv(VP9_COMMON *const cm, MACROBLOCK *mb,
BLOCK_SIZE_TYPE bs);
#endif // VP9_ENCODER_VP9_ENCODEINTRA_H_
......@@ -628,16 +628,23 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
const int txfm_b_size = 4 << tx_size;
int ib = raster_block;
int tx_ib = ib >> tx_size;
int plane_b_size;
TX_TYPE tx_type;
int mode, b_mode;
if (tx_size <= TX_16X16)
tx_type = txfm_map(xd->mode_info_context->bmi[ib].as_mode.first);
mode = plane == 0? xd->mode_info_context->mbmi.mode:
xd->mode_info_context->mbmi.uv_mode;
if (bsize <= BLOCK_SIZE_SB8X8 && mode == I4X4_PRED && plane == 0)
b_mode = xd->mode_info_context->bmi[ib].as_mode.first;
else
tx_type = DCT_DCT;
b_mode = mode;
vp9_predict_intra_block(&x->e_mbd, ib, bsize, tx_size,
xd->mode_info_context->bmi[ib].as_mode.first,
assert(b_mode >= B_DC_PRED && b_mode <= B_TM_PRED);
plane_b_size = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size, b_mode,
dst, xd->plane[plane].dst.stride);
vp9_subtract_block(txfm_b_size, txfm_b_size,
src_diff, bw,
......@@ -650,7 +657,6 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
if (x->optimize)
vp9_optimize_b(plane, block, bsize, ss_txfrm_size, args->cm, x, args->ctx);
*/
switch (ss_txfrm_size / 2) {
case TX_32X32:
vp9_short_idct32x32_add(BLOCK_OFFSET(xd->plane[plane].dqcoeff,
......@@ -695,8 +701,8 @@ static void encode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
}
}
void vp9_encode_intra4x4mby(VP9_COMMON *const cm, MACROBLOCK *x,
BLOCK_SIZE_TYPE bsize) {
void vp9_encode_intra_block_y(VP9_COMMON *const cm, MACROBLOCK *x,
BLOCK_SIZE_TYPE bsize) {
MACROBLOCKD* const xd = &x->e_mbd;
struct optimize_ctx ctx;
struct encode_b_args arg = {cm, x, &ctx};
......@@ -704,4 +710,12 @@ void vp9_encode_intra4x4mby(VP9_COMMON *const cm, MACROBLOCK *x,
foreach_transformed_block_in_plane(xd, bsize, 0,
encode_block_intra, &arg);
}
void vp9_encode_intra_block_uv(VP9_COMMON *const cm, MACROBLOCK *x,
BLOCK_SIZE_TYPE bsize) {
MACROBLOCKD* const xd = &x->e_mbd;
struct optimize_ctx ctx;
struct encode_b_args arg = {cm, x, &ctx};
foreach_transformed_block_uv(xd, bsize, encode_block_intra, &arg);
}
......@@ -3170,6 +3170,15 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
// Pick the loop filter level for the frame.
loopfilter_frame(cpi, cm);
#if WRITE_RECON_BUFFER
if (cm->show_frame)
write_cx_frame_to_file(cm->frame_to_show,
cm->current_video_frame + 2000);
else
write_cx_frame_to_file(cm->frame_to_show,
cm->current_video_frame + 3000);
#endif
// build the bitstream
cpi->dummy_packing = 0;
vp9_pack_bitstream(cpi, dest, size);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment