OSUOSL/Nero are experiencing Internet connectivity problems. This affects us as we're hosted with OSUOSL. We apologize for the inconvenience.

Commit 736ddef5 authored by Thomas Davies's avatar Thomas Davies

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
parent 53c08960
......@@ -214,32 +214,6 @@ static INLINE int aom_read_bin_(aom_reader *r, aom_cdf_prob *cdf,
// 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,
......
......@@ -146,31 +146,6 @@ static INLINE void aom_write_bin(aom_writer *w, int symb, aom_cdf_prob *cdf,
}
#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,
......
......@@ -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;
......
......@@ -156,7 +156,7 @@ int od_ec_decode_bool_q15(od_ec_dec *dec, unsigned f) {
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 @@ int od_ec_decode_cdf_q15(od_ec_dec *dec, const uint16_t *icdf, int nsyms) {
(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 @@ int od_ec_decode_cdf_q15(od_ec_dec *dec, const uint16_t *icdf, int nsyms) {
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);
......
......@@ -147,7 +147,8 @@ void od_ec_enc_clear(od_ec_enc *enc) {
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 @@ static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh) {
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 @@ void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f) {
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 @@ void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *icdf,
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
......
......@@ -171,7 +171,7 @@ uint8_t av1_read_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
(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 @@ uint8_t av1_read_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
#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;
......
......@@ -41,16 +41,6 @@ static INLINE int av1_read_record_bin(FRAME_COUNTS *counts, aom_reader *r,
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,
......
......@@ -71,7 +71,7 @@ void av1_cost_tokens_from_cdf(int *costs, const aom_cdf_prob *cdf,
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)
......
......@@ -377,8 +377,8 @@ void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
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 @@ void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
#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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment