You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.3 KiB
118 lines
3.3 KiB
#include "./bitstream.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <assert.h>
|
|
|
|
static const uint32_t BS_MASKS[33] = {
|
|
0, 0x1L, 0x3L, 0x7L, 0xFL, 0x1FL,
|
|
0x3FL, 0x7FL, 0xFFL, 0x1FFL, 0x3FFL, 0x7FFL,
|
|
0xFFFL, 0x1FFFL, 0x3FFFL, 0x7FFFL, 0xFFFFL, 0x1FFFFL,
|
|
0x3FFFFL, 0x7FFFFL, 0xFFFFFL, 0x1FFFFFL, 0x3FFFFFL, 0x7FFFFFL,
|
|
0xFFFFFFL, 0x1FFFFFFL, 0x3FFFFFFL, 0x7FFFFFFL, 0xFFFFFFFL, 0x1FFFFFFFL,
|
|
0x3FFFFFFFL, 0x7FFFFFFFL, 0xFFFFFFFFL};
|
|
|
|
void bs_init(struct bitstream* bs, const uint8_t* buffer, size_t input_size) {
|
|
bs->buffer_ptr = buffer;
|
|
bs->buffer_end = buffer + input_size;
|
|
bs->value = 0;
|
|
bs->pos = 0;
|
|
bs->shift = 8;
|
|
bs->size = input_size * 8;
|
|
}
|
|
|
|
uint32_t bs_get(struct bitstream* bs, int n) {
|
|
if (n > 32)
|
|
return 0;
|
|
|
|
bs->pos += n;
|
|
bs->shift += n;
|
|
while (bs->shift > 8) {
|
|
if (bs->buffer_ptr < bs->buffer_end) {
|
|
bs->value <<= 8;
|
|
bs->value |= *bs->buffer_ptr++;
|
|
bs->shift -= 8;
|
|
} else {
|
|
bs_seek(bs, bs->pos - n);
|
|
return 0;
|
|
// bs->value <<= 8;
|
|
// bs->shift -= 8;
|
|
}
|
|
}
|
|
return (bs->value >> (8 - bs->shift)) & BS_MASKS[n];
|
|
}
|
|
|
|
void bs_seek(struct bitstream* bs, size_t new_pos) {
|
|
bs->pos = (new_pos / 32) * 32;
|
|
bs->shift = 8;
|
|
bs->value = 0;
|
|
bs_get(bs, new_pos % 32);
|
|
}
|
|
|
|
uint32_t bs_peek(struct bitstream* bs, int n) {
|
|
struct bitstream bak = *bs;
|
|
return bs_get(&bak, n);
|
|
}
|
|
|
|
size_t bs_remain(struct bitstream* bs) {
|
|
return bs->size - bs->pos;
|
|
}
|
|
|
|
int bs_eof(struct bitstream* bs) {
|
|
return bs_remain(bs) == 0;
|
|
}
|
|
|
|
uint32_t bs_ue(struct bitstream* bs) {
|
|
static const uint8_t exp_golomb_bits[256] = {
|
|
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
|
|
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
};
|
|
uint32_t bits, read = 0;
|
|
int bits_left;
|
|
uint8_t coded;
|
|
int done = 0;
|
|
bits = 0;
|
|
// we want to read 8 bits at a time - if we don't have 8 bits,
|
|
// read what's left, and shift. The exp_golomb_bits calc remains the
|
|
// same.
|
|
while (!done) {
|
|
bits_left = bs_remain(bs);
|
|
if (bits_left < 8) {
|
|
read = bs_peek(bs, bits_left) << (8 - bits_left);
|
|
done = 1;
|
|
} else {
|
|
read = bs_peek(bs, 8);
|
|
if (read == 0) {
|
|
bs_get(bs, 8);
|
|
bits += 8;
|
|
} else {
|
|
done = 1;
|
|
}
|
|
}
|
|
}
|
|
coded = exp_golomb_bits[read];
|
|
bs_get(bs, coded);
|
|
bits += coded;
|
|
|
|
// printf("ue - bits %d\n", bits);
|
|
return bs_get(bs, bits + 1) - 1;
|
|
}
|
|
|
|
int32_t bs_se(struct bitstream* bs) {
|
|
uint32_t ret;
|
|
ret = bs_ue(bs);
|
|
if ((ret & 0x1) == 0) {
|
|
ret >>= 1;
|
|
int32_t temp = 0 - ret;
|
|
return temp;
|
|
}
|
|
return (ret + 1) >> 1;
|
|
}
|
|
|