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