/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description:
*
*/
/**************************************************************************
nok_bits2.c - Bitstream subroutines.
Author(s): Juha Ojanpera
Copyright (c) 1999-2003 by Nokia Research Center, Speech and Audio Systems.
*************************************************************************/
/**************************************************************************
External Objects Needed
*************************************************************************/
/*-- Project Headers --*/
#include "nok_bits.h"
/**************************************************************************
Internal Objects
*************************************************************************/
#ifdef USE_ASSERT
#define BITSASSERT(x) { \
MY_ASSERT(UpdateBufIdx(bs) == 1); \
}
#else
#define BITSASSERT(x) { \
UpdateBufIdx(bs); \
}
#endif
//typedef uint32 (*GETBITS_FUNCTION)(BitStream *bs, int16 n);
const uint32 bitMask[] =
{0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF,
0x1FFFL, 0x3FFFL, 0x7FFFL, 0xFFFFL, 0x1FFFFL, 0x3FFFFL, 0x7FFFFL, 0xFFFFFL,
0x1FFFFFL, 0x3FFFFFL, 0x7FFFFFL, 0xFFFFFFL, 0x1FFFFFFL, 0x3FFFFFFL, 0x7FFFFFFL,
0xFFFFFFFL, 0x1FFFFFFFL, 0x3FFFFFFFL, 0x7FFFFFFFL, 0xFFFFFFFFL};
/*
* Updates the read index of the bit buffer.
*/
static INLINE int16
UpdateBufIdx(TBitStream *bs)
{
bs->buf_index++;
bs->buf_index = MOD_OPCODE(bs->buf_index, bs->buf_mask);
bs->slots_read++;
#if 0
if(bs->slots_read == bs->buf_len)
return (0);
#endif
return (1);
}
/*
* Writes at most 8 bits to the bit buffer.
*/
void
PutBits(TBitStream *bs, uint16 n, uint32 word)
{
uint8 *buf = (bs->mode == BIT8) ? bs->bit_buffer : bs->dsp_buffer;
/*
* The number of bits left in the current buffer slot is too low.
* Therefore, the input word needs to be splitted into two parts.
* Each part is stored separately.
*/
int16 tmp = bs->bit_counter - n;
if(tmp < 0)
{
/*-- Zero those bits that are to be modified. --*/
buf[bs->buf_index] &= ~bitMask[bs->bit_counter];
/*-- Store the upper (MSB) part to the bitstream buffer. --*/
tmp = -tmp;
buf[bs->buf_index] |= (word >> tmp);
/*
* Explicitly update the bitstream buffer index. No need to
* test whether the bit counter is zero since it is known
* to be zero at this point.
*/
BITSASSERT(bs);
bs->bit_counter = bs->slotBits;
/*-- Store the lower (LSB) part to the bitstream buffer. --*/
bs->bit_counter = int16(bs->bit_counter - tmp);
buf[bs->buf_index] &= bitMask[bs->bit_counter];
buf[bs->buf_index] |= ((word & bitMask[tmp]) << bs->bit_counter);
}
else
{
/*
* Obtain the bit mask for the part that is to be modified. For example,
* 'bit_counter' = 5
* 'n' = 3,
* 'tmp' = 2
*
* x x x m m m x x (x = ignore, m = bits to be modified)
*
* mask :
*
* 1 1 1 0 0 0 1 1
*
*/
buf[bs->buf_index] &= (~bitMask[bs->bit_counter]) | bitMask[tmp];
bs->bit_counter = tmp;
buf[bs->buf_index] |= (word << bs->bit_counter);
}
/*-- Update the bitstream buffer index. --*/
if(bs->bit_counter == 0)
{
BITSASSERT(bs);
bs->bit_counter = bs->slotBits;
}
}
/*
* Reads at most 8 bits from the bit buffer.
*/
uint32
GetBits(TBitStream *bs, int16 n)
{
int16 idx;
uint32 tmp;
idx = bs->bit_counter - n;
if(idx < 0)
{
/* Mask the unwanted bits to zero. */
tmp = (bs->bit_buffer[bs->buf_index] & bitMask[bs->bit_counter]) << -idx;
/* Update the bitstream buffer. */
BITSASSERT(bs);
bs->bit_counter = bs->slotBits + idx;
tmp |= (bs->bit_buffer[bs->buf_index] >> bs->bit_counter) & bitMask[-idx];
}
else
{
bs->bit_counter = idx;
tmp = (bs->bit_buffer[bs->buf_index] >> bs->bit_counter) & bitMask[n];
}
/* Update the bitstream buffer index. */
if(bs->bit_counter == 0)
{
BITSASSERT(bs);
bs->bit_counter = bs->slotBits;
}
return (tmp);
}
/*
* Reads at most 16 bits from the bit buffer.
*/
uint32
GetBitsDSP(TBitStream *bs, int16 n)
{
int16 idx;
uint32 tmp;
idx = bs->bit_counter - n;
if(idx < 0)
{
/* Mask the unwanted bits to zero. */
tmp = (bs->dsp_buffer[bs->buf_index] & bitMask[bs->bit_counter]) << -idx;
/* Update the bitstream buffer. */
BITSASSERT(bs);
bs->bit_counter = bs->slotBits + idx;
tmp |= (bs->dsp_buffer[bs->buf_index] >> bs->bit_counter) & bitMask[-idx];
}
else
{
bs->bit_counter = idx;
tmp = (bs->dsp_buffer[bs->buf_index] >> bs->bit_counter) & bitMask[n];
}
/* Update the bitstream buffer index. */
if(bs->bit_counter == 0)
{
BITSASSERT(bs);
bs->bit_counter = bs->slotBits;
}
return (tmp);
}
//typedef uint32 (*GETBITS_FUNCTION)(BitStream *bs, int16 n);
//static GETBITS_FUNCTION GetFunc[2] = {GetBits, GetBitsDSP};
/*
* Returns the size of the buffer.
*/
EXPORT_C uint32 BsGetBufSize(TBitStream *bs)
{ return (bs->buf_len); }
/*
* Returns the size of the original buffer. Note that it is
* possible that the update procedure of the bit buffer
* (which is up to the implementor to specify), reduces the size
* temporarily for some reasons.
*/
EXPORT_C uint32 BsGetBufOriginalSize(TBitStream *bs)
{
#ifndef BITSMODULO_BUFFER
return (bs->buf_mask + 1);
#else
return (bs->buf_mask);
#endif
}
/*
* Returns the number of bits read.
*/
EXPORT_C uint32 BsGetBitsRead(TBitStream *bs)
{ return (bs->bits_read); }
/*
* Increments the value that describes how many
* bits are read from the bitstream.
*/
EXPORT_C void BsSetBitsRead(TBitStream *bs, uint32 bits_read)
{ bs->bits_read += bits_read; }
/*
* Clears the value that describes how many
* bits are read from the bitstream.
*/
EXPORT_C void BsClearBitsRead(TBitStream *bs)
{ bs->bits_read = 0; }
/*
* Returns the number of unread elements in the bit buffer.
*/
EXPORT_C uint32 BsSlotsLeft(TBitStream *bs)
{ return ((bs->buf_len < bs->slots_read) ? 0 : bs->buf_len - bs->slots_read); }
/*
* Resets the bitstream.
*/
EXPORT_C void BsReset(TBitStream *bs)
{
bs->buf_index = 0;
bs->buf_writeIndex = 0;
bs->bit_counter = bs->slotBits;
bs->slots_read = 0;
bs->bits_read = 0;
}
/*
* Updates the bitstream values according to the given input parameter.
*/
EXPORT_C void BsBufferUpdate(TBitStream *bs, int32 bytesRead)
{
int32 diff = bs->bits_read - (bytesRead << 3);
bs->buf_len = (bs->buf_len - bs->slots_read) + bytesRead;
bs->slots_read = 0;
if(diff < 0)
bs->bits_read = -diff;
else
bs->bits_read = diff;
}
/**************************************************************************
Title : BsInit
Purpose : Initializes the bit buffer.
Usage : BsInit(bs, bit_buffer, size)
Input : bs - bitstream structure
bit_buffer - address of bit buffer
size - size of buffer
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C void
BsInit(TBitStream *bs, uint8 *bit_buffer, uint32 size)
{
bs->dsp_buffer = NULL;
bs->bit_buffer = bit_buffer;
bs->mode = BIT8;
#ifndef BITSMODULO_BUFFER
bs->buf_mask = size - 1;
#else
bs->buf_mask = size;
#endif
bs->buf_len = size;
bs->slotBits = sizeof(uint8) << 3;
BsReset(bs);
}
void
BsInit2(TBitStream *bs, DSP_BYTE *dsp_buffer, uint32 size)
{
bs->dsp_buffer = dsp_buffer;
bs->bit_buffer = NULL;
bs->mode = BIT16;
#ifndef BITSMODULO_BUFFER
bs->buf_mask = size - 1;
#else
bs->buf_mask = size;
#endif
bs->buf_len = size;
bs->slotBits = sizeof(DSP_BYTE) << 3;
BsReset(bs);
}
/**************************************************************************
Title : BsByteAlign
Purpose : Byte aligns the bit counter of the buffer.
Usage : y = BsByteAlign(bs)
Input : bs - bitstream parameters
Output : y - # of bits read
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C int16
BsByteAlign(TBitStream *bs)
{
int16 bits_to_byte_align;
bits_to_byte_align = bs->bit_counter & 7;
if(bits_to_byte_align)
BsSkipBits(bs, bits_to_byte_align);
return (bits_to_byte_align);
}
/**************************************************************************
Title : BsLookAhead
Purpose : Looks ahead for the next 'n' bits from the bit buffer and
returns the read 'n' bits.
Usage : y = BsLookAhead(bs, n)
Input : bs - bitstream parameters
n - number of bits to be read from the bit buffer
Output : y - bits read
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C uint32
BsLookAhead(TBitStream *bs, int16 n)
{
TBitStream bs_tmp;
uint32 dword;
/*-- Save the current state. --*/
COPY_MEMORY(&bs_tmp, bs, sizeof(TBitStream));
dword = BsGetBits(bs, n);
/*-- Restore the original state. --*/
COPY_MEMORY(bs, &bs_tmp, sizeof(TBitStream));
return (dword);
}
/**************************************************************************
Title : BsPutBits
Purpose : Writes bits to the bit buffer.
Usage : BsPutBits(bs, n, word);
Input : bs - bitstream parameters
n - number of bits to write
word - bits to write
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C void
BsPutBits(TBitStream *bs, int16 n, uint32 word)
{
int16 rbits;
BsSetBitsRead(bs, n);
/*-- Mask the unwanted bits to zero, just for safety. --*/
word &= bitMask[n];
while(n)
{
rbits = (n > (int16)bs->slotBits) ? bs->slotBits : n;
n -= rbits;
PutBits(bs, rbits, ((word >> n) & bitMask[rbits]));
}
}
/**************************************************************************
Title : BsPutBitsByteAlign
Purpose : Byte aligns the write buffer.
Usage : y = BsPutBitsByteAlign(bs)
Input : bs - bitstream parameters
Output : y - # of bits written
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C int16
BsPutBitsByteAlign(TBitStream *bs)
{
int16 bits_to_byte_align;
bits_to_byte_align = bs->bit_counter & 7;
if(bits_to_byte_align)
BsPutBits(bs, bits_to_byte_align, 0);
return (bits_to_byte_align);
}
/**************************************************************************
Title : BsGetBits
Purpose : Reads bits from the bit buffer.
Usage : y = BsGetBits(bs, n);
Input : bs - bitstream parameters
n - number of bits to be read
Output : y - bits read
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C uint32
BsGetBits(TBitStream *bs, int16 n)
{
int16 rbits = 0;
uint32 value = 0;
BsSetBitsRead(bs, n);
while(n)
{
rbits = (n > (int16)bs->slotBits) ? bs->slotBits : n;
value <<= rbits;
// modified by Ali Ahmaniemi 7.6.04
if (bs->mode == BIT8)
{
value |= GetBits(bs, rbits);
}
else
{
value |= GetBitsDSP(bs, rbits);
}
//value |= GetFunc[bs->mode](bs, rbits);
n -= rbits;
}
return (value);
}
/**************************************************************************
Title : BsSkipBits
Purpose : Advances the bit buffer index.
Usage : BsSkipBits(bs, n);
Input : bs - bitstream parameters
n - number of bits to be discarded
Explanation : The maximum number of bits that can be discarded is 'bs->slotBits'.
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C void
BsSkipBits(TBitStream *bs, int16 n)
{
int16 idx;
#ifdef USE_ASSERT
MY_ASSERT(n < ((int16)bs->slotBits + 1));
#endif
BsSetBitsRead(bs, n);
idx = bs->bit_counter - n;
if(idx < 0)
{
BITSASSERT(bs);
bs->bit_counter = bs->slotBits + idx;
}
else
bs->bit_counter = idx;
if(bs->bit_counter == 0)
{
BITSASSERT(bs);
bs->bit_counter = bs->slotBits;
}
}
/**************************************************************************
Title : BsSkipNbits
Purpose : Same as 'BsSkipBits' with the exception that the number
of bits to be discarded can be of any value.
Usage : BsSkipNbits(bs, n);
Input : bs - bitstream parameters
n - number of bits to be discarded
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C void
BsSkipNBits(TBitStream *bs, int32 n)
{
int32 slots, bits_left, scale;
#ifdef BYTE_16bit
scale = (bs->mode == BIT8) ? 3 : 4;
#else
scale = 3;
#endif
slots = (n >> scale);
BsSetBitsRead(bs, slots << scale);
bs->buf_index += slots;
bs->buf_index = MOD_OPCODE(bs->buf_index, bs->buf_mask);
bs->slots_read += slots;
bits_left = n - (slots << scale);
if(bits_left)
BsSkipBits(bs, (int16) bits_left);
}
/**************************************************************************
Title : BsCopyBytes
Purpose : Copies 'bytesToCopy' bytes from the bit buffer (starting from
the current read index) to the specified output buffer.
Usage : y = BsCopyBytes(bs, outBuf, bytesToCopy)
Input : bs - bitstream to be copied
bytesToCopy - # of bytes to copy
Output : y - # of bytes copied
outBuf - copied bytes
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C uint32
BsCopyBytes(TBitStream *bs, uint8 *outBuf, uint32 bytesToCopy)
{
uint32 i;
uint8 *buf0 = (bs->mode == BIT8) ? bs->bit_buffer : bs->dsp_buffer;
for(i = bs->buf_index; i < (bytesToCopy + bs->buf_index); i++, outBuf++)
*outBuf = buf0[MOD_OPCODE(i, bs->buf_mask)];
return (i - bs->buf_index);
}
/**************************************************************************
Title : BsCopyBits
Purpose : Copies 'bitsToCopy' bits from the source bit buffer (starting from
the current read index) to the specified destination bit buffer.
Usage : y = BsCopyBits(bsSrc, bsDst, bitsToCopy)
Input : bsSrc - source bit buffer
bytesToCopy - # of bits to copy
Output : bsDst - destination bit buffer
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C void
BsCopyBits(TBitStream *bsSrc, TBitStream *bsDst, int32 bitsToCopy)
{
int32 i, nBytes;
nBytes = bitsToCopy >> 3;
for(i = 0; i < nBytes; i++)
BsPutBits(bsDst, 8, BsGetBits(bsSrc, 8));
i = bitsToCopy - (i << 3);
if(i > 0) BsPutBits(bsDst, (int16) i, BsGetBits(bsSrc, (uint16) i));
}
/**************************************************************************
Title : BsRewindNBits
Purpose : Rewinds the bit buffer 'nBits' bits.
Usage : BsRewindNbits(br, nBits)
Input : br - bitstream parameters
nBits - number of bits to rewind
Author(s) : Juha Ojanpera
*************************************************************************/
EXPORT_C void
BsRewindNBits(TBitStream *bs, uint32 nBits)
{
int32 tmp;
int16 new_buf_idx, new_bit_idx;
new_buf_idx = (int16) (nBits / bs->slotBits);
new_bit_idx = (int16) (nBits % bs->slotBits);
tmp = bs->bit_counter + new_bit_idx;
if(tmp > (int16)bs->slotBits)
{
new_buf_idx++;
bs->bit_counter = tmp - bs->slotBits;
}
else
bs->bit_counter += new_bit_idx;
bs->buf_index = MOD_OPCODE(bs->buf_index, bs->buf_mask);
tmp = bs->buf_index - new_buf_idx;
if(tmp > 0)
bs->buf_index = tmp;
else
bs->buf_index = MOD_OPCODE(bs->buf_len + tmp, bs->buf_mask);
bs->bits_read -= nBits;
}
EXPORT_C void
BsSaveBufState(TBitStream *bsSrc, TBitStream *bsDst)
{
COPY_MEMORY(bsDst, bsSrc, sizeof(TBitStream));
}