summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/bitstream_reader.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/rtc_base/bitstream_reader.h')
-rw-r--r--third_party/libwebrtc/rtc_base/bitstream_reader.h145
1 files changed, 145 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/bitstream_reader.h b/third_party/libwebrtc/rtc_base/bitstream_reader.h
new file mode 100644
index 0000000000..51c7914bd7
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/bitstream_reader.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2021 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_BITSTREAM_READER_H_
+#define RTC_BASE_BITSTREAM_READER_H_
+
+#include <stdint.h>
+
+#include "absl/base/attributes.h"
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+// A class to parse sequence of bits. Byte order is assumed big-endian/network.
+// This class is optimized for successful parsing and binary size.
+// Individual calls to `Read` and `ConsumeBits` never fail. Instead they may
+// change the class state into 'failure state'. User of this class should verify
+// parsing by checking if class is in that 'failure state' by calling `Ok`.
+// That verification can be done once after multiple reads.
+class BitstreamReader {
+ public:
+ explicit BitstreamReader(
+ rtc::ArrayView<const uint8_t> bytes ABSL_ATTRIBUTE_LIFETIME_BOUND);
+ explicit BitstreamReader(
+ absl::string_view bytes ABSL_ATTRIBUTE_LIFETIME_BOUND);
+ BitstreamReader(const BitstreamReader&) = default;
+ BitstreamReader& operator=(const BitstreamReader&) = default;
+ ~BitstreamReader();
+
+ // Return number of unread bits in the buffer, or negative number if there
+ // was a reading error.
+ int RemainingBitCount() const;
+
+ // Returns `true` iff all calls to `Read` and `ConsumeBits` were successful.
+ bool Ok() const { return RemainingBitCount() >= 0; }
+
+ // Sets `BitstreamReader` into the failure state.
+ void Invalidate() { remaining_bits_ = -1; }
+
+ // Moves current read position forward. `bits` must be non-negative.
+ void ConsumeBits(int bits);
+
+ // Reads single bit. Returns 0 or 1.
+ ABSL_MUST_USE_RESULT int ReadBit();
+
+ // Reads `bits` from the bitstream. `bits` must be in range [0, 64].
+ // Returns an unsigned integer in range [0, 2^bits - 1].
+ // On failure sets `BitstreamReader` into the failure state and returns 0.
+ ABSL_MUST_USE_RESULT uint64_t ReadBits(int bits);
+
+ // Reads unsigned integer of fixed width.
+ template <typename T,
+ typename std::enable_if<std::is_unsigned<T>::value &&
+ !std::is_same<T, bool>::value &&
+ sizeof(T) <= 8>::type* = nullptr>
+ ABSL_MUST_USE_RESULT T Read() {
+ return rtc::dchecked_cast<T>(ReadBits(sizeof(T) * 8));
+ }
+
+ // Reads single bit as boolean.
+ template <
+ typename T,
+ typename std::enable_if<std::is_same<T, bool>::value>::type* = nullptr>
+ ABSL_MUST_USE_RESULT bool Read() {
+ return ReadBit() != 0;
+ }
+
+ // Reads value in range [0, `num_values` - 1].
+ // This encoding is similar to ReadBits(val, Ceil(Log2(num_values)),
+ // but reduces wastage incurred when encoding non-power of two value ranges
+ // Non symmetric values are encoded as:
+ // 1) n = bit_width(num_values)
+ // 2) k = (1 << n) - num_values
+ // Value v in range [0, k - 1] is encoded in (n-1) bits.
+ // Value v in range [k, num_values - 1] is encoded as (v+k) in n bits.
+ // https://aomediacodec.github.io/av1-spec/#nsn
+ uint32_t ReadNonSymmetric(uint32_t num_values);
+
+ // Reads exponential golomb encoded value.
+ // On failure sets `BitstreamReader` into the failure state and returns
+ // unspecified value.
+ // Exponential golomb values are encoded as:
+ // 1) x = source val + 1
+ // 2) In binary, write [bit_width(x) - 1] 0s, then x
+ // To decode, we count the number of leading 0 bits, read that many + 1 bits,
+ // and increment the result by 1.
+ // Fails the parsing if the value wouldn't fit in a uint32_t.
+ uint32_t ReadExponentialGolomb();
+
+ // Reads signed exponential golomb values at the current offset. Signed
+ // exponential golomb values are just the unsigned values mapped to the
+ // sequence 0, 1, -1, 2, -2, etc. in order.
+ // On failure sets `BitstreamReader` into the failure state and returns
+ // unspecified value.
+ int ReadSignedExponentialGolomb();
+
+ private:
+ void set_last_read_is_verified(bool value) const;
+
+ // Next byte with at least one unread bit.
+ const uint8_t* bytes_;
+
+ // Number of bits remained to read.
+ int remaining_bits_;
+
+ // Unused in release mode.
+ mutable bool last_read_is_verified_ = true;
+};
+
+inline BitstreamReader::BitstreamReader(rtc::ArrayView<const uint8_t> bytes)
+ : bytes_(bytes.data()), remaining_bits_(bytes.size() * 8) {}
+
+inline BitstreamReader::BitstreamReader(absl::string_view bytes)
+ : bytes_(reinterpret_cast<const uint8_t*>(bytes.data())),
+ remaining_bits_(bytes.size() * 8) {}
+
+inline BitstreamReader::~BitstreamReader() {
+ RTC_DCHECK(last_read_is_verified_) << "Latest calls to Read or ConsumeBit "
+ "were not checked with Ok function.";
+}
+
+inline void BitstreamReader::set_last_read_is_verified(bool value) const {
+#ifdef RTC_DCHECK_IS_ON
+ last_read_is_verified_ = value;
+#endif
+}
+
+inline int BitstreamReader::RemainingBitCount() const {
+ set_last_read_is_verified(true);
+ return remaining_bits_;
+}
+
+} // namespace webrtc
+
+#endif // RTC_BASE_BITSTREAM_READER_H_