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

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 @@
#include <limits.h>
#include <stddef.h>
#include "av1/common/odintrin.h"
#include "aom_dsp/prob.h"
#define EC_PROB_SHIFT 6
#define EC_MIN_PROB 4 // must be <= (1<<EC_PROB_SHIFT)/16
......@@ -31,11 +32,7 @@ typedef uint32_t od_ec_window;
3 => 1/8th bits.*/
#define OD_BITRES (3)
/*The value stored in an iCDF is 32768 minus the actual Q15 cumulative
probability (an "inverse" CDF).
This function converts from one representation to the other (and is its own
inverse).*/
#define OD_ICDF(x) (32768U - (x))
#define OD_ICDF AOM_ICDF
/*See entcode.c for further documentation.*/
......
......@@ -14,6 +14,7 @@
#endif
#include "aom_dsp/entdec.h"
#include "aom_dsp/prob.h"
/*A range decoder.
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) {
/*Decodes a symbol given an inverse cumulative distribution function (CDF)
table in Q15.
icdf: 32768 minus the CDF, such that symbol s falls in the range
[s > 0 ? (32768 - icdf[s - 1]) : 0, 32768 - icdf[s]).
icdf: CDF_PROB_TOP minus the CDF, such that symbol s falls in the range
[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]
must be 0.
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) {
const int N = nsyms - 1;
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(7 - EC_PROB_SHIFT - CDF_SHIFT >= 0);
c = (unsigned)(dif >> (OD_EC_WINDOW_SIZE - 16));
v = r;
ret = -1;
do {
u = v;
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);
} while (c < v);
OD_ASSERT(v < u);
......
......@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include "aom_dsp/entenc.h"
#include "aom_dsp/prob.h"
/*A range encoder.
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) {
}
/*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.
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.*/
static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s,
int nsyms) {
......@@ -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(fh <= fl);
OD_ASSERT(fl <= 32768U);
OD_ASSERT(7 - EC_PROB_SHIFT - CDF_SHIFT >= 0);
const int N = nsyms - 1;
if (fl < 32768U) {
u = ((r >> 8) * (uint32_t)(fl >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) +
if (fl < CDF_PROB_TOP) {
u = ((r >> 8) * (uint32_t)(fl >> EC_PROB_SHIFT) >>
(7 - EC_PROB_SHIFT - CDF_SHIFT)) +
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));
l += r - u;
r = u - v;
} 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));
}
od_ec_enc_normalize(enc, l, r);
#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++;
#endif
}
......@@ -195,8 +202,7 @@ void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f) {
r = val ? v : r - v;
od_ec_enc_normalize(enc, l, r);
#if OD_MEASURE_EC_OVERHEAD
enc->entropy -=
OD_LOG2((double)(val ? 32768 - OD_ICDF(f) : OD_ICDF(f)) / 32768.);
enc->entropy -= OD_LOG2((double)(val ? f : (32768 - f)) / 32768.);
enc->nb_symbols++;
#endif
}
......@@ -214,7 +220,7 @@ void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *icdf,
(void)nsyms;
OD_ASSERT(s >= 0);
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);
}
......
This diff is collapsed.
......@@ -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);
prob1 = phead[is_dc + ONE_TOKEN_EOB] + phead[is_dc + ONE_TOKEN_NEOB];
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;
for (i = 0; i < TAIL_TOKENS; ++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) {
for (j = 0; j < sz; j++) {
data[j] = rand() / ((RAND_MAX >> 1) + 1);
fts[j] = 15;
fz[j] = (rand() % 32766) >> (15 - fts[j]);
fts[j] = CDF_PROB_BITS;
fz[j] = (rand() % (CDF_PROB_TOP - 2)) >> (CDF_PROB_BITS - fts[j]);
fz[j] = OD_MAXI(fz[j], 1);
enc_method[j] = 3 + (rand() & 1);
switch (enc_method[j]) {
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;
}
case 4: {
......@@ -69,7 +70,6 @@ TEST(EC_TEST, random_ec_test) {
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
od_ec_encode_cdf_q15(&enc, data[j], cdf, 2);
enc_method[j]++;
break;
}
}
......@@ -90,10 +90,15 @@ TEST(EC_TEST, random_ec_test) {
<< " (Random seed: " << seed << ").\n";
for (j = 0; j < sz; j++) {
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) {
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;
}
case 4: {
......@@ -101,7 +106,6 @@ TEST(EC_TEST, random_ec_test) {
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
sym = od_ec_decode_cdf_q15(&dec, cdf, 2);
dec_method++;
break;
}
}
......@@ -126,28 +130,30 @@ TEST(EC_TEST, random_ec_test) {
free(fz);
}
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, 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_enc_patch_initial_bits(&enc, 3, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
od_ec_enc_patch_initial_bits(&enc, 0, 5);
EXPECT_TRUE(enc.error)
<< "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n";
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(24576));
od_ec_enc_patch_initial_bits(&enc, 0, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_EQ(ptr_sz, 2u);
EXPECT_EQ(ptr[0], 63)
<< "Got " << ptr[0]
<< " when expecting 63 for od_ec_enc_patch_initial_bits().\n";
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(24576));
od_ec_enc_patch_initial_bits(&enc, 3, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
od_ec_enc_patch_initial_bits(&enc, 0, 5);
EXPECT_TRUE(enc.error)
<< "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n";
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(24576));
od_ec_enc_patch_initial_bits(&enc, 0, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_EQ(ptr_sz, 2u);
EXPECT_EQ(ptr[0], 63)
<< "Got " << ptr[0]
<< " when expecting 63 for od_ec_enc_patch_initial_bits().\n";
}
od_ec_enc_clear(&enc);
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