videoeditorengine/h263decoder/src/biblin.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description:  
* Bit buffer reading operations.
*
*/




/*
* Includes
*/

#include "h263dConfig.h"
#include "Biblin.h"
#include "debug.h"

#ifdef DEBUG_OUTPUT
bibBuffer_t * buffer_global;
#endif


/*
* Definitions
*/

#define bibMalloc malloc
#define bibCalloc calloc
#define bibRealloc realloc
#define bibDealloc free

#ifndef bibAssert
#define bibAssert(exp) assert(exp);
#endif


/*
* Local function prototypes
*/

static void bibInitialize(
                                                    bibBuffer_t *bibBuffer,
                                                    void *srcBuffer,
                                                    unsigned srcBufferLength,
                                                    int16 *errorCode);




/*
* Imported variables
*/



/*
* Global functions
*/

/* {{-output"bibCreate.txt"}} */
/*
*
* bibCreate
*    
*
* Parameters:
*    srcBuffer                  buffer containing the data
*    srcBufferLength            the length of the buffer
*    errorCode                  error code
*
* Function:
*    This function creates a bit buffer from a buffer given as a parameter.
*
* Returns:
*    The bibCreate function returns a pointer to a bibBuffer_t
*    structure. If the function is unsuccessful NULL is returned.
*
* Error codes:
*    ERR_BIB_STRUCT_ALLOC       if the bit buffer structure could not be
*                               allocated
*
*/

bibBuffer_t *bibCreate(void *srcBuffer, unsigned srcBufferLength, int16 *errorCode)
/* {{-output"bibCreate.txt"}} */
{
    bibBuffer_t *bibBuffer = NULL;
    int16 tmpError = 0;
    
    bibBuffer = (bibBuffer_t *) bibMalloc(sizeof(bibBuffer_t));
    if (bibBuffer == NULL) {
        *errorCode = ERR_BIB_STRUCT_ALLOC;
        deb("bibCreate: ERROR - bibMalloc failed.\n");
        return NULL;
    }
    
    bibInitialize(bibBuffer, srcBuffer, srcBufferLength, &tmpError);
    if (tmpError) {
        bibDealloc(bibBuffer);
        return NULL;
    }
    
#ifdef DEBUG_OUTPUT
    debLoad("deb_dec.log");
    buffer_global = bibBuffer;
#endif
    
    return bibBuffer;
}




bibBufferEdit_t *bibBufferEditCreate(int16 *errorCode)
/* {{-output"bibCreate.txt"}} */
{
    bibBufferEdit_t *bufEdit = NULL;    
    
    bufEdit = (bibBufferEdit_t *) bibMalloc(sizeof(bibBufferEdit_t));
    if (bufEdit == NULL) {
        *errorCode = ERR_BIB_STRUCT_ALLOC;
        deb("bibBufferEditCreate: ERROR - bibMalloc failed.\n");
        return NULL;
    }
     bufEdit->copyMode = CopyWhole/*CopyWhole*/;
     bufEdit->numChanges=0;
     bufEdit->editParams=NULL;
     
   return bufEdit;
}




/* {{-output"bibDelete.txt"}} */
/*
*
* bibDelete
*    
*
* Parameters:
*    buffer                     a pointer to a bit buffer structure
*    errorCode                  error code
*
* Function:
*    The bibDelete function frees the memory allocated for the buffer.
*
* Returns:
*    Nothing
*
* Error codes:
*    None
*
*/

void bibDelete(bibBuffer_t *buffer, int16 * /*errorCode*/)
/* {{-output"bibDelete.txt"}} */
{
    if (buffer) {
        // note that the BaseAddr is just a reference to memory allocated elsewhere
        // and there is no other dynamic allocations inside buffer
        bibDealloc((void *) buffer);
    }
}



void bibBufEditDelete(bibBufferEdit_t *bufEdit, int16 * /*errorCode*/)
{
     int i;
   if (bufEdit) {
         for(i=0; i<bufEdit->numChanges; i++)
             bibDealloc((void *) bufEdit->editParams);
         bibDealloc((void *) bufEdit);
   }
}


