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;