LV_MAP_MULTI: use reduced probability in EC. Do not round the lv_map probabilities but instead reduce the precision of the entropy coder to 9 bits for all CDFs, and modify operation so that the EC interval is never 0. Change-Id: I1b4e51019613106ae3b68519b20637bc0d7b51be
diff --git a/aom_dsp/bitreader.h b/aom_dsp/bitreader.h index 43c6f75..426914d 100644 --- a/aom_dsp/bitreader.h +++ b/aom_dsp/bitreader.h
@@ -214,32 +214,6 @@ // printf("bin: %d\n", this_cdf[0]); return ret; } - -#if CONFIG_LV_MAP_MULTI -#define CDF_SYM4_BITS (9) -static INLINE int aom_read_symbol4_(aom_reader *r, aom_cdf_prob *cdf, - int nsymbs ACCT_STR_PARAM) { - int ret; - const int shift = 15 - CDF_SYM4_BITS; - const int mask = ~((1 << shift) - 1); - const int min_prob = 1 << shift; - const int max_prob = 32767 & mask; - aom_cdf_prob this_cdf[5]; - this_cdf[2] = AOMMAX(cdf[2] & mask, min_prob); - this_cdf[1] = AOMMAX(cdf[1] & mask, this_cdf[2] + min_prob); - this_cdf[0] = AOMMAX(cdf[0] & mask, this_cdf[1] + min_prob); - this_cdf[0] = AOMMIN(this_cdf[0], max_prob); - this_cdf[1] = AOMMIN(this_cdf[1], this_cdf[0] - min_prob); - this_cdf[2] = AOMMIN(this_cdf[2], this_cdf[1] - min_prob); - this_cdf[3] = 0; - this_cdf[4] = 0; - // printf("cdf: %5d %5d %5d\n", cdf[0], cdf[1], cdf[2]); - // printf("newcdf: %5d %5d %5d\n", this_cdf[0], this_cdf[1], this_cdf[2]); - ret = aom_read_cdf(r, this_cdf, nsymbs, ACCT_STR_NAME); - if (r->allow_update_cdf) update_cdf(cdf, ret, nsymbs); - return ret; -} -#endif #endif static INLINE int aom_read_tree_as_cdf(aom_reader *r,
diff --git a/aom_dsp/bitwriter.h b/aom_dsp/bitwriter.h index c2d4cb7..389f512 100644 --- a/aom_dsp/bitwriter.h +++ b/aom_dsp/bitwriter.h
@@ -146,31 +146,6 @@ } #endif -#if CONFIG_LV_MAP_MULTI -#define CDF_SYM4_BITS (9) -static INLINE void aom_write_cdf4(aom_writer *w, int symb, aom_cdf_prob *cdf, - int nsymbs) { - assert(nsymbs == 4); - const int shift = 15 - CDF_SYM4_BITS; - const int mask = ~((1 << shift) - 1); - const int min_prob = 1 << shift; - const int max_prob = 32767 & mask; - aom_cdf_prob this_cdf[5]; - this_cdf[2] = AOMMAX(cdf[2] & mask, min_prob); - this_cdf[1] = AOMMAX(cdf[1] & mask, this_cdf[2] + min_prob); - this_cdf[0] = AOMMAX(cdf[0] & mask, this_cdf[1] + min_prob); - this_cdf[0] = AOMMIN(this_cdf[0], max_prob); - this_cdf[1] = AOMMIN(this_cdf[1], this_cdf[0] - min_prob); - this_cdf[2] = AOMMIN(this_cdf[2], this_cdf[1] - min_prob); - this_cdf[3] = 0; - this_cdf[4] = 0; - // printf("cdf: %5d %5d %5d\n", cdf[0], cdf[1], cdf[2]); - // printf("newcdf: %5d %5d %5d\n", this_cdf[0], this_cdf[1], this_cdf[2]); - aom_write_cdf(w, symb, this_cdf, nsymbs); - if (w->allow_update_cdf) update_bin(cdf, symb, nsymbs); -} -#endif - static INLINE void aom_write_tree_as_cdf(aom_writer *w, const aom_tree_index *tree, const aom_prob *probs, int bits,
diff --git a/aom_dsp/entcode.h b/aom_dsp/entcode.h index 981a951..cb2c961 100644 --- a/aom_dsp/entcode.h +++ b/aom_dsp/entcode.h
@@ -15,6 +15,14 @@ #include <stddef.h> #include "av1/common/odintrin.h" +#if CONFIG_LV_MAP_MULTI +#define EC_PROB_SHIFT 6 +#define EC_MIN_PROB 4 // must be <= (1<<EC_PROB_SHIFT)/16 +#else +#define EC_PROB_SHIFT 0 +#define EC_MIN_PROB 0 +#endif + /*OPT: od_ec_window must be at least 32 bits, but if you have fast arithmetic on a larger type, you can speed up the decoder by using it here.*/ typedef uint32_t od_ec_window;
diff --git a/aom_dsp/entdec.c b/aom_dsp/entdec.c index 45fb305..ba31710 100644 --- a/aom_dsp/entdec.c +++ b/aom_dsp/entdec.c
@@ -156,7 +156,7 @@ r = dec->rng; OD_ASSERT(dif >> (OD_EC_WINDOW_SIZE - 16) < r); OD_ASSERT(32768U <= r); - v = (r >> 8) * (uint32_t)f >> 7; + v = ((r >> 8) * (uint32_t)(f >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)); vw = (od_ec_window)v << (OD_EC_WINDOW_SIZE - 16); ret = 1; r_new = v; @@ -187,6 +187,8 @@ (void)nsyms; dif = dec->dif; r = dec->rng; + const int N = nsyms - 1; + OD_ASSERT(dif >> (OD_EC_WINDOW_SIZE - 16) < r); OD_ASSERT(icdf[nsyms - 1] == OD_ICDF(32768U)); OD_ASSERT(32768U <= r); @@ -195,7 +197,9 @@ ret = -1; do { u = v; - v = (r >> 8) * (uint32_t)icdf[++ret] >> 7; + v = ((r >> 8) * (uint32_t)(icdf[++ret] >> EC_PROB_SHIFT) >> + (7 - EC_PROB_SHIFT)); + v += EC_MIN_PROB * (N - ret); } while (c < v); OD_ASSERT(v < u); OD_ASSERT(u <= r);
diff --git a/aom_dsp/entenc.c b/aom_dsp/entenc.c index 41d0d41..751235f 100644 --- a/aom_dsp/entenc.c +++ b/aom_dsp/entenc.c
@@ -147,7 +147,8 @@ one to be encoded. fh: 32768 minus the cumulative frequency of all symbols up to and including the one to be encoded.*/ -static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh) { +static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s, + int nsyms) { od_ec_window l; unsigned r; unsigned u; @@ -157,13 +158,17 @@ OD_ASSERT(32768U <= r); OD_ASSERT(fh < fl); OD_ASSERT(fl <= 32768U); + const int N = nsyms - 1; if (fl < 32768U) { - u = (r >> 8) * (uint32_t)fl >> 7; - v = (r >> 8) * (uint32_t)fh >> 7; + u = ((r >> 8) * (uint32_t)(fl >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB * (N - (s - 1)); + v = ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB * (N - (s + 0)); l += r - u; r = u - v; } else { - r -= (r >> 8) * (uint32_t)fh >> 7; + r -= ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + + EC_MIN_PROB * (N - (s + 0)); } od_ec_enc_normalize(enc, l, r); #if OD_MEASURE_EC_OVERHEAD @@ -184,7 +189,7 @@ l = enc->low; r = enc->rng; OD_ASSERT(32768U <= r); - v = (r >> 8) * (uint32_t)f >> 7; + v = ((r >> 8) * (uint32_t)(f >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)); if (val) l += r - v; r = val ? v : r - v; od_ec_enc_normalize(enc, l, r); @@ -209,7 +214,7 @@ OD_ASSERT(s >= 0); OD_ASSERT(s < nsyms); OD_ASSERT(icdf[nsyms - 1] == OD_ICDF(32768U)); - od_ec_encode_q15(enc, s > 0 ? icdf[s - 1] : OD_ICDF(0), icdf[s]); + od_ec_encode_q15(enc, s > 0 ? icdf[s - 1] : OD_ICDF(0), icdf[s], s, nsyms); } /*Overwrites a few bits at the very start of an existing stream, after they