/*
*
* bibFlushBits
* bibGetBits
* bibShowBits
*    
*
* Parameters:
*    numberOfBits               the number of bits wanted (1..32)
*    buffer                     a pointer to a bit buffer structure
*    numberOfBitsGot            the number of bits actually got
*    syncStartIndex             the number of the first bit belonging to 
*                               a synchronization code (1 .. numberOfBits).
*                               Bits are numbered starting from 1 given to
*                               the most significant bit of the returned code.
*                               Thus, syncStartIndex - 1 most significant bits
*                               of the returned code are valid coding
*                               parameters (do not belong to a sync code).
*                               0 is returned if the returned code does not
*                               contain any part of a synchronization code.
*    bitErrorIndication         indication code for bit errors,
*                               see biterr.h for the possible values
*    errorCode                  error code
*
* Function:
*    The bibFlushBits function removes the next numberOfBits bits from
*    the buffer.
*
*    The bibGetBits function gets the next numberOfBits bits from the buffer.
*    The returned bits are removed.
*
*    The bibShowBits function gets the next numberOfBits bits from the
*    buffer. The returned bits are not removed from the buffer.
*
* Returns:
*   bibGetBits and bibShowBits:
*       the next numberOfBits bits / the rest of the buffer if the end of
*       the input file has been reached
*
* Error codes:
*    ERR_BIB_NOT_ENOUGH_DATA    if one tries to get more bits from the buffer
*                               than there is left
*
*/

void bibFlushBits(int numberOfBits, bibBuffer_t *buffer)
{
    bibAssert(buffer != NULL);
    bibAssert(numberOfBits > 0 && numberOfBits <= 32);
    
    /* Check if enough bits are available. */
    if (buffer->bitsLeft < (u_int32) numberOfBits) {
        goto flush_underflow;
    }
    buffer->bitsLeft -= numberOfBits;
    
    if ( buffer->bitIndex >= numberOfBits ) {
        /* All in the current byte, bits still left */
        buffer->bitIndex -= numberOfBits;
    }
    else if ( buffer->bitIndex == (numberOfBits-1) ) {
        /* Current byte used completely */
        buffer->bitIndex = 7;
        buffer->getIndex++;
        buffer->numBytesRead++;
    }
    else {
        /* Current byte plus then some */
        numberOfBits -= buffer->bitIndex + 1; /* this many bits after current byte */
        buffer->getIndex += ((numberOfBits>>3) + 1);
        buffer->numBytesRead += ((numberOfBits>>3) + 1);
        buffer->bitIndex = 7 - (numberOfBits&7); 
    }
    return;
flush_underflow:
    buffer->error = ERR_BIB_NOT_ENOUGH_DATA;
}



/*
*
* bibGetAlignedByte
*    
*
* A fast function to get one byte from byte-boundary.
*
*/
inline u_int8 bibGetAlignedByte(bibBuffer_t *buffer)   
    {
    return buffer->baseAddr[buffer->getIndex++];
    }


/*
*
* bibGetBits
*    
*
* See bibFlushBits.
*
*/

u_int32 bibGetBits(int numberOfBits, bibBuffer_t *buffer)   
{
    static const u_char
        msbMask[8] = {1, 3, 7, 15, 31, 63, 127, 255},
        lsbMask[9] = {255, 254, 252, 248, 240, 224, 192, 128, 0};
    u_char
        *startAddr;
    int32
        bitIndex;
    u_int32
        endShift;         /* the number of shifts after masking the last byte */
    u_int32
        numBytesFlushed;  /* the number of bytes flushed from the buffer */
    u_int32
        returnValue = 0;
    
    bibAssert(buffer != NULL);
    bibAssert(numberOfBits > 0 && numberOfBits <= 32);
    
    startAddr = buffer->baseAddr + buffer->getIndex;
    bitIndex = buffer->bitIndex;
    
    /* Check if enough bits are available. */
    if (buffer->bitsLeft < (u_int32) numberOfBits) {
        goto get_underflow;
    }
    
    buffer->bitsLeft -= numberOfBits;
    
    if ( bitIndex >= numberOfBits ) {
        /* All in the current byte, bits still left */
        endShift = bitIndex - numberOfBits + 1;
        buffer->bitIndex -= numberOfBits;
        return ((startAddr[0] & msbMask[bitIndex] & lsbMask[endShift]) >> endShift);
    }
    else if ( bitIndex == (numberOfBits-1) ) {
        /* Current byte used completely */
        buffer->bitIndex = 7;
        buffer->getIndex++;
        buffer->numBytesRead++;
        return startAddr[0] & msbMask[bitIndex];
    }
    else {
        /* Current byte plus then some */
        
        /* Remainder of this byte */
        returnValue = *(startAddr++) & msbMask[bitIndex];
        numberOfBits -= bitIndex + 1;
        numBytesFlushed = 1 + (numberOfBits >> 3);
        
        /* Get full bytes */
        while ( numberOfBits >= 8 ) {
            returnValue = (returnValue << 8) | *(startAddr++);
            numberOfBits -= 8;
        }
        
        /* Get bits from last byte */
        endShift = 8 - numberOfBits;
        returnValue = (returnValue << numberOfBits) | ((startAddr[0] & lsbMask[endShift]) >> endShift);
        /* (safe, since lsbMask[8]==0) */
        
        /* Update position in buffer */
        buffer->bitIndex = 7 - numberOfBits;
        buffer->getIndex += numBytesFlushed;
        buffer->numBytesRead += numBytesFlushed;
    }
    
    return returnValue;
get_underflow:
    buffer->error = ERR_BIB_NOT_ENOUGH_DATA;
    return 0;
}


