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 <array>
31 #include <cstdint>
32 #include <climits> // for CHAR_BIT
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  int quotient = m_bitIndex / CHAR_BIT;
62  m_bitIndex %= CHAR_BIT;
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 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 + CHAR_BIT * 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[(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 };
220 
224 inline int BitReader::get_ue_golomb(unsigned max_length)
225 {
226  uint32_t buf = show_bits(32);
227  unsigned lz = clz(buf);
228  unsigned length = lz + 1;
229  unsigned size = lz + length; // total length
230 
231  skip_bits(size);
232 
233  if (length > max_length || length > 16)
234  {
235  return -1;
236  }
237 
238  buf >>= 32 - size; // remove irrelevant trailing bits
239 
240  return buf - 1; // offset for storing 0
241 }
242 
243 inline void BitReader::refill_cache(unsigned min_bits)
244 {
245  while (m_cacheSize < min_bits && m_buffer < m_bufferEnd)
246  {
247  int shift = 64 - m_cacheSize;
248  int bits = CHAR_BIT - m_bitIndex;
249  if (shift > bits)
250  {
251  m_cache |= int64_t(*m_buffer & ((1 << bits) - 1)) << (shift - bits);
252  m_bitIndex = 0;
253  m_buffer++;
254  m_cacheSize += bits;
255  }
256  else
257  {
258  m_cache |= int64_t(*m_buffer & ((1 << bits) - 1)) >> (bits - shift);
259  m_bitIndex += shift;
260  m_cacheSize += shift;
261  }
262 
263  }
264 }
265 
266 #endif // BIT_READER_H
BitReader::refill_cache
void refill_cache(unsigned min_bits)
Definition: bitreader.h:243
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::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