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
diff --git a/av1/decoder/decodetxb.c b/av1/decoder/decodetxb.c
index ff19776..bc9f05c 100644
--- a/av1/decoder/decodetxb.c
+++ b/av1/decoder/decodetxb.c
@@ -171,7 +171,7 @@
(void)nz_map_count;
int coeff_ctx =
get_nz_map_ctx(levels, c, scan, bwl, height, tx_type, c == *eob - 1);
- int level = av1_read_record_symbol4(
+ int level = av1_read_record_symbol(
counts, r, ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], 4,
ACCT_STR);
levels[get_paded_idx(scan[c], bwl)] = level;
@@ -289,7 +289,7 @@
#if CONFIG_LV_MAP_MULTI
for (idx = 0; idx < COEFF_BASE_RANGE / (BR_CDF_SIZE - 1); ++idx) {
- int k = av1_read_record_symbol4(
+ int k = av1_read_record_symbol(
counts, r, ec_ctx->coeff_br_cdf[txs_ctx][plane_type][ctx],
BR_CDF_SIZE, ACCT_STR);
*level += k;
diff --git a/av1/decoder/symbolrate.h b/av1/decoder/symbolrate.h
index 00816ac..235919b 100644
--- a/av1/decoder/symbolrate.h
+++ b/av1/decoder/symbolrate.h
@@ -41,16 +41,6 @@
return aom_read_bin(r, cdf, nsymbs, str);
}
-#if CONFIG_LV_MAP_MULTI
-static INLINE int av1_read_record_symbol4(FRAME_COUNTS *counts, aom_reader *r,
- aom_cdf_prob *cdf, int nsymbs,
- const char *str) {
- (void)str;
- if (counts) ++counts->symbol_num[0];
- return aom_read_symbol4(r, cdf, nsymbs, str);
-}
-#endif
-
#endif
static INLINE int av1_read_record(FRAME_COUNTS *counts, aom_reader *r, int prob,
diff --git a/av1/encoder/cost.c b/av1/encoder/cost.c
index e33df53..240a16c 100644
--- a/av1/encoder/cost.c
+++ b/av1/encoder/cost.c
@@ -71,7 +71,7 @@
int i;
aom_cdf_prob prev_cdf = 0;
for (i = 0;; ++i) {
- const aom_cdf_prob p15 = AOM_ICDF(cdf[i]) - prev_cdf;
+ aom_cdf_prob p15 = AOM_ICDF(cdf[i]) - prev_cdf;
prev_cdf = AOM_ICDF(cdf[i]);
if (inv_map)
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index 21d4a1d..08c7135 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -377,8 +377,8 @@
coeff_ctx =
get_nz_map_ctx(levels, c, scan, bwl, height, tx_type, c == eob - 1);
tran_low_t v = tcoeff[scan[c]];
- aom_write_cdf4(w, AOMMIN(abs(v), 3),
- ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], 4);
+ aom_write_symbol(w, AOMMIN(abs(v), 3),
+ ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx], 4);
#else
coeff_ctx = get_nz_map_ctx(levels, c, scan, bwl, height, tx_type);
tran_low_t v = tcoeff[scan[c]];
@@ -473,8 +473,8 @@
#if CONFIG_LV_MAP_MULTI
for (idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
- aom_write_cdf4(w, k, ec_ctx->coeff_br_cdf[txs_ctx][plane_type][ctx],
- BR_CDF_SIZE);
+ aom_write_symbol(w, k, ec_ctx->coeff_br_cdf[txs_ctx][plane_type][ctx],
+ BR_CDF_SIZE);
if (k < BR_CDF_SIZE - 1) break;
}
if (base_range < COEFF_BASE_RANGE) continue;