blob: 17a9aa793b93cae9a5de37a1013b1c6f53e54a88 [file] [log] [blame]
Ronald S. Bultjea742a732012-06-25 09:58:09 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Ronald S. Bultjea742a732012-06-25 09:58:09 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Johann123e8a62017-12-28 14:40:49 -080010 */
Ronald S. Bultjea742a732012-06-25 09:58:09 -070011
Daniel Kang26641c72012-06-28 16:26:31 -070012#include <math.h>
13#include <stdlib.h>
14#include <string.h>
15
Tom Finegan7a07ece2017-02-07 17:14:05 -080016#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
Daniel Kang26641c72012-06-28 16:26:31 -070017
Jingning Han097d59c2015-07-29 14:51:36 -070018#include "test/acm_random.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070019#include "aom/aom_integer.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070020#include "aom_dsp/bitreader.h"
21#include "aom_dsp/bitwriter.h"
Ronald S. Bultjea742a732012-06-25 09:58:09 -070022
Yaowu Xuc27fc142016-08-22 16:08:15 -070023using libaom_test::ACMRandom;
Daniel Kang26641c72012-06-28 16:26:31 -070024
Ronald S. Bultjea742a732012-06-25 09:58:09 -070025namespace {
26const int num_tests = 10;
Ronald S. Bultjea742a732012-06-25 09:58:09 -070027} // namespace
28
Yaowu Xuf883b422016-08-30 14:01:10 -070029TEST(AV1, TestBitIO) {
Ronald S. Bultjea742a732012-06-25 09:58:09 -070030 ACMRandom rnd(ACMRandom::DeterministicSeed());
31 for (int n = 0; n < num_tests; ++n) {
clang-format3a826f12016-08-11 17:46:05 -070032 for (int method = 0; method <= 7; ++method) { // we generate various proba
Yaowu Xuafffa3d2013-09-05 08:45:56 -070033 const int kBitsToTest = 1000;
34 uint8_t probas[kBitsToTest];
Ronald S. Bultjea742a732012-06-25 09:58:09 -070035
Yaowu Xuafffa3d2013-09-05 08:45:56 -070036 for (int i = 0; i < kBitsToTest; ++i) {
Ronald S. Bultjea742a732012-06-25 09:58:09 -070037 const int parity = i & 1;
clang-format3a826f12016-08-11 17:46:05 -070038 /* clang-format off */
Ronald S. Bultjea742a732012-06-25 09:58:09 -070039 probas[i] =
John Koleszarc6b90392012-07-13 15:21:29 -070040 (method == 0) ? 0 : (method == 1) ? 255 :
41 (method == 2) ? 128 :
42 (method == 3) ? rnd.Rand8() :
43 (method == 4) ? (parity ? 0 : 255) :
Ronald S. Bultjea742a732012-06-25 09:58:09 -070044 // alternate between low and high proba:
45 (method == 5) ? (parity ? rnd(128) : 255 - rnd(128)) :
46 (method == 6) ?
John Koleszarc6b90392012-07-13 15:21:29 -070047 (parity ? rnd(64) : 255 - rnd(64)) :
48 (parity ? rnd(32) : 255 - rnd(32));
clang-format3a826f12016-08-11 17:46:05 -070049 /* clang-format on */
Ronald S. Bultjea742a732012-06-25 09:58:09 -070050 }
51 for (int bit_method = 0; bit_method <= 3; ++bit_method) {
52 const int random_seed = 6432;
Yaowu Xuafffa3d2013-09-05 08:45:56 -070053 const int kBufferSize = 10000;
Ronald S. Bultjea742a732012-06-25 09:58:09 -070054 ACMRandom bit_rnd(random_seed);
Yaowu Xuf883b422016-08-30 14:01:10 -070055 aom_writer bw;
Yaowu Xuafffa3d2013-09-05 08:45:56 -070056 uint8_t bw_buffer[kBufferSize];
Yaowu Xuf883b422016-08-30 14:01:10 -070057 aom_start_encode(&bw, bw_buffer);
Ronald S. Bultjea742a732012-06-25 09:58:09 -070058
59 int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
Yaowu Xuafffa3d2013-09-05 08:45:56 -070060 for (int i = 0; i < kBitsToTest; ++i) {
Ronald S. Bultjea742a732012-06-25 09:58:09 -070061 if (bit_method == 2) {
62 bit = (i & 1);
63 } else if (bit_method == 3) {
64 bit = bit_rnd(2);
65 }
Yaowu Xuf883b422016-08-30 14:01:10 -070066 aom_write(&bw, bit, static_cast<int>(probas[i]));
Ronald S. Bultjea742a732012-06-25 09:58:09 -070067 }
68
Yaowu Xuf883b422016-08-30 14:01:10 -070069 aom_stop_encode(&bw);
Ronald S. Bultjea742a732012-06-25 09:58:09 -070070
Yaowu Xuf883b422016-08-30 14:01:10 -070071 aom_reader br;
Sebastien Alaiwan2b1ec182017-12-21 09:38:27 +010072 aom_reader_init(&br, bw_buffer, bw.pos);
Ronald S. Bultjea742a732012-06-25 09:58:09 -070073 bit_rnd.Reset(random_seed);
Yaowu Xuafffa3d2013-09-05 08:45:56 -070074 for (int i = 0; i < kBitsToTest; ++i) {
Ronald S. Bultjea742a732012-06-25 09:58:09 -070075 if (bit_method == 2) {
76 bit = (i & 1);
77 } else if (bit_method == 3) {
78 bit = bit_rnd(2);
79 }
James Zern664f04d2022-05-24 17:30:58 -070080 GTEST_ASSERT_EQ(aom_read(&br, probas[i], nullptr), bit)
Yaowu Xuafffa3d2013-09-05 08:45:56 -070081 << "pos: " << i << " / " << kBitsToTest
clang-format3a826f12016-08-11 17:46:05 -070082 << " bit_method: " << bit_method << " method: " << method;
Ronald S. Bultjea742a732012-06-25 09:58:09 -070083 }
84 }
85 }
86 }
87}
Michael Bebenitad7baf452016-08-25 11:27:56 -070088
Angie Chiangde849bd2017-12-20 16:59:30 -080089#define FRAC_DIFF_TOTAL_ERROR 0.18
Michael Bebenitad7baf452016-08-25 11:27:56 -070090
91TEST(AV1, TestTell) {
92 const int kBufferSize = 10000;
93 aom_writer bw;
94 uint8_t bw_buffer[kBufferSize];
95 const int kSymbols = 1024;
96 // Coders are noisier at low probabilities, so we start at p = 4.
Yushin Cho3e4fcb42016-11-04 15:39:55 -070097 for (int p = 4; p < 256; p++) {
Michael Bebenitad7baf452016-08-25 11:27:56 -070098 double probability = p / 256.;
99 aom_start_encode(&bw, bw_buffer);
100 for (int i = 0; i < kSymbols; i++) {
101 aom_write(&bw, 0, p);
102 }
103 aom_stop_encode(&bw);
104 aom_reader br;
Sebastien Alaiwan2b1ec182017-12-21 09:38:27 +0100105 aom_reader_init(&br, bw_buffer, bw.pos);
Nathan E. Eggeb244f392016-09-06 23:48:43 -0400106 uint32_t last_tell = aom_reader_tell(&br);
107 uint32_t last_tell_frac = aom_reader_tell_frac(&br);
Michael Bebenitad7baf452016-08-25 11:27:56 -0700108 double frac_diff_total = 0;
Nathan E. Eggeb244f392016-09-06 23:48:43 -0400109 GTEST_ASSERT_GE(aom_reader_tell(&br), 0u);
110 GTEST_ASSERT_LE(aom_reader_tell(&br), 1u);
Wan-Teh Chang47d59ce2018-08-14 10:15:45 -0700111 ASSERT_FALSE(aom_reader_has_overflowed(&br));
Michael Bebenitad7baf452016-08-25 11:27:56 -0700112 for (int i = 0; i < kSymbols; i++) {
James Zern664f04d2022-05-24 17:30:58 -0700113 aom_read(&br, p, nullptr);
Nathan E. Eggeb244f392016-09-06 23:48:43 -0400114 uint32_t tell = aom_reader_tell(&br);
115 uint32_t tell_frac = aom_reader_tell_frac(&br);
clang-format4eafefe2017-09-04 12:51:20 -0700116 GTEST_ASSERT_GE(tell, last_tell)
117 << "tell: " << tell << ", last_tell: " << last_tell;
Michael Bebenitad7baf452016-08-25 11:27:56 -0700118 GTEST_ASSERT_GE(tell_frac, last_tell_frac)
119 << "tell_frac: " << tell_frac
120 << ", last_tell_frac: " << last_tell_frac;
121 // Frac tell should round up to tell.
122 GTEST_ASSERT_EQ(tell, (tell_frac + 7) >> 3);
123 last_tell = tell;
124 frac_diff_total +=
125 fabs(((tell_frac - last_tell_frac) / 8.0) + log2(probability));
126 last_tell_frac = tell_frac;
127 }
Nathan E. Eggeb244f392016-09-06 23:48:43 -0400128 const uint32_t expected = (uint32_t)(-kSymbols * log2(probability));
Michael Bebenitad7baf452016-08-25 11:27:56 -0700129 // Last tell should be close to the expected value.
Peter de Rivazf9948552016-10-20 16:21:20 +0100130 GTEST_ASSERT_LE(last_tell, expected + 20) << " last_tell: " << last_tell;
Michael Bebenitad7baf452016-08-25 11:27:56 -0700131 // The average frac_diff error should be pretty small.
132 GTEST_ASSERT_LE(frac_diff_total / kSymbols, FRAC_DIFF_TOTAL_ERROR)
133 << " frac_diff_total: " << frac_diff_total;
Wan-Teh Chang47d59ce2018-08-14 10:15:45 -0700134 ASSERT_FALSE(aom_reader_has_overflowed(&br));
135 }
136}
137
138TEST(AV1, TestHasOverflowed) {
139 const int kBufferSize = 10000;
140 aom_writer bw;
141 uint8_t bw_buffer[kBufferSize];
142 const int kSymbols = 1024;
143 // Coders are noisier at low probabilities, so we start at p = 4.
144 for (int p = 4; p < 256; p++) {
145 aom_start_encode(&bw, bw_buffer);
146 for (int i = 0; i < kSymbols; i++) {
147 aom_write(&bw, 1, p);
148 }
149 aom_stop_encode(&bw);
150 aom_reader br;
151 aom_reader_init(&br, bw_buffer, bw.pos);
152 ASSERT_FALSE(aom_reader_has_overflowed(&br));
153 for (int i = 0; i < kSymbols; i++) {
James Zern664f04d2022-05-24 17:30:58 -0700154 GTEST_ASSERT_EQ(aom_read(&br, p, nullptr), 1);
Wan-Teh Chang47d59ce2018-08-14 10:15:45 -0700155 ASSERT_FALSE(aom_reader_has_overflowed(&br));
156 }
157 // In the worst case, the encoder uses just a tiny fraction of the last
158 // byte in the buffer. So to guarantee that aom_reader_has_overflowed()
159 // returns true, we have to consume very nearly 8 additional bits of data.
160 // In the worse case, one of the bits in that byte will be 1, and the rest
161 // will be zero. Once we are past that 1 bit, when the probability of
162 // reading zero symbol from aom_read() is high, each additional symbol read
163 // will consume very little additional data (in the case that p == 255,
164 // approximately -log_2(255/256) ~= 0.0056 bits). In that case it would
165 // take around 178 calls to consume more than 8 bits. That is only an upper
166 // bound. In practice we are not guaranteed to hit the worse case and can
167 // get away with 174 calls.
168 for (int i = 0; i < 174; i++) {
James Zern664f04d2022-05-24 17:30:58 -0700169 aom_read(&br, p, nullptr);
Wan-Teh Chang47d59ce2018-08-14 10:15:45 -0700170 }
171 ASSERT_TRUE(aom_reader_has_overflowed(&br));
Michael Bebenitad7baf452016-08-25 11:27:56 -0700172 }
173}