159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ------------------------------------------------------------------
259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * Copyright (C) 1998-2009 PacketVideo
359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *
459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * Licensed under the Apache License, Version 2.0 (the "License");
559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * you may not use this file except in compliance with the License.
659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * You may obtain a copy of the License at
759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *
859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *      http://www.apache.org/licenses/LICENSE-2.0
959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *
1059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * Unless required by applicable law or agreed to in writing, software
1159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * distributed under the License is distributed on an "AS IS" BASIS,
1259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * express or implied.
1459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * See the License for the specific language governing permissions
1559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * and limitations under the License.
1659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong * -------------------------------------------------------------------
1759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong */
1859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* Date: 8/02/04                                                                */
1959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* Description:                                                                 */
2059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Change the bitstream parsing algorithm. Use temporary word of 2 or 4 bytes  */
2159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  before writing it to the bitstream buffer.                                  */
2259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Note byteCount doesn't have to be multiple of 2 or 4                        */
2359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*********************************************************************************/
2459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
2559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#include "bitstream_io.h"
2659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#include "m4venc_oscl.h"
2759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#include <stdlib.h>
2859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
2959f566c4ec3dfc097ad8163523e522280b27e5c3James Dongstatic const UChar Mask[ ] =
3059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
3159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
3259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong};
3359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
3459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#define WORD_SIZE   4   /* for 32-bit machine */
3559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
3659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*Note:
3759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    1. There is a problem when output the last bits(which can not form a byte yet
3859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    so when you output, you need to stuff to make sure it is a byte
3959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    2.  I now hard coded byte to be 8 bits*/
4059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
4159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
4259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
4359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitStreamCreateEnc(Int bufferSize )                          */
4459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
4559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Create a bitstream to hold one encoded video packet or frame */
4659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
4759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      bufferSize  :   size of the bitstream buffer in bytes               */
4859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   : Pointer to the BitstreamEncVideo                             */
4959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
5059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
5159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
5259f566c4ec3dfc097ad8163523e522280b27e5c3James DongBitstreamEncVideo *BitStreamCreateEnc(Int bufferSize)
5359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
5459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    BitstreamEncVideo *stream;
5559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream = (BitstreamEncVideo *) M4VENC_MALLOC(sizeof(BitstreamEncVideo));
5659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream == NULL)
5759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
5859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return NULL;
5959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
6059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bufferSize = bufferSize;
6159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitstreamBuffer = (UChar *) M4VENC_MALLOC(stream->bufferSize * sizeof(UChar));
6259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->bitstreamBuffer == NULL)
6359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
6459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        M4VENC_FREE(stream);
6559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream = NULL;
6659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return NULL;
6759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
6859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    M4VENC_MEMSET(stream->bitstreamBuffer, 0, stream->bufferSize*sizeof(UChar));
6959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->word = 0;
7059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#if WORD_SIZE==4
7159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitLeft = 32;
7259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#else
7359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitLeft = 16;
7459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#endif
7559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->byteCount = 0;
7659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
7759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->overrunBuffer = NULL;
7859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->oBSize = 0;
7959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
8059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return stream;
8159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
8259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
8359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
8459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamCloseEnc( )                                         */
8559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
8659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : close a bitstream                                            */
8759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :
8859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream  :   the bitstream to be closed                              */
8959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
9059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
9159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
9259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
9359f566c4ec3dfc097ad8163523e522280b27e5c3James DongVoid  BitstreamCloseEnc(BitstreamEncVideo *stream)
9459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
9559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream)
9659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
9759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (stream->bitstreamBuffer)
9859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
9959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            M4VENC_FREE(stream->bitstreamBuffer);
10059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
10159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
10259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        M4VENC_FREE(stream);
10359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
10459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
10559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
10659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
10759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
10859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamPutBits(BitstreamEncVideo *stream, Int Length,
10959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                         Int Value)                                         */
11059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
11159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : put Length (1-16) number of bits to the stream               */
11259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*            for 32-bit machine this function can do upto 32 bit input     */
11359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
11459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      stream      the bitstream where the bits are put in                 */
11559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      Length      bits length (should belong to 1 to 16)                  */
11659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      Value       those bits value                                        */
11759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :  PV_STATUS                                                   */
11859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
11959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
12059f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value)
12159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
12259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    PV_STATUS status;
12359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
12459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->bitLeft > Length)
12559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
12659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->word <<= Length;
12759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->word |= Value;  /* assuming Value is not larger than Length */
12859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->bitLeft -= Length;
12959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return PV_SUCCESS;
13059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
13159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    else
13259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
13359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
13459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->word <<= stream->bitLeft;
13559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        Length -= stream->bitLeft;
13659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->word |= ((UInt)Value >> Length);
13759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
13859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        status = BitstreamSaveWord(stream);
13959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (status != PV_SUCCESS)
14059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
14159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            return status;
14259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
14359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
14459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* we got new Length and Value */
14559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* note that Value is not "clean" because of msb are not masked out */
14659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->word = Value;
14759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        stream->bitLeft -= Length;
14859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* assuming that Length is no more than 16 bits */
14959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* stream->bitLeft should be greater than zero at this point */
15059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        //if(stream->bitLeft<=0)
15159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        //  exit(-1);
15259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return PV_SUCCESS;
15359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
15459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
15559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
15659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
15759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, UInt32 Value)    */
15859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
15959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Use this function to put Length (17-32) number of bits to    */
16059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*              for 16-bit machine  the stream.                             */
16159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
16259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      stream      the bitstream where the bits are put in                 */
16359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      Length      bits length (should belong to 17 to 32)                 */
16459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      Value       those bits value                                        */
16559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :  PV_STATUS                                                   */
16659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
16759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
16859f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value)
16959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
17059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    PV_STATUS status;
17159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UInt topValue;
17259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int topLength;
17359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
17459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    topValue = (Value >> 16);
17559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    topLength = Length - 16;
17659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
17759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (topLength > 0)
17859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
17959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        status = BitstreamPutBits(stream, topLength, topValue);
18059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
18159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (status != PV_SUCCESS)
18259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
18359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            return status;
18459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
18559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
18659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        status = BitstreamPutBits(stream, 16, (UInt)(Value & 0xFFFF));
18759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
18859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return status;
18959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
19059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    else
19159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
19259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        status = BitstreamPutBits(stream, Length, (UInt)Value);
19359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return status;
19459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
19559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
19659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
19759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
19859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamSaveWord                                            */
19959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/03/2004                                                   */
20059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : save written word into the bitstream buffer.                 */
20159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
20259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      stream      the bitstream where the bits are put in                 */
20359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :  PV_STATUS                                                   */
20459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
20559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
20659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
20759f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream)
20859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
20959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptr;
21059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UInt word;
21159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
21259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* assume that stream->bitLeft is always zero when this function is called */
21359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->byteCount + WORD_SIZE > stream->bufferSize)
21459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
21559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, WORD_SIZE))
21659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
21759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->byteCount += WORD_SIZE;
21859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            return PV_FAIL;
21959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
22059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
22159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
22259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptr = stream->bitstreamBuffer + stream->byteCount;
22359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    word = stream->word;
22459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->word = 0; /* important to reset to zero */
22559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
22659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* NOTE: byteCount does not have to be multiple of 2 or 4 */
22759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#if (WORD_SIZE == 4)
22859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    *ptr++ = word >> 24;
22959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    *ptr++ = 0xFF & (word >> 16);
23059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#endif
23159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
23259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    *ptr++ = 0xFF & (word >> 8);
23359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    *ptr = 0xFF & word;
23459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
23559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#if (WORD_SIZE == 4)
23659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->byteCount += 4;
23759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitLeft = 32;
23859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#else
23959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->byteCount += 2;
24059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitLeft = 16;
24159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#endif
24259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
24359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return PV_SUCCESS;
24459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
24559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
24659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
24759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
24859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamSavePartial                                         */
24959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/03/2004                                                   */
25059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : save unfinished written word into the bitstream buffer.      */
25159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
25259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*      stream      the bitstream where the bits are put in                 */
25359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :  PV_STATUS                                                   */
25459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
25559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
25659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
25759f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction)
25859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
25959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptr;
26059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UInt word, shift;
26159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int numbyte, bitleft, bitused;
26259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
26359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitleft = stream->bitLeft;
26459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitused = (WORD_SIZE << 3) - bitleft; /* number of bits used */
26559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    numbyte = bitused >> 3; /* number of byte fully used */
26659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
26759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->byteCount + numbyte > stream->bufferSize)
26859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
26959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, numbyte))
27059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
27159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->byteCount += numbyte;
27259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            return PV_FAIL;
27359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
27459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
27559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
27659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptr = stream->bitstreamBuffer + stream->byteCount;
27759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    word = stream->word;
27859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    word <<= bitleft;   /* word is not all consumed */
27959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitleft = bitused - (numbyte << 3); /* number of bits used (fraction) */
28059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->byteCount += numbyte;
28159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitleft)
28259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
28359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        *fraction = 1;
28459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
28559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    else
28659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
28759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        *fraction = 0;
28859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
28959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitleft = (WORD_SIZE << 3) - bitleft;
29059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* save new value */
29159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitLeft = bitleft;
29259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
29359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    shift = ((WORD_SIZE - 1) << 3);
29459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    while (numbyte)
29559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
29659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        *ptr++ = (UChar)((word >> shift) & 0xFF);
29759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        word <<= 8;
29859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        numbyte--;
29959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
30059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
30159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (*fraction)
30259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {// this could lead to buffer overrun when ptr is already out of bound.
30359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        //  *ptr = (UChar)((word>>shift)&0xFF); /* need to do it for the last fractional byte */
30459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
30559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
30659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* save new values */
30759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->word = word >> bitleft;
30859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
30959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* note we don't update byteCount, bitLeft and word */
31059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* so that encoder can continue PutBits if they don't */
31159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
31259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return PV_SUCCESS;
31359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
31459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
31559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
31659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
31759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamShortHeaderByteAlignStuffing(                       */
31859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                                      BitstreamEncVideo *stream)          */
31959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
32059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : bit stuffing for next start code in short video header       */
32159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
32259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :  number of bits to be stuffed                                */
32359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
32459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
32559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
32659f566c4ec3dfc097ad8163523e522280b27e5c3James DongInt BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream)
32759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
32859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UInt restBits;
32959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int fraction;
33059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
33159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    restBits = (stream->bitLeft & 0x7); /* modulo 8 */
33259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
33359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
33459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
33559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* H.263 style stuffing */
33659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        BitstreamPutBits(stream, restBits, 0);
33759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
33859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
33959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->bitLeft != (WORD_SIZE << 3))
34059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
34159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        BitstreamSavePartial(stream, &fraction);
34259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
34359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
34459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return restBits;
34559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
34659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
34759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
34859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)   */
34959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
35059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : bit stuffing for next start code in MPEG-4                  */
35159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
35259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :  number of bits to be stuffed                                */
35359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
35459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
35559f566c4ec3dfc097ad8163523e522280b27e5c3James DongInt BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)
35659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
35759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
35859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UInt restBits;
35959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int fraction;
36059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* Question: in MPEG-4 , short_video_header[0]==0 => even already byte aligned, will still stuff 8 bits
36159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong       need to check with  */
36259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /*if (!(getPointerENC(index1, index2)%8) && short_video_header[0]) return 0;*/
36359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
36459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* need stuffing bits, */
36559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    BitstreamPutBits(stream, 1, 0);
36659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
36759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    restBits = (stream->bitLeft & 0x7); /* modulo 8 */
36859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
36959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
37059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
37159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* need stuffing bits, */
37259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        BitstreamPutBits(stream, restBits, Mask[restBits]);
37359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
37459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
37559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->bitLeft != (WORD_SIZE << 3))
37659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
37759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        BitstreamSavePartial(stream, &fraction);
37859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
37959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
38059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return (restBits);
38159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
38259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
38359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*does bit stuffing for next resync marker*/
38459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  does bit stuffing for next resync marker
38559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                            "0"
38659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                           "01"
38759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                          "011"
38859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                         "0111"
38959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                        "01111"
39059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                       "011111"
39159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                      "0111111"
39259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong *                                     "01111111"   (8-bit codeword)
39359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong */
39459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
39559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*Int BitstreamNextResyncMarkerEnc(BitstreamEncVideo *stream)
39659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
39759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong  Int count;
39859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong  BitstreamPut1Bits(stream,0);
39959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong  count=8-stream->totalBits & 8;
40059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong  BitstreamPutBits(stream,count,Mask[count]);
40159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong  return count;
40259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}*/
40359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
40459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
40559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamAppendEnc( BitstreamEncVideo *bitstream1,           */
40659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                                      BitstreamEncVideo *bitstream2   )   */
40759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/29/2000                                                   */
40859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
40959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                              output bitstream(bitstream1)                */
41059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
41159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
41259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
41359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
41459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
41559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
41659f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
41759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
41859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    PV_STATUS status;
41959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptrBS2, *ptrBS1;
42059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar byteBS2, byteBS1;
42159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int  numbyte2;
42259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int bitused, bitleft, offset, fraction;
42359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
42459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    status = BitstreamSavePartial(bitstream1, &fraction);
42559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (status != PV_SUCCESS)
42659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
42759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return status;
42859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
42959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
43059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    offset = fraction;
43159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    status = BitstreamSavePartial(bitstream2, &fraction);
43259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (status != PV_SUCCESS)
43359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
43459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return status;
43559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
43659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
43759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (!offset) /* bitstream1 is byte-aligned */
43859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
43959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return BitstreamAppendPacket(bitstream1, bitstream2);
44059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
44159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
44259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    offset += fraction;
44359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
44459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* since bitstream1 doesn't have to be byte-aligned, we have to process byte by byte */
44559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* we read one byte from bitstream2 and use BitstreamPutBits to do the job */
44659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitstream1->byteCount + bitstream2->byteCount + offset > bitstream1->bufferSize)
44759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
44859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount + offset))
44959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
45059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            bitstream1->byteCount += (bitstream2->byteCount + offset);
45159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            return PV_FAIL;
45259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
45359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
45459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
45559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
45659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrBS2 = bitstream2->bitstreamBuffer;
45759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
45859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitused = (WORD_SIZE << 3) - bitstream1->bitLeft; /* this must be between 1-7 */
45959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitleft = 8 - bitused;
46059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
46159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    numbyte2 = bitstream2->byteCount;   /* number of byte to copy from bs2 */
46259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->byteCount += numbyte2;  /* new byteCount */
46359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
46459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    byteBS1 = ((UChar) bitstream1->word) << bitleft;    /* fraction byte from bs1 */
46559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
46659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    while (numbyte2)
46759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
46859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byteBS2 = *ptrBS2++;
46959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byteBS1 |= (byteBS2 >> bitused);
47059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        *ptrBS1++ = byteBS1;
47159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byteBS1 = byteBS2 << bitleft;
47259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        numbyte2--;
47359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
47459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
47559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->word = byteBS1 >> bitleft;  /* bitstream->bitLeft remains the same */
47659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
47759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* now save bs2->word in bs1 */
47859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    status = BitstreamPutBits(bitstream1, (WORD_SIZE << 3) - bitstream2->bitLeft, bitstream2->word);
47959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
48059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return status;
48159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
48259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
48359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
48459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamAppendPacket( BitstreamEncVideo *bitstream1,        */
48559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                                      BitstreamEncVideo *bitstream2   )   */
48659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 05/31/2001                                                   */
48759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
48859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*              output bitstream(bitstream1) knowing that bitstream1 is byte-aligned*/
48959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
49059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
49159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
49259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
49359f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
49459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
49559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptrBS2, *ptrBS1;
49659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int  numbyte2;
49759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
49859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitstream1->byteCount + bitstream2->byteCount  > bitstream1->bufferSize)
49959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
50059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount))
50159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
50259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            bitstream1->byteCount += bitstream2->byteCount; /* legacy, to keep track of total bytes */
50359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            return PV_FAIL;
50459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
50559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
50659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
50759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
50859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrBS2 = bitstream2->bitstreamBuffer;
50959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
51059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    numbyte2 = bitstream2->byteCount;
51159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->byteCount += numbyte2; /* new byteCount */
51259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
51359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /*copy all the bytes in bitstream2*/
51459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
51559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
51659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->word = bitstream2->word;  /* bitstream1->bitLeft is the same */
51759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->bitLeft = bitstream2->bitLeft;
51859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
51959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return PV_SUCCESS;
52059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
52159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
52259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
52359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamAppendPacketNoOffset( BitstreamEncVideo *bitstream1,*/
52459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                                      BitstreamEncVideo *bitstream2   )   */
52559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 04/23/2002                                                   */
52659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
52759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*              output bitstream(bitstream1) , for slice-based coding only */
52859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
52959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
53059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
53159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
53259f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
53359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
53459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    PV_STATUS status = PV_SUCCESS;
53559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptrBS2, *ptrBS1;
53659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int  numbyte2;
53759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int  byteleft;
53859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
53959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    numbyte2 = bitstream2->byteCount;
54059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
54159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
54259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
54359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        numbyte2 =  bitstream1->bufferSize - bitstream1->byteCount;
54459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        status =  PV_END_OF_BUF;    /* signal end of buffer */
54559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
54659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
54759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrBS1 = bitstream1->bitstreamBuffer; /* move ptr bs1*/
54859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrBS2 = bitstream2->bitstreamBuffer;
54959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
55059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->byteCount += numbyte2; /* should be equal to bufferSize */
55159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
55259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /*copy all the bytes in bitstream2*/
55359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
55459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->word = 0;
55559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->bitLeft = (WORD_SIZE << 3);
55659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
55759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (status == PV_END_OF_BUF) /* re-position bitstream2 */
55859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
55959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byteleft = bitstream2->byteCount - numbyte2;
56059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
56159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        M4VENC_MEMCPY(ptrBS2, ptrBS2 + numbyte2, sizeof(UChar)*byteleft);
56259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
56359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream2->byteCount = byteleft;
56459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* bitstream2->word and bitstream->bitLeft are unchanged.
56559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong           they should be 0 and (WORD_SIZE<<3) */
56659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
56759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
56859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return status;
56959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
57059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
57159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#ifndef NO_SLICE_ENCODE
57259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
57359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamRepos( BitstreamEncVideo *bitstream,                */
57459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                                      Int byteCount, Int bitCount)        */
57559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 04/28/2002                                                   */
57659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Reposition the size of the buffer content (curtail)          */
57759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
57859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
57959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
58059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
58159f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS   BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount)
58259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
58359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptr, byte;
58459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UInt word;
58559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int fraction;
58659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
58759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    BitstreamSavePartial(bitstream, &fraction);
58859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
58959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream->byteCount = byteCount;
59059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptr = bitstream->bitstreamBuffer + byteCount; /* get fraction of the byte */
59159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitCount)
59259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
59359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream->bitLeft = (WORD_SIZE << 3) - bitCount; /* bitCount should be 0-31 */
59459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        word = *ptr++;
59559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byte = *ptr++;
59659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        word = byte | (word << 8);
59759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#if (WORD_SIZE == 4)
59859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byte = *ptr++;
59959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        word = byte | (word << 8);
60059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        byte = *ptr++;
60159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        word = byte | (word << 8);
60259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#endif
60359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream->word = word >> (bitstream->bitLeft);
60459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
60559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    else
60659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
60759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream->word = 0;
60859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream->bitLeft = (WORD_SIZE << 3);
60959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
61059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
61159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return PV_SUCCESS;
61259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
61359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
61459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
61559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamFlushBits(BitstreamEncVideo *bitstream1,            */
61659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                              Int num_bit_left)                           */
61759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 04/24/2002                                                   */
61859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Flush buffer except the last num_bit_left bits.              */
61959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
62059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
62159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
62259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
62359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
62459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
62559f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left)
62659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
62759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int i;
62859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *ptrDst, *ptrSrc;
62959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int leftover, bitused;
63059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int new_byte = (num_bit_left >> 3);
63159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int new_bit = num_bit_left - (new_byte << 3); /* between 0-7 */
63259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
63359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
63459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    ptrDst = bitstream1->bitstreamBuffer;
63559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
63659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitused = (WORD_SIZE << 3) - bitstream1->bitLeft;
63759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
63859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    leftover = 8 - bitused; /* bitused should be between 0-7 */
63959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
64059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->byteCount = new_byte;
64159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->bitLeft = (WORD_SIZE << 3) - new_bit;
64259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
64359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (!bitused) /* byte aligned */
64459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
64559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        M4VENC_MEMCPY(ptrDst, ptrSrc, new_byte + 1);
64659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
64759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    else
64859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
64959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /*copy all the bytes in bitstream2*/
65059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        for (i = 0; i < new_byte; i++)
65159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
65259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
65359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            ptrSrc++;
65459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
65559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        /* copy for the last byte of ptrSrc, copy extra bits doesn't hurt */
65659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (new_bit)
65759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
65859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
65959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            ptrSrc++;
66059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
66159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
66259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (new_bit)
66359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
66459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        ptrSrc = bitstream1->bitstreamBuffer + new_byte;
66559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream1->word = (*ptrSrc) >> (8 - new_bit);
66659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
66759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
66859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return PV_SUCCESS;
66959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
67059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
67159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
67259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamPrependPacket( BitstreamEncVideo *bitstream1,       */
67359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*                                      BitstreamEncVideo *bitstream2   )   */
67459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 04/26/2002                                                   */
67559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Prepend the intermediate bitstream (bitstream2) to the beginning of */
67659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*              output bitstream(bitstream1) */
67759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
67859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
67959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
68059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
68159f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
68259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
68359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    UChar *pSrc, *pDst, byte;
68459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    Int     movebyte, bitused, leftover, i, fraction;
68559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
68659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    BitstreamSavePartial(bitstream2, &fraction); /* make sure only fraction of byte left */
68759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    BitstreamSavePartial(bitstream1, &fraction);
68859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
68959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitstream1->byteCount + bitstream2->byteCount >= bitstream1->bufferSize)
69059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
69159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream1->byteCount += bitstream2->byteCount;
69259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return PV_END_OF_BUF;
69359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
69459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
69559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    movebyte = bitstream1->byteCount;
69659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (movebyte < bitstream2->byteCount)
69759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        movebyte = bitstream2->byteCount;
69859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    movebyte++;
69959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
70059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* shift bitstream1 to the right by movebyte */
70159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    pSrc = bitstream1->bitstreamBuffer;
70259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    pDst = pSrc + movebyte;
70359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
70459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    M4VENC_MEMCPY(pDst, pSrc, bitstream1->byteCount + 1);
70559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
70659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* copy bitstream2 to the beginning of bitstream1 */
70759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    M4VENC_MEMCPY(pSrc, bitstream2->bitstreamBuffer, bitstream2->byteCount + 1);
70859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
70959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    /* now shift back previous bitstream1 buffer to the end */
71059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    pSrc = pDst;
71159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    pDst = bitstream1->bitstreamBuffer + bitstream2->byteCount;
71259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
71359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitused = (WORD_SIZE << 3) - bitstream2->bitLeft;
71459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    leftover = 8 - bitused;     /* bitused should be 0-7 */
71559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
71659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    byte = (bitstream2->word) << leftover;
71759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
71859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    *pDst++ = byte | (pSrc[0] >> bitused);
71959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
72059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    for (i = 0; i < bitstream1->byteCount + 1; i++)
72159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
72259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        *pDst++ = ((pSrc[0] << leftover) | (pSrc[1] >> bitused));
72359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        pSrc++;
72459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
72559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
72659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->byteCount += bitstream2->byteCount;
72759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    //bitstream1->bitCount += bitstream2->bitCount;
72859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitused = (WORD_SIZE << 4) - (bitstream1->bitLeft + bitstream2->bitLeft);
72959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
73059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (bitused >= 8)
73159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
73259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitused -= 8;
73359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        bitstream1->byteCount++;
73459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
73559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
73659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->bitLeft = (WORD_SIZE << 3) - bitused;
73759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
73859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream2->byteCount = bitstream2->word = 0;
73959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream2->bitLeft = (WORD_SIZE << 3);
74059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
74159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    pSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
74259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    leftover = 8 - bitused;
74359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    //*pSrc = (pSrc[0]>>leftover)<<leftover; /* make sure the rest of bits are zeros */
74459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
74559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    bitstream1->word = (UInt)((pSrc[0]) >> leftover);
74659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
74759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return PV_SUCCESS;
74859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
74959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong#endif  /* NO_SLICE_ENCODE */
75059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
75159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
75259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
75359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Function : BitstreamGetPos( BitstreamEncVideo *stream                   */
75459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Date     : 08/05/2004                                                   */
75559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Purpose  : Get the bit position.                                        */
75659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  In/out   :                                                              */
75759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Return   :                                                              */
75859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/*  Modified :                                                              */
75959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* ======================================================================== */
76059f566c4ec3dfc097ad8163523e522280b27e5c3James DongInt BitstreamGetPos(BitstreamEncVideo *stream)
76159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
76259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
76359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
76459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
76559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
76659f566c4ec3dfc097ad8163523e522280b27e5c3James Dongvoid BitstreamEncReset(BitstreamEncVideo *stream)
76759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
76859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->bitLeft = (WORD_SIZE << 3);
76959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->word = 0;
77059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->byteCount = 0;
77159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return ;
77259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
77359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
77459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* This function set the overrun buffer, and VideoEncData context for callback to reallocate
77559f566c4ec3dfc097ad8163523e522280b27e5c3James Dongoverrun buffer.  */
77659f566c4ec3dfc097ad8163523e522280b27e5c3James DongVoid  BitstreamSetOverrunBuffer(BitstreamEncVideo* stream, UChar* overrunBuffer, Int oBSize, VideoEncData *video)
77759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
77859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->overrunBuffer = overrunBuffer;
77959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->oBSize = oBSize;
78059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    stream->video = video;
78159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
78259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    return ;
78359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
78459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
78559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
78659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong/* determine whether overrun buffer can be used or not */
78759f566c4ec3dfc097ad8163523e522280b27e5c3James DongPV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes)
78859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong{
78959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    VideoEncData *video = stream->video;
79059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
79159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    if (stream->overrunBuffer != NULL) // overrunBuffer is set
79259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
79359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
79459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
79559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            if (stream->byteCount + numExtraBytes >= stream->oBSize)
79659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            {
79759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                stream->oBSize = stream->byteCount + numExtraBytes + 100;
79859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                stream->oBSize &= (~0x3); // make it multiple of 4
79959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
80059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                // allocate new overrun Buffer
80159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                if (video->overrunBuffer)
80259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                {
80359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                    M4VENC_FREE(video->overrunBuffer);
80459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                }
80559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                video->oBSize = stream->oBSize;
80659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
80759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                stream->overrunBuffer = video->overrunBuffer;
80859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                if (stream->overrunBuffer == NULL)
80959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                {
81059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                    return PV_FAIL;
81159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                }
81259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            }
81359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
81459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            // copy everything to overrun buffer and start using it.
81559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->byteCount);
81659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->bitstreamBuffer = stream->overrunBuffer;
81759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->bufferSize = stream->oBSize;
81859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
81959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        else // overrun buffer is already used
82059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        {
82159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            if (stream->byteCount + numExtraBytes >= stream->oBSize)
82259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            {
82359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                stream->oBSize = stream->byteCount + numExtraBytes + 100;
82459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            }
82559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
82659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            // allocate new overrun buffer
82759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->oBSize &= (~0x3); // make it multiple of 4
82859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            video->oBSize = stream->oBSize;
82959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
83059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            if (video->overrunBuffer == NULL)
83159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            {
83259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong                return PV_FAIL;
83359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            }
83459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
83559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            // copy from the old buffer to new buffer
83659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            memcpy(video->overrunBuffer, stream->overrunBuffer, stream->byteCount);
83759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            // free old buffer
83859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            M4VENC_FREE(stream->overrunBuffer);
83959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            // assign pointer to new buffer
84059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->overrunBuffer = video->overrunBuffer;
84159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->bitstreamBuffer = stream->overrunBuffer;
84259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong            stream->bufferSize = stream->oBSize;
84359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        }
84459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
84559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return PV_SUCCESS;
84659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
84759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    else // overrunBuffer is not enable.
84859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    {
84959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong        return PV_FAIL;
85059f566c4ec3dfc097ad8163523e522280b27e5c3James Dong    }
85159f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85259f566c4ec3dfc097ad8163523e522280b27e5c3James Dong}
85359f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85459f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85559f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85659f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85759f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85859f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
85959f566c4ec3dfc097ad8163523e522280b27e5c3James Dong
860