MythTV master
bitreader.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Scott Theisen
3 *
4 * This file is part of MythTV.
5 *
6 * MythTV is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * MythTV is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with MythTV; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
27#ifndef BIT_READER_H
28#define BIT_READER_H
29
30#include <algorithm>
31#include <array>
32#include <cstdint>
33
34#if __has_include(<bit>) // C++20
35#include <bit>
36#endif
37
39{
40 public:
41 BitReader(const uint8_t* buffer, uint64_t size) :
42 m_buffer(buffer),
43 m_bufferEnd(buffer + size)
44 {
45 }
46 ~BitReader() = default;
47
48 void skip_bits(unsigned n)
49 {
50 if (m_cacheSize > n)
51 {
52 m_cache <<= n;
53 m_cacheSize -= n;
54 }
55 else
56 {
57 n -= m_cacheSize;
58 m_cacheSize = 0;
59 m_cache = 0;
60 m_bitIndex += n;
61 unsigned quotient = m_bitIndex / kBitsPerRead;
63 m_buffer += quotient;
64 }
65 }
66 uint32_t show_bits(unsigned n)
67 {
68 //assert(n <= 32);
69 if (m_cacheSize < n)
70 {
71 refill_cache(32);
72 }
73 return static_cast<uint32_t>(get_upper_bits(m_cache, n));
74 }
75 uint64_t show_bits64(unsigned n)
76 {
77 //assert(n <= 64);
78 if (m_cacheSize < n)
79 {
80 refill_cache(64);
81 }
82 return get_upper_bits(m_cache, n);
83 }
84 bool next_bit() { return get_bits(1) == 1; }
86 uint32_t get_bits(unsigned n)
87 {
88 uint32_t ret = show_bits(n);
89 skip_bits(n);
90 return ret;
91 }
93 uint64_t get_bits64(unsigned n)
94 {
95 uint64_t ret = show_bits64(n);
96 skip_bits(n);
97 return ret;
98 }
99
106 {
107 return get_ue_golomb(13);
108 }
109
116 {
117 uint32_t buf = show_bits(32);
118 unsigned lz = clz(buf);
119 unsigned length = lz + 1;
120 skip_bits(lz);
121
122 if (length > 32)
123 {
124 skip_bits(length);
125 return UINT32_MAX;
126 }
127
128 return get_bits(length) - 1;
129 }
130
137 {
138 return get_ue_golomb(5);
139 }
140
145 {
146 uint32_t buf = get_ue_golomb_long() + 1;
147 // revert the -1 offset to get the raw value
148
149 if (buf & 1)
150 {
151 return -(buf >> 1);
152 }
153 return buf >> 1;
154 }
155
157 {
158 return m_cacheSize + (kBitsPerRead * static_cast<int64_t>(m_bufferEnd - m_buffer)) - m_bitIndex;
159 }
160
161 private:
162 int get_ue_golomb(unsigned max_length);
163 static unsigned clz(uint32_t v)
164 {
165#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L // C++20 <bit>
166 return std::countl_zero(v);
167#else
168 // based on public domain log2_floor
169 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
170 if (v == 0)
171 {
172 return 32;
173 }
174 static constexpr std::array<int,32> MultiplyDeBruijnBitPosition =
175 {
176 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
177 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
178 };
179
180 v |= v >> 1; // first round down to one less than a power of 2
181 v |= v >> 2;
182 v |= v >> 4;
183 v |= v >> 8;
184 v |= v >> 16;
185
186 return 31 - MultiplyDeBruijnBitPosition[static_cast<uint32_t>(v * 0x07C4ACDDU) >> 27];
187#endif
188 }
189
190 static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
191 {
192 // protect against undefined behavior
193 if (bits == 0)
194 {
195 return UINT64_C(0);
196 }
197 if (bits > 64)
198 {
199 return val;
200 }
201 return val >> (64 - bits);
202 }
203
204 void refill_cache(unsigned min_bits);
205
206 const uint8_t *m_buffer;
207 const uint8_t * const m_bufferEnd;
208 unsigned m_bitIndex {0};
209
216 uint64_t m_cache {0};
217 unsigned m_cacheSize {0};
218
219 static constexpr unsigned kCacheSizeMax {64};
220 static constexpr unsigned kBitsPerRead { 8};
221};
222
226inline int BitReader::get_ue_golomb(unsigned max_length)
227{
228 uint32_t buf = show_bits(32);
229 unsigned lz = clz(buf);
230 unsigned length = lz + 1;
231 unsigned size = lz + length; // total length
232
233 skip_bits(size);
234
235 if (length > max_length || length > 16)
236 {
237 return -1;
238 }
239
240 buf >>= 32 - size; // remove irrelevant trailing bits
241
242 return buf - 1; // offset for storing 0
243}
244
245inline void BitReader::refill_cache(unsigned min_bits)
246{
247 min_bits = std::min(min_bits, kCacheSizeMax);
248
249 //if (m_bitIndex >= kBitsPerRead)
250 {
251 unsigned quotient = m_bitIndex / kBitsPerRead;
253 m_buffer += quotient;
254 }
255
256 while (m_cacheSize < min_bits && m_buffer < m_bufferEnd)
257 {
258 unsigned shift = kCacheSizeMax - m_cacheSize;
259 unsigned bits = kBitsPerRead - m_bitIndex;
260 if (shift >= bits)
261 {
262 m_cache |= static_cast<uint64_t>(*m_buffer) << (shift - bits);
263 m_bitIndex = 0;
264 m_buffer++;
265 m_cacheSize += bits;
266 }
267 else
268 {
269 m_cache |= static_cast<uint64_t>(*m_buffer) >> (bits - shift);
270 m_bitIndex += shift;
271 m_cacheSize += shift;
272 return; // m_cacheSize == kCacheSizeMax
273 }
274
275 }
276}
277
278#endif // BIT_READER_H
unsigned m_cacheSize
Definition: bitreader.h:217
unsigned m_bitIndex
index for next bit read from the MSB
Definition: bitreader.h:208
int get_ue_golomb_31()
read unsigned exp golomb code, constraint to a max of 31.
Definition: bitreader.h:136
bool next_bit()
Definition: bitreader.h:84
uint32_t show_bits(unsigned n)
Definition: bitreader.h:66
int get_ue_golomb()
Read an unsigned Exp-Golomb code in the range 0 to 8190 (2^13 - 2).
Definition: bitreader.h:105
BitReader(const uint8_t *buffer, uint64_t size)
Definition: bitreader.h:41
static constexpr unsigned kCacheSizeMax
Definition: bitreader.h:219
static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
Definition: bitreader.h:190
int64_t get_bits_left()
Definition: bitreader.h:156
static constexpr unsigned kBitsPerRead
Definition: bitreader.h:220
static unsigned clz(uint32_t v)
Definition: bitreader.h:163
~BitReader()=default
uint64_t get_bits64(unsigned n)
Read 0-64 bits.
Definition: bitreader.h:93
void refill_cache(unsigned min_bits)
Definition: bitreader.h:245
const uint8_t *const m_bufferEnd
past the end pointer
Definition: bitreader.h:207
const uint8_t * m_buffer
next memory location to read from
Definition: bitreader.h:206
void skip_bits(unsigned n)
Definition: bitreader.h:48
uint32_t get_ue_golomb_long()
Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1.
Definition: bitreader.h:115
int get_se_golomb()
read signed exp golomb code.
Definition: bitreader.h:144
uint64_t m_cache
cache for reads.
Definition: bitreader.h:216
uint64_t show_bits64(unsigned n)
Definition: bitreader.h:75
uint32_t get_bits(unsigned n)
Read 0-32 bits.
Definition: bitreader.h:86