xref: /aosp_15_r20/external/webrtc/rtc_base/bitstream_reader.h (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 #ifndef RTC_BASE_BITSTREAM_READER_H_
12*d9f75844SAndroid Build Coastguard Worker #define RTC_BASE_BITSTREAM_READER_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include "absl/base/attributes.h"
17*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker // A class to parse sequence of bits. Byte order is assumed big-endian/network.
25*d9f75844SAndroid Build Coastguard Worker // This class is optimized for successful parsing and binary size.
26*d9f75844SAndroid Build Coastguard Worker // Individual calls to `Read` and `ConsumeBits` never fail. Instead they may
27*d9f75844SAndroid Build Coastguard Worker // change the class state into 'failure state'. User of this class should verify
28*d9f75844SAndroid Build Coastguard Worker // parsing by checking if class is in that 'failure state' by calling `Ok`.
29*d9f75844SAndroid Build Coastguard Worker // That verification can be done once after multiple reads.
30*d9f75844SAndroid Build Coastguard Worker class BitstreamReader {
31*d9f75844SAndroid Build Coastguard Worker  public:
32*d9f75844SAndroid Build Coastguard Worker   explicit BitstreamReader(
33*d9f75844SAndroid Build Coastguard Worker       rtc::ArrayView<const uint8_t> bytes ABSL_ATTRIBUTE_LIFETIME_BOUND);
34*d9f75844SAndroid Build Coastguard Worker   explicit BitstreamReader(
35*d9f75844SAndroid Build Coastguard Worker       absl::string_view bytes ABSL_ATTRIBUTE_LIFETIME_BOUND);
36*d9f75844SAndroid Build Coastguard Worker   BitstreamReader(const BitstreamReader&) = default;
37*d9f75844SAndroid Build Coastguard Worker   BitstreamReader& operator=(const BitstreamReader&) = default;
38*d9f75844SAndroid Build Coastguard Worker   ~BitstreamReader();
39*d9f75844SAndroid Build Coastguard Worker 
40*d9f75844SAndroid Build Coastguard Worker   // Return number of unread bits in the buffer, or negative number if there
41*d9f75844SAndroid Build Coastguard Worker   // was a reading error.
42*d9f75844SAndroid Build Coastguard Worker   int RemainingBitCount() const;
43*d9f75844SAndroid Build Coastguard Worker 
44*d9f75844SAndroid Build Coastguard Worker   // Returns `true` iff all calls to `Read` and `ConsumeBits` were successful.
Ok()45*d9f75844SAndroid Build Coastguard Worker   bool Ok() const { return RemainingBitCount() >= 0; }
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker   // Sets `BitstreamReader` into the failure state.
Invalidate()48*d9f75844SAndroid Build Coastguard Worker   void Invalidate() { remaining_bits_ = -1; }
49*d9f75844SAndroid Build Coastguard Worker 
50*d9f75844SAndroid Build Coastguard Worker   // Moves current read position forward. `bits` must be non-negative.
51*d9f75844SAndroid Build Coastguard Worker   void ConsumeBits(int bits);
52*d9f75844SAndroid Build Coastguard Worker 
53*d9f75844SAndroid Build Coastguard Worker   // Reads single bit. Returns 0 or 1.
54*d9f75844SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT int ReadBit();
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker   // Reads `bits` from the bitstream. `bits` must be in range [0, 64].
57*d9f75844SAndroid Build Coastguard Worker   // Returns an unsigned integer in range [0, 2^bits - 1].
58*d9f75844SAndroid Build Coastguard Worker   // On failure sets `BitstreamReader` into the failure state and returns 0.
59*d9f75844SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT uint64_t ReadBits(int bits);
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker   // Reads unsigned integer of fixed width.
62*d9f75844SAndroid Build Coastguard Worker   template <typename T,
63*d9f75844SAndroid Build Coastguard Worker             typename std::enable_if<std::is_unsigned<T>::value &&
64*d9f75844SAndroid Build Coastguard Worker                                     !std::is_same<T, bool>::value &&
65*d9f75844SAndroid Build Coastguard Worker                                     sizeof(T) <= 8>::type* = nullptr>
Read()66*d9f75844SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT T Read() {
67*d9f75844SAndroid Build Coastguard Worker     return rtc::dchecked_cast<T>(ReadBits(sizeof(T) * 8));
68*d9f75844SAndroid Build Coastguard Worker   }
69*d9f75844SAndroid Build Coastguard Worker 
70*d9f75844SAndroid Build Coastguard Worker   // Reads single bit as boolean.
71*d9f75844SAndroid Build Coastguard Worker   template <
72*d9f75844SAndroid Build Coastguard Worker       typename T,
73*d9f75844SAndroid Build Coastguard Worker       typename std::enable_if<std::is_same<T, bool>::value>::type* = nullptr>
Read()74*d9f75844SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT bool Read() {
75*d9f75844SAndroid Build Coastguard Worker     return ReadBit() != 0;
76*d9f75844SAndroid Build Coastguard Worker   }
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker   // Reads value in range [0, `num_values` - 1].
79*d9f75844SAndroid Build Coastguard Worker   // This encoding is similar to ReadBits(val, Ceil(Log2(num_values)),
80*d9f75844SAndroid Build Coastguard Worker   // but reduces wastage incurred when encoding non-power of two value ranges
81*d9f75844SAndroid Build Coastguard Worker   // Non symmetric values are encoded as:
82*d9f75844SAndroid Build Coastguard Worker   // 1) n = bit_width(num_values)
83*d9f75844SAndroid Build Coastguard Worker   // 2) k = (1 << n) - num_values
84*d9f75844SAndroid Build Coastguard Worker   // Value v in range [0, k - 1] is encoded in (n-1) bits.
85*d9f75844SAndroid Build Coastguard Worker   // Value v in range [k, num_values - 1] is encoded as (v+k) in n bits.
86*d9f75844SAndroid Build Coastguard Worker   // https://aomediacodec.github.io/av1-spec/#nsn
87*d9f75844SAndroid Build Coastguard Worker   uint32_t ReadNonSymmetric(uint32_t num_values);
88*d9f75844SAndroid Build Coastguard Worker 
89*d9f75844SAndroid Build Coastguard Worker   // Reads exponential golomb encoded value.
90*d9f75844SAndroid Build Coastguard Worker   // On failure sets `BitstreamReader` into the failure state and returns
91*d9f75844SAndroid Build Coastguard Worker   // unspecified value.
92*d9f75844SAndroid Build Coastguard Worker   // Exponential golomb values are encoded as:
93*d9f75844SAndroid Build Coastguard Worker   // 1) x = source val + 1
94*d9f75844SAndroid Build Coastguard Worker   // 2) In binary, write [bit_width(x) - 1] 0s, then x
95*d9f75844SAndroid Build Coastguard Worker   // To decode, we count the number of leading 0 bits, read that many + 1 bits,
96*d9f75844SAndroid Build Coastguard Worker   // and increment the result by 1.
97*d9f75844SAndroid Build Coastguard Worker   // Fails the parsing if the value wouldn't fit in a uint32_t.
98*d9f75844SAndroid Build Coastguard Worker   uint32_t ReadExponentialGolomb();
99*d9f75844SAndroid Build Coastguard Worker 
100*d9f75844SAndroid Build Coastguard Worker   // Reads signed exponential golomb values at the current offset. Signed
101*d9f75844SAndroid Build Coastguard Worker   // exponential golomb values are just the unsigned values mapped to the
102*d9f75844SAndroid Build Coastguard Worker   // sequence 0, 1, -1, 2, -2, etc. in order.
103*d9f75844SAndroid Build Coastguard Worker   // On failure sets `BitstreamReader` into the failure state and returns
104*d9f75844SAndroid Build Coastguard Worker   // unspecified value.
105*d9f75844SAndroid Build Coastguard Worker   int ReadSignedExponentialGolomb();
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker  private:
108*d9f75844SAndroid Build Coastguard Worker   void set_last_read_is_verified(bool value) const;
109*d9f75844SAndroid Build Coastguard Worker 
110*d9f75844SAndroid Build Coastguard Worker   // Next byte with at least one unread bit.
111*d9f75844SAndroid Build Coastguard Worker   const uint8_t* bytes_;
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   // Number of bits remained to read.
114*d9f75844SAndroid Build Coastguard Worker   int remaining_bits_;
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker   // Unused in release mode.
117*d9f75844SAndroid Build Coastguard Worker   mutable bool last_read_is_verified_ = true;
118*d9f75844SAndroid Build Coastguard Worker };
119*d9f75844SAndroid Build Coastguard Worker 
BitstreamReader(rtc::ArrayView<const uint8_t> bytes)120*d9f75844SAndroid Build Coastguard Worker inline BitstreamReader::BitstreamReader(rtc::ArrayView<const uint8_t> bytes)
121*d9f75844SAndroid Build Coastguard Worker     : bytes_(bytes.data()), remaining_bits_(bytes.size() * 8) {}
122*d9f75844SAndroid Build Coastguard Worker 
BitstreamReader(absl::string_view bytes)123*d9f75844SAndroid Build Coastguard Worker inline BitstreamReader::BitstreamReader(absl::string_view bytes)
124*d9f75844SAndroid Build Coastguard Worker     : bytes_(reinterpret_cast<const uint8_t*>(bytes.data())),
125*d9f75844SAndroid Build Coastguard Worker       remaining_bits_(bytes.size() * 8) {}
126*d9f75844SAndroid Build Coastguard Worker 
~BitstreamReader()127*d9f75844SAndroid Build Coastguard Worker inline BitstreamReader::~BitstreamReader() {
128*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(last_read_is_verified_) << "Latest calls to Read or ConsumeBit "
129*d9f75844SAndroid Build Coastguard Worker                                         "were not checked with Ok function.";
130*d9f75844SAndroid Build Coastguard Worker }
131*d9f75844SAndroid Build Coastguard Worker 
set_last_read_is_verified(bool value)132*d9f75844SAndroid Build Coastguard Worker inline void BitstreamReader::set_last_read_is_verified(bool value) const {
133*d9f75844SAndroid Build Coastguard Worker #ifdef RTC_DCHECK_IS_ON
134*d9f75844SAndroid Build Coastguard Worker   last_read_is_verified_ = value;
135*d9f75844SAndroid Build Coastguard Worker #endif
136*d9f75844SAndroid Build Coastguard Worker }
137*d9f75844SAndroid Build Coastguard Worker 
RemainingBitCount()138*d9f75844SAndroid Build Coastguard Worker inline int BitstreamReader::RemainingBitCount() const {
139*d9f75844SAndroid Build Coastguard Worker   set_last_read_is_verified(true);
140*d9f75844SAndroid Build Coastguard Worker   return remaining_bits_;
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker 
143*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker #endif  // RTC_BASE_BITSTREAM_READER_H_
146