/* {{-output"bibNumberOfFlushedBits.txt"}} */
/*
*
* bibNumberOfFlushedBits
*    
*
* Parameters:
*    buffer                     a pointer to a bit buffer structure
*
* Function:
*    The bibNumberOfFlushedBytes returns the number of bits which
*    are got (bibGetBits) or flushed (bibFlushBits) from the buffer since
*    the buffer was created
*
* Returns:
*    See above.
*
* Error codes:
*    None.
*
*/

u_int32 bibNumberOfFlushedBits(bibBuffer_t *buffer)
/* {{-output"bibNumberOfFlushedBits.txt"}} */
{
    bibAssert(buffer != NULL);
    
    return ((buffer->numBytesRead<<3) + (7-buffer->bitIndex));
}


/* {{-output"bibNumberOfFlushedBytes.txt"}} */
/*
*
* bibNumberOfFlushedBytes
*    
*
* Parameters:
*    buffer                     a pointer to a bit buffer structure
*
* Function:
*    The bibNumberOfFlushedBytes returns the number of whole bytes which
*    are got (bibGetBits) or flushed (bibFlushBits) from the buffer since
*    bibCreate was called.
*
* Returns:
*    See above.
*
* Error codes:
*    None.
*
*/

u_int32 bibNumberOfFlushedBytes(bibBuffer_t *buffer)
/* {{-output"bibNumberOfFlushedBytes.txt"}} */
{
    bibAssert(buffer != NULL);
    
    return buffer->numBytesRead;
}


/* {{-output"bibNumberOfRewBits.txt"}} */
/*
*
* bibNumberOfRewBits
*    
*
* Parameters:
*    buffer                     a pointer to a bit buffer structure
*
* Function:
*    The bibNumberOfRewBits returns the number of bits which can be
*    successfully rewinded.
*
* Returns:
*    See above.
*
* Error codes:
*    None.
*
*/

u_int32 bibNumberOfRewBits(bibBuffer_t *buffer)
/* {{-output"bibNumberOfRewBits.txt"}} */
{
    bibAssert(buffer != NULL);
    
    return ((buffer->numBytesRead<<3) + (7-buffer->bitIndex));
}


/* {{-output"bibRewindBits.txt"}} */
/*
*
* bibRewindBits
*    
*
* Parameters:
*    numberOfBits               the number of bits to rewind
*    buffer                     a pointer to a bit buffer structure
*    errorCode                  error code
*
* Function:
*    This function rewinds the pointers to the buffer
*    so that already flushed or got bits can be read
*    again.
*
* Returns:
*    Nothing.
*
* Error codes:
*    ERR_BIB_CANNOT_REWIND      if numberOfBits is larger than which is
*                               possible to get (see also bibNumberOfRewBits).
*
*    ERR_BIB_BUFLIST            if there was a fatal error when handling
*                               buffer lists
*
*/

void bibRewindBits(u_int32 numberOfBits, bibBuffer_t *buffer, int16 *errorCode)
/* {{-output"bibRewindBits.txt"}} */
{
    bibAssert(buffer != NULL);
    
    /* All bits to rewind are in the latest byte */
    if (numberOfBits <= (u_int32) (7 - buffer->bitIndex)) {
        buffer->bitIndex += numberOfBits;
    }
    /* Bits to rewind are within several bytes */
    else {
        u_int32
            numBitsWithoutFirstByte = numberOfBits - (7 - buffer->bitIndex),
            numWholeBytes = (numBitsWithoutFirstByte>>3),
            numBitsInLastByte = numBitsWithoutFirstByte - (numWholeBytes<<3);
        
        if (numBitsInLastByte) {
            if (buffer->getIndex >= numWholeBytes + 1) {
                buffer->getIndex -= numWholeBytes + 1;
                buffer->bitIndex = numBitsInLastByte - 1;
                buffer->numBytesRead -= numWholeBytes + 1;
            }
            else {
                *errorCode = ERR_BIB_CANNOT_REWIND;
                deb("bibRewindBits: ERROR - cannot rewind.\n");
            }
        }
        else {
            if (buffer->getIndex >= numWholeBytes) {
                buffer->getIndex -= numWholeBytes;
                buffer->bitIndex = 7;
                buffer->numBytesRead -= numWholeBytes;
            }
            else {
                *errorCode = ERR_BIB_CANNOT_REWIND;
                deb("bibRewindBits: ERROR - cannot rewind.\n");
            }
        }
    }
    buffer->bitsLeft += numberOfBits;
}


/* {{-output"bibShowBits.txt"}} */
/*
*
* bibShowBits
*    
*
* See bibFlushBits.
*
*/

u_int32 bibShowBits(int numberOfBits, bibBuffer_t *buffer)  
/* {{-output"bibShowBits.txt"}} */
{
    static const u_char
        msbMask[8] = {1, 3, 7, 15, 31, 63, 127, 255},
        lsbMask[9] = {255, 254, 252, 248, 240, 224, 192, 128, 0};
    u_char
        *startAddr;
    int32
        bitIndex;
    u_int32
        endShift;         /* the number of shifts after masking the last byte */
    u_int32
        returnValue = 0;
    
    bibAssert(buffer != NULL);
    bibAssert(numberOfBits > 0 && numberOfBits <= 32);
    
    startAddr = buffer->baseAddr + buffer->getIndex;
    bitIndex = buffer->bitIndex;
    
    /* Check if enough bits are available. */
    if (buffer->bitsLeft < (u_int32) numberOfBits) {
        goto show_underflow;
    }
    
    if ( bitIndex >= numberOfBits ) {
        /* All in the current byte, bits still left */
        endShift = bitIndex - numberOfBits + 1;
        return ((startAddr[0] & msbMask[bitIndex] & lsbMask[endShift]) >> endShift);
    }
    else if ( bitIndex == (numberOfBits-1) ) {
        /* Current byte used completely */
        return startAddr[0] & msbMask[bitIndex];
    }
    else {
        /* Current byte plus then some */
        
        /* Remainder of this byte */
        returnValue = *(startAddr++) & msbMask[bitIndex];
        numberOfBits -= bitIndex + 1;
        
        /* Get full bytes */
        while ( numberOfBits >= 8 )
        {
            returnValue = (returnValue << 8) | *(startAddr++);
            numberOfBits -= 8;
        }
        
        /* Get bits from last byte */
        endShift = 8 - numberOfBits;
        returnValue = (returnValue << numberOfBits) | ((startAddr[0] & lsbMask[endShift]) >> endShift);
        /* (safe, since lsbMask[8]==0) */
    }
    
    return returnValue;
show_underflow:
    buffer->error = ERR_BIB_NOT_ENOUGH_DATA;
    return 0;
}


/*
* Local functions
*/

/*
*
* bibInitialize
*    
*
* Parameters:
*    bibBuffer                  input bit buffer instance
*    srcBuffer                  buffer containing the data
*    srcBufferLength            the length of the buffer
*    errorCode                  error code
*
* Function:
*    This function initializes the values of the bibBuffer structure.
*
* Returns:
*    Nothing.
*
* Error codes:
*    ERR_BIB_BUFLIST            if the internal buffer list has been corrupted
*
*/

static void bibInitialize(
                            bibBuffer_t *bibBuffer,
                            void *srcBuffer,
                            unsigned srcBufferLength,
                            int16 */*errorCode*/)
{
    bibBuffer->baseAddr = (u_char *) srcBuffer;
    bibBuffer->size = srcBufferLength;
    bibBuffer->getIndex = 0;
    bibBuffer->bitIndex = 7;
    bibBuffer->bitsLeft = (u_int32) (srcBufferLength<<3);
    bibBuffer->numBytesRead = 0;
    bibBuffer->error = 0;
    
    
}



