xref: /aosp_15_r20/external/webrtc/rtc_base/bitstream_reader.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 <stdint.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <limits>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "absl/numeric/bits.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
22*d9f75844SAndroid Build Coastguard Worker 
ReadBits(int bits)23*d9f75844SAndroid Build Coastguard Worker uint64_t BitstreamReader::ReadBits(int bits) {
24*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(bits, 0);
25*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_LE(bits, 64);
26*d9f75844SAndroid Build Coastguard Worker   set_last_read_is_verified(false);
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker   if (remaining_bits_ < bits) {
29*d9f75844SAndroid Build Coastguard Worker     remaining_bits_ -= bits;
30*d9f75844SAndroid Build Coastguard Worker     return 0;
31*d9f75844SAndroid Build Coastguard Worker   }
32*d9f75844SAndroid Build Coastguard Worker 
33*d9f75844SAndroid Build Coastguard Worker   int remaining_bits_in_first_byte = remaining_bits_ % 8;
34*d9f75844SAndroid Build Coastguard Worker   remaining_bits_ -= bits;
35*d9f75844SAndroid Build Coastguard Worker   if (bits < remaining_bits_in_first_byte) {
36*d9f75844SAndroid Build Coastguard Worker     // Reading fewer bits than what's left in the current byte, just
37*d9f75844SAndroid Build Coastguard Worker     // return the portion of this byte that is needed.
38*d9f75844SAndroid Build Coastguard Worker     int offset = (remaining_bits_in_first_byte - bits);
39*d9f75844SAndroid Build Coastguard Worker     return ((*bytes_) >> offset) & ((1 << bits) - 1);
40*d9f75844SAndroid Build Coastguard Worker   }
41*d9f75844SAndroid Build Coastguard Worker 
42*d9f75844SAndroid Build Coastguard Worker   uint64_t result = 0;
43*d9f75844SAndroid Build Coastguard Worker   if (remaining_bits_in_first_byte > 0) {
44*d9f75844SAndroid Build Coastguard Worker     // Read all bits that were left in the current byte and consume that byte.
45*d9f75844SAndroid Build Coastguard Worker     bits -= remaining_bits_in_first_byte;
46*d9f75844SAndroid Build Coastguard Worker     uint8_t mask = (1 << remaining_bits_in_first_byte) - 1;
47*d9f75844SAndroid Build Coastguard Worker     result = static_cast<uint64_t>(*bytes_ & mask) << bits;
48*d9f75844SAndroid Build Coastguard Worker     ++bytes_;
49*d9f75844SAndroid Build Coastguard Worker   }
50*d9f75844SAndroid Build Coastguard Worker 
51*d9f75844SAndroid Build Coastguard Worker   // Read as many full bytes as we can.
52*d9f75844SAndroid Build Coastguard Worker   while (bits >= 8) {
53*d9f75844SAndroid Build Coastguard Worker     bits -= 8;
54*d9f75844SAndroid Build Coastguard Worker     result |= uint64_t{*bytes_} << bits;
55*d9f75844SAndroid Build Coastguard Worker     ++bytes_;
56*d9f75844SAndroid Build Coastguard Worker   }
57*d9f75844SAndroid Build Coastguard Worker   // Whatever is left to read is smaller than a byte, so grab just the needed
58*d9f75844SAndroid Build Coastguard Worker   // bits and shift them into the lowest bits.
59*d9f75844SAndroid Build Coastguard Worker   if (bits > 0) {
60*d9f75844SAndroid Build Coastguard Worker     result |= (*bytes_ >> (8 - bits));
61*d9f75844SAndroid Build Coastguard Worker   }
62*d9f75844SAndroid Build Coastguard Worker   return result;
63*d9f75844SAndroid Build Coastguard Worker }
64*d9f75844SAndroid Build Coastguard Worker 
ReadBit()65*d9f75844SAndroid Build Coastguard Worker int BitstreamReader::ReadBit() {
66*d9f75844SAndroid Build Coastguard Worker   set_last_read_is_verified(false);
67*d9f75844SAndroid Build Coastguard Worker   --remaining_bits_;
68*d9f75844SAndroid Build Coastguard Worker   if (remaining_bits_ < 0) {
69*d9f75844SAndroid Build Coastguard Worker     return 0;
70*d9f75844SAndroid Build Coastguard Worker   }
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker   int bit_position = remaining_bits_ % 8;
73*d9f75844SAndroid Build Coastguard Worker   if (bit_position == 0) {
74*d9f75844SAndroid Build Coastguard Worker     // Read the last bit from current byte and move to the next byte.
75*d9f75844SAndroid Build Coastguard Worker     return (*bytes_++) & 0x01;
76*d9f75844SAndroid Build Coastguard Worker   }
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker   return (*bytes_ >> bit_position) & 0x01;
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker 
ConsumeBits(int bits)81*d9f75844SAndroid Build Coastguard Worker void BitstreamReader::ConsumeBits(int bits) {
82*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(bits, 0);
83*d9f75844SAndroid Build Coastguard Worker   set_last_read_is_verified(false);
84*d9f75844SAndroid Build Coastguard Worker   if (remaining_bits_ < bits) {
85*d9f75844SAndroid Build Coastguard Worker     Invalidate();
86*d9f75844SAndroid Build Coastguard Worker     return;
87*d9f75844SAndroid Build Coastguard Worker   }
88*d9f75844SAndroid Build Coastguard Worker 
89*d9f75844SAndroid Build Coastguard Worker   int remaining_bytes = (remaining_bits_ + 7) / 8;
90*d9f75844SAndroid Build Coastguard Worker   remaining_bits_ -= bits;
91*d9f75844SAndroid Build Coastguard Worker   int new_remaining_bytes = (remaining_bits_ + 7) / 8;
92*d9f75844SAndroid Build Coastguard Worker   bytes_ += (remaining_bytes - new_remaining_bytes);
93*d9f75844SAndroid Build Coastguard Worker }
94*d9f75844SAndroid Build Coastguard Worker 
ReadNonSymmetric(uint32_t num_values)95*d9f75844SAndroid Build Coastguard Worker uint32_t BitstreamReader::ReadNonSymmetric(uint32_t num_values) {
96*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(num_values, 0);
97*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_LE(num_values, uint32_t{1} << 31);
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker   int width = absl::bit_width(num_values);
100*d9f75844SAndroid Build Coastguard Worker   uint32_t num_min_bits_values = (uint32_t{1} << width) - num_values;
101*d9f75844SAndroid Build Coastguard Worker 
102*d9f75844SAndroid Build Coastguard Worker   uint64_t val = ReadBits(width - 1);
103*d9f75844SAndroid Build Coastguard Worker   if (val < num_min_bits_values) {
104*d9f75844SAndroid Build Coastguard Worker     return val;
105*d9f75844SAndroid Build Coastguard Worker   }
106*d9f75844SAndroid Build Coastguard Worker   return (val << 1) + ReadBit() - num_min_bits_values;
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker 
ReadExponentialGolomb()109*d9f75844SAndroid Build Coastguard Worker uint32_t BitstreamReader::ReadExponentialGolomb() {
110*d9f75844SAndroid Build Coastguard Worker   // Count the number of leading 0.
111*d9f75844SAndroid Build Coastguard Worker   int zero_bit_count = 0;
112*d9f75844SAndroid Build Coastguard Worker   while (ReadBit() == 0) {
113*d9f75844SAndroid Build Coastguard Worker     if (++zero_bit_count >= 32) {
114*d9f75844SAndroid Build Coastguard Worker       // Golob value won't fit into 32 bits of the return value. Fail the parse.
115*d9f75844SAndroid Build Coastguard Worker       Invalidate();
116*d9f75844SAndroid Build Coastguard Worker       return 0;
117*d9f75844SAndroid Build Coastguard Worker     }
118*d9f75844SAndroid Build Coastguard Worker   }
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   // The bit count of the value is the number of zeros + 1.
121*d9f75844SAndroid Build Coastguard Worker   // However the first '1' was already read above.
122*d9f75844SAndroid Build Coastguard Worker   return (uint32_t{1} << zero_bit_count) +
123*d9f75844SAndroid Build Coastguard Worker          rtc::dchecked_cast<uint32_t>(ReadBits(zero_bit_count)) - 1;
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker 
ReadSignedExponentialGolomb()126*d9f75844SAndroid Build Coastguard Worker int BitstreamReader::ReadSignedExponentialGolomb() {
127*d9f75844SAndroid Build Coastguard Worker   uint32_t unsigned_val = ReadExponentialGolomb();
128*d9f75844SAndroid Build Coastguard Worker   if ((unsigned_val & 1) == 0) {
129*d9f75844SAndroid Build Coastguard Worker     return -static_cast<int>(unsigned_val / 2);
130*d9f75844SAndroid Build Coastguard Worker   } else {
131*d9f75844SAndroid Build Coastguard Worker     return (unsigned_val + 1) / 2;
132*d9f75844SAndroid Build Coastguard Worker   }
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker 
135*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
136