--- /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 <string.h>
+#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; i<removedBytes; i++)
+ {
+ bitbuf->data[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)<<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) {
+ 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)<<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);
+}
+
+
+// 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
+}
+