1 /*
2  *  Copyright 2015 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_BIT_BUFFER_H_
12 #define RTC_BASE_BIT_BUFFER_H_
13 
14 #include <stddef.h>  // For size_t.
15 #include <stdint.h>  // For integer types.
16 
17 #include "rtc_base/constructor_magic.h"
18 
19 namespace rtc {
20 
21 // A class, similar to ByteBuffer, that can parse bit-sized data out of a set of
22 // bytes. Has a similar API to ByteBuffer, plus methods for reading bit-sized
23 // and exponential golomb encoded data. For a writable version, use
24 // BitBufferWriter. Unlike ByteBuffer, this class doesn't make a copy of the
25 // source bytes, so it can be used on read-only data.
26 // Sizes/counts specify bits/bytes, for clarity.
27 // Byte order is assumed big-endian/network.
28 class BitBuffer {
29  public:
30   BitBuffer(const uint8_t* bytes, size_t byte_count);
31 
32   // Gets the current offset, in bytes/bits, from the start of the buffer. The
33   // bit offset is the offset into the current byte, in the range [0,7].
34   void GetCurrentOffset(size_t* out_byte_offset, size_t* out_bit_offset);
35 
36   // The remaining bits in the byte buffer.
37   uint64_t RemainingBitCount() const;
38 
39   // Reads byte-sized values from the buffer. Returns false if there isn't
40   // enough data left for the specified type.
41   bool ReadUInt8(uint8_t* val);
42   bool ReadUInt16(uint16_t* val);
43   bool ReadUInt32(uint32_t* val);
44 
45   // Reads bit-sized values from the buffer. Returns false if there isn't enough
46   // data left for the specified bit count.
47   bool ReadBits(uint32_t* val, size_t bit_count);
48 
49   // Peeks bit-sized values from the buffer. Returns false if there isn't enough
50   // data left for the specified number of bits. Doesn't move the current
51   // offset.
52   bool PeekBits(uint32_t* val, size_t bit_count);
53 
54   // Reads value in range [0, num_values - 1].
55   // This encoding is similar to ReadBits(val, Ceil(Log2(num_values)),
56   // but reduces wastage incurred when encoding non-power of two value ranges
57   // Non symmetric values are encoded as:
58   // 1) n = countbits(num_values)
59   // 2) k = (1 << n) - num_values
60   // Value v in range [0, k - 1] is encoded in (n-1) bits.
61   // Value v in range [k, num_values - 1] is encoded as (v+k) in n bits.
62   // https://aomediacodec.github.io/av1-spec/#nsn
63   // Returns false if there isn't enough data left.
64   bool ReadNonSymmetric(uint32_t* val, uint32_t num_values);
65 
66   // Reads the exponential golomb encoded value at the current offset.
67   // Exponential golomb values are encoded as:
68   // 1) x = source val + 1
69   // 2) In binary, write [countbits(x) - 1] 0s, then x
70   // To decode, we count the number of leading 0 bits, read that many + 1 bits,
71   // and increment the result by 1.
72   // Returns false if there isn't enough data left for the specified type, or if
73   // the value wouldn't fit in a uint32_t.
74   bool ReadExponentialGolomb(uint32_t* val);
75   // Reads signed exponential golomb values at the current offset. Signed
76   // exponential golomb values are just the unsigned values mapped to the
77   // sequence 0, 1, -1, 2, -2, etc. in order.
78   bool ReadSignedExponentialGolomb(int32_t* val);
79 
80   // Moves current position |byte_count| bytes forward. Returns false if
81   // there aren't enough bytes left in the buffer.
82   bool ConsumeBytes(size_t byte_count);
83   // Moves current position |bit_count| bits forward. Returns false if
84   // there aren't enough bits left in the buffer.
85   bool ConsumeBits(size_t bit_count);
86 
87   // Sets the current offset to the provied byte/bit offsets. The bit
88   // offset is from the given byte, in the range [0,7].
89   bool Seek(size_t byte_offset, size_t bit_offset);
90 
91  protected:
92   const uint8_t* const bytes_;
93   // The total size of |bytes_|.
94   size_t byte_count_;
95   // The current offset, in bytes, from the start of |bytes_|.
96   size_t byte_offset_;
97   // The current offset, in bits, into the current byte.
98   size_t bit_offset_;
99 
100   RTC_DISALLOW_COPY_AND_ASSIGN(BitBuffer);
101 };
102 
103 // A BitBuffer API for write operations. Supports symmetric write APIs to the
104 // reading APIs of BitBuffer. Note that the read/write offset is shared with the
105 // BitBuffer API, so both reading and writing will consume bytes/bits.
106 class BitBufferWriter : public BitBuffer {
107  public:
108   // Constructs a bit buffer for the writable buffer of |bytes|.
109   BitBufferWriter(uint8_t* bytes, size_t byte_count);
110 
111   // Writes byte-sized values from the buffer. Returns false if there isn't
112   // enough data left for the specified type.
113   bool WriteUInt8(uint8_t val);
114   bool WriteUInt16(uint16_t val);
115   bool WriteUInt32(uint32_t val);
116 
117   // Writes bit-sized values to the buffer. Returns false if there isn't enough
118   // room left for the specified number of bits.
119   bool WriteBits(uint64_t val, size_t bit_count);
120 
121   // Writes value in range [0, num_values - 1]
122   // See ReadNonSymmetric documentation for the format,
123   // Call SizeNonSymmetricBits to get number of bits needed to store the value.
124   // Returns false if there isn't enough room left for the value.
125   bool WriteNonSymmetric(uint32_t val, uint32_t num_values);
126   // Returns number of bits required to store |val| with NonSymmetric encoding.
127   static size_t SizeNonSymmetricBits(uint32_t val, uint32_t num_values);
128 
129   // Writes the exponential golomb encoded version of the supplied value.
130   // Returns false if there isn't enough room left for the value.
131   bool WriteExponentialGolomb(uint32_t val);
132   // Writes the signed exponential golomb version of the supplied value.
133   // Signed exponential golomb values are just the unsigned values mapped to the
134   // sequence 0, 1, -1, 2, -2, etc. in order.
135   bool WriteSignedExponentialGolomb(int32_t val);
136 
137  private:
138   // The buffer, as a writable array.
139   uint8_t* const writable_bytes_;
140 
141   RTC_DISALLOW_COPY_AND_ASSIGN(BitBufferWriter);
142 };
143 
144 }  // namespace rtc
145 
146 #endif  // RTC_BASE_BIT_BUFFER_H_
147