/*
*
* CopyStream
*    
*
* Function to copy stream from SrcBuffer to DestBuffer based on settings in bufEdit and ByteStart & BitStart
*    
*    
*/

void CopyStream(bibBuffer_t *SrcBuffer,bibBuffer_t *DestBuffer,bibBufferEdit_t *bufEdit, 
                                int ByteStart, int BitStart)
{
    int32 temp;
    unsigned tgetIndex;  
    int tbitIndex;
    u_int32 tbitsLeft;
    u_int32 tnumBytesRead;
    int tByteStart; 
    int tBitStart;  
    
    bibEditParams_t *edParam;
    
    //Add assertions and checks here !!
    bibAssert(SrcBuffer->baseAddr);
    bibAssert(DestBuffer->baseAddr);
    bibAssert(bufEdit);
    
    //Save the params of SrcBuffer to recover them later:
    tgetIndex=SrcBuffer->getIndex;
    tbitIndex=SrcBuffer->bitIndex;
    tbitsLeft=SrcBuffer->bitsLeft;
    tnumBytesRead=SrcBuffer->numBytesRead;
    
    
    
    // check to see if we need to change some header parameter
    if(bufEdit->copyMode == CopyWithEdit/*CopyWithEdit*/)
    {
        bibAssert(bufEdit->editParams);
        edParam = &(bufEdit->editParams[0]); 
        
        // check if the editing position is in the current range of bit data
        temp=((SrcBuffer->getIndex<<3) + (7-SrcBuffer->bitIndex))-
            ((edParam->StartByteIndex<<3) + 7-(edParam->StartBitIndex));
        if (temp>=0)    // yes, it is
        {
            // copy upto the editing point
            CopyBuffer(SrcBuffer, DestBuffer, ByteStart, BitStart, edParam->StartByteIndex, 
                edParam->StartBitIndex);
            
            CopyBufferEdit(SrcBuffer, DestBuffer, &(bufEdit->editParams[0]));
            
            // store new starting copy position 
            tByteStart = SrcBuffer->getIndex; 
            tBitStart  = SrcBuffer->bitIndex; 
            // restore original stop copy position 
            SrcBuffer->getIndex=tgetIndex;
            SrcBuffer->bitIndex=tbitIndex;
            SrcBuffer->bitsLeft=tbitsLeft;
            SrcBuffer->numBytesRead=tnumBytesRead;
            
            CopyBuffer(SrcBuffer, DestBuffer, tByteStart, tBitStart, tgetIndex, tbitIndex);

        }
        else                    // no
        {
            // put panic here !
            return;
        }
    }
    else if (bufEdit->copyMode == CopyWhole/*CopyWhole*/)
    {
        CopyBuffer(SrcBuffer, DestBuffer, ByteStart, BitStart, 
            SrcBuffer->getIndex, SrcBuffer->bitIndex);
    }
    else if (bufEdit->copyMode == EditOnly /*EditOnly*/)
    {
        CopyBufferEdit(SrcBuffer, DestBuffer, &(bufEdit->editParams[0]));
    }
    else if(bufEdit->copyMode == CopyNone/*CopyNone*/)
    {
        return; 
    }

    
  //4- Retrieve the original Srcbuffer params.
    // Using getbits it should be equal to where we started
    SrcBuffer->getIndex=tgetIndex;
    SrcBuffer->bitIndex=tbitIndex;
    SrcBuffer->bitsLeft=tbitsLeft;
    SrcBuffer->numBytesRead=tnumBytesRead;
    
    //5- Update the destbuffer statistics:
    DestBuffer->getIndex=DestBuffer->numBytesRead;

    DestBuffer->bitsLeft -= (DestBuffer->getIndex<<3);

}

/*
*
* CopyBuffer
*    
*
* Function to copy data from SrcBuffer to DestBuffer from ByteStart & BitStart to ByteEnd & BitEnd
*    
*    
*/

