xref: /aosp_15_r20/external/webrtc/rtc_base/bitstream_reader_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2021 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/bitstream_reader.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <array>
17*d9f75844SAndroid Build Coastguard Worker #include <limits>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "absl/numeric/bits.h"
20*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
23*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
24*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
27*d9f75844SAndroid Build Coastguard Worker namespace {
28*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,InDebugModeRequiresToCheckOkStatusBeforeDestruction)29*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, InDebugModeRequiresToCheckOkStatusBeforeDestruction) {
30*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[32] = {};
31*d9f75844SAndroid Build Coastguard Worker   absl::optional<BitstreamReader> reader(absl::in_place, bytes);
32*d9f75844SAndroid Build Coastguard Worker 
33*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(reader->ReadBits(7), 0u);
34*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(OS_ANDROID)
35*d9f75844SAndroid Build Coastguard Worker   EXPECT_DEATH(reader = absl::nullopt, "");
36*d9f75844SAndroid Build Coastguard Worker #endif
37*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader->Ok());
38*d9f75844SAndroid Build Coastguard Worker   reader = absl::nullopt;
39*d9f75844SAndroid Build Coastguard Worker }
40*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,InDebugModeMayCheckRemainingBitsInsteadOfOkStatus)41*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, InDebugModeMayCheckRemainingBitsInsteadOfOkStatus) {
42*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[32] = {};
43*d9f75844SAndroid Build Coastguard Worker   absl::optional<BitstreamReader> reader(absl::in_place, bytes);
44*d9f75844SAndroid Build Coastguard Worker 
45*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(reader->ReadBit(), 0);
46*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(OS_ANDROID)
47*d9f75844SAndroid Build Coastguard Worker   EXPECT_DEATH(reader = absl::nullopt, "");
48*d9f75844SAndroid Build Coastguard Worker #endif
49*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(reader->RemainingBitCount(), 0);
50*d9f75844SAndroid Build Coastguard Worker   reader = absl::nullopt;
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ConsumeBits)53*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ConsumeBits) {
54*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[32] = {};
55*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
56*d9f75844SAndroid Build Coastguard Worker 
57*d9f75844SAndroid Build Coastguard Worker   int total_bits = 32 * 8;
58*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), total_bits);
59*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(3);
60*d9f75844SAndroid Build Coastguard Worker   total_bits -= 3;
61*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), total_bits);
62*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(3);
63*d9f75844SAndroid Build Coastguard Worker   total_bits -= 3;
64*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), total_bits);
65*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(15);
66*d9f75844SAndroid Build Coastguard Worker   total_bits -= 15;
67*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), total_bits);
68*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(67);
69*d9f75844SAndroid Build Coastguard Worker   total_bits -= 67;
70*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), total_bits);
71*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(32 * 8);
74*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
75*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(reader.RemainingBitCount(), 0);
76*d9f75844SAndroid Build Coastguard Worker }
77*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ConsumeLotsOfBits)78*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ConsumeLotsOfBits) {
79*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[1] = {};
80*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
81*d9f75844SAndroid Build Coastguard Worker 
82*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(std::numeric_limits<int>::max());
83*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(std::numeric_limits<int>::max());
84*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(reader.ReadBit(), 0);
85*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBit)88*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBit) {
89*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0b0100'0001, 0b1011'0001};
90*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
91*d9f75844SAndroid Build Coastguard Worker   // First byte.
92*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
93*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 1);
94*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
95*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
96*d9f75844SAndroid Build Coastguard Worker 
97*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
98*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
99*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
100*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 1);
101*d9f75844SAndroid Build Coastguard Worker 
102*d9f75844SAndroid Build Coastguard Worker   // Second byte.
103*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 1);
104*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
105*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 1);
106*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 1);
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
109*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
110*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
111*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 1);
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
114*d9f75844SAndroid Build Coastguard Worker   // Try to read beyound the buffer.
115*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
116*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBoolConsumesSingleBit)119*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBoolConsumesSingleBit) {
120*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0b1010'1010};
121*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
122*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(reader.RemainingBitCount(), 8);
123*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Read<bool>());
124*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), 7);
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBytesAligned)127*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBytesAligned) {
128*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0x0A,        //
129*d9f75844SAndroid Build Coastguard Worker                            0xBC,        //
130*d9f75844SAndroid Build Coastguard Worker                            0xDE, 0xF1,  //
131*d9f75844SAndroid Build Coastguard Worker                            0x23, 0x45, 0x67, 0x89};
132*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
133*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint8_t>(), 0x0Au);
134*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint8_t>(), 0xBCu);
135*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint16_t>(), 0xDEF1u);
136*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint32_t>(), 0x23456789u);
137*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBytesOffset4)140*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBytesOffset4) {
141*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0x0A, 0xBC, 0xDE, 0xF1, 0x23,
142*d9f75844SAndroid Build Coastguard Worker                            0x45, 0x67, 0x89, 0x0A};
143*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
144*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(4);
145*d9f75844SAndroid Build Coastguard Worker 
146*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint8_t>(), 0xABu);
147*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint8_t>(), 0xCDu);
148*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint16_t>(), 0xEF12u);
149*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint32_t>(), 0x34567890u);
150*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBytesOffset3)153*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBytesOffset3) {
154*d9f75844SAndroid Build Coastguard Worker   // The pattern we'll check against is counting down from 0b1111. It looks
155*d9f75844SAndroid Build Coastguard Worker   // weird here because it's all offset by 3.
156*d9f75844SAndroid Build Coastguard Worker   // Byte pattern is:
157*d9f75844SAndroid Build Coastguard Worker   //    56701234
158*d9f75844SAndroid Build Coastguard Worker   //  0b00011111,
159*d9f75844SAndroid Build Coastguard Worker   //  0b11011011,
160*d9f75844SAndroid Build Coastguard Worker   //  0b10010111,
161*d9f75844SAndroid Build Coastguard Worker   //  0b01010011,
162*d9f75844SAndroid Build Coastguard Worker   //  0b00001110,
163*d9f75844SAndroid Build Coastguard Worker   //  0b11001010,
164*d9f75844SAndroid Build Coastguard Worker   //  0b10000110,
165*d9f75844SAndroid Build Coastguard Worker   //  0b01000010
166*d9f75844SAndroid Build Coastguard Worker   //       xxxxx <-- last 5 bits unused.
167*d9f75844SAndroid Build Coastguard Worker 
168*d9f75844SAndroid Build Coastguard Worker   // The bytes. It almost looks like counting down by two at a time, except the
169*d9f75844SAndroid Build Coastguard Worker   // jump at 5->3->0, since that's when the high bit is turned off.
170*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0x1F, 0xDB, 0x97, 0x53, 0x0E, 0xCA, 0x86, 0x42};
171*d9f75844SAndroid Build Coastguard Worker 
172*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
173*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(3);
174*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint8_t>(), 0xFEu);
175*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint16_t>(), 0xDCBAu);
176*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint32_t>(), 0x98765432u);
177*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
178*d9f75844SAndroid Build Coastguard Worker 
179*d9f75844SAndroid Build Coastguard Worker   // 5 bits left unread. Not enough to read a uint8_t.
180*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), 5);
181*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.Read<uint8_t>(), 0);
182*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBits)185*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBits) {
186*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0b010'01'101, 0b0011'00'1'0};
187*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
188*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(3), 0b010u);
189*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(2), 0b01u);
190*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(7), 0b101'0011u);
191*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(2), 0b00u);
192*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(1), 0b1u);
193*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(1), 0b0u);
194*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(1), 0u);
197*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadZeroBits)200*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadZeroBits) {
201*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(rtc::ArrayView<const uint8_t>(nullptr, 0));
202*d9f75844SAndroid Build Coastguard Worker 
203*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(0), 0u);
204*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
205*d9f75844SAndroid Build Coastguard Worker }
206*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBitFromEmptyArray)207*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBitFromEmptyArray) {
208*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(rtc::ArrayView<const uint8_t>(nullptr, 0));
209*d9f75844SAndroid Build Coastguard Worker 
210*d9f75844SAndroid Build Coastguard Worker   // Trying to read from the empty array shouldn't dereference the pointer,
211*d9f75844SAndroid Build Coastguard Worker   // i.e. shouldn't crash.
212*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
213*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
214*d9f75844SAndroid Build Coastguard Worker }
215*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBitsFromEmptyArray)216*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBitsFromEmptyArray) {
217*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(rtc::ArrayView<const uint8_t>(nullptr, 0));
218*d9f75844SAndroid Build Coastguard Worker 
219*d9f75844SAndroid Build Coastguard Worker   // Trying to read from the empty array shouldn't dereference the pointer,
220*d9f75844SAndroid Build Coastguard Worker   // i.e. shouldn't crash.
221*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(1), 0u);
222*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
223*d9f75844SAndroid Build Coastguard Worker }
224*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadBits64)225*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadBits64) {
226*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0x4D, 0x32, 0xAB, 0x54, 0x00, 0xFF, 0xFE, 0x01,
227*d9f75844SAndroid Build Coastguard Worker                            0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89};
228*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
229*d9f75844SAndroid Build Coastguard Worker 
230*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(33), 0x4D32AB5400FFFE01u >> (64 - 33));
231*d9f75844SAndroid Build Coastguard Worker 
232*d9f75844SAndroid Build Coastguard Worker   constexpr uint64_t kMask31Bits = (1ull << 32) - 1;
233*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(31), 0x4D32AB5400FFFE01ull & kMask31Bits);
234*d9f75844SAndroid Build Coastguard Worker 
235*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(64), 0xABCDEF0123456789ull);
236*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
237*d9f75844SAndroid Build Coastguard Worker 
238*d9f75844SAndroid Build Coastguard Worker   // Nothing more to read.
239*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBit(), 0);
240*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.Ok());
241*d9f75844SAndroid Build Coastguard Worker }
242*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,CanPeekBitsUsingCopyConstructor)243*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, CanPeekBitsUsingCopyConstructor) {
244*d9f75844SAndroid Build Coastguard Worker   // BitstreamReader doesn't have peek function. To simulate it, user may use
245*d9f75844SAndroid Build Coastguard Worker   // cheap BitstreamReader copy constructor.
246*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0x0A, 0xBC};
247*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
248*d9f75844SAndroid Build Coastguard Worker   reader.ConsumeBits(4);
249*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(reader.RemainingBitCount(), 12);
250*d9f75844SAndroid Build Coastguard Worker 
251*d9f75844SAndroid Build Coastguard Worker   BitstreamReader peeker = reader;
252*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(peeker.ReadBits(8), 0xABu);
253*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(peeker.RemainingBitCount(), 4);
254*d9f75844SAndroid Build Coastguard Worker 
255*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), 12);
256*d9f75844SAndroid Build Coastguard Worker   // Can resume reading from before peeker was created.
257*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadBits(4), 0xAu);
258*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), 8);
259*d9f75844SAndroid Build Coastguard Worker }
260*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadNonSymmetricSameNumberOfBitsWhenNumValuesPowerOf2)261*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest,
262*d9f75844SAndroid Build Coastguard Worker      ReadNonSymmetricSameNumberOfBitsWhenNumValuesPowerOf2) {
263*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[2] = {0xf3, 0xa0};
264*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
265*d9f75844SAndroid Build Coastguard Worker 
266*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(reader.RemainingBitCount(), 16);
267*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadNonSymmetric(/*num_values=*/1 << 4), 0xfu);
268*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadNonSymmetric(/*num_values=*/1 << 4), 0x3u);
269*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadNonSymmetric(/*num_values=*/1 << 4), 0xau);
270*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadNonSymmetric(/*num_values=*/1 << 4), 0x0u);
271*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), 0);
272*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.Ok());
273*d9f75844SAndroid Build Coastguard Worker }
274*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,ReadNonSymmetricOnlyValueConsumesZeroBits)275*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, ReadNonSymmetricOnlyValueConsumesZeroBits) {
276*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[2] = {};
277*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader(bytes);
278*d9f75844SAndroid Build Coastguard Worker 
279*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(reader.RemainingBitCount(), 16);
280*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.ReadNonSymmetric(/*num_values=*/1), 0u);
281*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader.RemainingBitCount(), 16);
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker 
GolombEncoded(uint32_t val)284*d9f75844SAndroid Build Coastguard Worker std::array<uint8_t, 8> GolombEncoded(uint32_t val) {
285*d9f75844SAndroid Build Coastguard Worker   int val_width = absl::bit_width(val + 1);
286*d9f75844SAndroid Build Coastguard Worker   int total_width = 2 * val_width - 1;
287*d9f75844SAndroid Build Coastguard Worker   uint64_t representation = (uint64_t{val} + 1) << (64 - total_width);
288*d9f75844SAndroid Build Coastguard Worker   std::array<uint8_t, 8> result;
289*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 8; ++i) {
290*d9f75844SAndroid Build Coastguard Worker     result[i] = representation >> (7 - i) * 8;
291*d9f75844SAndroid Build Coastguard Worker   }
292*d9f75844SAndroid Build Coastguard Worker   return result;
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,GolombUint32Values)295*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, GolombUint32Values) {
296*d9f75844SAndroid Build Coastguard Worker   // Test over the uint32_t range with a large enough step that the test doesn't
297*d9f75844SAndroid Build Coastguard Worker   // take forever. Around 20,000 iterations should do.
298*d9f75844SAndroid Build Coastguard Worker   const int kStep = std::numeric_limits<uint32_t>::max() / 20000;
299*d9f75844SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < std::numeric_limits<uint32_t>::max() - kStep;
300*d9f75844SAndroid Build Coastguard Worker        i += kStep) {
301*d9f75844SAndroid Build Coastguard Worker     std::array<uint8_t, 8> buffer = GolombEncoded(i);
302*d9f75844SAndroid Build Coastguard Worker     BitstreamReader reader(buffer);
303*d9f75844SAndroid Build Coastguard Worker     // Use assert instead of EXPECT to avoid spamming thousands of failed
304*d9f75844SAndroid Build Coastguard Worker     // expectation when this test fails.
305*d9f75844SAndroid Build Coastguard Worker     ASSERT_EQ(reader.ReadExponentialGolomb(), i);
306*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(reader.Ok());
307*d9f75844SAndroid Build Coastguard Worker   }
308*d9f75844SAndroid Build Coastguard Worker }
309*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,SignedGolombValues)310*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, SignedGolombValues) {
311*d9f75844SAndroid Build Coastguard Worker   uint8_t golomb_bits[][1] = {
312*d9f75844SAndroid Build Coastguard Worker       {0b1'0000000}, {0b010'00000}, {0b011'00000}, {0b00100'000}, {0b00111'000},
313*d9f75844SAndroid Build Coastguard Worker   };
314*d9f75844SAndroid Build Coastguard Worker   int expected[] = {0, 1, -1, 2, -3};
315*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < sizeof(golomb_bits); ++i) {
316*d9f75844SAndroid Build Coastguard Worker     BitstreamReader reader(golomb_bits[i]);
317*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(reader.ReadSignedExponentialGolomb(), expected[i])
318*d9f75844SAndroid Build Coastguard Worker         << "Mismatch in expected/decoded value for golomb_bits[" << i
319*d9f75844SAndroid Build Coastguard Worker         << "]: " << static_cast<int>(golomb_bits[i][0]);
320*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(reader.Ok());
321*d9f75844SAndroid Build Coastguard Worker   }
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker 
TEST(BitstreamReaderTest,NoGolombOverread)324*d9f75844SAndroid Build Coastguard Worker TEST(BitstreamReaderTest, NoGolombOverread) {
325*d9f75844SAndroid Build Coastguard Worker   const uint8_t bytes[] = {0x00, 0xFF, 0xFF};
326*d9f75844SAndroid Build Coastguard Worker   // Make sure the bit buffer correctly enforces byte length on golomb reads.
327*d9f75844SAndroid Build Coastguard Worker   // If it didn't, the above buffer would be valid at 3 bytes.
328*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader1(rtc::MakeArrayView(bytes, 1));
329*d9f75844SAndroid Build Coastguard Worker   // When parse fails, `ReadExponentialGolomb` may return any number.
330*d9f75844SAndroid Build Coastguard Worker   reader1.ReadExponentialGolomb();
331*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader1.Ok());
332*d9f75844SAndroid Build Coastguard Worker 
333*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader2(rtc::MakeArrayView(bytes, 2));
334*d9f75844SAndroid Build Coastguard Worker   reader2.ReadExponentialGolomb();
335*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(reader2.Ok());
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker   BitstreamReader reader3(bytes);
338*d9f75844SAndroid Build Coastguard Worker   // Golomb should have read 9 bits, so 0x01FF, and since it is golomb, the
339*d9f75844SAndroid Build Coastguard Worker   // result is 0x01FF - 1 = 0x01FE.
340*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(reader3.ReadExponentialGolomb(), 0x01FEu);
341*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(reader3.Ok());
342*d9f75844SAndroid Build Coastguard Worker }
343*d9f75844SAndroid Build Coastguard Worker 
344*d9f75844SAndroid Build Coastguard Worker }  // namespace
345*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
346