| /* ------------------------------------------------------------------ |
| * 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" |
| |
| 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. |
| oscl_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 |
| oscl_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; |
| } |
| |
| } |
| |
| |
| |
| |
| |
| |
| |