From 4b8c6d96ec0ec2cc7c78e8e663ab7329704c92b9 Mon Sep 17 00:00:00 2001 From: Jim Bankoski Date: Mon, 22 Dec 2014 08:42:52 -0800 Subject: [PATCH] Tokenization without huge tables. Change-Id: Iff528c4b7528cc70320343b3a7ce07a92b024dfd --- vp9/encoder/vp9_encodemb.c | 11 +--- vp9/encoder/vp9_rdopt.c | 4 +- vp9/encoder/vp9_tokenize.c | 113 +++++++++++++++---------------------- vp9/encoder/vp9_tokenize.h | 41 ++++++++++---- 4 files changed, 82 insertions(+), 87 deletions(-) diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c index 9b2165be6..47c485c8c 100644 --- a/vp9/encoder/vp9_encodemb.c +++ b/vp9/encoder/vp9_encodemb.c @@ -149,7 +149,6 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block, int64_t rd_cost0, rd_cost1; int rate0, rate1, error0, error1, t0, t1; int best, band, pt, i, final_eob; - const TOKENVALUE *dct_value_tokens; const int16_t *dct_value_cost; assert((!type && !plane) || (type && plane)); @@ -169,22 +168,18 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block, #if CONFIG_VP9_HIGHBITDEPTH if (xd->bd == 12) { - dct_value_tokens = vp9_dct_value_tokens_high12_ptr; dct_value_cost = vp9_dct_value_cost_high12_ptr; } else if (xd->bd == 10) { - dct_value_tokens = vp9_dct_value_tokens_high10_ptr; dct_value_cost = vp9_dct_value_cost_high10_ptr; } else { - dct_value_tokens = vp9_dct_value_tokens_ptr; dct_value_cost = vp9_dct_value_cost_ptr; } #else - dct_value_tokens = vp9_dct_value_tokens_ptr; dct_value_cost = vp9_dct_value_cost_ptr; #endif for (i = 0; i < eob; i++) token_cache[scan[i]] = - vp9_pt_energy_class[dct_value_tokens[qcoeff[scan[i]]].token]; + vp9_pt_energy_class[vp9_get_token(qcoeff[scan[i]])]; for (i = eob; i-- > 0;) { int base_bits, d2, dx; @@ -198,7 +193,7 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block, /* Evaluate the first possibility for this state. */ rate0 = tokens[next][0].rate; rate1 = tokens[next][1].rate; - t0 = (dct_value_tokens + x)->token; + t0 = vp9_get_token(x); /* Consider both possible successor states. */ if (next < default_eob) { band = band_translate[i + 1]; @@ -250,7 +245,7 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block, t0 = tokens[next][0].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN; t1 = tokens[next][1].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN; } else { - t0 = t1 = (dct_value_tokens + x)->token; + t0 = t1 = vp9_get_token(x); } if (next < default_eob) { band = band_translate[i + 1]; diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index b2d4d380a..ded082f86 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -373,7 +373,7 @@ static INLINE int cost_coeffs(MACROBLOCK *x, // dc token int v = qcoeff[0]; - int prev_t = vp9_dct_value_tokens_ptr[v].token; + int prev_t = vp9_get_token(v); cost = (*token_costs)[0][pt][prev_t] + vp9_dct_value_cost_ptr[v]; token_cache[0] = vp9_pt_energy_class[prev_t]; ++token_costs; @@ -384,7 +384,7 @@ static INLINE int cost_coeffs(MACROBLOCK *x, int t; v = qcoeff[rc]; - t = vp9_dct_value_tokens_ptr[v].token; + t = vp9_get_token(v); if (use_fast_coef_costing) { cost += (*token_costs)[!prev_t][!prev_t][t] + vp9_dct_value_cost_ptr[v]; } else { diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c index 393eb1a4a..57b8a35c3 100644 --- a/vp9/encoder/vp9_tokenize.c +++ b/vp9/encoder/vp9_tokenize.c @@ -23,23 +23,46 @@ #include "vp9/encoder/vp9_encoder.h" #include "vp9/encoder/vp9_tokenize.h" -static TOKENVALUE dct_value_tokens[DCT_MAX_VALUE * 2]; -const TOKENVALUE *vp9_dct_value_tokens_ptr; static int16_t dct_value_cost[DCT_MAX_VALUE * 2]; -const int16_t *vp9_dct_value_cost_ptr; +const int16_t *vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE; #if CONFIG_VP9_HIGHBITDEPTH -static TOKENVALUE dct_value_tokens_high10[DCT_MAX_VALUE_HIGH10 * 2]; -const TOKENVALUE *vp9_dct_value_tokens_high10_ptr; static int16_t dct_value_cost_high10[DCT_MAX_VALUE_HIGH10 * 2]; -const int16_t *vp9_dct_value_cost_high10_ptr; +const int16_t *vp9_dct_value_cost_high10_ptr = + dct_value_cost_high10 + DCT_MAX_VALUE_HIGH10; -static TOKENVALUE dct_value_tokens_high12[DCT_MAX_VALUE_HIGH12 * 2]; -const TOKENVALUE *vp9_dct_value_tokens_high12_ptr; static int16_t dct_value_cost_high12[DCT_MAX_VALUE_HIGH12 * 2]; -const int16_t *vp9_dct_value_cost_high12_ptr; +const int16_t *vp9_dct_value_cost_high12_ptr = + dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12; #endif +static const TOKENVALUE dct_cat_lt_10_value_tokens[] = { + {9, 63}, {9, 61}, {9, 59}, {9, 57}, {9, 55}, {9, 53}, {9, 51}, {9, 49}, + {9, 47}, {9, 45}, {9, 43}, {9, 41}, {9, 39}, {9, 37}, {9, 35}, {9, 33}, + {9, 31}, {9, 29}, {9, 27}, {9, 25}, {9, 23}, {9, 21}, {9, 19}, {9, 17}, + {9, 15}, {9, 13}, {9, 11}, {9, 9}, {9, 7}, {9, 5}, {9, 3}, {9, 1}, + {8, 31}, {8, 29}, {8, 27}, {8, 25}, {8, 23}, {8, 21}, + {8, 19}, {8, 17}, {8, 15}, {8, 13}, {8, 11}, {8, 9}, + {8, 7}, {8, 5}, {8, 3}, {8, 1}, + {7, 15}, {7, 13}, {7, 11}, {7, 9}, {7, 7}, {7, 5}, {7, 3}, {7, 1}, + {6, 7}, {6, 5}, {6, 3}, {6, 1}, {5, 3}, {5, 1}, + {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 0}, + {1, 0}, {2, 0}, {3, 0}, {4, 0}, + {5, 0}, {5, 2}, {6, 0}, {6, 2}, {6, 4}, {6, 6}, + {7, 0}, {7, 2}, {7, 4}, {7, 6}, {7, 8}, {7, 10}, {7, 12}, {7, 14}, + {8, 0}, {8, 2}, {8, 4}, {8, 6}, {8, 8}, {8, 10}, {8, 12}, + {8, 14}, {8, 16}, {8, 18}, {8, 20}, {8, 22}, {8, 24}, + {8, 26}, {8, 28}, {8, 30}, {9, 0}, {9, 2}, + {9, 4}, {9, 6}, {9, 8}, {9, 10}, {9, 12}, {9, 14}, {9, 16}, + {9, 18}, {9, 20}, {9, 22}, {9, 24}, {9, 26}, {9, 28}, + {9, 30}, {9, 32}, {9, 34}, {9, 36}, {9, 38}, {9, 40}, + {9, 42}, {9, 44}, {9, 46}, {9, 48}, {9, 50}, {9, 52}, + {9, 54}, {9, 56}, {9, 58}, {9, 60}, {9, 62} +}; +const TOKENVALUE *vp9_dct_cat_lt_10_value_tokens = dct_cat_lt_10_value_tokens + + (sizeof(dct_cat_lt_10_value_tokens) / sizeof(*dct_cat_lt_10_value_tokens)) + / 2; + // Array indices are identical to previously-existing CONTEXT_NODE indices const vp9_tree_index vp9_coef_tree[TREE_SIZE(ENTROPY_TOKENS)] = { -EOB_TOKEN, 2, // 0 = EOB @@ -171,39 +194,21 @@ void vp9_coef_tree_initialize() { vp9_tokens_from_tree(vp9_coef_encodings, vp9_coef_tree); } -static void tokenize_init_one(TOKENVALUE *t, const vp9_extra_bit *const e, +static void tokenize_init_one(const vp9_extra_bit *const e, int16_t *value_cost, int max_value) { int i = -max_value; - int sign = 1; + TOKENVALUE t; do { - if (!i) - sign = 0; - - { - const int a = sign ? -i : i; - int eb = sign; - - if (a > 4) { - int j = 4; - - while (++j < 11 && e[j].base_val <= a) {} - - t[i].token = --j; - eb |= (a - e[j].base_val) << 1; - } else { - t[i].token = a; - } - t[i].extra = eb; - } + vp9_get_token_extra(i, &t.token, &t.extra); // initialize the cost for extra bits for all possible coefficient value. { int cost = 0; - const vp9_extra_bit *p = &e[t[i].token]; + const vp9_extra_bit *p = &e[t.token]; if (p->base_val) { - const int extra = t[i].extra; + const int extra = t.extra; const int length = p->len; if (length) @@ -217,26 +222,14 @@ static void tokenize_init_one(TOKENVALUE *t, const vp9_extra_bit *const e, } void vp9_tokenize_initialize() { - vp9_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE; - vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE; - - tokenize_init_one(dct_value_tokens + DCT_MAX_VALUE, vp9_extra_bits, + tokenize_init_one(vp9_extra_bits, dct_value_cost + DCT_MAX_VALUE, DCT_MAX_VALUE); #if CONFIG_VP9_HIGHBITDEPTH - vp9_dct_value_tokens_high10_ptr = dct_value_tokens_high10 + - DCT_MAX_VALUE_HIGH10; - vp9_dct_value_cost_high10_ptr = dct_value_cost_high10 + DCT_MAX_VALUE_HIGH10; - - tokenize_init_one(dct_value_tokens_high10 + DCT_MAX_VALUE_HIGH10, - vp9_extra_bits_high10, + tokenize_init_one(vp9_extra_bits_high10, dct_value_cost_high10 + DCT_MAX_VALUE_HIGH10, DCT_MAX_VALUE_HIGH10); - vp9_dct_value_tokens_high12_ptr = dct_value_tokens_high12 + - DCT_MAX_VALUE_HIGH12; - vp9_dct_value_cost_high12_ptr = dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12; - tokenize_init_one(dct_value_tokens_high12 + DCT_MAX_VALUE_HIGH12, - vp9_extra_bits_high12, + tokenize_init_one(vp9_extra_bits_high12, dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12, DCT_MAX_VALUE_HIGH12); #endif @@ -322,8 +315,8 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, td->counts->eob_branch[tx_size][type][ref]; const uint8_t *const band = get_band_translate(tx_size); const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size); - const TOKENVALUE *dct_value_tokens; - + int16_t token; + EXTRABIT extra; int aoff, loff; txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff); @@ -333,17 +326,6 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, scan = so->scan; nb = so->neighbors; c = 0; -#if CONFIG_VP9_HIGHBITDEPTH - if (cpi->common.profile >= PROFILE_2) { - dct_value_tokens = (cpi->common.bit_depth == VPX_BITS_10 ? - vp9_dct_value_tokens_high10_ptr : - vp9_dct_value_tokens_high12_ptr); - } else { - dct_value_tokens = vp9_dct_value_tokens_ptr; - } -#else - dct_value_tokens = vp9_dct_value_tokens_ptr; -#endif while (c < eob) { int v = 0; @@ -362,14 +344,13 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, v = qcoeff[scan[c]]; } - add_token(&t, coef_probs[band[c]][pt], - dct_value_tokens[v].extra, - (uint8_t)dct_value_tokens[v].token, - (uint8_t)skip_eob, - counts[band[c]][pt]); + vp9_get_token_extra(v, &token, &extra); + + add_token(&t, coef_probs[band[c]][pt], extra, (uint8_t)token, + (uint8_t)skip_eob, counts[band[c]][pt]); eob_branch[band[c]][pt] += !skip_eob; - token_cache[scan[c]] = vp9_pt_energy_class[dct_value_tokens[v].token]; + token_cache[scan[c]] = vp9_pt_energy_class[token]; ++c; pt = get_coef_context(nb, token_cache, c); } diff --git a/vp9/encoder/vp9_tokenize.h b/vp9/encoder/vp9_tokenize.h index 00afb723e..845e139f2 100644 --- a/vp9/encoder/vp9_tokenize.h +++ b/vp9/encoder/vp9_tokenize.h @@ -24,24 +24,23 @@ void vp9_tokenize_initialize(); #define EOSB_TOKEN 127 // Not signalled, encoder only -typedef struct { - int16_t token; #if CONFIG_VP9_HIGHBITDEPTH - int32_t extra; + typedef int32_t EXTRABIT; #else - int16_t extra; + typedef int16_t EXTRABIT; #endif + + +typedef struct { + int16_t token; + EXTRABIT extra; } TOKENVALUE; typedef struct { const vp9_prob *context_tree; -#if CONFIG_VP9_HIGHBITDEPTH - int32_t extra; -#else - int16_t extra; -#endif - uint8_t token; - uint8_t skip_eob_node; + EXTRABIT extra; + uint8_t token; + uint8_t skip_eob_node; } TOKENEXTRA; extern const vp9_tree_index vp9_coef_tree[]; @@ -63,6 +62,7 @@ extern const int16_t *vp9_dct_value_cost_ptr; * fields are not. */ extern const TOKENVALUE *vp9_dct_value_tokens_ptr; +extern const TOKENVALUE *vp9_dct_cat_lt_10_value_tokens; #if CONFIG_VP9_HIGHBITDEPTH extern const int16_t *vp9_dct_value_cost_high10_ptr; extern const TOKENVALUE *vp9_dct_value_tokens_high10_ptr; @@ -70,6 +70,25 @@ extern const int16_t *vp9_dct_value_cost_high12_ptr; extern const TOKENVALUE *vp9_dct_value_tokens_high12_ptr; #endif // CONFIG_VP9_HIGHBITDEPTH +static INLINE void vp9_get_token_extra(int v, int16_t *token, EXTRABIT *extra) { + if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) { + *token = CATEGORY6_TOKEN; + if (v >= CAT6_MIN_VAL) + *extra = 2 * v - 2 * CAT6_MIN_VAL; + else + *extra = -2 * v - 2 * CAT6_MIN_VAL + 1; + return; + } + *token = vp9_dct_cat_lt_10_value_tokens[v].token; + *extra = vp9_dct_cat_lt_10_value_tokens[v].extra; +} +static INLINE int16_t vp9_get_token(int v) { + if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) + return 10; + return vp9_dct_cat_lt_10_value_tokens[v].token; +} + + #ifdef __cplusplus } // extern "C" #endif -- 2.40.0