libxcoder 5.8.0
Loading...
Searching...
No Matches
ni_bitstream.c
Go to the documentation of this file.
1/*****************************************************************************
2 * This file is part of Kvazaar HEVC encoder.
3 *
4 * Copyright (c) 2021, Tampere University, ITU/ISO/IEC, project contributors
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright notice, this
14 * list of conditions and the following disclaimer in the documentation and/or
15 * other materials provided with the distribution.
16 *
17 * * Neither the name of the Tampere University or ITU/ISO/IEC nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ****************************************************************************/
32
33/*!*****************************************************************************
34 * \file ni_bitstream.c
35 *
36 * \brief Utility definitions to operate on bits in a bitstream
37 ******************************************************************************/
38
39#include <stdio.h>
40#include <string.h>
41#include <assert.h>
42#include "ni_util.h"
43#include "ni_bitstream.h"
44
45// the following is for bitstream put operations
46
47const uint32_t ni_bit_set_mask[] = {
48 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
49 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800,
50 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
51 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000,
52 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
53 0x40000000, 0x80000000};
54
55/*!*****************************************************************************
56 * \brief allocate a new bitstream data chunk
57 *
58 * \return pointer to the new chunk, or NULL.
59 ******************************************************************************/
60static ni_data_chunk_t *ni_bs_writer_alloc_chunk(void)
61{
62 ni_data_chunk_t *chunk = malloc(sizeof(ni_data_chunk_t));
63 if (chunk)
64 {
65 chunk->len = 0;
66 chunk->next = NULL;
67 }
68 return chunk;
69}
70
71/*!*****************************************************************************
72 * \brief write a byte to bitstream
73 * Note: the stream must be byte-aligned already
74 *
75 * \param stream bitstream
76 * \param byte byte to write
77 * \return none
78 ******************************************************************************/
79static void ni_bs_writer_write_byte(ni_bitstream_writer_t *stream, uint8_t byte)
80{
81 assert(stream->cur_bit == 0);
82
83 if (stream->last == NULL || stream->last->len == NI_DATA_CHUNK_SIZE)
84 {
85 // need to allocate a new chunk.
86 ni_data_chunk_t *new_chunk = ni_bs_writer_alloc_chunk();
87 if (!new_chunk)
88 {
89 ni_log(NI_LOG_ERROR, "%s error: no memory\n", __func__);
90 return;
91 }
92
93 if (!stream->first)
94 stream->first = new_chunk;
95 if (stream->last)
96 stream->last->next = new_chunk;
97 stream->last = new_chunk;
98 }
99 if (stream->last->len >= NI_DATA_CHUNK_SIZE)
100 {
101 ni_log(NI_LOG_ERROR, "%s error: new_chunk size >= max %d\n", __func__,
103 return;
104 }
105
106 stream->last->data[stream->last->len] = byte;
107 stream->last->len += 1;
108 stream->len += 1;
109}
110
111/*!*****************************************************************************
112 * \brief free a list of chunks
113 *
114 * \param chunk start of the chunk list
115 * \return none
116 ******************************************************************************/
117static void ni_bs_writer_free_chunks(ni_data_chunk_t *chunk)
118{
119 while (chunk != NULL)
120 {
121 ni_data_chunk_t *next = chunk->next;
122 free(chunk);
123 chunk = next;
124 }
125}
126
127static inline unsigned ni_math_floor_log2(unsigned value)
128{
129 unsigned result = 0;
130 assert(value > 0);
131 int i;
132
133 for (i = 4; i >= 0; --i)
134 {
135 unsigned bits = 1ull << i;
136 unsigned shift = (value >= (1ull << bits)) ? bits : 0;
137 result += shift;
138 value >>= shift;
139 }
140
141 return result;
142}
143
144static inline unsigned ni_math_ceil_log2(unsigned value)
145{
146 assert(value > 0);
147
148 // the ceil_log2 is just floor_log2 + 1, except for exact powers of 2.
149 return ni_math_floor_log2(value) + ((value & (value - 1)) ? 1 : 0);
150}
151
152/*!*****************************************************************************
153 * \brief init a bitstream writer
154 *
155 * \param stream bitstream
156 * \return none
157 ******************************************************************************/
159{
160 memset(stream, 0, sizeof(ni_bitstream_writer_t));
161}
162
163/*!*****************************************************************************
164 * \brief return the number of bits written to bitstream so far
165 *
166 * \param stream bitstream
167 * \return position
168 ******************************************************************************/
169uint64_t ni_bs_writer_tell(const ni_bitstream_writer_t *const stream)
170{
171 uint64_t position = stream->len;
172 return position * 8 + stream->cur_bit;
173}
174
175/*!*****************************************************************************
176 * \brief write a specified number (<= 32) of bits to bitstream,
177 * buffer individual bits until a full byte is made
178 * \param stream bitstream
179 * \param data input data
180 * \param bits number of bits in data to write to stream, max 32
181 * \return none
182 ******************************************************************************/
183void ni_bs_writer_put(ni_bitstream_writer_t *stream, uint32_t data,
184 uint8_t bits)
185{
186 if (bits > 32)
187 {
188 ni_log(NI_LOG_ERROR, "%s error: too many bits to write: %u\n", __func__,
189 bits);
190 return;
191 }
192
193 while (bits--)
194 {
195 if (bits >= 32)
196 {
197 ni_log(NI_LOG_ERROR, "%s error: invalid bits to write: %u\n", __func__,
198 bits);
199 return;
200 }
201 stream->data <<= 1;
202
203 if (data & ni_bit_set_mask[bits])
204 {
205 stream->data |= 1;
206 }
207 stream->cur_bit++;
208
209 // write the complete byte
210 if (stream->cur_bit == 8)
211 {
212 stream->cur_bit = 0;
213 ni_bs_writer_write_byte(stream, stream->data);
214 }
215 }
216}
217
218/*!*****************************************************************************
219 * \brief write unsigned Exp-Golomb bit string to bitstream, 2^32-2 at most.
220 *
221 * \param stream bitstream
222 * \param data input data
223 * \return none
224 ******************************************************************************/
225void ni_bs_writer_put_ue(ni_bitstream_writer_t *stream, uint32_t data)
226{
227 unsigned data_log2 = ni_math_floor_log2(data + 1);
228 unsigned prefix = 0;
229 if (data_log2 < 32)
230 {
231 prefix = 1U << data_log2;
232 }
233 unsigned suffix = data + 1 - prefix;
234 unsigned num_bits = data_log2 * 2 + 1;
235 unsigned value = prefix | suffix;
236
237 if (data > 0xFFFFFFFE) // 2^32-2 at most
238 {
239 ni_log(NI_LOG_ERROR, "%s error: data overflow: %u\n", __func__,
240 data);
241 return;
242 }
243
244 if (num_bits <= 32)
245 {
246 ni_bs_writer_put(stream, value, num_bits);
247 }
248 else
249 {
250 // big endian
251 ni_bs_writer_put(stream, 0, num_bits - 32); // high (num_bits - 32) bits
252 ni_bs_writer_put(stream, value, 32); // low 32 bits
253 }
254}
255
256/*!*****************************************************************************
257 * \brief write signed Exp-Golomb bit string to bitstream
258 *
259 * \param stream bitstream
260 * \param data input data
261 * \return none
262 ******************************************************************************/
264{
265 // map positive value to even and negative to odd value
266 uint32_t data_num = data <= 0 ? (-data) << 1 : (data << 1) - 1;
267 ni_bs_writer_put_ue(stream, data_num);
268}
269
270/*!*****************************************************************************
271 * \brief align the bitstream with zero
272 *
273 * \param stream bitstream
274 * \return none
275 ******************************************************************************/
277{
278 if ((stream->cur_bit & 7) != 0)
279 {
280 ni_bs_writer_put(stream, 0, 8 - (stream->cur_bit & 7));
281 }
282}
283
284/*!*****************************************************************************
285 * \brief copy bitstream data to dst
286 * Note: caller must ensure sufficient space in dst
287 *
288 * \param dst copy destination
289 * \param stream bitstream
290 * \return none
291 ******************************************************************************/
292void ni_bs_writer_copy(uint8_t *dst, const ni_bitstream_writer_t *stream)
293{
294 ni_data_chunk_t *chunk = stream->first;
295 uint8_t *p_dst = dst;
296 while (chunk && chunk->len)
297 {
298 memcpy(p_dst, chunk->data, chunk->len);
299 p_dst += chunk->len;
300 chunk = chunk->next;
301 }
302}
303
304/*!*****************************************************************************
305 * \brief clear and reset bitstream
306 *
307 * \param stream bitstream
308 * \return none
309 ******************************************************************************/
311{
312 ni_bs_writer_free_chunks(stream->first);
314}
315
316/*!*****************************************************************************
317 * \brief write unsigned LEB128 bit string to bitstream and return bytes written.
318 * Commonly used for OBU sizes in AV1.
319 *
320 * \param stream bitstream writer
321 * \param data input data to encode
322 * \return int: number of bytes written to the bitstream
323 ******************************************************************************/
325{
326 int bytes_written = 0;
327
328 // LEB128 requires the stream to be byte-aligned as it writes full bytes
329 if (stream->cur_bit != 0)
330 {
331 ni_log(NI_LOG_DEBUG, "%s: aligning bitstream before LEB128 write\n", __func__);
333 }
334
335 do
336 {
337 uint8_t byte = data & 0x7F;
338 data >>= 7;
339
340 if (data != 0)
341 {
342 // Set the continuation bit (MSB) if more bytes follow
343 byte |= 0x80;
344 }
345
346 ni_bs_writer_write_byte(stream, byte);
347 bytes_written++;
348 } while (data != 0);
349
350 return bytes_written;
351}
352
353// the following is for bitstream get operations
354
355/*!*****************************************************************************
356 * \brief init a bitstream reader
357 * Note: bitstream_reader takes reading ownership of the data
358 *
359 * \param br bitstream reader
360 * \param data data to be parsed
361 * \param bit_size number of bits in the data
362 * \return none
363 ******************************************************************************/
365 int bit_size)
366{
367 if (!br || !data)
368 {
369 ni_log(NI_LOG_ERROR, "%s input is NULL !\n", __func__);
370 return;
371 }
372
373 br->buf = data;
374 br->size_in_bits = bit_size;
375 br->byte_offset = 0;
376 br->bit_offset = 0;
377}
378
379/*!*****************************************************************************
380 * \brief return the number of bits already parsed in stream
381 *
382 * \param br bitstream reader
383 * \return number of bits parsed
384 ******************************************************************************/
386{
387 return br->byte_offset * 8 + br->bit_offset;
388}
389
390/*!*****************************************************************************
391 * \brief return the number of bits left to parse in stream
392 *
393 * \param br bitstream reader
394 * \return number of bits left
395 ******************************************************************************/
400
401/*!*****************************************************************************
402 * \brief skip a number of bits ahead in the bitstream reader
403 *
404 * \param br bitstream reader
405 * \param n number of bits to skip
406 * \return none
407 ******************************************************************************/
409{
410 int new_offset = 8 * br->byte_offset + br->bit_offset + n;
411 if (new_offset > br->size_in_bits)
412 {
414 "%s: skip %d, current byte_offset "
415 "%d bit_offset %d, over total size %d, stop !\n",
416 __func__, n, br->byte_offset, br->bit_offset, br->size_in_bits);
417 return;
418 }
419
420 br->byte_offset = new_offset / 8;
421 br->bit_offset = new_offset % 8;
422}
423
424// read a single bit
426{
427 uint8_t ret = 0;
428
429 if (0 == br->bit_offset)
430 {
431 ret = (br->buf[br->byte_offset] >> 7);
432 br->bit_offset = 1;
433 } else
434 {
435 ret = ((br->buf[br->byte_offset] >> (7 - br->bit_offset)) & 0x1);
436 if (7 == br->bit_offset)
437 {
438 br->bit_offset = 0;
439 br->byte_offset++;
440 } else
441 {
442 br->bit_offset++;
443 }
444 }
445
446 return ret;
447}
448
449// read a single byte
451{
452 uint8_t ret = 0;
453
454 ret = (br->buf[br->byte_offset] << br->bit_offset);
455 br->byte_offset++;
456
457 if (0 != br->bit_offset)
458 {
459 ret |= (br->buf[br->byte_offset] >> (8 - br->bit_offset));
460 }
461
462 return ret;
463}
464
465// read a 16 bit integer
467{
468 uint16_t ret = 0;
469 int i;
470 int offset;
471 const uint8_t *src = NULL;
472
473 src = &(br->buf[br->byte_offset]);
474 offset = 16 + br->bit_offset;
475
476 for (i = 0; i < 2; i++)
477 {
478 offset -= 8;
479 ret |= ((uint16_t)src[i] << offset);
480 }
481
482 if (0 != offset)
483 {
484 ret |= (src[2] >> (8 - offset));
485 }
486
487 br->byte_offset += 2;
488
489 return ret;
490}
491
492// read <= 8 bits
494{
495 uint8_t ret = 0;
496
497 if (n > 8)
498 {
499 ni_log(NI_LOG_ERROR, "%s %d bits > 8, error!\n", __func__, n);
500 return 0;
501 }
502
503 while (n)
504 {
505 ret = ((ret << 1) | ni_bitstream_get_1bit(br));
506 n--;
507 }
508 return ret;
509}
510
511/*!*****************************************************************************
512 * \brief read bits (up to 32) from the bitstream reader, after reader init
513 *
514 * \param br bitstream reader
515 * \param n number of bits to read
516 * \return value read
517 ******************************************************************************/
519{
520 uint32_t ret = 0;
521 int bits_left;
522
523 if (n > 32)
524 {
525 ni_log(NI_LOG_ERROR, "%s %d bits > 32, not supported!\n", __func__, n);
526 return 0;
527 }
528
529 if (n <= 0)
530 {
531 // return 0
532 } else if (n < 8)
533 {
535 } else if (8 == n)
536 {
537 ret = ni_bitstream_get_u8(br);
538 } else if (n > 8 && n < 16)
539 {
540 bits_left = n % 8;
541 ret = ((ni_bitstream_get_8bits_or_less(br, bits_left) << 8) |
543 } else if (16 == n)
544 {
545 ret = ni_bitstream_get_u16(br);
546 } else if (n > 16 && n < 24)
547 {
548 bits_left = n % 16;
549 ret = (ni_bitstream_get_8bits_or_less(br, bits_left) << 16);
550 ret |= (ni_bitstream_get_u8(br) << 8);
551 ret |= ni_bitstream_get_u8(br);
552 } else // 32 >= n >= 24
553 {
554 bits_left = n % 24;
555 ret = (ni_bitstream_get_8bits_or_less(br, bits_left) << 24);
556 ret |= (ni_bitstream_get_u8(br) << 16);
557 ret |= (ni_bitstream_get_u8(br) << 8);
558 ret |= ni_bitstream_get_u8(br);
559 }
560 return ret;
561}
562
563/*!*****************************************************************************
564 * \brief read an unsigned Exp-Golomb code ue(v)
565 *
566 * \param br bitstream reader
567 * \return value read
568 ******************************************************************************/
570{
571 uint32_t ret = 0;
572 int i = 0; // leading zero bits
573
574 // count leading zero bits
575 while (0 == ni_bitstream_get_1bit(br) && i < 32)
576 {
577 i++;
578 }
579 if (i == 32)
580 return 0;
581 // calc get_bits(leading zero bits)
582 ret = ni_bs_reader_get_bits(br, i);
583 ret += (1U << i) - 1;
584 return ret;
585}
586
587/*!*****************************************************************************
588 * \brief read a signed Exp-Golomb code se(v)
589 *
590 * \param br bitstream reader
591 * \return value read
592 ******************************************************************************/
594{
595 // get ue
596 int32_t ret = (int32_t)ni_bs_reader_get_ue(br);
597
598 // determine if it's odd or even
599 if (ret & 0x01) // odd: value before encode > 0
600 {
601 ret = (ret + 1) / 2;
602 } else // even: value before encode <= 0
603 {
604 ret = -(ret / 2);
605 }
606 return ret;
607}
const uint32_t ni_bit_set_mask[]
int ni_bs_reader_bits_count(ni_bitstream_reader_t *br)
return the number of bits already parsed in stream
int ni_bs_writer_leb128(ni_bitstream_writer_t *stream, uint32_t data)
write unsigned LEB128 bit string to bitstream and return bytes written. Commonly used for OBU sizes i...
void ni_bs_writer_put_ue(ni_bitstream_writer_t *stream, uint32_t data)
write unsigned Exp-Golomb bit string to bitstream, 2^32-2 at most.
uint16_t ni_bitstream_get_u16(ni_bitstream_reader_t *br)
void ni_bitstream_writer_init(ni_bitstream_writer_t *stream)
init a bitstream writer
uint32_t ni_bs_reader_get_ue(ni_bitstream_reader_t *br)
read an unsigned Exp-Golomb code ue(v)
void ni_bs_writer_copy(uint8_t *dst, const ni_bitstream_writer_t *stream)
copy bitstream data to dst Note: caller must ensure sufficient space in dst
uint8_t ni_bitstream_get_1bit(ni_bitstream_reader_t *br)
int32_t ni_bs_reader_get_se(ni_bitstream_reader_t *br)
read a signed Exp-Golomb code se(v)
void ni_bs_writer_align_zero(ni_bitstream_writer_t *stream)
align the bitstream with zero
void ni_bitstream_reader_init(ni_bitstream_reader_t *br, const uint8_t *data, int bit_size)
init a bitstream reader Note: bitstream_reader takes reading ownership of the data
uint32_t ni_bs_reader_get_bits(ni_bitstream_reader_t *br, int n)
read bits (up to 32) from the bitstream reader, after reader init
void ni_bs_writer_clear(ni_bitstream_writer_t *stream)
clear and reset bitstream
uint8_t ni_bitstream_get_u8(ni_bitstream_reader_t *br)
uint64_t ni_bs_writer_tell(const ni_bitstream_writer_t *const stream)
return the number of bits written to bitstream so far
void ni_bs_writer_put(ni_bitstream_writer_t *stream, uint32_t data, uint8_t bits)
write a specified number (<= 32) of bits to bitstream, buffer individual bits until a full byte is ma...
void ni_bs_writer_put_se(ni_bitstream_writer_t *stream, int32_t data)
write signed Exp-Golomb bit string to bitstream
int ni_bs_reader_get_bits_left(ni_bitstream_reader_t *br)
return the number of bits left to parse in stream
void ni_bs_reader_skip_bits(ni_bitstream_reader_t *br, int n)
skip a number of bits ahead in the bitstream reader
uint8_t ni_bitstream_get_8bits_or_less(ni_bitstream_reader_t *br, int n)
Utility definitions to operate on bits in a bitstream.
#define NI_DATA_CHUNK_SIZE
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition ni_log.c:183
@ NI_LOG_DEBUG
Definition ni_log.h:64
@ NI_LOG_ERROR
Definition ni_log.h:62
Utility definitions.
const uint8_t * buf
ni_data_chunk_t * first
ni_data_chunk_t * last
struct ni_data_chunk_t * next
uint8_t data[NI_DATA_CHUNK_SIZE]