Merge "Adds ability to measure with a higher precision the number of bits read per symbol." into nextgenv2
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user