/**
libsmacker - A C library for decoding .smk Smacker Video files
Copyright (C) 2012-2017 Greg Kennedy
See smacker.h for more information.
smk_bitstream.c
Implements a bitstream structure, which can extract and
return a bit at a time from a raw block of bytes.
*/
#include "smk_bitstream.h"
/* malloc and friends */
#include "smk_malloc.h"
/*
Bitstream structure
Pointer to raw block of data and a size limit.
Maintains internal pointers to byte_num and bit_number.
*/
struct smk_bit_t
{
const unsigned char* buffer;
unsigned long size;
unsigned long byte_num;
char bit_num;
};
/* BITSTREAM Functions */
struct smk_bit_t* smk_bs_init(const unsigned char* b, const unsigned long size)
{
struct smk_bit_t* ret = NULL;
/* sanity check */
smk_assert(b);
/* allocate a bitstream struct */
smk_malloc(ret, sizeof(struct smk_bit_t));
/* set up the pointer to bitstream, and the size counter */
ret->buffer = b;
ret->size = size;
/* point to initial byte: note, smk_malloc already sets these to 0 */
/* ret->byte_num = 0;
ret->bit_num = 0; */
/* return ret or NULL if error : ) */
error:
return ret;
}
/* Reads a bit
Returns -1 if error encountered */
char _smk_bs_read_1(struct smk_bit_t* bs)
{
unsigned char ret = -1;
/* sanity check */
smk_assert(bs);
/* don't die when running out of bits, but signal */
if (bs->byte_num >= bs->size)
{
fprintf(stderr
, "libsmacker::_smk_bs_read_1(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs
->size
);
goto error;
}
/* get next bit and return */
ret = (((bs->buffer[bs->byte_num]) & (1 << bs->bit_num)) != 0);
/* advance to next bit */
bs->bit_num ++;
/* Out of bits in this byte: next! */
if (bs->bit_num > 7)
{
bs->byte_num ++;
bs->bit_num = 0;
}
/* return ret, or (default) -1 if error */
error:
return ret;
}
/* Reads a byte
Returns -1 if error. */
short _smk_bs_read_8(struct smk_bit_t* bs)
{
unsigned char ret = -1;
/* sanity check */
smk_assert(bs);
/* don't die when running out of bits, but signal */
if (bs->byte_num + (bs->bit_num > 0) >= bs->size)
{
fprintf(stderr
, "libsmacker::_smk_bs_read_8(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs
->size
);
goto error;
}
if (bs->bit_num)
{
/* unaligned read */
ret = bs->buffer[bs->byte_num] >> bs->bit_num;
bs->byte_num ++;
ret |= (bs->buffer[bs->byte_num] << (8 - bs->bit_num));
} else {
/* aligned read */
ret = bs->buffer[bs->byte_num ++];
}
/* return ret, or (default) -1 if error */
error:
return ret;
}