void CopyBuffer(bibBuffer_t *SrcBuffer,bibBuffer_t *DestBuffer,
                                int ByteStart,int BitStart, int ByteEnd, int BitEnd)
{
    u_char *DestStartAddr;
    u_int32 i;
    u_int32 temp;
    u_int32 BitsToRewind;
    u_int32 BitsToCopy;
    u_int32 BytesToCopy;
    u_int32 Bytes4ToCopy;
    u_int32 BitsRemaining;
    int16 errorCode;
    u_int32 bitshift;
    u_int32 bitstoget;
    static const u_char msbMask[8] = {1, 3, 7, 15, 31, 63, 127, 255};
    
    DestStartAddr = DestBuffer->baseAddr + DestBuffer->getIndex;
    
    //Rewind the src buffer to the start address(ByteStart,BitStart)
    BitsToRewind=((SrcBuffer->getIndex<<3) + (7-SrcBuffer->bitIndex))-
        ((ByteStart<<3) + (7-BitStart));
    bibRewindBits(BitsToRewind,SrcBuffer, &errorCode);
    
    // evaluate the number of bits to copy
    BitsToCopy = ((ByteEnd<<3) + (7-BitEnd))-((ByteStart<<3) + (7-BitStart));
    if (BitsToCopy<=0)
        return; 
    else if (BitsToCopy > BitsToRewind) 
        BitsToCopy = BitsToRewind;      // or else provide a panic here !!!
    
    //1- Fill the remaining of the byte in destination:
    bitshift=0;
    bitstoget=0;
    if(DestBuffer->bitIndex!=7)
        {
        bitshift = DestBuffer->bitIndex+1;
        bitstoget = ((BitsToCopy < bitshift) ? BitsToCopy : bitshift); 
        temp = bibGetBits(bitstoget,SrcBuffer);
        
        // update statistics to take care of bit addition or byte completion 
        if (BitsToCopy < bitshift)
        {
            // bits added but byte not completed
            *(DestStartAddr)=(unsigned char)((((*DestStartAddr)>>bitshift)<<bitshift) |
                ((temp << (bitshift-BitsToCopy)  ) & msbMask[bitshift-1]));
            DestBuffer->bitIndex -= BitsToCopy;
            bibAssert(DestBuffer->bitIndex >= 0)
        }
        else
        {
            // byte completed
            *(DestStartAddr)=(unsigned char)((((*DestStartAddr)>>bitshift)<<(bitshift)) | 
                (temp & msbMask[bitshift-1]));
            DestStartAddr+=1; 
            DestBuffer->numBytesRead++;
            DestBuffer->bitIndex=7;
        }
    }
    
    //2- Extract all bytes (in 8 bits) from src to destination.
    //Checks for BytesToCopy. 
    BytesToCopy=(BitsToCopy-bitstoget)>>3;
    if ( BytesToCopy > 0 )
    {

        if ( SrcBuffer->bitIndex == 7 )
        {
            // we can copy the data from src in full bytes, utilize faster inline method 
            // and try to utilize pipelining in the for-loop
            // truncate it to 4-byte-boundary
            Bytes4ToCopy = BytesToCopy>>2;
            for(i=0; i<Bytes4ToCopy; i++)
            {
                *(DestStartAddr++) = bibGetAlignedByte(SrcBuffer);
                *(DestStartAddr++) = bibGetAlignedByte(SrcBuffer);
                *(DestStartAddr++) = bibGetAlignedByte(SrcBuffer);
                *(DestStartAddr++) = bibGetAlignedByte(SrcBuffer);
            }
            i <<= 2;
            if ( BytesToCopy > i )
            {
                // copy the leftovers
                for(;i<BytesToCopy;i++)
                {
                    *(DestStartAddr++) = bibGetAlignedByte(SrcBuffer);
                }
            }
            SrcBuffer->numBytesRead+=i;
        }
        else
        {
            for(i=0;i<BytesToCopy;i++)
            {
                *(DestStartAddr++) = (unsigned char)bibGetBits(8,SrcBuffer);
            }
            
        }
    }
    DestBuffer->numBytesRead+=BytesToCopy;
    
    //3- Fill the last byte:
    BitsRemaining=((BitsToCopy-bitstoget))%8;
    if(BitsRemaining!=0)
    {
        temp = bibGetBits(BitsRemaining,SrcBuffer);
        *(DestStartAddr++)=(u_char)(temp<<(8-BitsRemaining)); 
        DestBuffer->bitIndex=7-BitsRemaining;
    }
    
    //5- Update the destbuffer statistics:
    DestBuffer->getIndex=DestBuffer->numBytesRead;
}

/*
*
* CopyBufferEdit
*    
*
* Function to copy data with editing from SrcBuffer to DestBuffer with settings in edParam
*    
*    
*/

