From: Alex Converse Date: Wed, 17 Feb 2016 19:07:20 +0000 (-0800) Subject: Write MB tokens using the forward buffered ANS writer. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d324c6b025b4cedcec9f91d2cf6bc65352048713;p=libvpx Write MB tokens using the forward buffered ANS writer. This allows sharing more code paths with the rest of the code an allows for easier compatibility with the other experiments. Change-Id: Id288b533805a4d0657ec2f17542f2e6ad23ebdb4 --- diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 84b01e0b2..6aa52544f 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -2322,7 +2322,7 @@ static void decode_partition(VP10Decoder *const pbi, MACROBLOCKD *const xd, for (col = 0; col < max_blocks_wide; col += step) eobtotal += reconstruct_inter_block(xd, #if CONFIG_ANS - pbi->token_tab, tok, + cm->token_tab, tok, #else r, #endif diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 386a17e87..5ae69cf79 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -28,6 +28,7 @@ #include "vp10/common/seg_common.h" #include "vp10/common/tile_common.h" +#include "vp10/encoder/buf_ans.h" #include "vp10/encoder/cost.h" #include "vp10/encoder/bitstream.h" #include "vp10/encoder/encodemv.h" @@ -659,65 +660,85 @@ static void pack_mb_tokens(vpx_writer *w, *tp = p; } #else -// This function serializes the tokens backwards both in token order and -// bit order in each token. -static void pack_mb_tokens_ans(struct AnsCoder *const ans, - rans_dec_lut token_tab[COEFF_PROB_MODELS], - const TOKENEXTRA *const start, +// This function serializes the tokens in forward order using a buffered ans +// coder. +static void pack_mb_tokens_ans(struct BufAnsCoder *ans, + const rans_dec_lut token_tab[COEFF_PROB_MODELS], + TOKENEXTRA **tp, const TOKENEXTRA *const stop, - vpx_bit_depth_t bit_depth) { - const TOKENEXTRA *p; - TX_SIZE tx_size = TX_SIZES; + vpx_bit_depth_t bit_depth, + const TX_SIZE tx) { + TOKENEXTRA *p = *tp; +#if CONFIG_VAR_TX + int count = 0; + const int seg_eob = 16 << (tx << 1); +#endif // CONFIG_VAR_TX - for (p = stop - 1; p >= start; --p) { + while (p < stop && p->token != EOSB_TOKEN) { const int t = p->token; - if (t == EOSB_TOKEN) { - tx_size = (TX_SIZE)p->extra; - } else { #if CONFIG_VP9_HIGHBITDEPTH - const vp10_extra_bit *const b = - (bit_depth == VPX_BITS_12) ? &vp10_extra_bits_high12[t] : - (bit_depth == VPX_BITS_10) ? &vp10_extra_bits_high10[t] : - &vp10_extra_bits[t]; + const vp10_extra_bit *b; + if (bit_depth == VPX_BITS_12) + b = &vp10_extra_bits_high12[t]; + else if (bit_depth == VPX_BITS_10) + b = &vp10_extra_bits_high10[t]; + else + b = &vp10_extra_bits[t]; #else const vp10_extra_bit *const b = &vp10_extra_bits[t]; - (void) bit_depth; + (void)bit_depth; #endif // CONFIG_VP9_HIGHBITDEPTH - if (t != EOB_TOKEN && t != ZERO_TOKEN) { - // Write extra bits first - const int e = p->extra; - const int l = b->len; - const int skip_bits = (t == CATEGORY6_TOKEN) ? TX_SIZES - 1 - tx_size : 0; - assert(tx_size < TX_SIZES); - uabs_write(ans, e & 1, 128); - if (l) { - const int v = e >> 1; - int n; - for (n = 0; n < l - skip_bits; ++n) { - const int bb = (v >> n) & 1; - uabs_write(ans, bb, b->prob[l - 1 - n]); - } - for (; n < l; ++n) { - assert(((v >> n) & 1) == 0); - } - } + /* skip one or two nodes */ + if (!p->skip_eob_node) + buf_uabs_write(ans, t != EOB_TOKEN, p->context_tree[0]); + + if (t != EOB_TOKEN) { + buf_uabs_write(ans, t != ZERO_TOKEN, p->context_tree[1]); - { + if (t != ZERO_TOKEN) { struct rans_sym s; const rans_dec_lut *token_cdf = &token_tab[p->context_tree[PIVOT_NODE] - 1]; s.cum_prob = (*token_cdf)[t - ONE_TOKEN]; s.prob = (*token_cdf)[t - ONE_TOKEN + 1] - s.cum_prob; - rans_write(ans, &s); + buf_rans_write(ans, &s); } } - if (t != EOB_TOKEN) - uabs_write(ans, t != ZERO_TOKEN, p->context_tree[1]); - if (!p->skip_eob_node) - uabs_write(ans, t != EOB_TOKEN, p->context_tree[0]); - } + + if (b->base_val) { + const int e = p->extra, l = b->len; + int skip_bits = (b->base_val == CAT6_MIN_VAL) ? TX_SIZES - 1 - tx : 0; + + if (l) { + const unsigned char *pb = b->prob; + int v = e >> 1; + int n = l; /* number of bits in v, assumed nonzero */ + int i = 0; + + do { + const int bb = (v >> --n) & 1; + if (skip_bits) { + skip_bits--; + assert(!bb); + } else { + buf_uabs_write(ans, bb, pb[i >> 1]); + } + i = b->tree[i + bb]; + } while (n); + } + + buf_uabs_write(ans, e & 1, 128); + } + ++p; + +#if CONFIG_VAR_TX + ++count; + if (t == EOB_TOKEN || count == seg_eob) break; +#endif // CONFIG_VAR_TX } + + *tp = p; } #endif // !CONFIG_ANS @@ -1436,8 +1457,11 @@ static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd, } static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile, - vpx_writer *w, TOKENEXTRA **tok, - const TOKENEXTRA *const tok_end, + vpx_writer *w, +#if CONFIG_ANS + struct BufAnsCoder *ans, +#endif // CONFIG_ANS + TOKENEXTRA **tok, const TOKENEXTRA *const tok_end, #if CONFIG_SUPERTX int supertx_enabled, #endif @@ -1492,7 +1516,6 @@ static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile, if (supertx_enabled) return; #endif // CONFIG_SUPERTX -#if !CONFIG_ANS if (!m->mbmi.skip) { assert(*tok < tok_end); for (plane = 0; plane < MAX_MB_PLANE; ++plane) { @@ -1528,18 +1551,26 @@ static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile, for (row = 0; row < num_4x4_h; row += bw) for (col = 0; col < num_4x4_w; col += bw) +#if CONFIG_ANS + pack_mb_tokens_ans(ans, cm->token_tab, tok, tok_end, cm->bit_depth, + tx); +#else pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx); +#endif // CONFIG_ANS } #else TX_SIZE tx = plane ? get_uv_tx_size(&m->mbmi, &xd->plane[plane]) : m->mbmi.tx_size; +#if CONFIG_ANS + pack_mb_tokens_ans(ans, cm->token_tab, tok, tok_end, cm->bit_depth, tx); +#else pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx); +#endif // CONFIG_ANS #endif // CONFIG_VAR_TX assert(*tok < tok_end && (*tok)->token == EOSB_TOKEN); (*tok)++; } } -#endif } static void write_partition(const VP10_COMMON *const cm, @@ -1564,8 +1595,11 @@ static void write_partition(const VP10_COMMON *const cm, } } -static void write_modes_sb(VP10_COMP *cpi, - const TileInfo *const tile, vpx_writer *w, +static void write_modes_sb(VP10_COMP *cpi, const TileInfo *const tile, + vpx_writer *w, +#if CONFIG_ANS + struct BufAnsCoder *ans, +#endif // CONFIG_ANS TOKENEXTRA **tok, const TOKENEXTRA *const tok_end, #if CONFIG_SUPERTX int supertx_enabled, @@ -1634,7 +1668,11 @@ static void write_modes_sb(VP10_COMP *cpi, } #endif // CONFIG_SUPERTX if (subsize < BLOCK_8X8) { - write_modes_b(cpi, tile, w, tok, tok_end, + write_modes_b(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX @@ -1642,55 +1680,91 @@ static void write_modes_sb(VP10_COMP *cpi, } else { switch (partition) { case PARTITION_NONE: - write_modes_b(cpi, tile, w, tok, tok_end, + write_modes_b(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row, mi_col); break; case PARTITION_HORZ: - write_modes_b(cpi, tile, w, tok, tok_end, + write_modes_b(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row, mi_col); if (mi_row + bs < cm->mi_rows) - write_modes_b(cpi, tile, w, tok, tok_end, + write_modes_b(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row + bs, mi_col); break; case PARTITION_VERT: - write_modes_b(cpi, tile, w, tok, tok_end, + write_modes_b(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row, mi_col); if (mi_col + bs < cm->mi_cols) - write_modes_b(cpi, tile, w, tok, tok_end, + write_modes_b(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row, mi_col + bs); break; case PARTITION_SPLIT: - write_modes_sb(cpi, tile, w, tok, tok_end, + write_modes_sb(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row, mi_col, subsize); - write_modes_sb(cpi, tile, w, tok, tok_end, + write_modes_sb(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row, mi_col + bs, subsize); - write_modes_sb(cpi, tile, w, tok, tok_end, + write_modes_sb(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX mi_row + bs, mi_col, subsize); - write_modes_sb(cpi, tile, w, tok, tok_end, + write_modes_sb(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX supertx_enabled, #endif // CONFIG_SUPERTX @@ -1716,7 +1790,12 @@ static void write_modes_sb(VP10_COMP *cpi, for (row = 0; row < num_4x4_h; row += bw) for (col = 0; col < num_4x4_w; col += bw) +#if CONFIG_ANS + pack_mb_tokens_ans(ans, cm->token_tab, tok, tok_end, cm->bit_depth, + tx); +#else pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx); +#endif assert(*tok < tok_end && (*tok)->token == EOSB_TOKEN); (*tok)++; } @@ -1729,8 +1808,11 @@ static void write_modes_sb(VP10_COMP *cpi, update_partition_context(xd, mi_row, mi_col, subsize, bsize); } -static void write_modes(VP10_COMP *cpi, - const TileInfo *const tile, vpx_writer *w, +static void write_modes(VP10_COMP *cpi, const TileInfo *const tile, + vpx_writer *w, +#if CONFIG_ANS + struct BufAnsCoder *ans, +#endif // CONFIG_ANS TOKENEXTRA **tok, const TOKENEXTRA *const tok_end) { MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; int mi_row, mi_col; @@ -1740,7 +1822,11 @@ static void write_modes(VP10_COMP *cpi, vp10_zero_left_context(xd); 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, + write_modes_sb(cpi, tile, w, +#if CONFIG_ANS + ans, +#endif // CONFIG_ANS + tok, tok_end, #if CONFIG_SUPERTX 0, #endif @@ -2206,13 +2292,18 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr, vpx_writer mode_bc; #if CONFIG_ANS struct AnsCoder token_ans; -#endif + struct BufAnsCoder buffered_ans; +#endif // CONFIG_ANS int tile_row, tile_col; TOKENEXTRA *tok_end; size_t total_size = 0; const int tile_cols = 1 << cm->log2_tile_cols; const int tile_rows = 1 << cm->log2_tile_rows; unsigned int max_tile = 0; + const int ans_window_size = get_token_alloc(cm->mb_rows, cm->mb_cols) * 3; + struct buffered_ans_symbol *uco_ans_buf = + malloc(ans_window_size * sizeof(*uco_ans_buf)); + assert(uco_ans_buf); vp10_zero_above_context(cm, 0, mi_cols_aligned_to_sb(cm->mi_cols)); @@ -2232,8 +2323,8 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr, #if !CONFIG_ANS (void) token_section_size; - write_modes(cpi, &cpi->tile_data[tile_idx].tile_info, - &mode_bc, &tok, tok_end); + write_modes(cpi, &cpi->tile_data[tile_idx].tile_info, &mode_bc, &tok, + tok_end); assert(tok == tok_end); vpx_stop_encode(&mode_bc); if (put_tile_size) { @@ -2248,12 +2339,13 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr, } total_size += mode_bc.pos; #else + buf_ans_write_init(&buffered_ans, uco_ans_buf, ans_window_size); write_modes(cpi, &cpi->tile_data[tile_idx].tile_info, &mode_bc, - NULL, NULL); + &buffered_ans, &tok, tok_end); + assert(tok == tok_end); vpx_stop_encode(&mode_bc); ans_write_init(&token_ans, mode_data_start + mode_bc.pos); - pack_mb_tokens_ans(&token_ans, cm->token_tab, tok, tok_end, - cm->bit_depth); + buf_ans_flush(&buffered_ans, &token_ans); token_section_size = ans_write_end(&token_ans); if (put_tile_size) { // size of this tile @@ -2267,6 +2359,9 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr, } *max_tile_sz = max_tile; +#if CONFIG_ANS + free(uco_ans_buf); +#endif // CONFIG_ANS return total_size; } diff --git a/vp10/encoder/tokenize.c b/vp10/encoder/tokenize.c index 7aaef5bcd..822ccc912 100644 --- a/vp10/encoder/tokenize.c +++ b/vp10/encoder/tokenize.c @@ -693,14 +693,6 @@ void vp10_tokenize_sb(VP10_COMP *cpi, ThreadData *td, TOKENEXTRA **t, vp10_foreach_transformed_block_in_plane(xd, bsize, plane, tokenize_b, &arg); (*t)->token = EOSB_TOKEN; -#if CONFIG_ANS - // TODO(aconverse): clip the number of bits in tokenize_b - // Smuggle TX_SIZE in the unused extrabits field so the ANS encoder - // knows the maximum number of extrabits to write at the end of the block - // (where it starts). - (*t)->extra = (EXTRABIT)(plane ? get_uv_tx_size(mbmi, &xd->plane[plane]) - : mbmi->tx_size); -#endif // CONFIG_ANS (*t)++; } } else {