diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c index 3a54de225816075de3c3c7c21540e3b4cb53ed8f..c3fdeb48a6c280ab08be7709a6d84a0e995c753b 100644 --- a/vp9/common/vp9_entropy.c +++ b/vp9/common/vp9_entropy.c @@ -23,6 +23,26 @@ const vp9_prob vp9_cat5_prob[] = { 180, 157, 141, 134, 130 }; const vp9_prob vp9_cat6_prob[] = { 254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; +#if CONFIG_VP9_HIGHBITDEPTH +const vp9_prob vp9_cat1_prob_high10[] = { 159 }; +const vp9_prob vp9_cat2_prob_high10[] = { 165, 145 }; +const vp9_prob vp9_cat3_prob_high10[] = { 173, 148, 140 }; +const vp9_prob vp9_cat4_prob_high10[] = { 176, 155, 140, 135 }; +const vp9_prob vp9_cat5_prob_high10[] = { 180, 157, 141, 134, 130 }; +const vp9_prob vp9_cat6_prob_high10[] = { + 255, 255, 254, 254, 254, 252, 249, 243, + 230, 196, 177, 153, 140, 133, 130, 129 +}; +const vp9_prob vp9_cat1_prob_high12[] = { 159 }; +const vp9_prob vp9_cat2_prob_high12[] = { 165, 145 }; +const vp9_prob vp9_cat3_prob_high12[] = { 173, 148, 140 }; +const vp9_prob vp9_cat4_prob_high12[] = { 176, 155, 140, 135 }; +const vp9_prob vp9_cat5_prob_high12[] = { 180, 157, 141, 134, 130 }; +const vp9_prob vp9_cat6_prob_high12[] = { + 255, 255, 255, 255, 254, 254, 254, 252, 249, + 243, 230, 196, 177, 153, 140, 133, 130, 129 +}; +#endif const uint8_t vp9_coefband_trans_8x8plus[1024] = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h index 8a10f2320475c85fbad871adace09a4b2b678165..d18478ed958963f281790d37d62178cabd64c6be 100644 --- a/vp9/common/vp9_entropy.h +++ b/vp9/common/vp9_entropy.h @@ -58,6 +58,21 @@ DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat4_prob[4]); DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat5_prob[5]); DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat6_prob[14]); +#if CONFIG_VP9_HIGHBITDEPTH +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat1_prob_high10[1]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat2_prob_high10[2]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat3_prob_high10[3]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat4_prob_high10[4]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat5_prob_high10[5]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat6_prob_high10[16]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat1_prob_high12[1]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat2_prob_high12[2]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat3_prob_high12[3]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat4_prob_high12[4]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat5_prob_high12[5]); +DECLARE_ALIGNED(16, extern const uint8_t, vp9_cat6_prob_high12[18]); +#endif // CONFIG_VP9_HIGHBITDEPTH + #define EOB_MODEL_TOKEN 3 extern const vp9_tree_index vp9_coefmodel_tree[]; @@ -70,8 +85,16 @@ typedef struct { // indexed by token value extern const vp9_extra_bit vp9_extra_bits[ENTROPY_TOKENS]; +#if CONFIG_VP9_HIGHBITDEPTH +extern const vp9_extra_bit vp9_extra_bits_high10[ENTROPY_TOKENS]; +extern const vp9_extra_bit vp9_extra_bits_high12[ENTROPY_TOKENS]; +#endif // CONFIG_VP9_HIGHBITDEPTH #define DCT_MAX_VALUE 16384 +#if CONFIG_VP9_HIGHBITDEPTH +#define DCT_MAX_VALUE_HIGH10 65536 +#define DCT_MAX_VALUE_HIGH12 262144 +#endif // CONFIG_VP9_HIGHBITDEPTH /* Coefficients are predicted via a 3-dimensional probability table. */ diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c index df46f64e71bf8183a7d86e0164cd7518cfbf8650..4abf1d12b59fce460dfd8313ea162472e03309c8 100644 --- a/vp9/decoder/vp9_detokenize.c +++ b/vp9/decoder/vp9_detokenize.c @@ -74,6 +74,46 @@ static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, PLANE_TYPE type, const int dq_shift = (tx_size == TX_32X32); int v, token; int16_t dqv = dq[0]; + const uint8_t *cat1_prob; + const uint8_t *cat2_prob; + const uint8_t *cat3_prob; + const uint8_t *cat4_prob; + const uint8_t *cat5_prob; + const uint8_t *cat6_prob; + +#if CONFIG_VP9_HIGHBITDEPTH + if (cm->use_highbitdepth) { + if (cm->bit_depth == VPX_BITS_10) { + cat1_prob = vp9_cat1_prob_high10; + cat2_prob = vp9_cat2_prob_high10; + cat3_prob = vp9_cat3_prob_high10; + cat4_prob = vp9_cat4_prob_high10; + cat5_prob = vp9_cat5_prob_high10; + cat6_prob = vp9_cat6_prob_high10; + } else { + cat1_prob = vp9_cat1_prob_high12; + cat2_prob = vp9_cat2_prob_high12; + cat3_prob = vp9_cat3_prob_high12; + cat4_prob = vp9_cat4_prob_high12; + cat5_prob = vp9_cat5_prob_high12; + cat6_prob = vp9_cat6_prob_high12; + } + } else { + cat1_prob = vp9_cat1_prob; + cat2_prob = vp9_cat2_prob; + cat3_prob = vp9_cat3_prob; + cat4_prob = vp9_cat4_prob; + cat5_prob = vp9_cat5_prob; + cat6_prob = vp9_cat6_prob; + } +#else + cat1_prob = vp9_cat1_prob; + cat2_prob = vp9_cat2_prob; + cat3_prob = vp9_cat3_prob; + cat4_prob = vp9_cat4_prob; + cat5_prob = vp9_cat5_prob; + cat6_prob = vp9_cat6_prob; +#endif while (c < max_eob) { int val = -1; @@ -113,22 +153,39 @@ static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, PLANE_TYPE type, val = token; break; case CATEGORY1_TOKEN: - val = CAT1_MIN_VAL + read_coeff(vp9_cat1_prob, 1, r); + val = CAT1_MIN_VAL + read_coeff(cat1_prob, 1, r); break; case CATEGORY2_TOKEN: - val = CAT2_MIN_VAL + read_coeff(vp9_cat2_prob, 2, r); + val = CAT2_MIN_VAL + read_coeff(cat2_prob, 2, r); break; case CATEGORY3_TOKEN: - val = CAT3_MIN_VAL + read_coeff(vp9_cat3_prob, 3, r); + val = CAT3_MIN_VAL + read_coeff(cat3_prob, 3, r); break; case CATEGORY4_TOKEN: - val = CAT4_MIN_VAL + read_coeff(vp9_cat4_prob, 4, r); + val = CAT4_MIN_VAL + read_coeff(cat4_prob, 4, r); break; case CATEGORY5_TOKEN: - val = CAT5_MIN_VAL + read_coeff(vp9_cat5_prob, 5, r); + val = CAT5_MIN_VAL + read_coeff(cat5_prob, 5, r); break; case CATEGORY6_TOKEN: - val = CAT6_MIN_VAL + read_coeff(vp9_cat6_prob, 14, r); +#if CONFIG_VP9_HIGHBITDEPTH + switch (cm->bit_depth) { + case VPX_BITS_8: + val = CAT6_MIN_VAL + read_coeff(cat6_prob, 14, r); + break; + case VPX_BITS_10: + val = CAT6_MIN_VAL + read_coeff(cat6_prob, 16, r); + break; + case VPX_BITS_12: + val = CAT6_MIN_VAL + read_coeff(cat6_prob, 18, r); + break; + default: + assert(0); + return -1; + } +#else + val = CAT6_MIN_VAL + read_coeff(cat6_prob, 14, r); +#endif break; } } diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c index 263883f664c86a8cef909700427fbfa63905feb8..c07adc30308adeb65d4781002f4abe0cf2da6861 100644 --- a/vp9/encoder/vp9_tokenize.c +++ b/vp9/encoder/vp9_tokenize.c @@ -28,6 +28,18 @@ 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; +#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; + +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; +#endif + // 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 @@ -57,6 +69,21 @@ const vp9_tree_index vp9_coef_con_tree[TREE_SIZE(ENTROPY_TOKENS)] = { static vp9_tree_index cat1[2], cat2[4], cat3[6], cat4[8], cat5[10], cat6[28]; +#if CONFIG_VP9_HIGHBITDEPTH +static vp9_tree_index cat1_high10[2]; +static vp9_tree_index cat2_high10[4]; +static vp9_tree_index cat3_high10[6]; +static vp9_tree_index cat4_high10[8]; +static vp9_tree_index cat5_high10[10]; +static vp9_tree_index cat6_high10[32]; +static vp9_tree_index cat1_high12[2]; +static vp9_tree_index cat2_high12[4]; +static vp9_tree_index cat3_high12[6]; +static vp9_tree_index cat4_high12[8]; +static vp9_tree_index cat5_high12[10]; +static vp9_tree_index cat6_high12[36]; +#endif + static void init_bit_tree(vp9_tree_index *p, int n) { int i = 0; @@ -75,6 +102,20 @@ static void init_bit_trees() { init_bit_tree(cat4, 4); init_bit_tree(cat5, 5); init_bit_tree(cat6, 14); +#if CONFIG_VP9_HIGHBITDEPTH + init_bit_tree(cat1_high10, 1); + init_bit_tree(cat2_high10, 2); + init_bit_tree(cat3_high10, 3); + init_bit_tree(cat4_high10, 4); + init_bit_tree(cat5_high10, 5); + init_bit_tree(cat6_high10, 16); + init_bit_tree(cat1_high12, 1); + init_bit_tree(cat2_high12, 2); + init_bit_tree(cat3_high12, 3); + init_bit_tree(cat4_high12, 4); + init_bit_tree(cat5_high12, 5); + init_bit_tree(cat6_high12, 18); +#endif } const vp9_extra_bit vp9_extra_bits[ENTROPY_TOKENS] = { @@ -92,6 +133,37 @@ const vp9_extra_bit vp9_extra_bits[ENTROPY_TOKENS] = { {0, 0, 0, 0} // EOB_TOKEN }; +#if CONFIG_VP9_HIGHBITDEPTH +const vp9_extra_bit vp9_extra_bits_high10[ENTROPY_TOKENS] = { + {0, 0, 0, 0}, // ZERO_TOKEN + {0, 0, 0, 1}, // ONE_TOKEN + {0, 0, 0, 2}, // TWO_TOKEN + {0, 0, 0, 3}, // THREE_TOKEN + {0, 0, 0, 4}, // FOUR_TOKEN + {cat1_high10, vp9_cat1_prob_high10, 1, CAT1_MIN_VAL}, // CATEGORY1_TOKEN + {cat2_high10, vp9_cat2_prob_high10, 2, CAT2_MIN_VAL}, // CATEGORY2_TOKEN + {cat3_high10, vp9_cat3_prob_high10, 3, CAT3_MIN_VAL}, // CATEGORY3_TOKEN + {cat4_high10, vp9_cat4_prob_high10, 4, CAT4_MIN_VAL}, // CATEGORY4_TOKEN + {cat5_high10, vp9_cat5_prob_high10, 5, CAT5_MIN_VAL}, // CATEGORY5_TOKEN + {cat6_high10, vp9_cat6_prob_high10, 16, CAT6_MIN_VAL}, // CATEGORY6_TOKEN + {0, 0, 0, 0} // EOB_TOKEN +}; +const vp9_extra_bit vp9_extra_bits_high12[ENTROPY_TOKENS] = { + {0, 0, 0, 0}, // ZERO_TOKEN + {0, 0, 0, 1}, // ONE_TOKEN + {0, 0, 0, 2}, // TWO_TOKEN + {0, 0, 0, 3}, // THREE_TOKEN + {0, 0, 0, 4}, // FOUR_TOKEN + {cat1_high12, vp9_cat1_prob_high12, 1, CAT1_MIN_VAL}, // CATEGORY1_TOKEN + {cat2_high12, vp9_cat2_prob_high12, 2, CAT2_MIN_VAL}, // CATEGORY2_TOKEN + {cat3_high12, vp9_cat3_prob_high12, 3, CAT3_MIN_VAL}, // CATEGORY3_TOKEN + {cat4_high12, vp9_cat4_prob_high12, 4, CAT4_MIN_VAL}, // CATEGORY4_TOKEN + {cat5_high12, vp9_cat5_prob_high12, 5, CAT5_MIN_VAL}, // CATEGORY5_TOKEN + {cat6_high12, vp9_cat6_prob_high12, 18, CAT6_MIN_VAL}, // CATEGORY6_TOKEN + {0, 0, 0, 0} // EOB_TOKEN +}; +#endif + struct vp9_token vp9_coef_encodings[ENTROPY_TOKENS]; void vp9_coef_tree_initialize() { @@ -99,11 +171,9 @@ void vp9_coef_tree_initialize() { vp9_tokens_from_tree(vp9_coef_encodings, vp9_coef_tree); } -void vp9_tokenize_initialize() { - TOKENVALUE *const t = dct_value_tokens + DCT_MAX_VALUE; - const vp9_extra_bit *const e = vp9_extra_bits; - - int i = -DCT_MAX_VALUE; +static void tokenize_init_one(TOKENVALUE *t, const vp9_extra_bit *const e, + int16_t *value_cost, int max_value) { + int i = -max_value; int sign = 1; do { @@ -130,7 +200,7 @@ void vp9_tokenize_initialize() { // initialize the cost for extra bits for all possible coefficient value. { int cost = 0; - const vp9_extra_bit *p = &vp9_extra_bits[t[i].token]; + const vp9_extra_bit *p = &e[t[i].token]; if (p->base_val) { const int extra = t[i].extra; @@ -140,13 +210,36 @@ void vp9_tokenize_initialize() { cost += treed_cost(p->tree, p->prob, extra >> 1, length); cost += vp9_cost_bit(vp9_prob_half, extra & 1); /* sign */ - dct_value_cost[i + DCT_MAX_VALUE] = cost; + value_cost[i] = cost; } } - } while (++i < DCT_MAX_VALUE); + } while (++i < max_value); +} +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, + 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, + 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, + dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12, + DCT_MAX_VALUE_HIGH12); +#endif } struct tokenize_b_args { @@ -225,6 +318,7 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, cpi->common.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; int aoff, loff; txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff); @@ -235,6 +329,18 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, scan = so->scan; nb = so->neighbors; c = 0; +#if CONFIG_VP9_HIGH && CONFIG_HIGH_QUANT + 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; int skip_eob = 0; @@ -253,14 +359,13 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, } add_token(&t, coef_probs[band[c]][pt], - vp9_dct_value_tokens_ptr[v].extra, - (uint8_t)vp9_dct_value_tokens_ptr[v].token, + dct_value_tokens[v].extra, + (uint8_t)dct_value_tokens[v].token, (uint8_t)skip_eob, counts[band[c]][pt]); eob_branch[band[c]][pt] += !skip_eob; - token_cache[scan[c]] = - vp9_pt_energy_class[vp9_dct_value_tokens_ptr[v].token]; + token_cache[scan[c]] = vp9_pt_energy_class[dct_value_tokens[v].token]; ++c; pt = get_coef_context(nb, token_cache, c); }