📄 bitbuffer.c
字号:
/*COPYRIGHT, LICENSE AND WARRANTY INFORMATIONThis software module has been originally developed by Nokia Corporation. Provided that a person, entity or a company willing to use the Software (hereinafter Licensee) comply with all the terms and conditions of this Statement and subject to the limitations set forth in this Statement Nokia grants to such Licensee a non-exclusive, sub-licensable, worldwide, limited license under copyrights owned by Nokia to use the Software for the sole purpose of creating, manufacturing, selling, marketing, or distributing (including the right to make modifications to the Software) a fully compliant decoder implementation (hereinafter "Decoder") of ITU-T Recommendation H.264 / ISO/IEC International Standard 14496-10 and an encoder implementation producing output that is decodable with the Decoder.Nokia retains the ownership of copyrights to the Software. There is no patent nor other intellectual property right of Nokia licensed under this Statement (except the copyright license above). Licensee hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if patent licenses are required, it is their responsibility to acquire the license before utilizing the Software.The license by Nokia is subject to that the Licensee grants to Nokia the non-exclusive, worldwide, royalty-free, perpetual and irrevocable covenant that the Licensee(s) shall not bring a suit before any court or administrative agency or otherwise assert a claim for infringement under the Licensee intellectual property rights that, but for a license, would be infringed by the Software against (a) Nokia or Nokia's Affiliate; or (b) other recipient of a license and covenant not to sue with respect to the Software from Nokia; or (c) contractor, customer or distributor of a party listed above in a or b, which suit or claim is related to the Software or use thereof.The Licensee(s) further agrees to grant a reciprocal license to Nokia (as granted by Nokia to the Licensee(s) on the modifications made by Licensee(s) to the Software. THE SOFTWARE IS PROVIDED "AS IS" AND THE ORIGINAL DEVELOPER DISCLAIMS ANY AND ALL WARRANTIES WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. THOSE INTENDING TO USE THE SOFTWARE ARE EXPRESSLY ADVISED THAT ITS USE MAY INFRINGE EXISTING PATENTS AND BE SUBJECT TO ROYALTY PAYMENTS TO PATENT OWNERS. ANYONE USING THE SOFTWARE ON THE BASIS OF THIS LICENSE AGREES TO OBTAIN THE NECESSARY PERMISSIONS FROM ANY AND ALL APPLICABLE PATENT OWNERS FOR SUCH USE.IN NO EVENT SHALL THE ORIGINAL DEVELOPER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.This copyright, license and warranty information notice must be retained in all copies and derivative works of the Software or substantial portions thereof.*/#include <string.h>#include "nccglob.h"#include "globals.h"#include "debug.h"#include "bitbuffer.h"/* * Static functions */static int removeStartCodeEmulationBytes(bitbuffer_s *bitbuf);/* * * bibOpen: * * Parameters: * * Function: * Open bitbuffer * * Returns: * Pointer to bitbuffer object or NULL for allocation failure. * */bitbuffer_s *bibOpen(){ bitbuffer_s *bitbuf; bitbuf = (bitbuffer_s *)nccMalloc(sizeof(bitbuffer_s)); if (bitbuf != NULL) memset(bitbuf, 0, sizeof(bitbuffer_s)); return bitbuf;}/* * * bibInit: * * Parameters: * bitbuf Bitbuffer object * streamBytes Pointer to data * length Data length in bytes * * Function: * Initialize bitbuffer * * Returns: * BIB_ok for ok, BIB_ERROR for error * */int bibInit(bitbuffer_s *bitbuf, u_int8 *streamBytes, int length){ bitbuf->data = streamBytes; bitbuf->dataLen = length; bitbuf->bytePos = 0; bitbuf->bitpos = 0; bitbuf->errorStatus = BIB_OK; if (removeStartCodeEmulationBytes(bitbuf) < 0) return BIB_ERROR; return BIB_OK;}/* * * bibClose: * * Parameters: * bitbuf Bitbuffer object * * Function: * Close bitbuffer * * Returns: * - * */void bibClose(bitbuffer_s *bitbuf){ nccFree(bitbuf);}/* * * removeStartCodeEmulationBytes: * * Parameters: * bitbuf Bitbuffer object * * Function: * Remove start code emulation bytes from the bitbuffer * * Returns: * - * */static int removeStartCodeEmulationBytes(bitbuffer_s *bitbuf){ int i; int j; int numZero; int32 lastBytes; /* * Skip the start code if it exists */ numZero = 0; i = 0; while (i < bitbuf->dataLen) { if (bitbuf->data[i] == 0) numZero++; else if (numZero > 1 && bitbuf->data[i] == 1) { /* Start code found */ i++; break; } else { /* No start code found */ i = 0; break; } i++; } /* * Convert EBSP to RBSP. Note that the nal head byte is kept within the buffer */ lastBytes = 0xffffffff; j = 0; while (i < bitbuf->dataLen) { lastBytes = (lastBytes << 8) | bitbuf->data[i]; if ((lastBytes & 0xffffff) != 0x000003) { bitbuf->data[j] = bitbuf->data[i]; j++; } i++; } bitbuf->dataLen = j; return BIB_OK;}/* * * bibGetBitFunc: * * Parameters: * bitbuf Bitbuffer object * * Function: * Get next bit from bitbuffer. * * Returns: * Next bit in bitbuffer or BIB_ERR_NO_BITS if no bits left. * */int bibGetBitFunc(bitbuffer_s *bitbuf){ /* If there are no bits left in buffer return an error */ if (bitbuf->bitpos == 0 && bitbuf->bytePos >= bitbuf->dataLen) { deb0f(stderr, "Error: unexpected end of bitbuffer\n"); bitbuf->errorStatus = BIB_ERR_NO_BITS; return 0; } /* Fill bitbuf->currentBits with bits */ while (bitbuf->bitpos <= 24 && bitbuf->bytePos < bitbuf->dataLen) { bitbuf->currentBits = (bitbuf->currentBits << 8) | bitbuf->data[bitbuf->bytePos++]; bitbuf->bitpos += 8; } /* Return bit */ bitbuf->bitpos--; return (bitbuf->currentBits >> bitbuf->bitpos) & 1;}/* * * bibGetBitsFunc: * * Parameters: * bitbuf Bitbuffer object * n Number of bits requested * * Function: * Get next n bits from bitbuffer. * * NOTE: maximum of 24 bits can be fetched * * Returns: * Next n bits from bitbuffer * */int32 bibGetBitsFunc(bitbuffer_s *bitbuf, int n){ /* Fill bitbuf->currentBits with bits */ while (n > bitbuf->bitpos && bitbuf->bytePos < bitbuf->dataLen) { bitbuf->currentBits = (bitbuf->currentBits << 8) | bitbuf->data[bitbuf->bytePos++]; bitbuf->bitpos += 8; } /* If there are not enought bits there was an error */ if (n > bitbuf->bitpos) { deb0f(stderr, "Error: unexpected end of bitbuffer\n"); bitbuf->errorStatus = BIB_ERR_NO_BITS; return 0; } /* Return bits */ bitbuf->bitpos -= n; return (bitbuf->currentBits >> (bitbuf->bitpos)) & ~(((u_int32)-1)<<n);}/* * * bibShowBitsFunc: * * Parameters: * bitbuf Bitbuffer object * n Number of bits requested * * Function: * Get next n bits from bitbuffer without advancing bitbuffer pointer. * This function will not failt even if there are not enough bits in * the bitbuffer. * * NOTE: maximum of 24 bits can be fetched * * Returns: * Next n bits of bitbuffer * */int32 bibShowBitsFunc(bitbuffer_s *bitbuf, int n){ /* Fill bitbuf->currentBits with bits */ while (n > bitbuf->bitpos && bitbuf->bytePos < bitbuf->dataLen) { bitbuf->currentBits = (bitbuf->currentBits << 8) | bitbuf->data[bitbuf->bytePos++]; bitbuf->bitpos += 8; } /* Check if there are enought bits in currentBits */ if (n <= bitbuf->bitpos) /* Return bits normally */ return (bitbuf->currentBits >> (bitbuf->bitpos-n)) & ~(((u_int32)-1)<<n); else /* Return bits padded with zero bits */ return (bitbuf->currentBits << (n-bitbuf->bitpos)) & ~(((u_int32)-1)<<n);}/* * * bibSkipBitsFunc: * * Parameters: * bitbuf Bitbuffer object * n Number of bits to skip * * Function: * Skip next n bits in the bitbuffer * * Returns: * BIB_OK for no error and BIB_ERR_NO_BITS for end of buffer. * */int bibSkipBitsFunc(bitbuffer_s *bitbuf, int n){ /* Fill bitbuf->currentBits with bits */ while (n > bitbuf->bitpos && bitbuf->bytePos < bitbuf->dataLen) { bitbuf->currentBits = (bitbuf->currentBits << 8) | bitbuf->data[bitbuf->bytePos++]; bitbuf->bitpos += 8; } bitbuf->bitpos -= n; /* Check for buffer underrun */ if (bitbuf->bitpos < 0) { deb0f(stderr, "Error: unexpected end of bitbuffer\n"); bitbuf->errorStatus = BIB_ERR_NO_BITS; return BIB_ERR_NO_BITS; } return BIB_OK;}/* * * bibGetByte: * * Parameters: * bitbuf Bitbuffer object * byteRet Return pointer for byte * * Function: * Get next byte aligned byte from bitbuffer. * * Returns: * 1 for End Of Stream, 0 otherwise * */int bibGetByte(bitbuffer_s *bitbuf, int *byteRet){ if (bitbuf->bitpos >= 8) { bitbuf->bitpos = bitbuf->bitpos & ~7; *byteRet = (bitbuf->currentBits >> (bitbuf->bitpos - 8)) & 0xff; bitbuf->bitpos -= 8; } else { bitbuf->bitpos = 0; if (bitbuf->bytePos >= bitbuf->dataLen) { return 1; } *byteRet = bitbuf->data[bitbuf->bytePos++]; } return 0;}/* * * bibByteAlign: * * Parameters: * bitbuf Bitbuffer object * * Function: * Set bitbuffer pointer to next byte aligned position. * * Returns: * Number of bits skipped as a result of aligning. * */int bibByteAlign(bitbuffer_s *bitbuf){ int bitpos = bitbuf->bitpos; bitbuf->bitpos = bitbuf->bitpos & ~7; return (bitpos - bitbuf->bitpos);}/* * bibSkipTrailingBits: * * Parameters: * bitbuf Bitbuffer object * * Function: * Skip the trailing bits at the end of a NAL unit * * Returns: * The number of bits being skipped or <0 for error. */int bibSkipTrailingBits(bitbuffer_s *bitbuf){ int ret; int len = 0; int bit = 0; bit = bibGetBitFunc(bitbuf); len++; ret = bibGetStatus(bitbuf); if (ret < 0) return ret; /* First we expect to receive 1 bit */ if (bit != 1) { deb0f(stderr, "Error: Unexpected trailing bit (0).\n"); bibRaiseError(bitbuf, BIB_INCORRECT_TRAILING_BIT); return BIB_INCORRECT_TRAILING_BIT; } /* Remaining bits in current byte should be zero */ while ( bitbuf->bitpos % 8 != 0 ) { bibGetBit(bitbuf, &bit); len++; if (bit != 0) { deb0f(stderr, "Error: Unexpected trailing bit (1).\n"); bibRaiseError(bitbuf, BIB_INCORRECT_TRAILING_BIT); return BIB_INCORRECT_TRAILING_BIT; } } ret = bibGetStatus(bitbuf); if (ret < 0) return ret; return len;}/* * bibMoreRbspData: * * Parameters: * bitbuf Bitbuffer object * * Function: * Check if there is more RBSP data in the bitbuffer. * * Returns: * 0: no more rbsp data * 1: more rbsp data */int bibMoreRbspData(bitbuffer_s *bitbuf){ int numBytesLeft; u_int32 lastBits; numBytesLeft = bitbuf->dataLen - bitbuf->bytePos; if (numBytesLeft >= 2 || (numBytesLeft*8 + bitbuf->bitpos >= 9)) /* If there are at least 9 bits left, it is certain to have more rbsp data */ return 1; if (numBytesLeft == 0 && bitbuf->bitpos == 0) /* Something may be wrong. Normally, there should be at least one bit left */ return 0; if (numBytesLeft == 1) { /* Insert last byte to currentBits */ bitbuf->currentBits = (bitbuf->currentBits << 8) | bitbuf->data[bitbuf->bytePos++]; bitbuf->bitpos += 8; } /* Copy the last bits into "lastBits", then compare it with 0x1..00 */ lastBits = bitbuf->currentBits & ~(((u_int32)-1)<<bitbuf->bitpos); if (lastBits == ((u_int32)1 << (bitbuf->bitpos-1))) return 0; else return 1;}/* * bibGetNumOfRemainingBits: * * Parameters: * bitbuf Bitbuffer object * * Function: * Return number of bits in bitbuffer. * * Returns: * Number of bits */int32 bibGetNumRemainingBits(bitbuffer_s *bitbuf){ return bitbuf->bitpos + 8*(bitbuf->dataLen - bitbuf->bytePos);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -