Commit d7baf45f authored by Michael Bebenita's avatar Michael Bebenita Committed by Yaowu Xu

Adds ability to measure with a higher precision the number of bits

read per symbol.

Change-Id: I218abaa5172b769b66dba45050381c0212602668
parent 470efbcf
......@@ -79,6 +79,7 @@ static INLINE int aom_reader_has_error(aom_reader *r) {
#endif
}
// Returns the position in the bit reader in bits.
static INLINE ptrdiff_t aom_reader_tell(const aom_reader *r) {
#if CONFIG_ANS
(void)r;
......@@ -91,6 +92,19 @@ static INLINE ptrdiff_t aom_reader_tell(const aom_reader *r) {
#endif
}
// Returns the position in the bit reader in 1/8th bits.
static INLINE ptrdiff_t aom_reader_tell_frac(const aom_reader *r) {
#if CONFIG_ANS
(void)r;
assert(0 && "aom_reader_tell_frac() is unimplemented for ANS");
return 0;
#elif CONFIG_DAALA_EC
return aom_daala_reader_tell_frac(r);
#else
return aom_dk_reader_tell_frac(r);
#endif
}
static INLINE int aom_read(aom_reader *r, int prob) {
#if CONFIG_ANS
return uabs_read(r, prob);
......
......@@ -28,3 +28,7 @@ const uint8_t *aom_daala_reader_find_end(daala_reader *r) {
ptrdiff_t aom_daala_reader_tell(const daala_reader *r) {
return od_ec_dec_tell(&r->ec);
}
ptrdiff_t aom_daala_reader_tell_frac(const daala_reader *r) {
return od_ec_dec_tell_frac(&r->ec);
}
......@@ -30,6 +30,7 @@ typedef struct daala_reader daala_reader;
int aom_daala_reader_init(daala_reader *r, const uint8_t *buffer, int size);
const uint8_t *aom_daala_reader_find_end(daala_reader *r);
ptrdiff_t aom_daala_reader_tell(const daala_reader *r);
ptrdiff_t aom_daala_reader_tell_frac(const daala_reader *r);
static INLINE int aom_daala_read(daala_reader *r, int prob) {
if (prob == 128) {
......
......@@ -65,7 +65,29 @@ static INLINE ptrdiff_t aom_dk_reader_tell(const struct aom_dk_reader *r) {
const size_t bits_read = (r->buffer - r->buffer_start) * CHAR_BIT;
const int count =
(r->count < LOTS_OF_BITS) ? r->count : r->count - LOTS_OF_BITS;
return bits_read + BD_VALUE_SIZE - (count + CHAR_BIT);
return bits_read - (count + CHAR_BIT);
}
/*The resolution of fractional-precision bit usage measurements, i.e.,
3 => 1/8th bits.*/
#define DK_BITRES (3)
static INLINE ptrdiff_t aom_dk_reader_tell_frac(const struct aom_dk_reader *r) {
uint32_t num_bits;
uint32_t range;
int l;
int i;
num_bits = aom_dk_reader_tell(r) << DK_BITRES;
range = r->range;
l = 0;
for (i = DK_BITRES; i-- > 0;) {
int b;
range = range * range >> 7;
b = (int)(range >> 8);
l = l << 1 | b;
range >>= b;
}
return num_bits - l;
}
static INLINE int aom_dk_reader_has_error(struct aom_dk_reader *r) {
......
......@@ -88,3 +88,54 @@ TEST(AV1, TestBitIO) {
}
}
}
#if CONFIG_DAALA_EC
#define FRAC_DIFF_TOTAL_ERROR 0.07
#else
#define FRAC_DIFF_TOTAL_ERROR 0.2
#endif
TEST(AV1, TestTell) {
const int kBufferSize = 10000;
aom_writer bw;
uint8_t bw_buffer[kBufferSize];
const int kSymbols = 1024;
// Coders are noisier at low probabilities, so we start at p = 4.
for (int p = 4; p <= 256; p++) {
double probability = p / 256.;
aom_start_encode(&bw, bw_buffer);
for (int i = 0; i < kSymbols; i++) {
aom_write(&bw, 0, p);
}
aom_stop_encode(&bw);
aom_reader br;
aom_reader_init(&br, bw_buffer, kBufferSize, NULL, NULL);
ptrdiff_t last_tell = aom_reader_tell(&br);
ptrdiff_t last_tell_frac = aom_reader_tell_frac(&br);
double frac_diff_total = 0;
GTEST_ASSERT_GE(aom_reader_tell(&br), 0);
GTEST_ASSERT_LE(aom_reader_tell(&br), 1);
for (int i = 0; i < kSymbols; i++) {
aom_read(&br, p);
ptrdiff_t tell = aom_reader_tell(&br);
ptrdiff_t tell_frac = aom_reader_tell_frac(&br);
GTEST_ASSERT_GE(tell, last_tell) << "tell: " << tell
<< ", last_tell: " << last_tell;
GTEST_ASSERT_GE(tell_frac, last_tell_frac)
<< "tell_frac: " << tell_frac
<< ", last_tell_frac: " << last_tell_frac;
// Frac tell should round up to tell.
GTEST_ASSERT_EQ(tell, (tell_frac + 7) >> 3);
last_tell = tell;
frac_diff_total +=
fabs(((tell_frac - last_tell_frac) / 8.0) + log2(probability));
last_tell_frac = tell_frac;
}
const int expected = (int)(-kSymbols * log2(probability));
// Last tell should be close to the expected value.
GTEST_ASSERT_LE(last_tell - expected, 20) << " last_tell: " << last_tell;
// The average frac_diff error should be pretty small.
GTEST_ASSERT_LE(frac_diff_total / kSymbols, FRAC_DIFF_TOTAL_ERROR)
<< " frac_diff_total: " << frac_diff_total;
}
}
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