diff -r 000000000000 -r 951a5db380a0 videoeditorengine/avcedit/src/bitbuffer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/avcedit/src/bitbuffer.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,613 @@ +/* +* 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: +* +*/ + + +#include +#include "globals.h" +#include "nrctyp32.h" +#include "bitbuffer.h" + +#include "parameterset.h" + + +/* + * Static functions + */ + +static int removeStartCodeEmulationBytes(bitbuffer_s *bitbuf); +static int addStartCodeEmulationBytes(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 *)User::Alloc(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 ENCAPSULATED_NAL_PAYLOAD + if (removeStartCodeEmulationBytes(bitbuf) < 0) + return BIB_ERROR; +#endif + + return BIB_OK; +} + + +/* + * + * bibClose: + * + * Parameters: + * bitbuf Bitbuffer object + * + * Function: + * Close bitbuffer + * + * Returns: + * - + * + */ +void bibClose(bitbuffer_s *bitbuf) +{ + User::Free(bitbuf); +} + + +/* + * + * removeStartCodeEmulationBytes: + * + * Parameters: + * bitbuf Bitbuffer object + * + * Function: + * Remove start code emulation bytes from the bitbuffer + * + * Returns: + * - + * + */ +static int removeStartCodeEmulationBytes(bitbuffer_s *bitbuf) +{ + TInt i; + TInt j; + TInt numZero; + TInt32 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++; + } + + // If bytes were removed, set as many bytes zero at the end of the buffer + if (j < bitbuf->dataLen) + { + // Prevention bytes have been removed, set the last bytes to zero + TInt removedBytes = bitbuf->dataLen - j; + for (i=0; idata[bitbuf->dataLen-1-i] = 0; + } + } + + // Adjust the bitbuffer dataLen + 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) { + 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) { + bitbuf->errorStatus = BIB_ERR_NO_BITS; + return 0; + } + + /* Return bits */ + bitbuf->bitpos -= n; + return (bitbuf->currentBits >> (bitbuf->bitpos)) & ~(((u_int32)-1)<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)<currentBits << (n-bitbuf->bitpos)) & ~(((u_int32)-1)<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) { + 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) { + 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) { + 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)<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); +} + + +// syncBitBufferBitpos +// Synchronizes the input bit buffer's bit position to be between one and eight, +// modifies the byte position and current bits if required. +void syncBitBufferBitpos(bitbuffer_s *bitbuf) +{ + // To be able to edit the bitbuffer, reset the bit position to be eight at the maximum + while (bitbuf->bitpos > 8) + { + // If bit position is modified, then modify byte position and current bits accordingly + bitbuf->bitpos -= 8; + bitbuf->bytePos--; + bitbuf->currentBits >>= 8; + } +} + + +// addStartCodeEmulationBytes +// Adds start code emulation bytes to the input bit buffer. +static int addStartCodeEmulationBytes(bitbuffer_s *bitbuf) +{ + TInt i = 0; + TInt32 lastBytes; + + + // Add prevention bytes that were removed for processing + lastBytes = 0xffffffff; + while (i < bitbuf->dataLen) + { + lastBytes = (lastBytes << 8) | bitbuf->data[i]; + + if(((lastBytes & 0xffff) == 0x0000) && ((i+1) < bitbuf->dataLen) && (bitbuf->data[i+1] < 4)) + { + // Add byte(s) to the bit buffer + TInt error = AddBytesToBuffer(bitbuf, 1); + + if (error != 0) + return error; + + // Adjust data length + bitbuf->dataLen++; + + // Make room for the emulation prevention byte 0x03 to the buffer + for (TInt k=bitbuf->dataLen; k>i; k--) + { + bitbuf->data[k] = bitbuf->data[k-1]; + } + + // Add the emulation prevention byte to the buffer + bitbuf->data[i+1] = 0x03; + } + + i++; + } + return KErrNone; +} + + +// bibEnd +// Takes care of the bit buffer after the frame has been processed. +int bibEnd(bitbuffer_s *bitbuf) +{ +#if ENCAPSULATED_NAL_PAYLOAD + return addStartCodeEmulationBytes(bitbuf); +#endif +} + + +// addStartCodeEmulationBytesSlice +// Adds start code emulation bytes to the input bit buffer. +static void addStartCodeEmulationBytesSlice(bitbuffer_s *bitbuf) +{ + TInt i = 0; + TInt32 lastBytes; + + + // Add prevention bytes that were removed for processing + lastBytes = 0xffffffff; + while (i < bitbuf->dataLen) + { + lastBytes = (lastBytes << 8) | bitbuf->data[i]; + + if(((lastBytes & 0xffff) == 0x0000) && ((i+1) < bitbuf->dataLen) && (bitbuf->data[i+1] < 4)) + { + // Make room for the emulation prevention byte 0x03 to the buffer + for (TInt k=bitbuf->dataLen; k>i; k--) + { + bitbuf->data[k] = bitbuf->data[k-1]; + } + // Adjust data length + bitbuf->dataLen++; + + // Add the emulation prevention byte to the buffer + bitbuf->data[i+1] = 0x03; + } + + i++; + } +} + + +// bibEndSlice +// Takes care of the bit buffer after the frame has been processed. +void bibEndSlice(bitbuffer_s *bitbuf) +{ +#if ENCAPSULATED_NAL_PAYLOAD + addStartCodeEmulationBytesSlice(bitbuf); +#endif +} +