From 3edad6e8878ac3a917a821e5d072a8d1f2c3a57d Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Wed, 14 Oct 2015 09:38:17 -0700 Subject: [PATCH] Enable entropy coding of recursive transform block partition This commit enables the entropy coding of the recursive transform block partition syntax. Change-Id: I0c2509fb7b9822d12a721f9ebf9327fac83c777e --- vp10/common/alloccommon.c | 12 ++ vp10/common/blockd.h | 6 + vp10/common/entropymode.c | 17 +++ vp10/common/entropymode.h | 6 + vp10/common/enums.h | 5 + vp10/common/onyxc_int.h | 28 ++++ vp10/common/thread_common.c | 6 + vp10/decoder/decodeframe.c | 21 ++- vp10/decoder/decodemv.c | 25 +++- vp10/encoder/bitstream.c | 43 +++++- vp10/encoder/encodeframe.c | 263 ++++++++++++++++++++++++++++++++++-- vp10/encoder/rdopt.c | 21 ++- 12 files changed, 430 insertions(+), 23 deletions(-) diff --git a/vp10/common/alloccommon.c b/vp10/common/alloccommon.c index 9ca86e5e5..364afde47 100644 --- a/vp10/common/alloccommon.c +++ b/vp10/common/alloccommon.c @@ -97,6 +97,10 @@ void vp10_free_context_buffers(VP10_COMMON *cm) { cm->above_context = NULL; vpx_free(cm->above_seg_context); cm->above_seg_context = NULL; +#if CONFIG_VAR_TX + vpx_free(cm->above_txfm_context); + cm->above_txfm_context = NULL; +#endif } int vp10_alloc_context_buffers(VP10_COMMON *cm, int width, int height) { @@ -128,6 +132,14 @@ int vp10_alloc_context_buffers(VP10_COMMON *cm, int width, int height) { cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc( mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context)); if (!cm->above_seg_context) goto fail; + +#if CONFIG_VAR_TX + vpx_free(cm->above_txfm_context); + cm->above_txfm_context = (TXFM_CONTEXT *)vpx_calloc( + mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_txfm_context)); + if (!cm->above_txfm_context) goto fail; +#endif + cm->above_context_alloc_cols = cm->mi_cols; } diff --git a/vp10/common/blockd.h b/vp10/common/blockd.h index 4bf06d186..6c018186f 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -216,6 +216,12 @@ typedef struct macroblockd { PARTITION_CONTEXT *above_seg_context; PARTITION_CONTEXT left_seg_context[8]; +#if CONFIG_VAR_TX + TXFM_CONTEXT *above_txfm_context; + TXFM_CONTEXT *left_txfm_context; + TXFM_CONTEXT left_txfm_context_buffer[8]; +#endif + #if CONFIG_VP9_HIGHBITDEPTH /* Bit depth: 8, 10, 12 */ int bd; diff --git a/vp10/common/entropymode.c b/vp10/common/entropymode.c index 59e6df8f3..af15b2d2d 100644 --- a/vp10/common/entropymode.c +++ b/vp10/common/entropymode.c @@ -742,6 +742,12 @@ void vp10_tx_counts_to_branch_counts_8x8(const unsigned int *tx_count_8x8p, ct_8x8p[0][1] = tx_count_8x8p[TX_8X8]; } +#if CONFIG_VAR_TX +static const vpx_prob default_txfm_partition_probs[TXFM_PARTITION_CONTEXTS] = { + 192, 128, 64, 192, 128, 64, 192, 128, 64, +}; +#endif + static const vpx_prob default_skip_probs[SKIP_CONTEXTS] = { 192, 128, 64 }; @@ -959,6 +965,9 @@ static void init_mode_probs(FRAME_CONTEXT *fc) { vp10_copy(fc->comp_ref_prob, default_comp_ref_p); vp10_copy(fc->single_ref_prob, default_single_ref_p); fc->tx_probs = default_tx_probs; +#if CONFIG_VAR_TX + vp10_copy(fc->txfm_partition_prob, default_txfm_partition_probs); +#endif vp10_copy(fc->skip_probs, default_skip_probs); vp10_copy(fc->inter_mode_probs, default_inter_mode_probs); #if CONFIG_EXT_TX @@ -1054,6 +1063,14 @@ void vp10_adapt_intra_frame_probs(VP10_COMMON *cm) { } } +#if CONFIG_VAR_TX + if (cm->tx_mode == TX_MODE_SELECT) + for (i = 0; i < TXFM_PARTITION_CONTEXTS; ++i) + fc->txfm_partition_prob[i] = + mode_mv_merge_probs(pre_fc->txfm_partition_prob[i], + counts->txfm_partition[i]); +#endif + for (i = 0; i < SKIP_CONTEXTS; ++i) fc->skip_probs[i] = mode_mv_merge_probs( pre_fc->skip_probs[i], counts->skip[i]); diff --git a/vp10/common/entropymode.h b/vp10/common/entropymode.h index b53b4e157..cb7807d45 100644 --- a/vp10/common/entropymode.h +++ b/vp10/common/entropymode.h @@ -67,6 +67,9 @@ typedef struct frame_contexts { vpx_prob single_ref_prob[REF_CONTEXTS][2]; vpx_prob comp_ref_prob[REF_CONTEXTS]; struct tx_probs tx_probs; +#if CONFIG_VAR_TX + vpx_prob txfm_partition_prob[TXFM_PARTITION_CONTEXTS]; +#endif vpx_prob skip_probs[SKIP_CONTEXTS]; nmv_context nmvc; #if CONFIG_EXT_TX @@ -96,6 +99,9 @@ typedef struct FRAME_COUNTS { unsigned int single_ref[REF_CONTEXTS][2][2]; unsigned int comp_ref[REF_CONTEXTS][2]; struct tx_counts tx; +#if CONFIG_VAR_TX + unsigned int txfm_partition[TXFM_PARTITION_CONTEXTS][2]; +#endif unsigned int skip[SKIP_CONTEXTS][2]; nmv_context_counts mv; #if CONFIG_EXT_TX diff --git a/vp10/common/enums.h b/vp10/common/enums.h index 33c5eaf20..53db356bd 100644 --- a/vp10/common/enums.h +++ b/vp10/common/enums.h @@ -187,6 +187,11 @@ typedef uint8_t PREDICTION_MODE; #define COMP_INTER_CONTEXTS 5 #define REF_CONTEXTS 5 +#if CONFIG_VAR_TX +#define TXFM_PARTITION_CONTEXTS 9 +typedef TX_SIZE TXFM_CONTEXT; +#endif + #ifdef __cplusplus } // extern "C" #endif diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h index 681413377..4178fe70d 100644 --- a/vp10/common/onyxc_int.h +++ b/vp10/common/onyxc_int.h @@ -301,6 +301,9 @@ typedef struct VP10Common { PARTITION_CONTEXT *above_seg_context; ENTROPY_CONTEXT *above_context; +#if CONFIG_VAR_TX + TXFM_CONTEXT *above_txfm_context; +#endif int above_context_alloc_cols; // scratch memory for intraonly/keyframe forward updates from default tables @@ -397,6 +400,9 @@ static INLINE void vp10_init_macroblockd(VP10_COMMON *cm, MACROBLOCKD *xd, } xd->above_seg_context = cm->above_seg_context; +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context; +#endif xd->mi_stride = cm->mi_stride; xd->error_info = &cm->error; } @@ -489,6 +495,28 @@ static INLINE int partition_plane_context(const MACROBLOCKD *xd, return (left * 2 + above) + bsl * PARTITION_PLOFFSET; } +#if CONFIG_VAR_TX +static INLINE void txfm_partition_update(TXFM_CONTEXT *above_ctx, + TXFM_CONTEXT *left_ctx, + TX_SIZE tx_size) { + BLOCK_SIZE bsize = txsize_to_bsize[tx_size]; + int bs = num_8x8_blocks_high_lookup[bsize]; + int i; + for (i = 0; i < bs; ++i) { + above_ctx[i] = tx_size; + left_ctx[i] = tx_size; + } +} + +static INLINE int txfm_partition_context(TXFM_CONTEXT *above_ctx, + TXFM_CONTEXT *left_ctx, + TX_SIZE tx_size) { + int above = *above_ctx < tx_size; + int left = *left_ctx < tx_size; + return (tx_size - 1) * 3 + above + left; +} +#endif + #ifdef __cplusplus } // extern "C" #endif diff --git a/vp10/common/thread_common.c b/vp10/common/thread_common.c index 7508195f3..6395e9615 100644 --- a/vp10/common/thread_common.c +++ b/vp10/common/thread_common.c @@ -401,6 +401,12 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts, for (i = 0; i < TX_SIZES; i++) cm->counts.tx.tx_totals[i] += counts->tx.tx_totals[i]; +#if CONFIG_VAR_TX + for (i = 0; i < TXFM_PARTITION_CONTEXTS; ++i) + for (j = 0; j < 2; ++j) + cm->counts.txfm_partition[i][j] += counts->txfm_partition[i][j]; +#endif + for (i = 0; i < SKIP_CONTEXTS; i++) for (j = 0; j < 2; j++) cm->counts.skip[i][j] += counts->skip[i][j]; diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index eaa31f181..f61ac2a9e 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -1619,6 +1619,11 @@ static const uint8_t *decode_tiles(VP10Decoder *pbi, memset(cm->above_seg_context, 0, sizeof(*cm->above_seg_context) * aligned_cols); +#if CONFIG_VAR_TX + memset(cm->above_txfm_context, 0, + sizeof(*cm->above_txfm_context) * aligned_cols); +#endif + get_tile_buffers(pbi, data, data_end, tile_cols, tile_rows, tile_buffers); if (pbi->tile_data == NULL || @@ -1665,6 +1670,9 @@ static const uint8_t *decode_tiles(VP10Decoder *pbi, vp10_tile_set_col(&tile, tile_data->cm, col); vp10_zero(tile_data->xd.left_context); vp10_zero(tile_data->xd.left_seg_context); +#if CONFIG_VAR_TX + vp10_zero(tile_data->xd.left_txfm_context_buffer); +#endif for (mi_col = tile.mi_col_start; mi_col < tile.mi_col_end; mi_col += MI_BLOCK_SIZE) { decode_partition(pbi, &tile_data->xd, mi_row, @@ -1738,6 +1746,9 @@ static int tile_worker_hook(TileWorkerData *const tile_data, mi_row += MI_BLOCK_SIZE) { vp10_zero(tile_data->xd.left_context); vp10_zero(tile_data->xd.left_seg_context); +#if CONFIG_VAR_TX + vp10_zero(tile_data->xd.left_txfm_context_buffer); +#endif for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end; mi_col += MI_BLOCK_SIZE) { decode_partition(tile_data->pbi, &tile_data->xd, @@ -1815,7 +1826,10 @@ static const uint8_t *decode_tiles_mt(VP10Decoder *pbi, sizeof(*cm->above_context) * MAX_MB_PLANE * 2 * aligned_mi_cols); memset(cm->above_seg_context, 0, sizeof(*cm->above_seg_context) * aligned_mi_cols); - +#if CONFIG_VAR_TX + memset(cm->above_txfm_context, 0, + sizeof(*cm->above_txfm_context) * aligned_mi_cols); +#endif // Load tile data into tile_buffers get_tile_buffers(pbi, data, data_end, tile_cols, tile_rows, tile_buffers); @@ -2270,6 +2284,11 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data, read_tx_mode_probs(&fc->tx_probs, &r); read_coef_probs(fc, cm->tx_mode, &r); +#if CONFIG_VAR_TX + for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k) + vp10_diff_update_prob(&r, &fc->txfm_partition_prob[k]); +#endif + for (k = 0; k < SKIP_CONTEXTS; ++k) vp10_diff_update_prob(&r, &fc->skip_probs[k]); diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index 803d0df9d..a4fb8de22 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -80,13 +80,17 @@ static int read_segment_id(vpx_reader *r, #if CONFIG_VAR_TX static void read_tx_size_inter(VP10_COMMON *cm, MACROBLOCKD *xd, - MB_MODE_INFO *mbmi, + MB_MODE_INFO *mbmi, FRAME_COUNTS *counts, TX_SIZE tx_size, int blk_row, int blk_col, vpx_reader *r) { int is_split = 0; const int tx_idx = (blk_row >> 1) * 8 + (blk_col >> 1); int max_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type]; int max_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type]; + int ctx = txfm_partition_context(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), + tx_size); + if (xd->mb_to_bottom_edge < 0) max_blocks_high += xd->mb_to_bottom_edge >> 5; if (xd->mb_to_right_edge < 0) @@ -95,15 +99,21 @@ static void read_tx_size_inter(VP10_COMMON *cm, MACROBLOCKD *xd, if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return; - is_split = vpx_read_bit(r); + is_split = vpx_read(r, cm->fc->txfm_partition_prob[ctx]); if (is_split) { BLOCK_SIZE bsize = txsize_to_bsize[tx_size]; int bsl = b_width_log2_lookup[bsize]; int i; + + if (counts) + ++counts->txfm_partition[ctx][1]; + if (tx_size == TX_8X8) { mbmi->inter_tx_size[tx_idx] = TX_4X4; mbmi->tx_size = mbmi->inter_tx_size[tx_idx]; + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), TX_4X4); return; } @@ -112,7 +122,8 @@ static void read_tx_size_inter(VP10_COMMON *cm, MACROBLOCKD *xd, for (i = 0; i < 4; ++i) { int offsetr = blk_row + ((i >> 1) << bsl); int offsetc = blk_col + ((i & 0x01) << bsl); - read_tx_size_inter(cm, xd, mbmi, tx_size - 1, offsetr, offsetc, r); + read_tx_size_inter(cm, xd, mbmi, counts, + tx_size - 1, offsetr, offsetc, r); } } else { int idx, idy; @@ -121,6 +132,10 @@ static void read_tx_size_inter(VP10_COMMON *cm, MACROBLOCKD *xd, for (idx = 0; idx < (1 << tx_size) / 2; ++idx) mbmi->inter_tx_size[tx_idx + (idy << 3) + idx] = tx_size; mbmi->tx_size = mbmi->inter_tx_size[tx_idx]; + if (counts) + ++counts->txfm_partition[ctx][0]; + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), tx_size); } } #endif @@ -764,9 +779,11 @@ static void read_inter_frame_mode_info(VP10Decoder *const pbi, const int width = num_4x4_blocks_wide_lookup[bsize]; const int height = num_4x4_blocks_high_lookup[bsize]; int idx, idy; + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); for (idy = 0; idy < height; idy += bs) for (idx = 0; idx < width; idx += bs) - read_tx_size_inter(cm, xd, mbmi, max_tx_size, + read_tx_size_inter(cm, xd, mbmi, xd->counts, max_tx_size, idy, idx, r); if (xd->counts) { const int ctx = get_tx_size_context(xd); diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index e4dcc00aa..1bc3d583e 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -160,6 +160,10 @@ static void write_tx_size_inter(const VP10_COMMON *cm, const int tx_idx = (blk_row >> 1) * 8 + (blk_col >> 1); int max_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type]; int max_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type]; + int ctx = txfm_partition_context(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), + tx_size); + if (xd->mb_to_bottom_edge < 0) max_blocks_high += xd->mb_to_bottom_edge >> 5; if (xd->mb_to_right_edge < 0) @@ -169,15 +173,20 @@ static void write_tx_size_inter(const VP10_COMMON *cm, return; if (tx_size == mbmi->inter_tx_size[tx_idx]) { - vpx_write_bit(w, 0); + vpx_write(w, 0, cm->fc->txfm_partition_prob[ctx]); + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), tx_size); } else { const BLOCK_SIZE bsize = txsize_to_bsize[tx_size]; int bsl = b_width_log2_lookup[bsize]; int i; - vpx_write_bit(w, 1); + vpx_write(w, 1, cm->fc->txfm_partition_prob[ctx]); - if (tx_size == TX_8X8) + if (tx_size == TX_8X8) { + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), TX_4X4); return; + } assert(bsl > 0); --bsl; @@ -188,6 +197,14 @@ static void write_tx_size_inter(const VP10_COMMON *cm, } } } + +static void update_txfm_partition_probs(VP10_COMMON *cm, vpx_writer *w, + FRAME_COUNTS *counts) { + int k; + for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k) + vp10_cond_prob_diff_update(w, &cm->fc->txfm_partition_prob[k], + counts->txfm_partition[k]); +} #endif static void write_selected_tx_size(const VP10_COMMON *cm, @@ -498,8 +515,8 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, vpx_writer *w) { VP10_COMMON *const cm = &cpi->common; const nmv_context *nmvc = &cm->fc->nmvc; - const MACROBLOCK *const x = &cpi->td.mb; - const MACROBLOCKD *const xd = &x->e_mbd; + const MACROBLOCK *x = &cpi->td.mb; + const MACROBLOCKD *xd = &x->e_mbd; const struct segmentation *const seg = &cm->seg; #if CONFIG_MISC_FIXES const struct segmentation_probs *const segp = &cm->fc->seg; @@ -750,6 +767,10 @@ static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile, if (frame_is_intra_only(cm)) { write_mb_modes_kf(cm, xd, xd->mi, w); } else { +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); +#endif pack_inter_mode_mvs(cpi, m, w); } @@ -897,6 +918,9 @@ static void write_modes(VP10_COMP *cpi, for (mi_row = tile->mi_row_start; mi_row < tile->mi_row_end; mi_row += MI_BLOCK_SIZE) { vp10_zero(xd->left_seg_context); +#if CONFIG_VAR_TX + vp10_zero(xd->left_txfm_context_buffer); +#endif for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end; mi_col += MI_BLOCK_SIZE) write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, @@ -1385,6 +1409,10 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr, memset(cm->above_seg_context, 0, sizeof(*cm->above_seg_context) * mi_cols_aligned_to_sb(cm->mi_cols)); +#if CONFIG_VAR_TX + memset(cm->above_txfm_context, 0, + sizeof(*cm->above_txfm_context) * mi_cols_aligned_to_sb(cm->mi_cols)); +#endif for (tile_row = 0; tile_row < tile_rows; tile_row++) { for (tile_col = 0; tile_col < tile_cols; tile_col++) { @@ -1659,6 +1687,11 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) { update_txfm_probs(cm, &header_bc, counts); #endif update_coef_probs(cpi, &header_bc); + +#if CONFIG_VAR_TX + update_txfm_partition_probs(cm, &header_bc, counts); +#endif + update_skip_probs(cm, &header_bc, counts); #if CONFIG_MISC_FIXES update_seg_probs(cpi, &header_bc); diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index ea09f6e0b..32f00f750 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -196,6 +196,11 @@ static void set_offsets(VP10_COMP *cpi, const TileInfo *const tile, set_mode_info_offsets(cpi, x, xd, mi_row, mi_col); +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); +#endif + mbmi = &xd->mi[0]->mbmi; // Set up destination pointers. @@ -1302,6 +1307,9 @@ static void restore_context(MACROBLOCK *const x, int mi_row, int mi_col, ENTROPY_CONTEXT a[16 * MAX_MB_PLANE], ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8], +#if CONFIG_VAR_TX + TXFM_CONTEXT ta[8], TXFM_CONTEXT tl[8], +#endif BLOCK_SIZE bsize) { MACROBLOCKD *const xd = &x->e_mbd; int p; @@ -1326,12 +1334,21 @@ static void restore_context(MACROBLOCK *const x, int mi_row, int mi_col, sizeof(*xd->above_seg_context) * mi_width); memcpy(xd->left_seg_context + (mi_row & MI_MASK), sl, sizeof(xd->left_seg_context[0]) * mi_height); +#if CONFIG_VAR_TX + memcpy(xd->above_txfm_context, ta, + sizeof(*xd->above_txfm_context) * mi_width); + memcpy(xd->left_txfm_context, tl, + sizeof(*xd->left_txfm_context) * mi_height); +#endif } static void save_context(MACROBLOCK *const x, int mi_row, int mi_col, ENTROPY_CONTEXT a[16 * MAX_MB_PLANE], ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8], +#if CONFIG_VAR_TX + TXFM_CONTEXT ta[8], TXFM_CONTEXT tl[8], +#endif BLOCK_SIZE bsize) { const MACROBLOCKD *const xd = &x->e_mbd; int p; @@ -1358,6 +1375,12 @@ static void save_context(MACROBLOCK *const x, int mi_row, int mi_col, sizeof(*xd->above_seg_context) * mi_width); memcpy(sl, xd->left_seg_context + (mi_row & MI_MASK), sizeof(xd->left_seg_context[0]) * mi_height); +#if CONFIG_VAR_TX + memcpy(ta, xd->above_txfm_context, + sizeof(*xd->above_txfm_context) * mi_width); + memcpy(tl, xd->left_txfm_context, + sizeof(*xd->left_txfm_context) * mi_height); +#endif } static void encode_b(VP10_COMP *cpi, const TileInfo *const tile, @@ -1542,6 +1565,9 @@ static void rd_use_partition(VP10_COMP *cpi, BLOCK_SIZE subsize; ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT sl[8], sa[8]; +#if CONFIG_VAR_TX + TXFM_CONTEXT tl[8], ta[8]; +#endif RD_COST last_part_rdc, none_rdc, chosen_rdc; BLOCK_SIZE sub_subsize = BLOCK_4X4; int splits_below = 0; @@ -1562,8 +1588,16 @@ static void rd_use_partition(VP10_COMP *cpi, partition = partition_lookup[bsl][bs_type]; subsize = get_subsize(bsize, partition); +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); +#endif pc_tree->partitioning = partition; - save_context(x, mi_row, mi_col, a, l, sa, sl, bsize); + save_context(x, mi_row, mi_col, a, l, sa, sl, +#if CONFIG_VAR_TX + ta, tl, +#endif + bsize); if (bsize == BLOCK_16X16 && cpi->oxcf.aq_mode) { set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize); @@ -1603,7 +1637,11 @@ static void rd_use_partition(VP10_COMP *cpi, none_rdc.dist); } - restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); + restore_context(x, mi_row, mi_col, a, l, sa, sl, +#if CONFIG_VAR_TX + ta, tl, +#endif + bsize); mi_8x8[0]->mbmi.sb_type = bs_type; pc_tree->partitioning = partition; } @@ -1714,7 +1752,11 @@ static void rd_use_partition(VP10_COMP *cpi, BLOCK_SIZE split_subsize = get_subsize(bsize, PARTITION_SPLIT); chosen_rdc.rate = 0; chosen_rdc.dist = 0; - restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); + restore_context(x, mi_row, mi_col, a, l, sa, sl, +#if CONFIG_VAR_TX + ta, tl, +#endif + bsize); pc_tree->partitioning = PARTITION_SPLIT; // Split partition. @@ -1724,17 +1766,28 @@ static void rd_use_partition(VP10_COMP *cpi, RD_COST tmp_rdc; ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT sl[8], sa[8]; +#if CONFIG_VAR_TX + TXFM_CONTEXT tl[8], ta[8]; +#endif if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols)) continue; - save_context(x, mi_row, mi_col, a, l, sa, sl, bsize); + save_context(x, mi_row, mi_col, a, l, sa, sl, +#if CONFIG_VAR_TX + ta, tl, +#endif + bsize); pc_tree->split[i]->partitioning = PARTITION_NONE; rd_pick_sb_modes(cpi, tile_data, x, mi_row + y_idx, mi_col + x_idx, &tmp_rdc, split_subsize, &pc_tree->split[i]->none, INT64_MAX); - restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); + restore_context(x, mi_row, mi_col, a, l, sa, sl, +#if CONFIG_VAR_TX + ta, tl, +#endif + bsize); if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { vp10_rd_cost_reset(&chosen_rdc); @@ -1774,7 +1827,15 @@ static void rd_use_partition(VP10_COMP *cpi, chosen_rdc = none_rdc; } - restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); +#endif + restore_context(x, mi_row, mi_col, a, l, sa, sl, +#if CONFIG_VAR_TX + ta, tl, +#endif + bsize); // We must have chosen a partitioning and encoding or we'll fail later on. // No other opportunities for success. @@ -2046,6 +2107,9 @@ static void rd_pick_partition(VP10_COMP *cpi, ThreadData *td, const int mi_step = num_8x8_blocks_wide_lookup[bsize] / 2; ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT sl[8], sa[8]; +#if CONFIG_VAR_TX + TXFM_CONTEXT tl[8], ta[8]; +#endif TOKENEXTRA *tp_orig = *tp; PICK_MODE_CONTEXT *ctx = &pc_tree->none; int i, pl; @@ -2111,7 +2175,13 @@ static void rd_pick_partition(VP10_COMP *cpi, ThreadData *td, partition_vert_allowed &= force_vert_split; } +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + save_context(x, mi_row, mi_col, a, l, sa, sl, ta, tl, bsize); +#else save_context(x, mi_row, mi_col, a, l, sa, sl, bsize); +#endif #if CONFIG_FP_MB_STATS if (cpi->use_fp_mb_stats) { @@ -2257,7 +2327,13 @@ static void rd_pick_partition(VP10_COMP *cpi, ThreadData *td, #endif } } +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + restore_context(x, mi_row, mi_col, a, l, sa, sl, ta, tl, bsize); +#else restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); +#endif } // store estimated motion vector @@ -2322,7 +2398,13 @@ static void rd_pick_partition(VP10_COMP *cpi, ThreadData *td, if (cpi->sf.less_rectangular_check) do_rect &= !partition_none_allowed; } +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + restore_context(x, mi_row, mi_col, a, l, sa, sl, ta, tl, bsize); +#else restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); +#endif } // PARTITION_HORZ @@ -2371,7 +2453,13 @@ static void rd_pick_partition(VP10_COMP *cpi, ThreadData *td, pc_tree->partitioning = PARTITION_HORZ; } } +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + restore_context(x, mi_row, mi_col, a, l, sa, sl, ta, tl, bsize); +#else restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); +#endif } // PARTITION_VERT if (partition_vert_allowed && @@ -2420,7 +2508,13 @@ static void rd_pick_partition(VP10_COMP *cpi, ThreadData *td, pc_tree->partitioning = PARTITION_VERT; } } +#if CONFIG_VAR_TX + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + restore_context(x, mi_row, mi_col, a, l, sa, sl, ta, tl, bsize); +#else restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize); +#endif } // TODO(jbb): This code added so that we avoid static analysis @@ -2461,7 +2555,10 @@ static void encode_rd_sb_row(VP10_COMP *cpi, // Initialize the left context for the new SB row memset(&xd->left_context, 0, sizeof(xd->left_context)); memset(xd->left_seg_context, 0, sizeof(xd->left_seg_context)); - +#if CONFIG_VAR_TX + memset(xd->left_txfm_context_buffer, 0, + sizeof(xd->left_txfm_context_buffer)); +#endif // Code each SB in the row for (mi_col = tile_info->mi_col_start; mi_col < tile_info->mi_col_end; mi_col += MI_BLOCK_SIZE) { @@ -2549,6 +2646,10 @@ static void init_encode_frame_mb_context(VP10_COMP *cpi) { 2 * aligned_mi_cols * MAX_MB_PLANE); memset(xd->above_seg_context, 0, sizeof(*xd->above_seg_context) * aligned_mi_cols); +#if CONFIG_VAR_TX + memset(cm->above_txfm_context, 0, + sizeof(*xd->above_txfm_context) * aligned_mi_cols); +#endif } static int check_dual_ref_flags(VP10_COMP *cpi) { @@ -2947,6 +3048,140 @@ static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi, ++counts->uv_mode[y_mode][uv_mode]; } +#if CONFIG_VAR_TX +static void update_txfm_count(MACROBLOCKD *xd, + FRAME_COUNTS *counts, + TX_SIZE tx_size, int blk_row, int blk_col) { + MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi; + int tx_idx = (blk_row >> 1) * 8 + (blk_col >> 1); + int max_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type]; + int max_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type]; + int ctx = txfm_partition_context(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), + tx_size); + TX_SIZE plane_tx_size = mbmi->inter_tx_size[tx_idx]; + + if (xd->mb_to_bottom_edge < 0) + max_blocks_high += xd->mb_to_bottom_edge >> 5; + if (xd->mb_to_right_edge < 0) + max_blocks_wide += xd->mb_to_right_edge >> 5; + + if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) + return; + + if (tx_size == plane_tx_size) { + ++counts->txfm_partition[ctx][0]; + mbmi->tx_size = tx_size; + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), tx_size); + } else { + BLOCK_SIZE bsize = txsize_to_bsize[tx_size]; + int bh = num_4x4_blocks_high_lookup[bsize]; + int i; + ++counts->txfm_partition[ctx][1]; + + if (tx_size == TX_8X8) { + mbmi->inter_tx_size[tx_idx] = TX_4X4; + mbmi->tx_size = TX_4X4; + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), TX_4X4); + return; + } + + for (i = 0; i < 4; ++i) { + int offsetr = (i >> 1) * bh / 2; + int offsetc = (i & 0x01) * bh / 2; + update_txfm_count(xd, counts, tx_size - 1, + blk_row + offsetr, blk_col + offsetc); + } + } +} + +static void tx_partition_count_update(VP10_COMMON *cm, + MACROBLOCKD *xd, + BLOCK_SIZE plane_bsize, + int mi_row, int mi_col, + FRAME_COUNTS *td_counts) { + const int mi_width = num_4x4_blocks_wide_lookup[plane_bsize]; + const int mi_height = num_4x4_blocks_high_lookup[plane_bsize]; + TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize]; + BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size]; + int bh = num_4x4_blocks_wide_lookup[txb_size]; + int idx, idy; + + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + + for (idy = 0; idy < mi_height; idy += bh) + for (idx = 0; idx < mi_width; idx += bh) + update_txfm_count(xd, td_counts, max_tx_size, idy, idx); +} + +static void set_txfm_context(MACROBLOCKD *xd, TX_SIZE tx_size, + int blk_row, int blk_col) { + MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi; + int tx_idx = (blk_row >> 1) * 8 + (blk_col >> 1); + int max_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type]; + int max_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type]; + TX_SIZE plane_tx_size = mbmi->inter_tx_size[tx_idx]; + + if (xd->mb_to_bottom_edge < 0) + max_blocks_high += xd->mb_to_bottom_edge >> 5; + if (xd->mb_to_right_edge < 0) + max_blocks_wide += xd->mb_to_right_edge >> 5; + + if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) + return; + + if (tx_size == plane_tx_size) { + mbmi->tx_size = tx_size; + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), tx_size); + + } else { + BLOCK_SIZE bsize = txsize_to_bsize[tx_size]; + int bsl = b_width_log2_lookup[bsize]; + int i; + + if (tx_size == TX_8X8) { + mbmi->inter_tx_size[tx_idx] = TX_4X4; + mbmi->tx_size = TX_4X4; + txfm_partition_update(xd->above_txfm_context + (blk_col >> 1), + xd->left_txfm_context + (blk_row >> 1), TX_4X4); + return; + } + + assert(bsl > 0); + --bsl; + for (i = 0; i < 4; ++i) { + int offsetr = (i >> 1) << bsl; + int offsetc = (i & 0x01) << bsl; + set_txfm_context(xd, tx_size - 1, + blk_row + offsetr, blk_col + offsetc); + } + } +} + +static void tx_partition_set_contexts(VP10_COMMON *cm, + MACROBLOCKD *xd, + BLOCK_SIZE plane_bsize, + int mi_row, int mi_col) { + const int mi_width = num_4x4_blocks_wide_lookup[plane_bsize]; + const int mi_height = num_4x4_blocks_high_lookup[plane_bsize]; + TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize]; + BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size]; + int bh = num_4x4_blocks_wide_lookup[txb_size]; + int idx, idy; + + xd->above_txfm_context = cm->above_txfm_context + mi_col; + xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & 0x07); + + for (idy = 0; idy < mi_height; idy += bh) + for (idx = 0; idx < mi_width; idx += bh) + set_txfm_context(xd, max_tx_size, idy, idx); +} +#endif + static void encode_superblock(VP10_COMP *cpi, ThreadData *td, TOKENEXTRA **t, int output_enabled, int mi_row, int mi_col, BLOCK_SIZE bsize, @@ -3027,12 +3262,15 @@ static void encode_superblock(VP10_COMP *cpi, ThreadData *td, !(is_inter_block(mbmi) && (mbmi->skip || seg_skip))) { #if CONFIG_VAR_TX int tx_size_ctx = get_tx_size_context(xd); - if (is_inter_block(mbmi)) + if (is_inter_block(mbmi)) { + tx_partition_count_update(cm, xd, bsize, mi_row, mi_col, + td->counts); inter_block_tx_count_update(cm, xd, mbmi, bsize, tx_size_ctx, &td->counts->tx); - else + } else { ++get_tx_counts(max_txsize_lookup[bsize], get_tx_size_context(xd), &td->counts->tx)[mbmi->tx_size]; + } #else ++get_tx_counts(max_txsize_lookup[bsize], get_tx_size_context(xd), &td->counts->tx)[mbmi->tx_size]; @@ -3072,4 +3310,11 @@ static void encode_superblock(VP10_COMP *cpi, ThreadData *td, } #endif // CONFIG_EXT_TX } + +#if CONFIG_VAR_TX + if (cm->tx_mode == TX_MODE_SELECT && mbmi->sb_type >= BLOCK_8X8 && + is_inter_block(mbmi) && !(mbmi->skip || seg_skip) && + !output_enabled) + tx_partition_set_contexts(cm, xd, bsize, mi_row, mi_col); +#endif } diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c index fc7a107d6..4a4362e00 100644 --- a/vp10/encoder/rdopt.c +++ b/vp10/encoder/rdopt.c @@ -1708,6 +1708,7 @@ static void select_tx_block(const VP10_COMP *cpi, MACROBLOCK *x, int blk_row, int blk_col, int plane, int block, TX_SIZE tx_size, BLOCK_SIZE plane_bsize, ENTROPY_CONTEXT *ta, ENTROPY_CONTEXT *tl, + TXFM_CONTEXT *tx_above, TXFM_CONTEXT *tx_left, int *rate, int64_t *dist, int64_t *bsse, int *skip, int64_t ref_best_rd, int *is_cost_valid) { @@ -1724,9 +1725,12 @@ static void select_tx_block(const VP10_COMP *cpi, MACROBLOCK *x, ENTROPY_CONTEXT *ptl = tl + blk_row; ENTROPY_CONTEXT stxa = 0, stxl = 0; int coeff_ctx, i; + int ctx = txfm_partition_context(tx_above + (blk_col >> 1), + tx_left + (blk_row >> 1), tx_size); + int64_t sum_dist = 0, sum_bsse = 0; int64_t sum_rd = INT64_MAX; - int sum_rate = vp10_cost_bit(128, 1); + int sum_rate = vp10_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 1); int all_skip = 1; int tmp_eob = 0; @@ -1776,7 +1780,7 @@ static void select_tx_block(const VP10_COMP *cpi, MACROBLOCK *x, tx_block_rd_b(cpi, x, tx_size, blk_row, blk_col, plane, block, plane_bsize, coeff_ctx, rate, dist, bsse, skip); if (tx_size > TX_4X4) - *rate += vp10_cost_bit(128, 0); + *rate += vp10_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 0); this_rd = RDCOST(x->rdmult, x->rddiv, *rate, *dist); tmp_eob = p->eobs[block]; } @@ -1799,7 +1803,8 @@ static void select_tx_block(const VP10_COMP *cpi, MACROBLOCK *x, int offsetc = (i & 0x01) << bsl; select_tx_block(cpi, x, blk_row + offsetr, blk_col + offsetc, plane, block + i * sub_step, tx_size - 1, - plane_bsize, ta, tl, &this_rate, &this_dist, + plane_bsize, ta, tl, tx_above, tx_left, + &this_rate, &this_dist, &this_bsse, &this_skip, ref_best_rd - tmp_rd, &this_cost_valid); sum_rate += this_rate; @@ -1818,6 +1823,8 @@ static void select_tx_block(const VP10_COMP *cpi, MACROBLOCK *x, int idx, idy; for (i = 0; i < (1 << tx_size); ++i) pta[i] = ptl[i] = !(tmp_eob == 0); + txfm_partition_update(tx_above + (blk_col >> 1), + tx_left + (blk_row >> 1), tx_size); mbmi->inter_tx_size[tx_idx] = tx_size; for (idy = 0; idy < (1 << tx_size) / 2; ++idy) @@ -1867,17 +1874,23 @@ static void inter_block_yrd(const VP10_COMP *cpi, MACROBLOCK *x, int block = 0; int step = 1 << (max_txsize_lookup[plane_bsize] * 2); ENTROPY_CONTEXT ctxa[16], ctxl[16]; + TXFM_CONTEXT tx_above[8], tx_left[8]; int pnrate = 0, pnskip = 1; int64_t pndist = 0, pnsse = 0; vp10_get_entropy_contexts(bsize, TX_4X4, pd, ctxa, ctxl); + memcpy(tx_above, xd->above_txfm_context, + sizeof(TXFM_CONTEXT) * (mi_width >> 1)); + memcpy(tx_left, xd->left_txfm_context, + sizeof(TXFM_CONTEXT) * (mi_height >> 1)); for (idy = 0; idy < mi_height; idy += bh) { for (idx = 0; idx < mi_width; idx += bh) { select_tx_block(cpi, x, idy, idx, 0, block, max_txsize_lookup[plane_bsize], plane_bsize, - ctxa, ctxl, &pnrate, &pndist, &pnsse, &pnskip, + ctxa, ctxl, tx_above, tx_left, + &pnrate, &pndist, &pnsse, &pnskip, ref_best_rd - this_rd, &is_cost_valid); *rate += pnrate; *distortion += pndist; -- 2.40.0