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