Commit 837262bf authored by Thomas Daede's avatar Thomas Daede
Browse files

Allow CDF precision to be configured with CDF_PROB_BITS.

This does not change the precision used for od_ec_enc_bool_q15
(used by aom_write and aom_write_bit), which means these two
paths will use different CDF precision for now.

The test that verifies that q15's code identically to CDFs
is disabled.

Change-Id: I4cd40a60d472eb58f37ac4fda1056b5dfe8b39a5
parent 79c763bf
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>
#include "av1/common/odintrin.h" #include "av1/common/odintrin.h"
#include "aom_dsp/prob.h"
#define EC_PROB_SHIFT 6 #define EC_PROB_SHIFT 6
#define EC_MIN_PROB 4 // must be <= (1<<EC_PROB_SHIFT)/16 #define EC_MIN_PROB 4 // must be <= (1<<EC_PROB_SHIFT)/16
...@@ -31,11 +32,7 @@ typedef uint32_t od_ec_window; ...@@ -31,11 +32,7 @@ typedef uint32_t od_ec_window;
3 => 1/8th bits.*/ 3 => 1/8th bits.*/
#define OD_BITRES (3) #define OD_BITRES (3)
/*The value stored in an iCDF is 32768 minus the actual Q15 cumulative #define OD_ICDF AOM_ICDF
probability (an "inverse" CDF).
This function converts from one representation to the other (and is its own
inverse).*/
#define OD_ICDF(x) (32768U - (x))
/*See entcode.c for further documentation.*/ /*See entcode.c for further documentation.*/
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#endif #endif
#include "aom_dsp/entdec.h" #include "aom_dsp/entdec.h"
#include "aom_dsp/prob.h"
/*A range decoder. /*A range decoder.
This is an entropy decoder based upon \cite{Mar79}, which is itself a This is an entropy decoder based upon \cite{Mar79}, which is itself a
...@@ -171,8 +172,8 @@ int od_ec_decode_bool_q15(od_ec_dec *dec, unsigned f) { ...@@ -171,8 +172,8 @@ int od_ec_decode_bool_q15(od_ec_dec *dec, unsigned f) {
/*Decodes a symbol given an inverse cumulative distribution function (CDF) /*Decodes a symbol given an inverse cumulative distribution function (CDF)
table in Q15. table in Q15.
icdf: 32768 minus the CDF, such that symbol s falls in the range icdf: CDF_PROB_TOP minus the CDF, such that symbol s falls in the range
[s > 0 ? (32768 - icdf[s - 1]) : 0, 32768 - icdf[s]). [s > 0 ? (CDF_PROB_TOP - icdf[s - 1]) : 0, CDF_PROB_TOP - icdf[s]).
The values must be monotonically non-increasing, and icdf[nsyms - 1] The values must be monotonically non-increasing, and icdf[nsyms - 1]
must be 0. must be 0.
nsyms: The number of symbols in the alphabet. nsyms: The number of symbols in the alphabet.
...@@ -191,15 +192,16 @@ int od_ec_decode_cdf_q15(od_ec_dec *dec, const uint16_t *icdf, int nsyms) { ...@@ -191,15 +192,16 @@ int od_ec_decode_cdf_q15(od_ec_dec *dec, const uint16_t *icdf, int nsyms) {
const int N = nsyms - 1; const int N = nsyms - 1;
OD_ASSERT(dif >> (OD_EC_WINDOW_SIZE - 16) < r); OD_ASSERT(dif >> (OD_EC_WINDOW_SIZE - 16) < r);
OD_ASSERT(icdf[nsyms - 1] == OD_ICDF(32768U)); OD_ASSERT(icdf[nsyms - 1] == OD_ICDF(CDF_PROB_TOP));
OD_ASSERT(32768U <= r); OD_ASSERT(32768U <= r);
OD_ASSERT(7 - EC_PROB_SHIFT - CDF_SHIFT >= 0);
c = (unsigned)(dif >> (OD_EC_WINDOW_SIZE - 16)); c = (unsigned)(dif >> (OD_EC_WINDOW_SIZE - 16));
v = r; v = r;
ret = -1; ret = -1;
do { do {
u = v; u = v;
v = ((r >> 8) * (uint32_t)(icdf[++ret] >> EC_PROB_SHIFT) >> v = ((r >> 8) * (uint32_t)(icdf[++ret] >> EC_PROB_SHIFT) >>
(7 - EC_PROB_SHIFT)); (7 - EC_PROB_SHIFT - CDF_SHIFT));
v += EC_MIN_PROB * (N - ret); v += EC_MIN_PROB * (N - ret);
} while (c < v); } while (c < v);
OD_ASSERT(v < u); OD_ASSERT(v < u);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "aom_dsp/entenc.h" #include "aom_dsp/entenc.h"
#include "aom_dsp/prob.h"
/*A range encoder. /*A range encoder.
See entdec.c and the references for implementation details \cite{Mar79,MNW98}. See entdec.c and the references for implementation details \cite{Mar79,MNW98}.
...@@ -143,9 +144,11 @@ void od_ec_enc_clear(od_ec_enc *enc) { ...@@ -143,9 +144,11 @@ void od_ec_enc_clear(od_ec_enc *enc) {
} }
/*Encodes a symbol given its frequency in Q15. /*Encodes a symbol given its frequency in Q15.
fl: 32768 minus the cumulative frequency of all symbols that come before the fl: CDF_PROB_TOP minus the cumulative frequency of all symbols that come
before the
one to be encoded. one to be encoded.
fh: 32768 minus the cumulative frequency of all symbols up to and including fh: CDF_PROB_TOP minus the cumulative frequency of all symbols up to and
including
the one to be encoded.*/ the one to be encoded.*/
static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s, static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s,
int nsyms) { int nsyms) {
...@@ -158,21 +161,25 @@ static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s, ...@@ -158,21 +161,25 @@ static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s,
OD_ASSERT(32768U <= r); OD_ASSERT(32768U <= r);
OD_ASSERT(fh <= fl); OD_ASSERT(fh <= fl);
OD_ASSERT(fl <= 32768U); OD_ASSERT(fl <= 32768U);
OD_ASSERT(7 - EC_PROB_SHIFT - CDF_SHIFT >= 0);
const int N = nsyms - 1; const int N = nsyms - 1;
if (fl < 32768U) { if (fl < CDF_PROB_TOP) {
u = ((r >> 8) * (uint32_t)(fl >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + u = ((r >> 8) * (uint32_t)(fl >> EC_PROB_SHIFT) >>
(7 - EC_PROB_SHIFT - CDF_SHIFT)) +
EC_MIN_PROB * (N - (s - 1)); EC_MIN_PROB * (N - (s - 1));
v = ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + v = ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >>
(7 - EC_PROB_SHIFT - CDF_SHIFT)) +
EC_MIN_PROB * (N - (s + 0)); EC_MIN_PROB * (N - (s + 0));
l += r - u; l += r - u;
r = u - v; r = u - v;
} else { } else {
r -= ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + r -= ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >>
(7 - EC_PROB_SHIFT - CDF_SHIFT)) +
EC_MIN_PROB * (N - (s + 0)); EC_MIN_PROB * (N - (s + 0));
} }
od_ec_enc_normalize(enc, l, r); od_ec_enc_normalize(enc, l, r);
#if OD_MEASURE_EC_OVERHEAD #if OD_MEASURE_EC_OVERHEAD
enc->entropy -= OD_LOG2((double)(OD_ICDF(fh) - OD_ICDF(fl)) / 32768.); enc->entropy -= OD_LOG2((double)(OD_ICDF(fh) - OD_ICDF(fl)) / CDF_PROB_TOP.);
enc->nb_symbols++; enc->nb_symbols++;
#endif #endif
} }
...@@ -195,8 +202,7 @@ void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f) { ...@@ -195,8 +202,7 @@ void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f) {
r = val ? v : r - v; r = val ? v : r - v;
od_ec_enc_normalize(enc, l, r); od_ec_enc_normalize(enc, l, r);
#if OD_MEASURE_EC_OVERHEAD #if OD_MEASURE_EC_OVERHEAD
enc->entropy -= enc->entropy -= OD_LOG2((double)(val ? f : (32768 - f)) / 32768.);
OD_LOG2((double)(val ? 32768 - OD_ICDF(f) : OD_ICDF(f)) / 32768.);
enc->nb_symbols++; enc->nb_symbols++;
#endif #endif
} }
...@@ -214,7 +220,7 @@ void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *icdf, ...@@ -214,7 +220,7 @@ void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *icdf,
(void)nsyms; (void)nsyms;
OD_ASSERT(s >= 0); OD_ASSERT(s >= 0);
OD_ASSERT(s < nsyms); OD_ASSERT(s < nsyms);
OD_ASSERT(icdf[nsyms - 1] == OD_ICDF(32768U)); OD_ASSERT(icdf[nsyms - 1] == OD_ICDF(CDF_PROB_TOP));
od_ec_encode_q15(enc, s > 0 ? icdf[s - 1] : OD_ICDF(0), icdf[s], s, nsyms); od_ec_encode_q15(enc, s > 0 ? icdf[s - 1] : OD_ICDF(0), icdf[s], s, nsyms);
} }
......
This diff is collapsed.
...@@ -530,12 +530,16 @@ static void build_tail_cdfs(aom_cdf_prob cdf_tail[CDF_SIZE(ENTROPY_TOKENS)], ...@@ -530,12 +530,16 @@ static void build_tail_cdfs(aom_cdf_prob cdf_tail[CDF_SIZE(ENTROPY_TOKENS)],
probNZ = CDF_PROB_TOP - phead[ZERO_TOKEN + is_dc] - (is_dc ? phead[0] : 0); probNZ = CDF_PROB_TOP - phead[ZERO_TOKEN + is_dc] - (is_dc ? phead[0] : 0);
prob1 = phead[is_dc + ONE_TOKEN_EOB] + phead[is_dc + ONE_TOKEN_NEOB]; prob1 = phead[is_dc + ONE_TOKEN_EOB] + phead[is_dc + ONE_TOKEN_NEOB];
prob_idx = prob_idx =
AOMMIN(COEFF_PROB_MODELS - 1, AOMMAX(0, ((256 * prob1) / probNZ) - 1)); AOMMIN(COEFF_PROB_MODELS - 1, AOMMAX(0, (256 * prob1 / probNZ) - 1));
sum = 0; sum = 0;
for (i = 0; i < TAIL_TOKENS; ++i) { for (i = 0; i < TAIL_TOKENS; ++i) {
sum += av1_pareto8_tail_probs[prob_idx][i]; sum += av1_pareto8_tail_probs[prob_idx][i];
cdf_tail[i] = AOM_ICDF(sum); cdf_tail[i] = AOM_ICDF(
((sum - (i + 1)) * ((CDF_INIT_TOP >> CDF_SHIFT) - TAIL_TOKENS) +
((CDF_INIT_TOP - TAIL_TOKENS) >> 1)) /
((CDF_INIT_TOP - TAIL_TOKENS)) +
(i + 1));
} }
} }
......
...@@ -55,13 +55,14 @@ TEST(EC_TEST, random_ec_test) { ...@@ -55,13 +55,14 @@ TEST(EC_TEST, random_ec_test) {
for (j = 0; j < sz; j++) { for (j = 0; j < sz; j++) {
data[j] = rand() / ((RAND_MAX >> 1) + 1); data[j] = rand() / ((RAND_MAX >> 1) + 1);
fts[j] = 15; fts[j] = CDF_PROB_BITS;
fz[j] = (rand() % 32766) >> (15 - fts[j]); fz[j] = (rand() % (CDF_PROB_TOP - 2)) >> (CDF_PROB_BITS - fts[j]);
fz[j] = OD_MAXI(fz[j], 1); fz[j] = OD_MAXI(fz[j], 1);
enc_method[j] = 3 + (rand() & 1); enc_method[j] = 3 + (rand() & 1);
switch (enc_method[j]) { switch (enc_method[j]) {
case 3: { case 3: {
od_ec_encode_bool_q15(&enc, data[j], OD_ICDF(fz[j] << (15 - fts[j]))); od_ec_encode_bool_q15(&enc, data[j],
OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
break; break;
} }
case 4: { case 4: {
...@@ -69,7 +70,6 @@ TEST(EC_TEST, random_ec_test) { ...@@ -69,7 +70,6 @@ TEST(EC_TEST, random_ec_test) {
cdf[0] = OD_ICDF(fz[j]); cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]); cdf[1] = OD_ICDF(1U << fts[j]);
od_ec_encode_cdf_q15(&enc, data[j], cdf, 2); od_ec_encode_cdf_q15(&enc, data[j], cdf, 2);
enc_method[j]++;
break; break;
} }
} }
...@@ -90,10 +90,15 @@ TEST(EC_TEST, random_ec_test) { ...@@ -90,10 +90,15 @@ TEST(EC_TEST, random_ec_test) {
<< " (Random seed: " << seed << ").\n"; << " (Random seed: " << seed << ").\n";
for (j = 0; j < sz; j++) { for (j = 0; j < sz; j++) {
int dec_method; int dec_method;
dec_method = 3 + (rand() & 1); if (CDF_SHIFT == 0) {
dec_method = 3 + (rand() & 1);
} else {
dec_method = enc_method[j];
}
switch (dec_method) { switch (dec_method) {
case 3: { case 3: {
sym = od_ec_decode_bool_q15(&dec, OD_ICDF(fz[j] << (15 - fts[j]))); sym = od_ec_decode_bool_q15(
&dec, OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
break; break;
} }
case 4: { case 4: {
...@@ -101,7 +106,6 @@ TEST(EC_TEST, random_ec_test) { ...@@ -101,7 +106,6 @@ TEST(EC_TEST, random_ec_test) {
cdf[0] = OD_ICDF(fz[j]); cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]); cdf[1] = OD_ICDF(1U << fts[j]);
sym = od_ec_decode_cdf_q15(&dec, cdf, 2); sym = od_ec_decode_cdf_q15(&dec, cdf, 2);
dec_method++;
break; break;
} }
} }
...@@ -126,28 +130,30 @@ TEST(EC_TEST, random_ec_test) { ...@@ -126,28 +130,30 @@ TEST(EC_TEST, random_ec_test) {
free(fz); free(fz);
} }
od_ec_enc_reset(&enc); od_ec_enc_reset(&enc);
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384)); if (CDF_SHIFT == 0) {
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384)); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384)); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384)); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576)); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_enc_patch_initial_bits(&enc, 3, 2); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n"; od_ec_enc_patch_initial_bits(&enc, 3, 2);
od_ec_enc_patch_initial_bits(&enc, 0, 5); EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
EXPECT_TRUE(enc.error) od_ec_enc_patch_initial_bits(&enc, 0, 5);
<< "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n"; EXPECT_TRUE(enc.error)
od_ec_enc_reset(&enc); << "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n";
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384)); od_ec_enc_reset(&enc);
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384)); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 1, OD_ICDF(32256)); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576)); od_ec_encode_bool_q15(&enc, 1, OD_ICDF(32256));
od_ec_enc_patch_initial_bits(&enc, 0, 2); od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n"; od_ec_enc_patch_initial_bits(&enc, 0, 2);
ptr = od_ec_enc_done(&enc, &ptr_sz); EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
EXPECT_EQ(ptr_sz, 2u); ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_EQ(ptr[0], 63) EXPECT_EQ(ptr_sz, 2u);
<< "Got " << ptr[0] EXPECT_EQ(ptr[0], 63)
<< " when expecting 63 for od_ec_enc_patch_initial_bits().\n"; << "Got " << ptr[0]
<< " when expecting 63 for od_ec_enc_patch_initial_bits().\n";
}
od_ec_enc_clear(&enc); od_ec_enc_clear(&enc);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
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