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 
38 class BitReader
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 
156  int64_t get_bits_left()
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 
226 inline 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 
245 inline 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
BitReader::kBitsPerRead
static constexpr unsigned kBitsPerRead
Definition: bitreader.h:220
BitReader::refill_cache
void refill_cache(unsigned min_bits)
Definition: bitreader.h:245
BitReader::clz
static unsigned clz(uint32_t v)
Definition: bitreader.h:163
BitReader::get_bits
uint32_t get_bits(unsigned n)
Read 0-32 bits.
Definition: bitreader.h:86
BitReader::get_ue_golomb_31
int get_ue_golomb_31()
read unsigned exp golomb code, constraint to a max of 31.
Definition: bitreader.h:136
BitReader::~BitReader
~BitReader()=default
BitReader
Definition: bitreader.h:38
BitReader::get_se_golomb
int get_se_golomb()
read signed exp golomb code.
Definition: bitreader.h:144
BitReader::kCacheSizeMax
static constexpr unsigned kCacheSizeMax
Definition: bitreader.h:219
BitReader::m_buffer
const uint8_t * m_buffer
next memory location to read from
Definition: bitreader.h:206
BitReader::m_bitIndex
unsigned m_bitIndex
index for next bit read from the MSB
Definition: bitreader.h:208
BitReader::get_bits64
uint64_t get_bits64(unsigned n)
Read 0-64 bits.
Definition: bitreader.h:93
BitReader::BitReader
BitReader(const uint8_t *buffer, uint64_t size)
Definition: bitreader.h:41
BitReader::get_ue_golomb_long
uint32_t get_ue_golomb_long()
Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1.
Definition: bitreader.h:115
BitReader::m_cache
uint64_t m_cache
cache for reads.
Definition: bitreader.h:216
BitReader::m_bufferEnd
const uint8_t *const m_bufferEnd
past the end pointer
Definition: bitreader.h:207
BitReader::m_cacheSize
unsigned m_cacheSize
Definition: bitreader.h:217
BitReader::get_bits_left
int64_t get_bits_left()
Definition: bitreader.h:156
BitReader::show_bits
uint32_t show_bits(unsigned n)
Definition: bitreader.h:66
BitReader::skip_bits
void skip_bits(unsigned n)
Definition: bitreader.h:48
BitReader::next_bit
bool next_bit()
Definition: bitreader.h:84
BitReader::get_upper_bits
static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
Definition: bitreader.h:190
BitReader::get_ue_golomb
int get_ue_golomb()
Read an unsigned Exp-Golomb code in the range 0 to 8190 (2^13 - 2).
Definition: bitreader.h:105
BitReader::show_bits64
uint64_t show_bits64(unsigned n)
Definition: bitreader.h:75