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