void CopyBufferEdit(bibBuffer_t *SrcBuffer, bibBuffer_t *DestBuffer, 
                                        bibEditParams_t *edParam, int updateSrcBufferStats)
{
    u_char *DestStartAddr;
    u_int32 i;
    u_int32 temp;
    u_int32 BitsToSkip;
    u_int32 BitsToEdit;
    u_int32 BytesToSkip;
    u_int32 BitsRemaining;
    u_int32 BytesToEdit;
    unsigned bitshift;
    unsigned bitstoget;
    unsigned bitstomove;
    u_int32 StartBitPosition; 
    static const u_char msbMask[8] = {1, 3, 7, 15, 31, 63, 127, 255};
    
    DestStartAddr = DestBuffer->baseAddr + DestBuffer->getIndex;
    
    // evaluate the number of bits to copy
    BitsToEdit = edParam->newNumBits; 
    StartBitPosition = edParam->newNumBits-1;
    
    //1- Fill the remaining of the byte in destination:
    bitshift=0;
    bitstoget=0;
    if(DestBuffer->bitIndex!=7)
    {
        bitshift=DestBuffer->bitIndex+1;
        bitstoget = ((BitsToEdit < bitshift) ? BitsToEdit : bitshift); 
        
        temp = bibGetBitsFromWord(edParam->newValue, bitstoget, &StartBitPosition, 
            edParam->newNumBits); 
        
        // update statistics to take care of bit addition or byte completion 
        if (BitsToEdit < bitshift)
        {
            // bits added but byte not completed
            *(DestStartAddr)=(unsigned char)((((*DestStartAddr)>>bitshift)<<(bitshift)) |
                ((temp << (bitshift-BitsToEdit)  ) & msbMask[bitshift-1]));
            DestBuffer->bitIndex -= BitsToEdit;
            bibAssert(DestBuffer->bitIndex >= 0)
        }
        else
        {
            // byte completed
            *(DestStartAddr)=(unsigned char)((((*DestStartAddr)>>bitshift)<<(bitshift)) | 
                (temp & msbMask[bitshift-1]));
            DestStartAddr++; 
            DestBuffer->numBytesRead++;
            DestBuffer->bitIndex=7;
        }
    }
    
    
    //2- Extract all bytes (in 8 bits) from src to destination.
    //Checks for BytesToCopy
    BytesToEdit=(BitsToEdit-bitstoget)>>3;
    for(i=0;i<BytesToEdit;i++)
    {
        *(DestStartAddr++)=(unsigned char)bibGetBitsFromWord(edParam->newValue, 8, &StartBitPosition, edParam->newNumBits);
    }
    DestBuffer->numBytesRead+=BytesToEdit;
    
    //3- Fill the last byte:
    BitsRemaining=((BitsToEdit-bitstoget))%8;
    if(BitsRemaining!=0)
    {
        temp = bibGetBitsFromWord(edParam->newValue, BitsRemaining, &StartBitPosition, 
            edParam->newNumBits); 
        *(DestStartAddr++)=(u_char)(temp<<(8-BitsRemaining)); 
        DestBuffer->bitIndex=7-BitsRemaining;
    }
    
    //5- Update the destbuffer statistics:
    DestBuffer->getIndex=DestBuffer->numBytesRead;
    
    
    // update the src buffer statistics to reflect skipping of the value 
    if(updateSrcBufferStats)
    {
        BitsToSkip = edParam->curNumBits; 
        bitshift=0;
        bitstomove=0;
        if (SrcBuffer->bitIndex!=7)
        {
            bitshift=SrcBuffer->bitIndex+1;
            bitstomove = ((BitsToSkip < bitshift) ? BitsToSkip : bitshift); 
            // update statistics to take care of bit addition or byte completion 
            if (BitsToSkip < bitshift)
            {
                // bits skipped but byte not completed
                SrcBuffer->bitIndex -= bitstomove;
                bibAssert(SrcBuffer->bitIndex >= 0)
            }
            else
            {
                // byte completed
                SrcBuffer->numBytesRead++;
                SrcBuffer->bitIndex=7;
            }
        }
        // full bytes to skip
        BytesToSkip=(BitsToSkip-bitstomove)>>3;
        SrcBuffer->numBytesRead+=BytesToSkip;
        
        // skip the remaining bits
        BitsRemaining=((BitsToSkip-bitstomove))%8;
        if(BitsRemaining!=0)
        {
            SrcBuffer->bitIndex=7-BitsRemaining;
        }
        SrcBuffer->bitsLeft -= BitsToSkip;
        SrcBuffer->getIndex=SrcBuffer->numBytesRead;
    }
}

