/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: bitstream.c,v 1.2 2005/09/27 20:31:11 jrecker Exp $ * * Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ /************************************************************************************** * Fixed-point HE-AAC decoder * Jon Recker (jrecker@real.com) * February 2005 * * bitstream.c - bitstream parsing functions **************************************************************************************/ #include "bitstream.h" /************************************************************************************** * Function: SetBitstreamPointer * * Description: initialize bitstream reader * * Inputs: pointer to BitStreamInfo struct * number of bytes in bitstream * pointer to byte-aligned buffer of data to read from * * Outputs: initialized bitstream info struct * * Return: none **************************************************************************************/ void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf) { /* init bitstream */ bsi->bytePtr = buf; bsi->iCache = 0; /* 4-byte unsigned int */ bsi->cachedBits = 0; /* i.e. zero bits in cache */ bsi->nBytes = nBytes; } /************************************************************************************** * Function: RefillBitstreamCache * * Description: read new data from bitstream buffer into 32-bit cache * * Inputs: pointer to initialized BitStreamInfo struct * * Outputs: updated bitstream info struct * * Return: none * * Notes: only call when iCache is completely drained (resets bitOffset to 0) * always loads 4 new bytes except when bsi->nBytes < 4 (end of buffer) * stores data as big-endian in cache, regardless of machine endian-ness **************************************************************************************/ //Optimized for REV16, REV32 (FB) static __inline void RefillBitstreamCache(BitStreamInfo *bsi) { int nBytes = bsi->nBytes; if (nBytes >= 4) { /* optimize for common case, independent of machine endian-ness */ bsi->iCache = (*bsi->bytePtr++) << 24; bsi->iCache |= (*bsi->bytePtr++) << 16; bsi->iCache |= (*bsi->bytePtr++) << 8; bsi->iCache |= (*bsi->bytePtr++); bsi->cachedBits = 32; bsi->nBytes -= 4; } else { bsi->iCache = 0; while (nBytes--) { bsi->iCache |= (*bsi->bytePtr++); bsi->iCache <<= 8; } bsi->iCache <<= ((3 - bsi->nBytes)*8); bsi->cachedBits = 8*bsi->nBytes; bsi->nBytes = 0; } } /************************************************************************************** * Function: GetBits * * Description: get bits from bitstream, advance bitstream pointer * * Inputs: pointer to initialized BitStreamInfo struct * number of bits to get from bitstream * * Outputs: updated bitstream info struct * * Return: the next nBits bits of data from bitstream buffer * * Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f * for speed, does not indicate error if you overrun bit buffer * if nBits == 0, returns 0 **************************************************************************************/ unsigned int GetBits(BitStreamInfo *bsi, int nBits) { unsigned int data, lowBits; nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */ data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */ data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */ bsi->iCache <<= nBits; /* left-justify cache */ bsi->cachedBits -= nBits; /* how many bits have we drawn from the cache so far */ /* if we cross an int boundary, refill the cache */ if (bsi->cachedBits < 0) { lowBits = -bsi->cachedBits; RefillBitstreamCache(bsi); data |= bsi->iCache >> (32 - lowBits); /* get the low-order bits */ bsi->cachedBits -= lowBits; /* how many bits have we drawn from the cache so far */ bsi->iCache <<= lowBits; /* left-justify cache */ } return data; } /************************************************************************************** * Function: GetBitsNoAdvance * * Description: get bits from bitstream, do not advance bitstream pointer * * Inputs: pointer to initialized BitStreamInfo struct * number of bits to get from bitstream * * Outputs: none (state of BitStreamInfo struct left unchanged) * * Return: the next nBits bits of data from bitstream buffer * * Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f * for speed, does not indicate error if you overrun bit buffer * if nBits == 0, returns 0 **************************************************************************************/ unsigned int GetBitsNoAdvance(BitStreamInfo *bsi, int nBits) { unsigned char *buf; unsigned int data, iCache; signed int lowBits; nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */ data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */ data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */ lowBits = nBits - bsi->cachedBits; /* how many bits do we have left to read */ /* if we cross an int boundary, read next bytes in buffer */ if (lowBits > 0) { iCache = 0; buf = bsi->bytePtr; while (lowBits > 0) { iCache <<= 8; if (buf < bsi->bytePtr + bsi->nBytes) iCache |= (unsigned int)*buf++; lowBits -= 8; } lowBits = -lowBits; data |= iCache >> lowBits; } return data; } /************************************************************************************** * Function: AdvanceBitstream * * Description: move bitstream pointer ahead * * Inputs: pointer to initialized BitStreamInfo struct * number of bits to advance bitstream * * Outputs: updated bitstream info struct * * Return: none * * Notes: generally used following GetBitsNoAdvance(bsi, maxBits) **************************************************************************************/ void AdvanceBitstream(BitStreamInfo *bsi, int nBits) { nBits &= 0x1f; if (nBits > bsi->cachedBits) { nBits -= bsi->cachedBits; RefillBitstreamCache(bsi); } bsi->iCache <<= nBits; bsi->cachedBits -= nBits; } /************************************************************************************** * Function: CalcBitsUsed * * Description: calculate how many bits have been read from bitstream * * Inputs: pointer to initialized BitStreamInfo struct * pointer to start of bitstream buffer * bit offset into first byte of startBuf (0-7) * * Outputs: none * * Return: number of bits read from bitstream, as offset from startBuf:startOffset **************************************************************************************/ int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset) { int bitsUsed; bitsUsed = (bsi->bytePtr - startBuf) * 8; bitsUsed -= bsi->cachedBits; bitsUsed -= startOffset; return bitsUsed; } /************************************************************************************** * Function: ByteAlignBitstream * * Description: bump bitstream pointer to start of next byte * * Inputs: pointer to initialized BitStreamInfo struct * * Outputs: byte-aligned bitstream BitStreamInfo struct * * Return: none * * Notes: if bitstream is already byte-aligned, do nothing **************************************************************************************/ void ByteAlignBitstream(BitStreamInfo *bsi) { int offset; offset = bsi->cachedBits & 0x07; AdvanceBitstream(bsi, offset); }