blob: 5c4c4abc7ff247ab040b90a2b2a016a3d97cf4e1 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/* Date: 8/02/04 */
/* Description: */
/* Change the bitstream parsing algorithm. Use temporary word of 2 or 4 bytes */
/* before writing it to the bitstream buffer. */
/* Note byteCount doesn't have to be multiple of 2 or 4 */
/*********************************************************************************/
#include "bitstream_io.h"
#include "m4venc_oscl.h"
#include <stdlib.h>
static const UChar Mask[ ] =
{
0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
};
#define WORD_SIZE 4 /* for 32-bit machine */
/*Note:
1. There is a problem when output the last bits(which can not form a byte yet
so when you output, you need to stuff to make sure it is a byte
2. I now hard coded byte to be 8 bits*/
/* ======================================================================== */
/* Function : BitStreamCreateEnc(Int bufferSize ) */
/* Date : 08/29/2000 */
/* Purpose : Create a bitstream to hold one encoded video packet or frame */
/* In/out : */
/* bufferSize : size of the bitstream buffer in bytes */
/* Return : Pointer to the BitstreamEncVideo */
/* Modified : */
/* ======================================================================== */
BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize)
{
BitstreamEncVideo *stream;
stream = (BitstreamEncVideo *) M4VENC_MALLOC(sizeof(BitstreamEncVideo));
if (stream == NULL)
{
return NULL;
}
stream->bufferSize = bufferSize;
stream->bitstreamBuffer = (UChar *) M4VENC_MALLOC(stream->bufferSize * sizeof(UChar));
if (stream->bitstreamBuffer == NULL)
{
M4VENC_FREE(stream);
stream = NULL;
return NULL;
}
M4VENC_MEMSET(stream->bitstreamBuffer, 0, stream->bufferSize*sizeof(UChar));
stream->word = 0;
#if WORD_SIZE==4
stream->bitLeft = 32;
#else
stream->bitLeft = 16;
#endif
stream->byteCount = 0;
stream->overrunBuffer = NULL;
stream->oBSize = 0;
return stream;
}
/* ======================================================================== */
/* Function : BitstreamCloseEnc( ) */
/* Date : 08/29/2000 */
/* Purpose : close a bitstream */
/* In/out :
stream : the bitstream to be closed */
/* Return : */
/* Modified : */
/* ======================================================================== */
Void BitstreamCloseEnc(BitstreamEncVideo *stream)
{
if (stream)
{
if (stream->bitstreamBuffer)
{
M4VENC_FREE(stream->bitstreamBuffer);
}
M4VENC_FREE(stream);
}
}
/* ======================================================================== */
/* Function : BitstreamPutBits(BitstreamEncVideo *stream, Int Length,
Int Value) */
/* Date : 08/29/2000 */
/* Purpose : put Length (1-16) number of bits to the stream */
/* for 32-bit machine this function can do upto 32 bit input */
/* In/out : */
/* stream the bitstream where the bits are put in */
/* Length bits length (should belong to 1 to 16) */
/* Value those bits value */
/* Return : PV_STATUS */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value)
{
PV_STATUS status;
if (stream->bitLeft > Length)
{
stream->word <<= Length;
stream->word |= Value; /* assuming Value is not larger than Length */
stream->bitLeft -= Length;
return PV_SUCCESS;
}
else
{
stream->word <<= stream->bitLeft;
Length -= stream->bitLeft;
stream->word |= ((UInt)Value >> Length);
status = BitstreamSaveWord(stream);
if (status != PV_SUCCESS)
{
return status;
}
/* we got new Length and Value */
/* note that Value is not "clean" because of msb are not masked out */
stream->word = Value;
stream->bitLeft -= Length;
/* assuming that Length is no more than 16 bits */
/* stream->bitLeft should be greater than zero at this point */
//if(stream->bitLeft<=0)
// exit(-1);
return PV_SUCCESS;
}
}
/* ======================================================================== */
/* Function : BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, UInt32 Value) */
/* Date : 08/29/2000 */
/* Purpose : Use this function to put Length (17-32) number of bits to */
/* for 16-bit machine the stream. */
/* In/out : */
/* stream the bitstream where the bits are put in */
/* Length bits length (should belong to 17 to 32) */
/* Value those bits value */
/* Return : PV_STATUS */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value)
{
PV_STATUS status;
UInt topValue;
Int topLength;
topValue = (Value >> 16);
topLength = Length - 16;
if (topLength > 0)
{
status = BitstreamPutBits(stream, topLength, topValue);
if (status != PV_SUCCESS)
{
return status;
}
status = BitstreamPutBits(stream, 16, (UInt)(Value & 0xFFFF));
return status;
}
else
{
status = BitstreamPutBits(stream, Length, (UInt)Value);
return status;
}
}
/* ======================================================================== */
/* Function : BitstreamSaveWord */
/* Date : 08/03/2004 */
/* Purpose : save written word into the bitstream buffer. */
/* In/out : */
/* stream the bitstream where the bits are put in */
/* Return : PV_STATUS */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream)
{
UChar *ptr;
UInt word;
/* assume that stream->bitLeft is always zero when this function is called */
if (stream->byteCount + WORD_SIZE > stream->bufferSize)
{
if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, WORD_SIZE))
{
stream->byteCount += WORD_SIZE;
return PV_FAIL;
}
}
ptr = stream->bitstreamBuffer + stream->byteCount;
word = stream->word;
stream->word = 0; /* important to reset to zero */
/* NOTE: byteCount does not have to be multiple of 2 or 4 */
#if (WORD_SIZE == 4)
*ptr++ = word >> 24;
*ptr++ = 0xFF & (word >> 16);
#endif
*ptr++ = 0xFF & (word >> 8);
*ptr = 0xFF & word;
#if (WORD_SIZE == 4)
stream->byteCount += 4;
stream->bitLeft = 32;
#else
stream->byteCount += 2;
stream->bitLeft = 16;
#endif
return PV_SUCCESS;
}
/* ======================================================================== */
/* Function : BitstreamSavePartial */
/* Date : 08/03/2004 */
/* Purpose : save unfinished written word into the bitstream buffer. */
/* In/out : */
/* stream the bitstream where the bits are put in */
/* Return : PV_STATUS */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction)
{
UChar *ptr;
UInt word, shift;
Int numbyte, bitleft, bitused;
bitleft = stream->bitLeft;
bitused = (WORD_SIZE << 3) - bitleft; /* number of bits used */
numbyte = bitused >> 3; /* number of byte fully used */
if (stream->byteCount + numbyte > stream->bufferSize)
{
if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, numbyte))
{
stream->byteCount += numbyte;
return PV_FAIL;
}
}
ptr = stream->bitstreamBuffer + stream->byteCount;
word = stream->word;
word <<= bitleft; /* word is not all consumed */
bitleft = bitused - (numbyte << 3); /* number of bits used (fraction) */
stream->byteCount += numbyte;
if (bitleft)
{
*fraction = 1;
}
else
{
*fraction = 0;
}
bitleft = (WORD_SIZE << 3) - bitleft;
/* save new value */
stream->bitLeft = bitleft;
shift = ((WORD_SIZE - 1) << 3);
while (numbyte)
{
*ptr++ = (UChar)((word >> shift) & 0xFF);
word <<= 8;
numbyte--;
}
if (*fraction)
{// this could lead to buffer overrun when ptr is already out of bound.
// *ptr = (UChar)((word>>shift)&0xFF); /* need to do it for the last fractional byte */
}
/* save new values */
stream->word = word >> bitleft;
/* note we don't update byteCount, bitLeft and word */
/* so that encoder can continue PutBits if they don't */
return PV_SUCCESS;
}
/* ======================================================================== */
/* Function : BitstreamShortHeaderByteAlignStuffing( */
/* BitstreamEncVideo *stream) */
/* Date : 08/29/2000 */
/* Purpose : bit stuffing for next start code in short video header */
/* In/out : */
/* Return : number of bits to be stuffed */
/* Modified : */
/* ======================================================================== */
Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream)
{
UInt restBits;
Int fraction;
restBits = (stream->bitLeft & 0x7); /* modulo 8 */
if (restBits) /*short_video_header[0] is 1 in h263 baseline*/
{
/* H.263 style stuffing */
BitstreamPutBits(stream, restBits, 0);
}
if (stream->bitLeft != (WORD_SIZE << 3))
{
BitstreamSavePartial(stream, &fraction);
}
return restBits;
}
/* ======================================================================== */
/* Function : BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream) */
/* Date : 08/29/2000 */
/* Purpose : bit stuffing for next start code in MPEG-4 */
/* In/out : */
/* Return : number of bits to be stuffed */
/* Modified : */
/* ======================================================================== */
Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)
{
UInt restBits;
Int fraction;
/* Question: in MPEG-4 , short_video_header[0]==0 => even already byte aligned, will still stuff 8 bits
need to check with */
/*if (!(getPointerENC(index1, index2)%8) && short_video_header[0]) return 0;*/
/* need stuffing bits, */
BitstreamPutBits(stream, 1, 0);
restBits = (stream->bitLeft & 0x7); /* modulo 8 */
if (restBits) /*short_video_header[0] is 1 in h263 baseline*/
{
/* need stuffing bits, */
BitstreamPutBits(stream, restBits, Mask[restBits]);
}
if (stream->bitLeft != (WORD_SIZE << 3))
{
BitstreamSavePartial(stream, &fraction);
}
return (restBits);
}
/*does bit stuffing for next resync marker*/
/* does bit stuffing for next resync marker
* "0"
* "01"
* "011"
* "0111"
* "01111"
* "011111"
* "0111111"
* "01111111" (8-bit codeword)
*/
/*Int BitstreamNextResyncMarkerEnc(BitstreamEncVideo *stream)
{
Int count;
BitstreamPut1Bits(stream,0);
count=8-stream->totalBits & 8;
BitstreamPutBits(stream,count,Mask[count]);
return count;
}*/
/* ======================================================================== */
/* Function : BitstreamAppendEnc( BitstreamEncVideo *bitstream1, */
/* BitstreamEncVideo *bitstream2 ) */
/* Date : 08/29/2000 */
/* Purpose : Append the intermediate bitstream (bitstream2) to the end of */
/* output bitstream(bitstream1) */
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
{
PV_STATUS status;
UChar *ptrBS2, *ptrBS1;
UChar byteBS2, byteBS1;
Int numbyte2;
Int bitused, bitleft, offset, fraction;
status = BitstreamSavePartial(bitstream1, &fraction);
if (status != PV_SUCCESS)
{
return status;
}
offset = fraction;
status = BitstreamSavePartial(bitstream2, &fraction);
if (status != PV_SUCCESS)
{
return status;
}
if (!offset) /* bitstream1 is byte-aligned */
{
return BitstreamAppendPacket(bitstream1, bitstream2);
}
offset += fraction;
/* since bitstream1 doesn't have to be byte-aligned, we have to process byte by byte */
/* we read one byte from bitstream2 and use BitstreamPutBits to do the job */
if (bitstream1->byteCount + bitstream2->byteCount + offset > bitstream1->bufferSize)
{
if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount + offset))
{
bitstream1->byteCount += (bitstream2->byteCount + offset);
return PV_FAIL;
}
}
ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
ptrBS2 = bitstream2->bitstreamBuffer;
bitused = (WORD_SIZE << 3) - bitstream1->bitLeft; /* this must be between 1-7 */
bitleft = 8 - bitused;
numbyte2 = bitstream2->byteCount; /* number of byte to copy from bs2 */
bitstream1->byteCount += numbyte2; /* new byteCount */
byteBS1 = ((UChar) bitstream1->word) << bitleft; /* fraction byte from bs1 */
while (numbyte2)
{
byteBS2 = *ptrBS2++;
byteBS1 |= (byteBS2 >> bitused);
*ptrBS1++ = byteBS1;
byteBS1 = byteBS2 << bitleft;
numbyte2--;
}
bitstream1->word = byteBS1 >> bitleft; /* bitstream->bitLeft remains the same */
/* now save bs2->word in bs1 */
status = BitstreamPutBits(bitstream1, (WORD_SIZE << 3) - bitstream2->bitLeft, bitstream2->word);
return status;
}
/* ======================================================================== */
/* Function : BitstreamAppendPacket( BitstreamEncVideo *bitstream1, */
/* BitstreamEncVideo *bitstream2 ) */
/* Date : 05/31/2001 */
/* Purpose : Append the intermediate bitstream (bitstream2) to the end of */
/* output bitstream(bitstream1) knowing that bitstream1 is byte-aligned*/
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
{
UChar *ptrBS2, *ptrBS1;
Int numbyte2;
if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
{
if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount))
{
bitstream1->byteCount += bitstream2->byteCount; /* legacy, to keep track of total bytes */
return PV_FAIL;
}
}
ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
ptrBS2 = bitstream2->bitstreamBuffer;
numbyte2 = bitstream2->byteCount;
bitstream1->byteCount += numbyte2; /* new byteCount */
/*copy all the bytes in bitstream2*/
M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
bitstream1->word = bitstream2->word; /* bitstream1->bitLeft is the same */
bitstream1->bitLeft = bitstream2->bitLeft;
return PV_SUCCESS;
}
/* ======================================================================== */
/* Function : BitstreamAppendPacketNoOffset( BitstreamEncVideo *bitstream1,*/
/* BitstreamEncVideo *bitstream2 ) */
/* Date : 04/23/2002 */
/* Purpose : Append the intermediate bitstream (bitstream2) to the end of */
/* output bitstream(bitstream1) , for slice-based coding only */
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
{
PV_STATUS status = PV_SUCCESS;
UChar *ptrBS2, *ptrBS1;
Int numbyte2;
Int byteleft;
numbyte2 = bitstream2->byteCount;
if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
{
numbyte2 = bitstream1->bufferSize - bitstream1->byteCount;
status = PV_END_OF_BUF; /* signal end of buffer */
}
ptrBS1 = bitstream1->bitstreamBuffer; /* move ptr bs1*/
ptrBS2 = bitstream2->bitstreamBuffer;
bitstream1->byteCount += numbyte2; /* should be equal to bufferSize */
/*copy all the bytes in bitstream2*/
M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
bitstream1->word = 0;
bitstream1->bitLeft = (WORD_SIZE << 3);
if (status == PV_END_OF_BUF) /* re-position bitstream2 */
{
byteleft = bitstream2->byteCount - numbyte2;
M4VENC_MEMCPY(ptrBS2, ptrBS2 + numbyte2, sizeof(UChar)*byteleft);
bitstream2->byteCount = byteleft;
/* bitstream2->word and bitstream->bitLeft are unchanged.
they should be 0 and (WORD_SIZE<<3) */
}
return status;
}
#ifndef NO_SLICE_ENCODE
/* ======================================================================== */
/* Function : BitstreamRepos( BitstreamEncVideo *bitstream, */
/* Int byteCount, Int bitCount) */
/* Date : 04/28/2002 */
/* Purpose : Reposition the size of the buffer content (curtail) */
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount)
{
UChar *ptr, byte;
UInt word;
Int fraction;
BitstreamSavePartial(bitstream, &fraction);
bitstream->byteCount = byteCount;
ptr = bitstream->bitstreamBuffer + byteCount; /* get fraction of the byte */
if (bitCount)
{
bitstream->bitLeft = (WORD_SIZE << 3) - bitCount; /* bitCount should be 0-31 */
word = *ptr++;
byte = *ptr++;
word = byte | (word << 8);
#if (WORD_SIZE == 4)
byte = *ptr++;
word = byte | (word << 8);
byte = *ptr++;
word = byte | (word << 8);
#endif
bitstream->word = word >> (bitstream->bitLeft);
}
else
{
bitstream->word = 0;
bitstream->bitLeft = (WORD_SIZE << 3);
}
return PV_SUCCESS;
}
/* ======================================================================== */
/* Function : BitstreamFlushBits(BitstreamEncVideo *bitstream1, */
/* Int num_bit_left) */
/* Date : 04/24/2002 */
/* Purpose : Flush buffer except the last num_bit_left bits. */
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left)
{
Int i;
UChar *ptrDst, *ptrSrc;
Int leftover, bitused;
Int new_byte = (num_bit_left >> 3);
Int new_bit = num_bit_left - (new_byte << 3); /* between 0-7 */
ptrSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
ptrDst = bitstream1->bitstreamBuffer;
bitused = (WORD_SIZE << 3) - bitstream1->bitLeft;
leftover = 8 - bitused; /* bitused should be between 0-7 */
bitstream1->byteCount = new_byte;
bitstream1->bitLeft = (WORD_SIZE << 3) - new_bit;
if (!bitused) /* byte aligned */
{
M4VENC_MEMCPY(ptrDst, ptrSrc, new_byte + 1);
}
else
{
/*copy all the bytes in bitstream2*/
for (i = 0; i < new_byte; i++)
{
*ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
ptrSrc++;
}
/* copy for the last byte of ptrSrc, copy extra bits doesn't hurt */
if (new_bit)
{
*ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
ptrSrc++;
}
}
if (new_bit)
{
ptrSrc = bitstream1->bitstreamBuffer + new_byte;
bitstream1->word = (*ptrSrc) >> (8 - new_bit);
}
return PV_SUCCESS;
}
/* ======================================================================== */
/* Function : BitstreamPrependPacket( BitstreamEncVideo *bitstream1, */
/* BitstreamEncVideo *bitstream2 ) */
/* Date : 04/26/2002 */
/* Purpose : Prepend the intermediate bitstream (bitstream2) to the beginning of */
/* output bitstream(bitstream1) */
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
{
UChar *pSrc, *pDst, byte;
Int movebyte, bitused, leftover, i, fraction;
BitstreamSavePartial(bitstream2, &fraction); /* make sure only fraction of byte left */
BitstreamSavePartial(bitstream1, &fraction);
if (bitstream1->byteCount + bitstream2->byteCount >= bitstream1->bufferSize)
{
bitstream1->byteCount += bitstream2->byteCount;
return PV_END_OF_BUF;
}
movebyte = bitstream1->byteCount;
if (movebyte < bitstream2->byteCount)
movebyte = bitstream2->byteCount;
movebyte++;
/* shift bitstream1 to the right by movebyte */
pSrc = bitstream1->bitstreamBuffer;
pDst = pSrc + movebyte;
M4VENC_MEMCPY(pDst, pSrc, bitstream1->byteCount + 1);
/* copy bitstream2 to the beginning of bitstream1 */
M4VENC_MEMCPY(pSrc, bitstream2->bitstreamBuffer, bitstream2->byteCount + 1);
/* now shift back previous bitstream1 buffer to the end */
pSrc = pDst;
pDst = bitstream1->bitstreamBuffer + bitstream2->byteCount;
bitused = (WORD_SIZE << 3) - bitstream2->bitLeft;
leftover = 8 - bitused; /* bitused should be 0-7 */
byte = (bitstream2->word) << leftover;
*pDst++ = byte | (pSrc[0] >> bitused);
for (i = 0; i < bitstream1->byteCount + 1; i++)
{
*pDst++ = ((pSrc[0] << leftover) | (pSrc[1] >> bitused));
pSrc++;
}
bitstream1->byteCount += bitstream2->byteCount;
//bitstream1->bitCount += bitstream2->bitCount;
bitused = (WORD_SIZE << 4) - (bitstream1->bitLeft + bitstream2->bitLeft);
if (bitused >= 8)
{
bitused -= 8;
bitstream1->byteCount++;
}
bitstream1->bitLeft = (WORD_SIZE << 3) - bitused;
bitstream2->byteCount = bitstream2->word = 0;
bitstream2->bitLeft = (WORD_SIZE << 3);
pSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
leftover = 8 - bitused;
//*pSrc = (pSrc[0]>>leftover)<<leftover; /* make sure the rest of bits are zeros */
bitstream1->word = (UInt)((pSrc[0]) >> leftover);
return PV_SUCCESS;
}
#endif /* NO_SLICE_ENCODE */
/* ======================================================================== */
/* Function : BitstreamGetPos( BitstreamEncVideo *stream */
/* Date : 08/05/2004 */
/* Purpose : Get the bit position. */
/* In/out : */
/* Return : */
/* Modified : */
/* ======================================================================== */
Int BitstreamGetPos(BitstreamEncVideo *stream)
{
return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
}
void BitstreamEncReset(BitstreamEncVideo *stream)
{
stream->bitLeft = (WORD_SIZE << 3);
stream->word = 0;
stream->byteCount = 0;
return ;
}
/* This function set the overrun buffer, and VideoEncData context for callback to reallocate
overrun buffer. */
Void BitstreamSetOverrunBuffer(BitstreamEncVideo* stream, UChar* overrunBuffer, Int oBSize, VideoEncData *video)
{
stream->overrunBuffer = overrunBuffer;
stream->oBSize = oBSize;
stream->video = video;
return ;
}
/* determine whether overrun buffer can be used or not */
PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes)
{
VideoEncData *video = stream->video;
if (stream->overrunBuffer != NULL) // overrunBuffer is set
{
if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
{
if (stream->byteCount + numExtraBytes >= stream->oBSize)
{
stream->oBSize = stream->byteCount + numExtraBytes + 100;
stream->oBSize &= (~0x3); // make it multiple of 4
// allocate new overrun Buffer
if (video->overrunBuffer)
{
M4VENC_FREE(video->overrunBuffer);
}
video->oBSize = stream->oBSize;
video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
stream->overrunBuffer = video->overrunBuffer;
if (stream->overrunBuffer == NULL)
{
return PV_FAIL;
}
}
// copy everything to overrun buffer and start using it.
memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->byteCount);
stream->bitstreamBuffer = stream->overrunBuffer;
stream->bufferSize = stream->oBSize;
}
else // overrun buffer is already used
{
if (stream->byteCount + numExtraBytes >= stream->oBSize)
{
stream->oBSize = stream->byteCount + numExtraBytes + 100;
}
// allocate new overrun buffer
stream->oBSize &= (~0x3); // make it multiple of 4
video->oBSize = stream->oBSize;
video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
if (video->overrunBuffer == NULL)
{
return PV_FAIL;
}
// copy from the old buffer to new buffer
memcpy(video->overrunBuffer, stream->overrunBuffer, stream->byteCount);
// free old buffer
M4VENC_FREE(stream->overrunBuffer);
// assign pointer to new buffer
stream->overrunBuffer = video->overrunBuffer;
stream->bitstreamBuffer = stream->overrunBuffer;
stream->bufferSize = stream->oBSize;
}
return PV_SUCCESS;
}
else // overrunBuffer is not enable.
{
return PV_FAIL;
}
}