blob: 8c0f66fa91802b2420a8cfd77a50682fc59d4ac5 [file] [log] [blame]
Danil Chapovalov5af152c2021-08-31 15:27:51 +02001/*
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
22namespace 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.
30class 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.
45 bool Ok() const { return RemainingBitCount() >= 0; }
46
47 // Sets `BitstreamReader` into the failure state.
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 sizeof(T) <= 8>::type* = nullptr>
65 ABSL_MUST_USE_RESULT T Read() {
66 return rtc::dchecked_cast<T>(ReadBits(sizeof(T) * 8));
67 }
68
69 // Reads single bit as boolean.
70 template <>
71 ABSL_MUST_USE_RESULT bool Read<bool>() {
72 return ReadBit() != 0;
73 }
74
75 // Reads value in range [0, `num_values` - 1].
76 // This encoding is similar to ReadBits(val, Ceil(Log2(num_values)),
77 // but reduces wastage incurred when encoding non-power of two value ranges
78 // Non symmetric values are encoded as:
79 // 1) n = bit_width(num_values)
80 // 2) k = (1 << n) - num_values
81 // Value v in range [0, k - 1] is encoded in (n-1) bits.
82 // Value v in range [k, num_values - 1] is encoded as (v+k) in n bits.
83 // https://aomediacodec.github.io/av1-spec/#nsn
84 uint32_t ReadNonSymmetric(uint32_t num_values);
85
86 // Reads exponential golomb encoded value.
87 // On failure sets `BitstreamReader` into the failure state and returns
88 // unspecified value.
89 // Exponential golomb values are encoded as:
90 // 1) x = source val + 1
91 // 2) In binary, write [bit_width(x) - 1] 0s, then x
92 // To decode, we count the number of leading 0 bits, read that many + 1 bits,
93 // and increment the result by 1.
94 // Fails the parsing if the value wouldn't fit in a uint32_t.
95 uint32_t ReadExponentialGolomb();
96
97 // Reads signed exponential golomb values at the current offset. Signed
98 // exponential golomb values are just the unsigned values mapped to the
99 // sequence 0, 1, -1, 2, -2, etc. in order.
100 // On failure sets `BitstreamReader` into the failure state and returns
101 // unspecified value.
102 int ReadSignedExponentialGolomb();
103
104 private:
105 void set_last_read_is_verified(bool value) const;
106
107 // Next byte with at least one unread bit.
108 const uint8_t* bytes_;
109
110 // Number of bits remained to read.
111 int remaining_bits_;
112
113 // Unused in release mode.
114 mutable bool last_read_is_verified_ = true;
115};
116
117inline BitstreamReader::BitstreamReader(rtc::ArrayView<const uint8_t> bytes)
118 : bytes_(bytes.data()), remaining_bits_(bytes.size() * 8) {}
119
120inline BitstreamReader::BitstreamReader(absl::string_view bytes)
121 : bytes_(reinterpret_cast<const uint8_t*>(bytes.data())),
122 remaining_bits_(bytes.size() * 8) {}
123
124inline BitstreamReader::~BitstreamReader() {
125 RTC_DCHECK(last_read_is_verified_) << "Latest calls to Read or ConsumeBit "
126 "were not checked with Ok function.";
127}
128
129inline void BitstreamReader::set_last_read_is_verified(bool value) const {
130#ifdef RTC_DCHECK_IS_ON
131 last_read_is_verified_ = value;
132#endif
133}
134
135inline int BitstreamReader::RemainingBitCount() const {
136 set_last_read_is_verified(true);
137 return remaining_bits_;
138}
139
140} // namespace webrtc
141
142#endif // RTC_BASE_BITSTREAM_READER_H_