MythTV master
bitreader.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Unlicense
2// Created by Scott Theisen, 2022-2024
3/* The Unlicense
4This is free and unencumbered software released into the public domain.
5
6Anyone is free to copy, modify, publish, use, compile, sell, or
7distribute this software, either in source code form or as a compiled
8binary, for any purpose, commercial or non-commercial, and by any
9means.
10
11In jurisdictions that recognize copyright laws, the author or authors
12of this software dedicate any and all copyright interest in the
13software to the public domain. We make this dedication for the benefit
14of the public at large and to the detriment of our heirs and
15successors. We intend this dedication to be an overt act of
16relinquishment in perpetuity of all present and future rights to this
17software under copyright law.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27For more information, please refer to <https://unlicense.org>
28*/
29
36#ifndef BIT_READER_H
37#define BIT_READER_H
38
39#include <algorithm>
40#include <array>
41#include <bit>
42#include <cstdint>
43
45{
46 public:
47 BitReader(const uint8_t* buffer, uint64_t size) :
48 m_buffer(buffer),
49 m_bufferEnd(buffer + size)
50 {
51 }
52 ~BitReader() = default;
53
54 void skip_bits(unsigned n)
55 {
56 if (m_cacheSize > n)
57 {
58 m_cache <<= n;
59 m_cacheSize -= n;
60 }
61 else
62 {
63 n -= m_cacheSize;
64 m_cacheSize = 0;
65 m_cache = 0;
66 m_bitIndex += n;
67 unsigned quotient = m_bitIndex / kBitsPerRead;
69 m_buffer += quotient;
70 }
71 }
72 uint32_t show_bits(unsigned n)
73 {
74 //assert(n <= 32);
75 if (m_cacheSize < n)
76 {
77 refill_cache(32);
78 }
79 return static_cast<uint32_t>(get_upper_bits(m_cache, n));
80 }
81 uint64_t show_bits64(unsigned n)
82 {
83 //assert(n <= 64);
84 if (m_cacheSize < n)
85 {
86 refill_cache(64);
87 }
88 return get_upper_bits(m_cache, n);
89 }
90 bool next_bit() { return get_bits(1) == 1; }
92 uint32_t get_bits(unsigned n)
93 {
94 uint32_t ret = show_bits(n);
95 skip_bits(n);
96 return ret;
97 }
99 uint64_t get_bits64(unsigned n)
100 {
101 uint64_t ret = show_bits64(n);
102 skip_bits(n);
103 return ret;
104 }
105
112 {
113 return get_ue_golomb(13);
114 }
115
122 {
123 uint32_t buf = show_bits(32);
124 unsigned lz = clz(buf);
125 unsigned length = lz + 1;
126 skip_bits(lz);
127
128 if (length > 32)
129 {
130 skip_bits(length);
131 return UINT32_MAX;
132 }
133
134 return get_bits(length) - 1;
135 }
136
143 {
144 return get_ue_golomb(5);
145 }
146
151 {
152 uint32_t buf = get_ue_golomb_long() + 1;
153 // revert the -1 offset to get the raw value
154
155 if (buf & 1)
156 {
157 return -(buf >> 1);
158 }
159 return buf >> 1;
160 }
161
163 {
164 return m_cacheSize + (kBitsPerRead * static_cast<int64_t>(m_bufferEnd - m_buffer)) - m_bitIndex;
165 }
166
167 private:
168 int get_ue_golomb(unsigned max_length);
169 static unsigned clz(uint32_t v)
170 {
171 return std::countl_zero(v);
172 }
173
174 static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
175 {
176 // protect against undefined behavior
177 if (bits == 0)
178 {
179 return UINT64_C(0);
180 }
181 if (bits > 64)
182 {
183 return val;
184 }
185 return val >> (64 - bits);
186 }
187
188 void refill_cache(unsigned min_bits);
189
190 const uint8_t *m_buffer;
191 const uint8_t * const m_bufferEnd;
192 unsigned m_bitIndex {0};
193
200 uint64_t m_cache {0};
201 unsigned m_cacheSize {0};
202
203 static constexpr unsigned kCacheSizeMax {64};
204 static constexpr unsigned kBitsPerRead { 8};
205};
206
210inline int BitReader::get_ue_golomb(unsigned max_length)
211{
212 uint32_t buf = show_bits(32);
213 unsigned lz = clz(buf);
214 unsigned length = lz + 1;
215 unsigned size = lz + length; // total length
216
217 skip_bits(size);
218
219 if (length > max_length || length > 16)
220 {
221 return -1;
222 }
223
224 buf >>= 32 - size; // remove irrelevant trailing bits
225
226 return buf - 1; // offset for storing 0
227}
228
229inline void BitReader::refill_cache(unsigned min_bits)
230{
231 min_bits = std::min(min_bits, kCacheSizeMax);
232
233 //if (m_bitIndex >= kBitsPerRead)
234 {
235 unsigned quotient = m_bitIndex / kBitsPerRead;
237 m_buffer += quotient;
238 }
239
240 while (m_cacheSize < min_bits && m_buffer < m_bufferEnd)
241 {
242 unsigned shift = kCacheSizeMax - m_cacheSize;
243 unsigned bits = kBitsPerRead - m_bitIndex;
244 if (shift >= bits)
245 {
246 m_cache |= static_cast<uint64_t>(*m_buffer) << (shift - bits);
247 m_bitIndex = 0;
248 m_buffer++;
249 m_cacheSize += bits;
250 }
251 else
252 {
253 m_cache |= static_cast<uint64_t>(*m_buffer) >> (bits - shift);
254 m_bitIndex += shift;
255 m_cacheSize += shift;
256 return; // m_cacheSize == kCacheSizeMax
257 }
258
259 }
260}
261
262#endif // BIT_READER_H
unsigned m_cacheSize
Definition: bitreader.h:201
unsigned m_bitIndex
index for next bit read from the MSB
Definition: bitreader.h:192
int get_ue_golomb_31()
read unsigned exp golomb code, constraint to a max of 31.
Definition: bitreader.h:142
bool next_bit()
Definition: bitreader.h:90
uint32_t show_bits(unsigned n)
Definition: bitreader.h:72
int get_ue_golomb()
Read an unsigned Exp-Golomb code in the range 0 to 8190 (2^13 - 2).
Definition: bitreader.h:111
BitReader(const uint8_t *buffer, uint64_t size)
Definition: bitreader.h:47
static constexpr unsigned kCacheSizeMax
Definition: bitreader.h:203
static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
Definition: bitreader.h:174
int64_t get_bits_left()
Definition: bitreader.h:162
static constexpr unsigned kBitsPerRead
Definition: bitreader.h:204
static unsigned clz(uint32_t v)
Definition: bitreader.h:169
~BitReader()=default
uint64_t get_bits64(unsigned n)
Read 0-64 bits.
Definition: bitreader.h:99
void refill_cache(unsigned min_bits)
Definition: bitreader.h:229
const uint8_t *const m_bufferEnd
past the end pointer
Definition: bitreader.h:191
const uint8_t * m_buffer
next memory location to read from
Definition: bitreader.h:190
void skip_bits(unsigned n)
Definition: bitreader.h:54
uint32_t get_ue_golomb_long()
Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1.
Definition: bitreader.h:121
int get_se_golomb()
read signed exp golomb code.
Definition: bitreader.h:150
uint64_t m_cache
cache for reads.
Definition: bitreader.h:200
uint64_t show_bits64(unsigned n)
Definition: bitreader.h:81
uint32_t get_bits(unsigned n)
Read 0-32 bits.
Definition: bitreader.h:92