Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 /* Date: 8/02/04                                                                */
     19 /* Description:                                                                 */
     20 /*  Change the bitstream parsing algorithm. Use temporary word of 2 or 4 bytes  */
     21 /*  before writing it to the bitstream buffer.                                  */
     22 /*  Note byteCount doesn't have to be multiple of 2 or 4                        */
     23 /*********************************************************************************/
     24 
     25 #include "bitstream_io.h"
     26 #include "m4venc_oscl.h"
     27 #include <stdlib.h>
     28 
     29 static const UChar Mask[ ] =
     30 {
     31     0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
     32 };
     33 
     34 #define WORD_SIZE   4   /* for 32-bit machine */
     35 
     36 /*Note:
     37     1. There is a problem when output the last bits(which can not form a byte yet
     38     so when you output, you need to stuff to make sure it is a byte
     39     2.  I now hard coded byte to be 8 bits*/
     40 
     41 
     42 /* ======================================================================== */
     43 /*  Function : BitStreamCreateEnc(Int bufferSize )                          */
     44 /*  Date     : 08/29/2000                                                   */
     45 /*  Purpose  : Create a bitstream to hold one encoded video packet or frame */
     46 /*  In/out   :                                                              */
     47 /*      bufferSize  :   size of the bitstream buffer in bytes               */
     48 /*  Return   : Pointer to the BitstreamEncVideo                             */
     49 /*  Modified :                                                              */
     50 /* ======================================================================== */
     51 
     52 BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize)
     53 {
     54     BitstreamEncVideo *stream;
     55     stream = (BitstreamEncVideo *) M4VENC_MALLOC(sizeof(BitstreamEncVideo));
     56     if (stream == NULL)
     57     {
     58         return NULL;
     59     }
     60     stream->bufferSize = bufferSize;
     61     stream->bitstreamBuffer = (UChar *) M4VENC_MALLOC(stream->bufferSize * sizeof(UChar));
     62     if (stream->bitstreamBuffer == NULL)
     63     {
     64         M4VENC_FREE(stream);
     65         stream = NULL;
     66         return NULL;
     67     }
     68     M4VENC_MEMSET(stream->bitstreamBuffer, 0, stream->bufferSize*sizeof(UChar));
     69     stream->word = 0;
     70 #if WORD_SIZE==4
     71     stream->bitLeft = 32;
     72 #else
     73     stream->bitLeft = 16;
     74 #endif
     75     stream->byteCount = 0;
     76 
     77     stream->overrunBuffer = NULL;
     78     stream->oBSize = 0;
     79 
     80     return stream;
     81 }
     82 
     83 /* ======================================================================== */
     84 /*  Function : BitstreamCloseEnc( )                                         */
     85 /*  Date     : 08/29/2000                                                   */
     86 /*  Purpose  : close a bitstream                                            */
     87 /*  In/out   :
     88         stream  :   the bitstream to be closed                              */
     89 /*  Return   :                                                              */
     90 /*  Modified :                                                              */
     91 /* ======================================================================== */
     92 
     93 Void  BitstreamCloseEnc(BitstreamEncVideo *stream)
     94 {
     95     if (stream)
     96     {
     97         if (stream->bitstreamBuffer)
     98         {
     99             M4VENC_FREE(stream->bitstreamBuffer);
    100         }
    101 
    102         M4VENC_FREE(stream);
    103     }
    104 }
    105 
    106 
    107 /* ======================================================================== */
    108 /*  Function : BitstreamPutBits(BitstreamEncVideo *stream, Int Length,
    109                          Int Value)                                         */
    110 /*  Date     : 08/29/2000                                                   */
    111 /*  Purpose  : put Length (1-16) number of bits to the stream               */
    112 /*            for 32-bit machine this function can do upto 32 bit input     */
    113 /*  In/out   :                                                              */
    114 /*      stream      the bitstream where the bits are put in                 */
    115 /*      Length      bits length (should belong to 1 to 16)                  */
    116 /*      Value       those bits value                                        */
    117 /*  Return   :  PV_STATUS                                                   */
    118 /*  Modified :                                                              */
    119 /* ======================================================================== */
    120 PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value)
    121 {
    122     PV_STATUS status;
    123 
    124     if (stream->bitLeft > Length)
    125     {
    126         stream->word <<= Length;
    127         stream->word |= Value;  /* assuming Value is not larger than Length */
    128         stream->bitLeft -= Length;
    129         return PV_SUCCESS;
    130     }
    131     else
    132     {
    133 
    134         stream->word <<= stream->bitLeft;
    135         Length -= stream->bitLeft;
    136         stream->word |= ((UInt)Value >> Length);
    137 
    138         status = BitstreamSaveWord(stream);
    139         if (status != PV_SUCCESS)
    140         {
    141             return status;
    142         }
    143 
    144         /* we got new Length and Value */
    145         /* note that Value is not "clean" because of msb are not masked out */
    146         stream->word = Value;
    147         stream->bitLeft -= Length;
    148         /* assuming that Length is no more than 16 bits */
    149         /* stream->bitLeft should be greater than zero at this point */
    150         //if(stream->bitLeft<=0)
    151         //  exit(-1);
    152         return PV_SUCCESS;
    153     }
    154 }
    155 
    156 /* ======================================================================== */
    157 /*  Function : BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, UInt32 Value)    */
    158 /*  Date     : 08/29/2000                                                   */
    159 /*  Purpose  : Use this function to put Length (17-32) number of bits to    */
    160 /*              for 16-bit machine  the stream.                             */
    161 /*  In/out   :                                                              */
    162 /*      stream      the bitstream where the bits are put in                 */
    163 /*      Length      bits length (should belong to 17 to 32)                 */
    164 /*      Value       those bits value                                        */
    165 /*  Return   :  PV_STATUS                                                   */
    166 /*  Modified :                                                              */
    167 /* ======================================================================== */
    168 PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value)
    169 {
    170     PV_STATUS status;
    171     UInt topValue;
    172     Int topLength;
    173 
    174     topValue = (Value >> 16);
    175     topLength = Length - 16;
    176 
    177     if (topLength > 0)
    178     {
    179         status = BitstreamPutBits(stream, topLength, topValue);
    180 
    181         if (status != PV_SUCCESS)
    182         {
    183             return status;
    184         }
    185 
    186         status = BitstreamPutBits(stream, 16, (UInt)(Value & 0xFFFF));
    187 
    188         return status;
    189     }
    190     else
    191     {
    192         status = BitstreamPutBits(stream, Length, (UInt)Value);
    193         return status;
    194     }
    195 }
    196 
    197 /* ======================================================================== */
    198 /*  Function : BitstreamSaveWord                                            */
    199 /*  Date     : 08/03/2004                                                   */
    200 /*  Purpose  : save written word into the bitstream buffer.                 */
    201 /*  In/out   :                                                              */
    202 /*      stream      the bitstream where the bits are put in                 */
    203 /*  Return   :  PV_STATUS                                                   */
    204 /*  Modified :                                                              */
    205 /* ======================================================================== */
    206 
    207 PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream)
    208 {
    209     UChar *ptr;
    210     UInt word;
    211 
    212     /* assume that stream->bitLeft is always zero when this function is called */
    213     if (stream->byteCount + WORD_SIZE > stream->bufferSize)
    214     {
    215         if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, WORD_SIZE))
    216         {
    217             stream->byteCount += WORD_SIZE;
    218             return PV_FAIL;
    219         }
    220     }
    221 
    222     ptr = stream->bitstreamBuffer + stream->byteCount;
    223     word = stream->word;
    224     stream->word = 0; /* important to reset to zero */
    225 
    226     /* NOTE: byteCount does not have to be multiple of 2 or 4 */
    227 #if (WORD_SIZE == 4)
    228     *ptr++ = word >> 24;
    229     *ptr++ = 0xFF & (word >> 16);
    230 #endif
    231 
    232     *ptr++ = 0xFF & (word >> 8);
    233     *ptr = 0xFF & word;
    234 
    235 #if (WORD_SIZE == 4)
    236     stream->byteCount += 4;
    237     stream->bitLeft = 32;
    238 #else
    239     stream->byteCount += 2;
    240     stream->bitLeft = 16;
    241 #endif
    242 
    243     return PV_SUCCESS;
    244 }
    245 
    246 
    247 /* ======================================================================== */
    248 /*  Function : BitstreamSavePartial                                         */
    249 /*  Date     : 08/03/2004                                                   */
    250 /*  Purpose  : save unfinished written word into the bitstream buffer.      */
    251 /*  In/out   :                                                              */
    252 /*      stream      the bitstream where the bits are put in                 */
    253 /*  Return   :  PV_STATUS                                                   */
    254 /*  Modified :                                                              */
    255 /* ======================================================================== */
    256 
    257 PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction)
    258 {
    259     UChar *ptr;
    260     UInt word, shift;
    261     Int numbyte, bitleft, bitused;
    262 
    263     bitleft = stream->bitLeft;
    264     bitused = (WORD_SIZE << 3) - bitleft; /* number of bits used */
    265     numbyte = bitused >> 3; /* number of byte fully used */
    266 
    267     if (stream->byteCount + numbyte > stream->bufferSize)
    268     {
    269         if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, numbyte))
    270         {
    271             stream->byteCount += numbyte;
    272             return PV_FAIL;
    273         }
    274     }
    275 
    276     ptr = stream->bitstreamBuffer + stream->byteCount;
    277     word = stream->word;
    278     word <<= bitleft;   /* word is not all consumed */
    279     bitleft = bitused - (numbyte << 3); /* number of bits used (fraction) */
    280     stream->byteCount += numbyte;
    281     if (bitleft)
    282     {
    283         *fraction = 1;
    284     }
    285     else
    286     {
    287         *fraction = 0;
    288     }
    289     bitleft = (WORD_SIZE << 3) - bitleft;
    290     /* save new value */
    291     stream->bitLeft = bitleft;
    292 
    293     shift = ((WORD_SIZE - 1) << 3);
    294     while (numbyte)
    295     {
    296         *ptr++ = (UChar)((word >> shift) & 0xFF);
    297         word <<= 8;
    298         numbyte--;
    299     }
    300 
    301     if (*fraction)
    302     {// this could lead to buffer overrun when ptr is already out of bound.
    303         //  *ptr = (UChar)((word>>shift)&0xFF); /* need to do it for the last fractional byte */
    304     }
    305 
    306     /* save new values */
    307     stream->word = word >> bitleft;
    308 
    309     /* note we don't update byteCount, bitLeft and word */
    310     /* so that encoder can continue PutBits if they don't */
    311 
    312     return PV_SUCCESS;
    313 }
    314 
    315 
    316 /* ======================================================================== */
    317 /*  Function : BitstreamShortHeaderByteAlignStuffing(                       */
    318 /*                                      BitstreamEncVideo *stream)          */
    319 /*  Date     : 08/29/2000                                                   */
    320 /*  Purpose  : bit stuffing for next start code in short video header       */
    321 /*  In/out   :                                                              */
    322 /*  Return   :  number of bits to be stuffed                                */
    323 /*  Modified :                                                              */
    324 /* ======================================================================== */
    325 
    326 Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream)
    327 {
    328     UInt restBits;
    329     Int fraction;
    330 
    331     restBits = (stream->bitLeft & 0x7); /* modulo 8 */
    332 
    333     if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
    334     {
    335         /* H.263 style stuffing */
    336         BitstreamPutBits(stream, restBits, 0);
    337     }
    338 
    339     if (stream->bitLeft != (WORD_SIZE << 3))
    340     {
    341         BitstreamSavePartial(stream, &fraction);
    342     }
    343 
    344     return restBits;
    345 }
    346 
    347 /* ======================================================================== */
    348 /*  Function : BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)   */
    349 /*  Date     : 08/29/2000                                                   */
    350 /*  Purpose  : bit stuffing for next start code in MPEG-4                  */
    351 /*  In/out   :                                                              */
    352 /*  Return   :  number of bits to be stuffed                                */
    353 /*  Modified :                                                              */
    354 /* ======================================================================== */
    355 Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)
    356 {
    357 
    358     UInt restBits;
    359     Int fraction;
    360     /* Question: in MPEG-4 , short_video_header[0]==0 => even already byte aligned, will still stuff 8 bits
    361        need to check with  */
    362     /*if (!(getPointerENC(index1, index2)%8) && short_video_header[0]) return 0;*/
    363 
    364     /* need stuffing bits, */
    365     BitstreamPutBits(stream, 1, 0);
    366 
    367     restBits = (stream->bitLeft & 0x7); /* modulo 8 */
    368 
    369     if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
    370     {
    371         /* need stuffing bits, */
    372         BitstreamPutBits(stream, restBits, Mask[restBits]);
    373     }
    374 
    375     if (stream->bitLeft != (WORD_SIZE << 3))
    376     {
    377         BitstreamSavePartial(stream, &fraction);
    378     }
    379 
    380     return (restBits);
    381 }
    382 
    383 /*does bit stuffing for next resync marker*/
    384 /*  does bit stuffing for next resync marker
    385  *                                            "0"
    386  *                                           "01"
    387  *                                          "011"
    388  *                                         "0111"
    389  *                                        "01111"
    390  *                                       "011111"
    391  *                                      "0111111"
    392  *                                     "01111111"   (8-bit codeword)
    393  */
    394 
    395 /*Int BitstreamNextResyncMarkerEnc(BitstreamEncVideo *stream)
    396 {
    397   Int count;
    398   BitstreamPut1Bits(stream,0);
    399   count=8-stream->totalBits & 8;
    400   BitstreamPutBits(stream,count,Mask[count]);
    401   return count;
    402 }*/
    403 
    404 /* ======================================================================== */
    405 /*  Function : BitstreamAppendEnc( BitstreamEncVideo *bitstream1,           */
    406 /*                                      BitstreamEncVideo *bitstream2   )   */
    407 /*  Date     : 08/29/2000                                                   */
    408 /*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
    409 /*                              output bitstream(bitstream1)                */
    410 /*  In/out   :                                                              */
    411 /*  Return   :                                                              */
    412 /*  Modified :                                                              */
    413 /* ======================================================================== */
    414 
    415 
    416 PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
    417 {
    418     PV_STATUS status;
    419     UChar *ptrBS2, *ptrBS1;
    420     UChar byteBS2, byteBS1;
    421     Int  numbyte2;
    422     Int bitused, bitleft, offset, fraction;
    423 
    424     status = BitstreamSavePartial(bitstream1, &fraction);
    425     if (status != PV_SUCCESS)
    426     {
    427         return status;
    428     }
    429 
    430     offset = fraction;
    431     status = BitstreamSavePartial(bitstream2, &fraction);
    432     if (status != PV_SUCCESS)
    433     {
    434         return status;
    435     }
    436 
    437     if (!offset) /* bitstream1 is byte-aligned */
    438     {
    439         return BitstreamAppendPacket(bitstream1, bitstream2);
    440     }
    441 
    442     offset += fraction;
    443 
    444     /* since bitstream1 doesn't have to be byte-aligned, we have to process byte by byte */
    445     /* we read one byte from bitstream2 and use BitstreamPutBits to do the job */
    446     if (bitstream1->byteCount + bitstream2->byteCount + offset > bitstream1->bufferSize)
    447     {
    448         if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount + offset))
    449         {
    450             bitstream1->byteCount += (bitstream2->byteCount + offset);
    451             return PV_FAIL;
    452         }
    453     }
    454 
    455     ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
    456     ptrBS2 = bitstream2->bitstreamBuffer;
    457 
    458     bitused = (WORD_SIZE << 3) - bitstream1->bitLeft; /* this must be between 1-7 */
    459     bitleft = 8 - bitused;
    460 
    461     numbyte2 = bitstream2->byteCount;   /* number of byte to copy from bs2 */
    462     bitstream1->byteCount += numbyte2;  /* new byteCount */
    463 
    464     byteBS1 = ((UChar) bitstream1->word) << bitleft;    /* fraction byte from bs1 */
    465 
    466     while (numbyte2)
    467     {
    468         byteBS2 = *ptrBS2++;
    469         byteBS1 |= (byteBS2 >> bitused);
    470         *ptrBS1++ = byteBS1;
    471         byteBS1 = byteBS2 << bitleft;
    472         numbyte2--;
    473     }
    474 
    475     bitstream1->word = byteBS1 >> bitleft;  /* bitstream->bitLeft remains the same */
    476 
    477     /* now save bs2->word in bs1 */
    478     status = BitstreamPutBits(bitstream1, (WORD_SIZE << 3) - bitstream2->bitLeft, bitstream2->word);
    479 
    480     return status;
    481 }
    482 
    483 /* ======================================================================== */
    484 /*  Function : BitstreamAppendPacket( BitstreamEncVideo *bitstream1,        */
    485 /*                                      BitstreamEncVideo *bitstream2   )   */
    486 /*  Date     : 05/31/2001                                                   */
    487 /*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
    488 /*              output bitstream(bitstream1) knowing that bitstream1 is byte-aligned*/
    489 /*  In/out   :                                                              */
    490 /*  Return   :                                                              */
    491 /*  Modified :                                                              */
    492 /* ======================================================================== */
    493 PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
    494 {
    495     UChar *ptrBS2, *ptrBS1;
    496     Int  numbyte2;
    497 
    498     if (bitstream1->byteCount + bitstream2->byteCount  > bitstream1->bufferSize)
    499     {
    500         if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount))
    501         {
    502             bitstream1->byteCount += bitstream2->byteCount; /* legacy, to keep track of total bytes */
    503             return PV_FAIL;
    504         }
    505     }
    506 
    507     ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
    508     ptrBS2 = bitstream2->bitstreamBuffer;
    509 
    510     numbyte2 = bitstream2->byteCount;
    511     bitstream1->byteCount += numbyte2; /* new byteCount */
    512 
    513     /*copy all the bytes in bitstream2*/
    514     M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
    515 
    516     bitstream1->word = bitstream2->word;  /* bitstream1->bitLeft is the same */
    517     bitstream1->bitLeft = bitstream2->bitLeft;
    518 
    519     return PV_SUCCESS;
    520 }
    521 
    522 /* ======================================================================== */
    523 /*  Function : BitstreamAppendPacketNoOffset( BitstreamEncVideo *bitstream1,*/
    524 /*                                      BitstreamEncVideo *bitstream2   )   */
    525 /*  Date     : 04/23/2002                                                   */
    526 /*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
    527 /*              output bitstream(bitstream1) , for slice-based coding only */
    528 /*  In/out   :                                                              */
    529 /*  Return   :                                                              */
    530 /*  Modified :                                                              */
    531 /* ======================================================================== */
    532 PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
    533 {
    534     PV_STATUS status = PV_SUCCESS;
    535     UChar *ptrBS2, *ptrBS1;
    536     Int  numbyte2;
    537     Int  byteleft;
    538 
    539     numbyte2 = bitstream2->byteCount;
    540 
    541     if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
    542     {
    543         numbyte2 =  bitstream1->bufferSize - bitstream1->byteCount;
    544         status =  PV_END_OF_BUF;    /* signal end of buffer */
    545     }
    546 
    547     ptrBS1 = bitstream1->bitstreamBuffer; /* move ptr bs1*/
    548     ptrBS2 = bitstream2->bitstreamBuffer;
    549 
    550     bitstream1->byteCount += numbyte2; /* should be equal to bufferSize */
    551 
    552     /*copy all the bytes in bitstream2*/
    553     M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
    554     bitstream1->word = 0;
    555     bitstream1->bitLeft = (WORD_SIZE << 3);
    556 
    557     if (status == PV_END_OF_BUF) /* re-position bitstream2 */
    558     {
    559         byteleft = bitstream2->byteCount - numbyte2;
    560 
    561         M4VENC_MEMCPY(ptrBS2, ptrBS2 + numbyte2, sizeof(UChar)*byteleft);
    562 
    563         bitstream2->byteCount = byteleft;
    564         /* bitstream2->word and bitstream->bitLeft are unchanged.
    565            they should be 0 and (WORD_SIZE<<3) */
    566     }
    567 
    568     return status;
    569 }
    570 
    571 #ifndef NO_SLICE_ENCODE
    572 /* ======================================================================== */
    573 /*  Function : BitstreamRepos( BitstreamEncVideo *bitstream,                */
    574 /*                                      Int byteCount, Int bitCount)        */
    575 /*  Date     : 04/28/2002                                                   */
    576 /*  Purpose  : Reposition the size of the buffer content (curtail)          */
    577 /*  In/out   :                                                              */
    578 /*  Return   :                                                              */
    579 /*  Modified :                                                              */
    580 /* ======================================================================== */
    581 PV_STATUS   BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount)
    582 {
    583     UChar *ptr, byte;
    584     UInt word;
    585     Int fraction;
    586 
    587     BitstreamSavePartial(bitstream, &fraction);
    588 
    589     bitstream->byteCount = byteCount;
    590     ptr = bitstream->bitstreamBuffer + byteCount; /* get fraction of the byte */
    591     if (bitCount)
    592     {
    593         bitstream->bitLeft = (WORD_SIZE << 3) - bitCount; /* bitCount should be 0-31 */
    594         word = *ptr++;
    595         byte = *ptr++;
    596         word = byte | (word << 8);
    597 #if (WORD_SIZE == 4)
    598         byte = *ptr++;
    599         word = byte | (word << 8);
    600         byte = *ptr++;
    601         word = byte | (word << 8);
    602 #endif
    603         bitstream->word = word >> (bitstream->bitLeft);
    604     }
    605     else
    606     {
    607         bitstream->word = 0;
    608         bitstream->bitLeft = (WORD_SIZE << 3);
    609     }
    610 
    611     return PV_SUCCESS;
    612 }
    613 
    614 /* ======================================================================== */
    615 /*  Function : BitstreamFlushBits(BitstreamEncVideo *bitstream1,            */
    616 /*                              Int num_bit_left)                           */
    617 /*  Date     : 04/24/2002                                                   */
    618 /*  Purpose  : Flush buffer except the last num_bit_left bits.              */
    619 /*  In/out   :                                                              */
    620 /*  Return   :                                                              */
    621 /*  Modified :                                                              */
    622 /* ======================================================================== */
    623 
    624 
    625 PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left)
    626 {
    627     Int i;
    628     UChar *ptrDst, *ptrSrc;
    629     Int leftover, bitused;
    630     Int new_byte = (num_bit_left >> 3);
    631     Int new_bit = num_bit_left - (new_byte << 3); /* between 0-7 */
    632 
    633     ptrSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
    634     ptrDst = bitstream1->bitstreamBuffer;
    635 
    636     bitused = (WORD_SIZE << 3) - bitstream1->bitLeft;
    637 
    638     leftover = 8 - bitused; /* bitused should be between 0-7 */
    639 
    640     bitstream1->byteCount = new_byte;
    641     bitstream1->bitLeft = (WORD_SIZE << 3) - new_bit;
    642 
    643     if (!bitused) /* byte aligned */
    644     {
    645         M4VENC_MEMCPY(ptrDst, ptrSrc, new_byte + 1);
    646     }
    647     else
    648     {
    649         /*copy all the bytes in bitstream2*/
    650         for (i = 0; i < new_byte; i++)
    651         {
    652             *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
    653             ptrSrc++;
    654         }
    655         /* copy for the last byte of ptrSrc, copy extra bits doesn't hurt */
    656         if (new_bit)
    657         {
    658             *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
    659             ptrSrc++;
    660         }
    661     }
    662     if (new_bit)
    663     {
    664         ptrSrc = bitstream1->bitstreamBuffer + new_byte;
    665         bitstream1->word = (*ptrSrc) >> (8 - new_bit);
    666     }
    667 
    668     return PV_SUCCESS;
    669 }
    670 
    671 /* ======================================================================== */
    672 /*  Function : BitstreamPrependPacket( BitstreamEncVideo *bitstream1,       */
    673 /*                                      BitstreamEncVideo *bitstream2   )   */
    674 /*  Date     : 04/26/2002                                                   */
    675 /*  Purpose  : Prepend the intermediate bitstream (bitstream2) to the beginning of */
    676 /*              output bitstream(bitstream1) */
    677 /*  In/out   :                                                              */
    678 /*  Return   :                                                              */
    679 /*  Modified :                                                              */
    680 /* ======================================================================== */
    681 PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
    682 {
    683     UChar *pSrc, *pDst, byte;
    684     Int     movebyte, bitused, leftover, i, fraction;
    685 
    686     BitstreamSavePartial(bitstream2, &fraction); /* make sure only fraction of byte left */
    687     BitstreamSavePartial(bitstream1, &fraction);
    688 
    689     if (bitstream1->byteCount + bitstream2->byteCount >= bitstream1->bufferSize)
    690     {
    691         bitstream1->byteCount += bitstream2->byteCount;
    692         return PV_END_OF_BUF;
    693     }
    694 
    695     movebyte = bitstream1->byteCount;
    696     if (movebyte < bitstream2->byteCount)
    697         movebyte = bitstream2->byteCount;
    698     movebyte++;
    699 
    700     /* shift bitstream1 to the right by movebyte */
    701     pSrc = bitstream1->bitstreamBuffer;
    702     pDst = pSrc + movebyte;
    703 
    704     M4VENC_MEMCPY(pDst, pSrc, bitstream1->byteCount + 1);
    705 
    706     /* copy bitstream2 to the beginning of bitstream1 */
    707     M4VENC_MEMCPY(pSrc, bitstream2->bitstreamBuffer, bitstream2->byteCount + 1);
    708 
    709     /* now shift back previous bitstream1 buffer to the end */
    710     pSrc = pDst;
    711     pDst = bitstream1->bitstreamBuffer + bitstream2->byteCount;
    712 
    713     bitused = (WORD_SIZE << 3) - bitstream2->bitLeft;
    714     leftover = 8 - bitused;     /* bitused should be 0-7 */
    715 
    716     byte = (bitstream2->word) << leftover;
    717 
    718     *pDst++ = byte | (pSrc[0] >> bitused);
    719 
    720     for (i = 0; i < bitstream1->byteCount + 1; i++)
    721     {
    722         *pDst++ = ((pSrc[0] << leftover) | (pSrc[1] >> bitused));
    723         pSrc++;
    724     }
    725 
    726     bitstream1->byteCount += bitstream2->byteCount;
    727     //bitstream1->bitCount += bitstream2->bitCount;
    728     bitused = (WORD_SIZE << 4) - (bitstream1->bitLeft + bitstream2->bitLeft);
    729 
    730     if (bitused >= 8)
    731     {
    732         bitused -= 8;
    733         bitstream1->byteCount++;
    734     }
    735 
    736     bitstream1->bitLeft = (WORD_SIZE << 3) - bitused;
    737 
    738     bitstream2->byteCount = bitstream2->word = 0;
    739     bitstream2->bitLeft = (WORD_SIZE << 3);
    740 
    741     pSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
    742     leftover = 8 - bitused;
    743     //*pSrc = (pSrc[0]>>leftover)<<leftover; /* make sure the rest of bits are zeros */
    744 
    745     bitstream1->word = (UInt)((pSrc[0]) >> leftover);
    746 
    747     return PV_SUCCESS;
    748 }
    749 #endif  /* NO_SLICE_ENCODE */
    750 
    751 
    752 /* ======================================================================== */
    753 /*  Function : BitstreamGetPos( BitstreamEncVideo *stream                   */
    754 /*  Date     : 08/05/2004                                                   */
    755 /*  Purpose  : Get the bit position.                                        */
    756 /*  In/out   :                                                              */
    757 /*  Return   :                                                              */
    758 /*  Modified :                                                              */
    759 /* ======================================================================== */
    760 Int BitstreamGetPos(BitstreamEncVideo *stream)
    761 {
    762 
    763     return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
    764 }
    765 
    766 void BitstreamEncReset(BitstreamEncVideo *stream)
    767 {
    768     stream->bitLeft = (WORD_SIZE << 3);
    769     stream->word = 0;
    770     stream->byteCount = 0;
    771     return ;
    772 }
    773 
    774 /* This function set the overrun buffer, and VideoEncData context for callback to reallocate
    775 overrun buffer.  */
    776 Void  BitstreamSetOverrunBuffer(BitstreamEncVideo* stream, UChar* overrunBuffer, Int oBSize, VideoEncData *video)
    777 {
    778     stream->overrunBuffer = overrunBuffer;
    779     stream->oBSize = oBSize;
    780     stream->video = video;
    781 
    782     return ;
    783 }
    784 
    785 
    786 /* determine whether overrun buffer can be used or not */
    787 PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes)
    788 {
    789     VideoEncData *video = stream->video;
    790 
    791     if (stream->overrunBuffer != NULL) // overrunBuffer is set
    792     {
    793         if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
    794         {
    795             if (stream->byteCount + numExtraBytes >= stream->oBSize)
    796             {
    797                 stream->oBSize = stream->byteCount + numExtraBytes + 100;
    798                 stream->oBSize &= (~0x3); // make it multiple of 4
    799 
    800                 // allocate new overrun Buffer
    801                 if (video->overrunBuffer)
    802                 {
    803                     M4VENC_FREE(video->overrunBuffer);
    804                 }
    805                 video->oBSize = stream->oBSize;
    806                 video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
    807                 stream->overrunBuffer = video->overrunBuffer;
    808                 if (stream->overrunBuffer == NULL)
    809                 {
    810                     return PV_FAIL;
    811                 }
    812             }
    813 
    814             // copy everything to overrun buffer and start using it.
    815             memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->byteCount);
    816             stream->bitstreamBuffer = stream->overrunBuffer;
    817             stream->bufferSize = stream->oBSize;
    818         }
    819         else // overrun buffer is already used
    820         {
    821             if (stream->byteCount + numExtraBytes >= stream->oBSize)
    822             {
    823                 stream->oBSize = stream->byteCount + numExtraBytes + 100;
    824             }
    825 
    826             // allocate new overrun buffer
    827             stream->oBSize &= (~0x3); // make it multiple of 4
    828             video->oBSize = stream->oBSize;
    829             video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
    830             if (video->overrunBuffer == NULL)
    831             {
    832                 return PV_FAIL;
    833             }
    834 
    835             // copy from the old buffer to new buffer
    836             memcpy(video->overrunBuffer, stream->overrunBuffer, stream->byteCount);
    837             // free old buffer
    838             M4VENC_FREE(stream->overrunBuffer);
    839             // assign pointer to new buffer
    840             stream->overrunBuffer = video->overrunBuffer;
    841             stream->bitstreamBuffer = stream->overrunBuffer;
    842             stream->bufferSize = stream->oBSize;
    843         }
    844 
    845         return PV_SUCCESS;
    846     }
    847     else // overrunBuffer is not enable.
    848     {
    849         return PV_FAIL;
    850     }
    851 
    852 }
    853 
    854 
    855 
    856 
    857 
    858 
    859 
    860