void ResetH263IntraDcUV(bibBuffer_t *DestBuffer, int uValue, int vValue)
{
    bibEditParams_t edParam;

    edParam.curNumBits = edParam.newNumBits = 8;
    edParam.StartByteIndex = edParam.StartBitIndex = 0; // used for source buffer only 

  // u
    edParam.newValue = uValue; 
    CopyBufferEdit((bibBuffer_t*)NULL, DestBuffer, &edParam, 0); 
    // v
    edParam.newValue = vValue; 
    CopyBufferEdit((bibBuffer_t*)NULL, DestBuffer, &edParam, 0); 
}

void ResetMPEG4IntraDcUV(bibBuffer_t *DestBuffer, int IntraDC_size)
{
    int i;
    bibEditParams_t edParam;
    const int DctDcSizeChrominanceNumBits[13] = { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; 

    // u,v
    for(i=0; i<2; i++)
    {
        // change dct dc size chrominance - IntraDC for U.V is 0 (codeword '11')
        edParam.curNumBits = DctDcSizeChrominanceNumBits[IntraDC_size]; 
        edParam.newNumBits = 2;  
        edParam.StartByteIndex = edParam.StartBitIndex = 0; // used or source buffer only 
        edParam.newValue = 3; 
        CopyBufferEdit((bibBuffer_t*)NULL, DestBuffer, &edParam, 0);    
    }
}

// assume SrcValue is max 32 bits 
u_int32 bibGetBitsFromWord(u_int32 SrcValue, u_int32 getBits, u_int32 *StartBit, 
                                                     u_int32 MaxNumBits)
{
    int val;
    u_int32 bitshift; 
    static const u_int32 mask[32] = 
            {0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 
             0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
             0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 
             0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};

    bibAssert(MaxNumBits <= 32);
    bibAssert(*StartBit < MaxNumBits);
    bibAssert(getBits-1 <= *StartBit);
    bibAssert(getBits > 0);
    
    bitshift = *StartBit - getBits + 1; 
    val = (SrcValue>>bitshift) & mask[getBits-1]; 
    if ( getBits > *StartBit )
        {
        // taking the last bits of the word; *StartBit is uint32, so it goes to max uint32 unless this special handling
        // other cases asserted already above
        *StartBit = 31;
        }
    else
        {
        *StartBit -= getBits; 
        }

    return val;
}

void bibForwardBits(u_int32 numberOfBits, bibBuffer_t *buffer)
{
    u_int32 BitsToForward;
    u_int32 BytesToForward;
    u_int32 BitsRemaining;
    unsigned bitshift;
    unsigned bitstomove;
        
    BitsToForward = numberOfBits; 
    bitshift=0;
    bitstomove=0;
        
    bibAssert(buffer != NULL);
        
        // complete the byte
    if (buffer->bitIndex!=7)
    {
        bitshift=buffer->bitIndex+1;
        bitstomove = ((BitsToForward < bitshift) ? BitsToForward : bitshift); 
        // update statistics to take care of bit addition or byte completion 
        if (BitsToForward < bitshift)
        {
            // bits skipped but byte not completed
            buffer->bitIndex -= bitstomove;
            bibAssert(buffer->bitIndex >= 0)
        }
        else
        {
            // byte completed
            buffer->numBytesRead++;
            buffer->bitIndex=7;
        }
    }
        // full bytes to skip
    BytesToForward=(BitsToForward-bitstomove)>>3;
    buffer->numBytesRead+=BytesToForward;
        
        // skip the remaining bits
    BitsRemaining=((BitsToForward-bitstomove))%8;
    if(BitsRemaining!=0)
    {
        buffer->bitIndex=7-BitsRemaining;
    }
    buffer->bitsLeft -= BitsToForward;
    buffer->getIndex=buffer->numBytesRead;
}

void bibStuffBits(bibBuffer_t *buffer)
{
    // the extra bits are already set to zero 
    bibAssert(buffer->baseAddr);
    if(buffer->bitIndex!=7)
    {
        buffer->bitIndex=7;
        buffer->getIndex++;
        buffer->numBytesRead++;
    }
}




// End of File