--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/MPEG4Transcoder.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,4335 @@
+/*
+* 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:
+* Implementation for MPEG4(H263) video transcoder. Operations may include:
+* 1. Bitstream Copying
+* 2. BlackAndWhite Effect
+* 3. MPEG4 to VDT_RESYN (Simple profile)
+* 4. H.263 -> MPEG4 (Open Loop structure, no MV refinement)
+* 5. MPEG4 -> H263, partial implemented
+*
+* We call functions 2~5 as transcoding functions since they involve MB level data processing
+*
+* Note:
+* When RVLC is used and errors occur during forward decoding,
+* We don't do backward transcoding, the rest of the data is discarded,
+*
+*/
+
+
+
+/*
+* Includes
+*/
+#include "MPEG4Transcoder.h"
+#include "debug.h"
+
+/* Print macro */
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x
+#else
+#define PRINT(x)
+#endif
+
+/*
+* Defines and Typedefs
+*/
+typedef unsigned int uint32;
+
+#define EInternalAssertionFailure 1000
+#define VDT_NO_DATA(a, b, c, d) ((a) == (c) && (b) == (d))
+
+const int KDataNotValid = -1;
+const int KMpeg4VopTimeIncrementResolutionLength = 16;
+const int KOutputMpeg4TimeIncResolution = 30000;
+const int KShortHeaderMpeg4VosSize = 14;
+const int KH263ToMpeg4VosSize = 28;
+
+
+
+/*Bit stream formating*/
+#define WRITE32(op, x) sPutBits((op), 16, ((uint32)(x)) >> 16); \
+sPutBits((op), 16, (x) & 0x0000ffff)
+
+/*
+* Constants
+*/
+#ifdef _DEBUG
+const TUint KInitialBufferSize = 200000; /* MPEG4 Simple Visual Profile (Levels 0,1,2,3) initial frame data buffer size vga support */
+#endif
+ /*
+ * Function Declarations
+*/
+
+//Static Functions
+
+static void sStuffBitsH263(bibBuffer_t *outBuffer);
+static TVedVideoBitstreamMode sGetMPEG4Mode(int error_resilience_disable, int dp, int rvlc);
+static int sFindCBP(int *mbdata, int fUseIntraDCVLC);
+
+
+
+void vdtPutInterMBCMT(bibBuffer_t *outBuffer, int coeffStart, int *coeff, int *numTextureBits, int svh);
+void vdtPutIntraMBCMT(bibBuffer_t *outBuffer, int *coeff, int *numTextureBits, int index, int skipDC, int skipAC);
+void vbmEncodeMVDifferential(int32 mvdx, int32 mvdy, int32 fCode, bibBuffer_t *outBuffer);
+void vbmGetH263IMCBPC(int lDQuant, int vopCodingType, int colorEffect, int cbpy, int& mcbpcVal, int& len);
+void vbmGetH263PMCBPC(int lDQuant, int colorEffect, int cbpy, int& mcbpcVal, int& len);
+tBool vbmMVOutsideBound(tMBPosition *mbPos, tMotionVector* bestMV, tBool halfPixel);
+void vbmMvPrediction(tMBInfo *mbi, int32 mBCnt, tMotionVector *predMV, int32 mbinWidth);
+void vbmPutInterMB(tMBPosition* mbPos, bibBuffer_t *outBuf, dmdPParam_t *paramMB, tMotionVector *initPred,
+ int32 noOfPredictors, u_int32 vopWidth, u_int32 vopHeight, int32 searchRange,
+ int32 mbNo, int32* numTextureBits, int16 colorEffect, tMBInfo *mbsinfo);
+
+void sPutBits (bibBuffer_t *buf, int numBits, unsigned int value); //forward decl
+
+/*
+* Function Definitions
+*/
+
+/*
+* sStuffBitsH263
+*
+* Parameters:
+* outBuffer output buffer
+*
+* Function:
+* This function stuffs bits for H.263 format
+* Returns:
+* None
+* Error codes:
+* None.
+*
+*/
+static void sStuffBitsH263(bibBuffer_t *outBuffer)
+{
+ const int stuffingBits[8][2] = { {1,0}, {2,0}, {3,0}, {4,0}, {5,0}, {6,0}, {7,0}, {0,0} };
+
+ VDTASSERT(outBuffer->baseAddr);
+
+ /* find the number of stuffing bits to insert in the output buffer */
+ int bi = outBuffer->bitIndex;
+ int newNumBits = stuffingBits[bi][0];
+ int newValue = stuffingBits[bi][1];
+ sPutBits(outBuffer, newNumBits, newValue);
+
+ return;
+}
+
+
+
+/*
+* sGetMPEG4Mode
+*
+* Parameters:
+*
+*
+* Function:
+* This function gets the mode of the MPEG-4 bitstream
+* Returns:
+* Nothing
+* Error codes:
+* None.
+*
+*/
+static TVedVideoBitstreamMode sGetMPEG4Mode(int error_resilience_disable, int dp, int rvlc)
+{
+ TVedVideoBitstreamMode mode = EVedVideoBitstreamModeUnknown;
+ int combination = ((!error_resilience_disable) << 2) | (dp << 1) | rvlc;
+ switch (combination)
+ {
+ case 0:
+ mode = EVedVideoBitstreamModeMPEG4Regular;
+ break;
+ case 2:
+ mode = EVedVideoBitstreamModeMPEG4DP;
+ break;
+ case 3:
+ mode = EVedVideoBitstreamModeMPEG4DP_RVLC;
+ break;
+ case 4:
+ mode = EVedVideoBitstreamModeMPEG4Resyn;
+ break;
+ case 6:
+ mode = EVedVideoBitstreamModeMPEG4Resyn_DP;
+ break;
+ case 7:
+ mode = EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC;
+ break;
+ default:
+ mode = EVedVideoBitstreamModeUnknown;
+ }
+
+ return mode;
+}
+
+
+/* {{-output"vdtGetVideoBitstreamInfo.txt"}} */
+/*
+* sFindCBP
+*
+* Parameters:
+* mbdata Contains the actual MB data to be quantized
+* fUseIntraDCVLC ON for INTRA, OFF for INTER
+*
+* Function:
+* This function finds the coded bit pattern of the MB
+* Returns:
+* Coded Block Pattern.
+* Error codes:
+* None.
+*
+*/
+static int sFindCBP(int *mbdata, int fUseIntraDCVLC)
+{
+ int coeffCnt;
+ int *block;
+ int blkCnt;
+ int cbpFlag = 0;
+ int codedBlockPattern = 0;
+
+ for (blkCnt = 0; blkCnt < 6; blkCnt++)
+ {
+ cbpFlag = 0;
+ codedBlockPattern <<= 1;
+ block = &mbdata[blkCnt * BLOCK_COEFF_SIZE];
+ for (coeffCnt = fUseIntraDCVLC; coeffCnt < BLOCK_COEFF_SIZE;
+ coeffCnt++)
+ {
+ if (block[coeffCnt])
+ {
+ cbpFlag = 1;
+ codedBlockPattern |= cbpFlag;
+ break;
+ }
+ }
+ }
+
+ return codedBlockPattern;
+}
+
+
+
+
+
+
+/* {{-output"sPutBits.txt"}} */
+/*
+* sPutBits
+*
+* Parameters:
+* outBuf output buffer
+* numBits number of bits to output
+* value new value
+*
+* Function:
+* This function puts some bits to the output buffer
+* Returns:
+* Nothing.
+* Error codes:
+* None.
+*
+*/
+void sPutBits (bibBuffer_t *buf, int numBits, unsigned int value)
+{
+
+ bibEditParams_t edParam;
+
+ edParam.curNumBits = edParam.newNumBits = numBits;
+ edParam.StartByteIndex = edParam.StartBitIndex = 0; /* used for source buffer only */
+ edParam.newValue = value; /* use value 128, encoded as codeword "1111 1111" = 255 */
+
+ CopyBufferEdit((bibBuffer_t*)NULL, buf, &edParam, 0);
+}
+
+
+
+/*
+* GetTimeIncPosition
+*
+*
+* Parameters:
+* hInstance instance handle
+*
+* Function:
+* Calculates the time increment position for the current VOP.
+*
+* Returns:
+* VDX error codes
+*
+*/
+
+int GetTimeIncPosition(
+ bibBuffer_t *inBuffer,
+ const vdxGetVopHeaderInputParam_t *inpParam,
+ vdxVopHeader_t *header,
+ int * ModuloByteIndex,
+ int * ModuloBitIndex,
+ int * ByteIndex,
+ int * BitIndex,
+ int *bitErrorIndication)
+/* {{-output"vdxGetVopHeader.txt"}} */
+{
+ /* Get VOP header */
+ int ret = vdxGetVopHeader(inBuffer, inpParam, header,
+ ModuloByteIndex, ModuloBitIndex, ByteIndex, BitIndex,
+ bitErrorIndication);
+
+ return ret;
+
+}
+
+
+
+/*
+* CopyEditVop
+*
+*
+* Parameters:
+* hInstance instance handle
+*
+* Function:
+* This function copies the VOP header with edited time stamps of the VOP.
+*
+* Returns:
+* TX error codes
+*/
+
+int CopyEditVop(vdeHInstance_t hInstance, int aNrOfBytesToSkip, bibBuffer_t * inBuffer,
+ vdeDecodeParamters_t *aDecoderInfo)
+{
+ PRINT((_L("CopyEditVop() begin")));
+ int StartByteIndex = 0;
+ int StartBitIndex = 7;
+ int16 error;
+ int sncCode;
+ int timeIncByteIndex, timeIncBitIndex;
+ int moduloBaseByteIndex, moduloBaseBitIndex;
+ int vopheaderBitLeft;
+ int numBitChange = 0;
+ int increaseBytes = 0;
+ int stuffingLength = 0;
+
+ tMPEG4TimeParameter * timeStamp = aDecoderInfo->aMPEG4TimeStamp;
+ MPEG4TimeParameter CurNewTimeCode;
+
+ int outTirDecreased = 0;
+ int outputTimeResolution = *aDecoderInfo->aMPEG4TargetTimeResolution;
+ int numOutputTrBits;
+ for (numOutputTrBits = 1; ((outputTimeResolution-1) >> numOutputTrBits) != 0; numOutputTrBits++)
+ {
+ }
+
+ int num_bits;
+ vdxGetVopHeaderInputParam_t inpParam;
+ vdxVopHeader_t vopheader;
+ int bitErrorIndication;
+ vdeInstance_t * vdeTemp = (vdeInstance_t *)hInstance;
+ bibBuffer_t *outBuffer = vdeTemp->outBuffer;
+ bibBufferEdit_t * bufEdit = vdeTemp->bufEdit;
+
+ int FrameSizeInByte = outBuffer->numBytesRead;
+ bibRewindBits(bibNumberOfFlushedBits(inBuffer),inBuffer,&error);
+ bibRewindBits(bibNumberOfFlushedBits(outBuffer),outBuffer,&error);
+ if ( aNrOfBytesToSkip > 0 )
+ {
+ // VOS header is already in the beginning of the output buffer
+ bibForwardBits(aNrOfBytesToSkip<<3, outBuffer);
+ // need to also skip the VOS header from input
+ }
+ bufEdit->copyMode = CopyWhole; /* CopyWhole - default */
+
+ /* record position */
+ StartByteIndex = inBuffer->numBytesRead;
+ StartBitIndex = inBuffer->bitIndex;
+
+ /* get time increment resolution */
+ vdcInstance_t * vdcTemp = (vdcInstance_t *)(vdeTemp->vdcHInstance);
+ int currentTimeIncResolution = vdcTemp->pictureParam.time_increment_resolution > 0? vdcTemp->pictureParam.time_increment_resolution : outputTimeResolution;
+ inpParam.time_increment_resolution = currentTimeIncResolution;
+
+ /* find the next vop start code */
+ do
+ {
+ sncCode = sncSeekMPEGStartCode(inBuffer, vdcTemp->pictureParam.fcode_forward, vdcTemp->pictureParam.error_res_disable, 0, &error);
+ bibForwardBits(32,inBuffer); // one start code is found, move on
+ if(inBuffer->bitsLeft <= 0)
+ {
+ return TX_ERR; // did not find any sync code --- vop is corrupted
+ }
+ }
+ while (sncCode != SNC_VOP);
+ bibRewindBits(32,inBuffer, &error); // go back
+
+ // if we have VOS header in the input, we are now just after it. If aNrOfBytesToSkip > 0, we should not copy it
+ // however, aNrOfBytesToSkip refers to output buffer, so we should not use it when skipping the input
+ if ( aNrOfBytesToSkip > 0 )
+ {
+ StartByteIndex = inBuffer->numBytesRead;
+ StartBitIndex = inBuffer->bitIndex;
+ }
+
+ /* read vop header */
+ GetTimeIncPosition(inBuffer, &inpParam, &vopheader,
+ &moduloBaseByteIndex, &moduloBaseBitIndex, &timeIncByteIndex,
+ &timeIncBitIndex, &bitErrorIndication);
+
+ /* record the header end; */
+ vopheaderBitLeft = inBuffer->bitsLeft;
+
+ /* copy-edit the part from the begin to the end of modulo base */
+ CurNewTimeCode = *timeStamp;
+
+ if (CurNewTimeCode.modulo_time_base != vopheader.time_base_incr)
+ {
+ if (!bufEdit->editParams)
+ {
+ bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ if(!bufEdit->editParams)
+ {
+ //Memory not available
+ return TX_ERR; //indicating error;
+ }
+ else
+ {
+ bufEdit->numChanges = 1;
+ }
+ }
+ bufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */
+ bufEdit->editParams->curNumBits = vopheader.time_base_incr + 1;
+ bufEdit->editParams->newNumBits = CurNewTimeCode.modulo_time_base + 1;
+ bufEdit->editParams->newValue = ((1 << CurNewTimeCode.modulo_time_base) - 1) << 1;
+ bufEdit->editParams->StartByteIndex = moduloBaseByteIndex;
+ bufEdit->editParams->StartBitIndex = moduloBaseBitIndex;
+ numBitChange += bufEdit->editParams->newNumBits - bufEdit->editParams->curNumBits;
+ }
+ else
+ {
+ bufEdit->copyMode = CopyWhole; /* CopyWithEdit */
+ }
+ /* set the end of copy point */
+ bibRewindBits((inBuffer->numBytesRead<<3)+7-inBuffer->bitIndex,inBuffer,&error);
+ bibForwardBits((moduloBaseByteIndex<<3)+7-moduloBaseBitIndex+vopheader.time_base_incr+2, inBuffer);
+
+ /* copy data */
+ CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex);
+ StartByteIndex=inBuffer->getIndex;
+ StartBitIndex=inBuffer->bitIndex;
+ bufEdit->copyMode = CopyWhole; /* CopyWhole */
+
+ /* copy and edit until the end of Vop header */
+ if (currentTimeIncResolution != outputTimeResolution /* && volheader.time_increment_resolution != 30 */
+ || vopheader.time_inc != CurNewTimeCode.time_inc)
+ {
+ for (num_bits = 1; ((currentTimeIncResolution-1) >> num_bits) != 0; num_bits++)
+ {
+ }
+ /* prepare editing position */
+ if (!bufEdit->editParams)
+ {
+ bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ if(!bufEdit->editParams)
+ {
+ //Memory not available
+ return TX_ERR; //indicating error no memory;
+ }
+ else
+ {
+ bufEdit->numChanges = 1;
+ }
+
+ }
+ bufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */
+ bufEdit->editParams->StartByteIndex = timeIncByteIndex;
+ bufEdit->editParams->StartBitIndex = timeIncBitIndex;
+ bufEdit->editParams->curNumBits = num_bits;
+ bufEdit->editParams->newNumBits = numOutputTrBits;
+ bufEdit->editParams->newValue = vopheader.time_inc;
+
+ /* update time increment */
+ if (vopheader.time_inc != CurNewTimeCode.time_inc)
+ {
+ /*bufEdit->editParams->newValue = (int)(vopheader.time_inc * (float)outputTimeResolution /
+ (float)currentTimeIncResolution + 0.5); //CurNewTimeCode.time_inc;
+ */
+ bufEdit->editParams->newValue = CurNewTimeCode.time_inc;
+ }
+ numBitChange += bufEdit->editParams->newNumBits - bufEdit->editParams->curNumBits;
+ }
+
+ /* set the copy end point to the end of vop header */
+ bibForwardBits(inBuffer->bitsLeft - vopheaderBitLeft, inBuffer);
+
+ /* copy data */
+ CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex);
+ StartByteIndex=inBuffer->getIndex;
+ StartBitIndex=inBuffer->bitIndex;
+
+ if ( vdcTemp->pictureParam.error_res_disable && (inBuffer->bitsLeft > 40) ) // 40 as below to avoid negative values below
+ {
+ // there are no VP headers => no need to search for VP start codes => can jump to the end.
+ // 40 = 5 bytes; in the end there is a start code that has 4 bytes
+ bibForwardBits( inBuffer->bitsLeft-40 ,inBuffer);
+ }
+
+ PRINT((_L("CopyEditVop() seek sync")));
+ /* find the next resync marker */
+ sncCode = sncSeekMPEGStartCode(inBuffer, vopheader.fcode_forward, vdcTemp->pictureParam.error_res_disable, 0, &error);
+ if ( sncCode == SNC_NO_SYNC )
+ {
+ PRINT((_L("CopyEditVop() sync NOT found, interrupt the copying and return")));
+ return TX_ERR;
+ }
+ PRINT((_L("CopyEditVop() sync found")));
+
+ /* record next resync position */
+ int resyncBitsLeft = inBuffer->bitsLeft;
+
+ /* rewind stuffing bits */
+ sncRewindStuffing(inBuffer, &error);
+
+ if (!bufEdit->editParams)
+ {
+ bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ if(!bufEdit->editParams)
+ {
+ //Memory not available
+ return TX_ERR; //indicating error no memory;
+ }
+ else
+ {
+ bufEdit->numChanges = 1;
+ }
+ }
+
+ /* record position */
+ bufEdit->editParams->StartByteIndex = inBuffer->getIndex;
+ bufEdit->editParams->StartBitIndex = inBuffer->bitIndex;
+
+ /* calculate new stuffing bits */
+ bufEdit->editParams->curNumBits = inBuffer->bitsLeft - resyncBitsLeft;
+ /* calculate number of bits/bytes changed */
+ if (numBitChange<0)
+ {
+ outTirDecreased = 1;
+ numBitChange = -numBitChange;
+ }
+ int numByteChange = numBitChange >> 3;
+
+ if (outTirDecreased)
+ {
+ increaseBytes -= numByteChange;
+ stuffingLength = bufEdit->editParams->curNumBits + (numBitChange - (numByteChange << 3));
+ if (stuffingLength > 8)
+ {
+ stuffingLength -= 8;
+ increaseBytes --;
+ }
+ }
+ else
+ {
+ increaseBytes += numByteChange;
+ stuffingLength = bufEdit->editParams->curNumBits - (numBitChange - (numByteChange << 3));
+ if (stuffingLength <= 0)
+ {
+ stuffingLength += 8;
+ increaseBytes ++;
+ }
+ }
+
+ /* adjust the output buffer size */
+ if (increaseBytes != 0)
+ {
+ outBuffer->size += increaseBytes;
+ if (increaseBytes>=0)
+ {
+ outBuffer->bitsLeft += (increaseBytes << 3);
+ }
+ else
+ {
+ outBuffer->bitsLeft -= ((-increaseBytes) << 3);
+ }
+ }
+
+ /* update edit statistics */
+ bufEdit->editParams->newNumBits = stuffingLength;
+ bufEdit->editParams->newValue = stuffingLength>0?(1<<(stuffingLength-1))-1:0;
+ if (stuffingLength != bufEdit->editParams->curNumBits)
+ {
+ bufEdit->copyMode = CopyWithEdit;
+ }
+
+ bibForwardBits(bufEdit->editParams->curNumBits, inBuffer);
+ /* copy data */
+ CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex);
+ /* record position */
+ StartByteIndex = inBuffer->getIndex;
+ StartBitIndex = inBuffer->bitIndex;
+
+ do
+ {
+ /* if it is the start of a video packet, copy it with edit */
+ if (sncCode == SNC_VIDPACK )
+ {
+ /* copy video packet with edit */
+ int retVal = CopyEditVideoPacket(inBuffer, outBuffer, bufEdit, vdcTemp, aDecoderInfo, &vopheader,
+ &sncCode, &StartByteIndex, &StartBitIndex);
+ if(retVal<0)
+ {
+ //error inside function return error
+ return TX_ERR;
+ }
+ }
+ else if (sncCode == SNC_EOB || sncCode == SNC_EOS || sncCode == SNC_GOV)
+ {
+ // since it is EOB, so end of sequence has occurred, so no more data, so exit
+ break;
+ }
+ }
+ while(sncCode != SNC_VOP);
+
+ /* copy the rest of bits */
+ if ((int)inBuffer->numBytesRead < FrameSizeInByte)
+ {
+ bufEdit->copyMode = CopyWhole;
+ bibForwardBits((FrameSizeInByte-StartByteIndex)<<3, inBuffer);
+ CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex);
+ }
+
+ PRINT((_L("CopyEditVop() end")));
+ return TX_OK;
+ }
+
+
+/*
+* CopyEditVideoPacket
+*
+*
+* Parameters:
+*
+* Function:
+* This function copies the video packet with edited time stamps, if HEC is enabled
+*
+* Returns:
+* TX error codes
+*/
+
+int CopyEditVideoPacket(bibBuffer_t* aInBuffer,
+ bibBuffer_t* aOutBuffer,
+ bibBufferEdit_t* aBufEdit,
+ vdcInstance_t * aVdcTemp,
+ vdeDecodeParamters_t* aDecoderInfo,
+ vdxVopHeader_t* aVopheader,
+ int* aSncCode,
+ int* aStartByteIndex,
+ int* aStartBitIndex)
+{
+ int16 error = 0;
+ int value = 0;
+ int bitsGot = 0;
+ int num_bits = 0;
+ int *bitErrorIndication = 0;
+ int numOutputTrBits = 0;
+ int resyncMarkerLength = 0;
+ int numMBs = 0;
+ int mbNumberLength = 0;
+ int startByteIndex = *aStartByteIndex;
+ int startBitIndex = *aStartBitIndex;
+ int currentTimeIncResolution = 0;
+ int outputTimeResolution = 0;
+ MPEG4TimeParameter curNewTimeCode;
+ MPEG4TimeParameter* timeStamp = aDecoderInfo->aMPEG4TimeStamp;
+
+ int numBitChange = 0;
+ int increaseBytes = 0;
+ int stuffingLength = 0;
+ int outTirDecreased = 0;
+
+ currentTimeIncResolution = aVdcTemp->pictureParam.time_increment_resolution > 0? aVdcTemp->pictureParam.time_increment_resolution : 30000;
+ outputTimeResolution = *aDecoderInfo->aMPEG4TargetTimeResolution;
+ for (numOutputTrBits=1; ((outputTimeResolution-1)>>numOutputTrBits)!=0; numOutputTrBits++)
+ {
+ }
+ /* evaluate resync marker length */
+ resyncMarkerLength = (aVopheader->coding_type == 0 ? 17 : 16+aVopheader->fcode_forward);
+ /* evaluate MB number length */
+ numMBs = ((aVdcTemp->pictureParam.lumWidth+15)>>4) * ((aVdcTemp->pictureParam.lumHeight+15)>>4);
+ for (mbNumberLength = 1; ((numMBs-1) >> mbNumberLength) != 0; mbNumberLength++)
+ {
+ }
+
+ value = bibGetBits(resyncMarkerLength, aInBuffer, &bitsGot, bitErrorIndication, &error); // resync marker
+ value = bibGetBits(mbNumberLength, aInBuffer, &bitsGot, bitErrorIndication, &error); // mb number
+ value = bibGetBits(5, aInBuffer, &bitsGot, bitErrorIndication, &error); // quant scale
+ value = bibGetBits(1, aInBuffer, &bitsGot, bitErrorIndication, &error); // header extension code
+
+ /* if HEC enabled, copy edit time increment fields in the video packet */
+ if (value == 1)
+ {
+ /* copy-edit the part from the begin to the end of modulo base */
+ curNewTimeCode = *timeStamp;
+
+ if (curNewTimeCode.modulo_time_base != aVopheader->time_base_incr)
+ {
+ if (!aBufEdit->editParams)
+ {
+ aBufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ if(!aBufEdit->editParams)
+ {
+ //Memory not available
+ return TX_ERR; //indicating error no memory;
+ }
+ else
+ {
+ aBufEdit->numChanges = 1;
+ }
+ }
+ aBufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */
+ aBufEdit->editParams->curNumBits = aVopheader->time_base_incr + 1;
+ aBufEdit->editParams->newNumBits = curNewTimeCode.modulo_time_base + 1;
+ aBufEdit->editParams->newValue = ((1 << curNewTimeCode.modulo_time_base) - 1) << 1;
+ aBufEdit->editParams->StartByteIndex = aInBuffer->getIndex;
+ aBufEdit->editParams->StartBitIndex = aInBuffer->bitIndex;
+ numBitChange += aBufEdit->editParams->newNumBits - aBufEdit->editParams->curNumBits;
+ }
+ else
+ {
+ aBufEdit->copyMode = CopyWhole; /* CopyWithEdit */
+ }
+ /* set the end of copy point */
+ bibForwardBits(aVopheader->time_base_incr+2, aInBuffer); // includes one bit for Marker
+
+ /* copy data */
+ CopyStream(aInBuffer,aOutBuffer,aBufEdit,startByteIndex,startBitIndex);
+ startByteIndex = aInBuffer->getIndex;
+ startBitIndex = aInBuffer->bitIndex;
+ aBufEdit->copyMode = CopyWhole; /* CopyWhole */
+
+ /* copy and edit 'time increment' field */
+ if (currentTimeIncResolution != outputTimeResolution /* && volheader.time_increment_resolution != 30 */
+ || aVopheader->time_inc != curNewTimeCode.time_inc)
+ {
+ for (num_bits = 1; ((currentTimeIncResolution-1) >> num_bits) != 0; num_bits++)
+ {
+ }
+
+ /* prepare editing position */
+ if (!aBufEdit->editParams)
+ {
+ aBufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ if(!aBufEdit->editParams)
+ {
+ //Memory not available
+ return TX_ERR; //indicating error no memory;
+ }
+ else
+ {
+ aBufEdit->numChanges = 1;
+ }
+ }
+ aBufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */
+ aBufEdit->editParams->StartByteIndex = aInBuffer->getIndex;
+ aBufEdit->editParams->StartBitIndex = aInBuffer->bitIndex;
+ aBufEdit->editParams->curNumBits = num_bits;
+ aBufEdit->editParams->newNumBits = numOutputTrBits;
+ aBufEdit->editParams->newValue = aDecoderInfo->aMPEG4TimeStamp->time_inc;
+
+ /* move to end position of 'time increment' field */
+ bibForwardBits(num_bits, aInBuffer); // move to end of 'time increment' field
+ /* update time increment */
+ if (aVopheader->time_inc != curNewTimeCode.time_inc)
+ {
+ aBufEdit->editParams->newValue = curNewTimeCode.time_inc;
+ }
+ numBitChange += aBufEdit->editParams->newNumBits - aBufEdit->editParams->curNumBits;
+ }
+
+ /* copy time increment field with edit */
+ CopyStream(aInBuffer,aOutBuffer,aBufEdit,startByteIndex,startBitIndex);
+ startByteIndex=aInBuffer->getIndex;
+ startBitIndex=aInBuffer->bitIndex;
+
+ }
+
+ /* copy rest of video packet */
+
+ /* find the next resync marker */
+ *aSncCode = sncSeekMPEGStartCode(aInBuffer, aVopheader->fcode_forward, 0 /* VPs used*/, 0, &error);
+
+ /* record next resync position */
+ int resyncBitsLeft = aInBuffer->bitsLeft;
+
+ /* rewind stuffing bits */
+ sncRewindStuffing(aInBuffer, &error);
+
+ if (!aBufEdit->editParams)
+ {
+ aBufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ if(!aBufEdit->editParams)
+ {
+ //Memory not available
+ return TX_ERR; //indicating error no memory;
+ }
+ else
+ {
+ aBufEdit->numChanges = 1;
+ }
+ }
+
+ /* record position */
+ aBufEdit->editParams->StartByteIndex = aInBuffer->getIndex;
+ aBufEdit->editParams->StartBitIndex = aInBuffer->bitIndex;
+
+ /* calculate new stuffing bits */
+ aBufEdit->editParams->curNumBits = aInBuffer->bitsLeft - resyncBitsLeft;
+
+ /* calculate number of bits/bytes changed */
+ if (numBitChange<0)
+ {
+ outTirDecreased = 1;
+ numBitChange = -numBitChange;
+ }
+ int numByteChange = numBitChange >> 3;
+
+ /* evaluate change in buffer size */
+ if (outTirDecreased)
+ {
+ increaseBytes -= numByteChange;
+ stuffingLength = aBufEdit->editParams->curNumBits + (numBitChange - (numByteChange << 3));
+ if (stuffingLength > 8)
+ {
+ stuffingLength -= 8;
+ increaseBytes --;
+ }
+ }
+ else
+ {
+ increaseBytes += numByteChange;
+ stuffingLength = aBufEdit->editParams->curNumBits - (numBitChange - (numByteChange << 3));
+ if (stuffingLength <= 0)
+ {
+ stuffingLength += 8;
+ increaseBytes ++;
+ }
+ }
+
+ /* adjust the output buffer size */
+ if (increaseBytes != 0)
+ {
+ aOutBuffer->size += increaseBytes;
+ if (increaseBytes>=0)
+ {
+ aOutBuffer->bitsLeft += (increaseBytes << 3);
+ }
+ else
+ {
+ aOutBuffer->bitsLeft -= ((-increaseBytes) << 3);
+ }
+ }
+ /* update edit statistics */
+ aBufEdit->editParams->newNumBits = stuffingLength;
+ aBufEdit->editParams->newValue = stuffingLength>0?(1<<(stuffingLength-1))-1:0;
+ if (stuffingLength != aBufEdit->editParams->curNumBits)
+ {
+ aBufEdit->copyMode = CopyWithEdit; // copy with edit
+ }
+ else
+ {
+ aBufEdit->copyMode = CopyWhole; // copy whole
+ }
+
+ bibForwardBits(aBufEdit->editParams->curNumBits, aInBuffer);
+ /* copy video packet with stuffing bits edited */
+ CopyStream(aInBuffer, aOutBuffer, aBufEdit, startByteIndex, startBitIndex);
+ /* record position */
+ startByteIndex = aInBuffer->getIndex;
+ startBitIndex = aInBuffer->bitIndex;
+
+ /* update position for return */
+ *aStartByteIndex = startByteIndex;
+ *aStartBitIndex = startBitIndex;
+
+ return TX_OK;
+}
+
+
+/*
+* sPutBits
+*
+* Parameters:
+* outBuf output buffer
+* numBits number of bits to output
+* value new value
+*
+* Function:
+* Wrapper to sPutBits
+* Returns:
+* None.
+* Error codes:
+* None.
+*
+*/
+void vdtPutBits (void *buf, int numBits, unsigned int value)
+{
+ /* must be in this type! "void" is used here only because of the interface with vlb.cpp */
+ sPutBits ((bibBuffer_t *)(buf), numBits, value);
+}
+
+
+
+/* {{-output"vdtCopyBuffer.txt"}} */
+/*
+* vdtCopyBuffer
+*
+* Parameters:
+*
+* Function:
+* This function copies some data from source buffer to destination buffer
+* Returns:
+* None.
+* Error codes:
+* None.
+*
+*/
+void vdtCopyBuffer(bibBuffer_t *SrcBuffer,bibBuffer_t *DestBuffer,
+ int ByteStart,int BitStart, int ByteEnd, int BitEnd)
+{
+ int startByteIndex = SrcBuffer->getIndex;
+ int startBitIndex = SrcBuffer->bitIndex;
+ int bitsLeft = SrcBuffer->bitsLeft;
+ int numBytesRead = SrcBuffer->numBytesRead;
+
+ CopyBuffer(SrcBuffer,DestBuffer, ByteStart, BitStart, ByteEnd, BitEnd);
+
+ /* recover the postion */
+ SrcBuffer->getIndex = startByteIndex ;
+ SrcBuffer->bitIndex = startBitIndex;
+ SrcBuffer->bitsLeft = bitsLeft;
+ SrcBuffer->numBytesRead = numBytesRead;
+}
+
+
+
+
+/* {{-output"vdtStuffBitsMPEG4.txt"}} */
+/*
+* vdtStuffBitsMPEG4
+*
+* Parameters:
+* outBuf output buffer
+*
+* Function:
+* This function puts some stuffing bits to the output buffer
+* bits need to be stuffed in the output buffer at the end of vp in all cases (bw or not)
+* Returns:
+* None.
+* Error codes:
+* None.
+*
+*/
+void vdtStuffBitsMPEG4(bibBuffer_t *outBuffer)
+{
+ const int stuffingBits[8][2] = { {1,0}, {2,1}, {3,3}, {4,7}, {5,15}, {6,31}, {7,63}, {8,127} };
+ VDTASSERT(outBuffer->baseAddr);
+
+ /* find the number of stuffing bits to insert in the output buffer */
+ int bi = outBuffer->bitIndex;
+ int newNumBits = stuffingBits[bi][0];
+ int newValue = stuffingBits[bi][1];
+ sPutBits(outBuffer, newNumBits, newValue);
+
+ return;
+}
+
+
+/*************************************************************/
+
+
+/* {{-output"sResetH263IntraDcUV.txt"}} */
+/*
+* sResetH263IntraDcUV
+*
+* Parameters: output buffer
+* uValue
+* vValue
+*
+* Function:
+* This function reset the chrominace INTRADC when black and white color effect is applied
+* Returns:
+* none
+* Error codes:
+* None.
+*
+*/
+inline void sResetH263IntraDcUV(bibBuffer_t *DestBuffer, TInt uValue, TInt vValue)
+{
+ /* For the Color Effects Fill the U and V buffers with the
+ corresponding color values */
+
+ sPutBits(DestBuffer, 8, uValue);
+ sPutBits(DestBuffer, 8, vValue);
+}
+
+
+/* {{-output"vdtGetPMBBlackAndWhiteMCBPC.txt"}} */
+/*
+* vdtGetPMBBlackAndWhiteMCBPC
+*
+* Parameters:
+*
+* Function:
+* This function compute the new mcbpc for black and white effect *
+* Returns:
+* the length of the input mcbpc.
+* Error codes:
+* None.
+*
+*/
+int vdtGetPMBBlackAndWhiteMCBPC(int& new_len, int& new_val, int mcbpc)
+{
+ int cur_index, new_index, cur_len;
+
+ const tVLCTable sCBPCPType[21] =
+ {
+ {1, 1}, {3, 4}, {2, 4}, {5, 6},
+ {3, 3}, {7, 7}, {6, 7}, {5, 9},
+ {2, 3}, {5, 7}, {4, 7}, {5, 8},
+ {3, 5}, {4, 8}, {3, 8}, {3, 7},
+ {4, 6}, {4, 9}, {3, 9}, {2, 9},
+ {1, 9}
+ };
+
+ /* evaluate MCBPC parameters */
+ int cur_cbpc = mcbpc & 3;
+ int new_cbpc = 0; // cpbc=0 indicates chroma is 0
+ int mbType;
+
+ mbType = mcbpc / 4;
+ /* evaluate indices in table */
+ cur_index = mbType * 4 + cur_cbpc;
+ new_index = mbType * 4 + new_cbpc;
+
+ /* retrieve values */
+ cur_len = sCBPCPType[cur_index].length;
+ new_len = sCBPCPType[new_index].length;
+ new_val = sCBPCPType[new_index].code;
+
+ return cur_len;
+}
+
+
+/* {{-output"vdtGetIMBBlackAndWhiteMCBPC.txt"}} */
+/*
+* vdtGetIMBBlackAndWhiteMCBPC
+*
+* Parameters: None
+*
+* Function:
+* This function compute the new mcbpc for black and white effect
+* Returns:
+* the length of the input mcbpc.
+* Error codes:
+* None.
+*
+*/
+int vdtGetIMBBlackAndWhiteMCBPC(int& new_len, int& new_val, int mcbpc)
+{
+ int cur_index, new_index, cur_len;
+
+ const tVLCTable sCBPCIType[9] =
+ {
+ {1, 1}, {1, 3}, {2, 3}, {3, 3}, {1, 4},
+ {1, 6}, {2, 6}, {3, 6}, {1, 9}
+ };
+
+ /* evaluate MCBPC parameters */
+ int cur_cbpc = mcbpc & 3;
+ int new_cbpc = 0; // cpbc=0 indicates chroma is 0
+ int mbType = (mcbpc <4)?3:4;
+
+ /* evaluate indices in table */
+ cur_index = (mbType == 3 ? 0 : 4) + cur_cbpc;
+ new_index = (mbType == 3 ? 0 : 4) + new_cbpc;
+
+ /* retrieve values */
+ cur_len = sCBPCIType[cur_index].length;
+ new_len = sCBPCIType[new_index].length;
+ new_val = sCBPCIType[new_index].code;
+
+ return cur_len;
+}
+
+
+
+
+
+/* {{-output"vdtGetVideoBitstreamInfo.txt"}} */
+/*
+* vdtGetVideoBitstreamInfo
+*
+* Parameters:
+*
+* Function:
+* This function provides the bitstream info to the processor *
+* Returns:
+* VDE error codes
+* Error codes:
+* None.
+*
+*/
+int vdtGetVideoBitstreamInfo(bibBuffer_t *inBuffer, vdeDecodeParamters_t *aInfoOut, int *aByteIndex, int *aBitIndex)
+{
+ int numBitsGot,
+ bitErrorIndication = 0;
+ int16 error = 0;
+ u_int32 bits;
+ int timeResolution = 0;
+ TVedVideoBitstreamMode streamMode = EVedVideoBitstreamModeUnknown;
+ vdxVolHeader_t volHeader;
+ volHeader.user_data = NULL;
+
+ bits = bibShowBits(32, inBuffer, &numBitsGot, &bitErrorIndication, &error);
+ if (error)
+ {
+ streamMode = EVedVideoBitstreamModeUnknown;
+ goto exitFunction;
+ }
+ /* If PSC */
+ if ((bits >> 10) == 32) {
+ streamMode = EVedVideoBitstreamModeH263;
+ }
+
+ /* Else check for Visual Sequence, Visual Object or Video Object start code */
+ else if ((bits == MP4_VOS_START_CODE) ||
+ (bits == MP4_VO_START_CODE) ||
+ ((bits >> MP4_VID_ID_CODE_LENGTH) == MP4_VID_START_CODE) ||
+ ((bits >> MP4_VOL_ID_CODE_LENGTH) == MP4_VOL_START_CODE))
+ {
+
+ /* read the Stream headers from the bitstream */
+ if ((vdxGetVolHeader(inBuffer, &volHeader, &bitErrorIndication, 1, aByteIndex, aBitIndex, NULL) != 0) ||
+ (bitErrorIndication != 0))
+ {
+ goto exitFunction;
+ }
+
+ timeResolution = volHeader.time_increment_resolution;
+ streamMode = sGetMPEG4Mode(volHeader.error_res_disable, volHeader.data_partitioned, volHeader.reversible_vlc);
+ bits = bibShowBits(22, inBuffer, &numBitsGot, &bitErrorIndication, &error);
+ if (error)
+ goto exitFunction;
+
+ /* Check if H.263 PSC follows the VOL header, in which case this is
+ MPEG-4 with short header and is decoded as H.263 */
+ if ( bits == 32 )
+ {
+ streamMode = EVedVideoBitstreamModeMPEG4ShortHeader;
+ }
+ }
+
+ /* Else no H.263 and no MPEG-4 start code detected */
+ else {
+ streamMode = EVedVideoBitstreamModeUnknown;
+ }
+
+exitFunction:
+ /* copy the got user data to the core data structure */
+ if (volHeader.user_data != NULL)
+ {
+ free(volHeader.user_data);
+ }
+
+ bibRewindBits( bibNumberOfFlushedBits( inBuffer ), inBuffer, &error );
+ aInfoOut->streamMode = streamMode;
+ aInfoOut->iTimeIncrementResolution = timeResolution;
+ return TX_OK;
+}
+
+
+
+
+
+/* {{-output"vdtGetVideoBitstreamInfo.txt"}} */
+/*
+* sQuantizeMB
+*
+* Parameters:
+* mbdata Contains the actual MB data to be quantized
+* oldQuant:
+* newQuant:
+* intra
+*
+* Function:
+* This function requantizes the AC/DCT data for one MB, used in MPEG4 -> H263 transcoding
+* Returns:
+* Coded Block Pattern.
+* Error codes:
+* None.
+*
+*/
+static void sQuantizeMB(int *mbdata, int oldQuant, int newQuant, int intra, int colorEffect)
+{
+#define SIGN(x) (((x)<0) ? -1:1 )
+ int coeffCnt;
+ int *block;
+ int blkCnt;
+
+ for (blkCnt = 0; blkCnt < (colorEffect ? 4 : 6); blkCnt++)
+ {
+ block = &mbdata[blkCnt * BLOCK_COEFF_SIZE];
+ for (coeffCnt = (intra == VDX_MB_INTRA); coeffCnt < BLOCK_COEFF_SIZE;
+ coeffCnt++)
+ {
+ if (block[coeffCnt])
+ {
+ int level = abs(block[coeffCnt]);
+ int sign = SIGN(block[coeffCnt]);
+ int rcoeff;
+ // dequantize
+ if ((oldQuant % 2) == 1)
+ rcoeff = oldQuant * ((level << 1) + 1);
+ else
+ rcoeff = oldQuant * ((level << 1) + 1) - 1;
+
+ rcoeff = min (2047, max (-2048, sign * rcoeff));
+
+ // requantize
+ if (intra == VDX_MB_INTRA)
+ {
+ level = (abs (rcoeff)) / (newQuant << 1);
+ }
+ else
+ {
+ level = (abs (rcoeff) - (newQuant >> 1)) / (newQuant << 1);
+ /* clipping to [-127,+127] */
+ }
+
+ /* clipping to [-127,+127] */
+ block[coeffCnt] = min (127, max (-127, sign * level));
+ }
+ else
+ {
+ /* Nothing */
+ }
+ }
+ }
+ return ;
+}
+
+
+
+
+/* {{-output"vdtGetVideoBitstreamInfo.txt"}} */
+/*
+* vdtChangeVosHeaderRegResyncL
+*
+* Parameters:
+*
+* Function:
+* This function finds the error resillence bit and change it if necessary
+* to make it Regular Resynchronization mode
+* Returns:
+* ETrue if buffer changed.
+* Error codes:
+* None
+*
+*/
+TBool vdtChangeVosHeaderRegResyncL(TPtrC8& aInputBuffer, TUint aBufferSize)
+{
+ int16 errorCode = 0; /* return code for bib functions */
+ bibBuffer_t *buffer; /* input buffer */
+
+ /* Create bit buffer */
+ buffer = bibCreate((TAny*)aInputBuffer.Ptr(), aBufferSize, &errorCode);
+ if (!buffer || errorCode)
+ return EFalse;
+
+ int startByte = 0, startBit = 7;
+ vdeDecodeParamters_t decInfo;
+ vdtGetVideoBitstreamInfo(buffer, &decInfo, &startByte, &startBit);
+
+ if (decInfo.streamMode == EVedVideoBitstreamModeMPEG4Regular)
+ {
+ char *temp = (char *) (TAny*)aInputBuffer.Ptr();
+ unsigned char patern[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
+ temp[startByte] &= patern[startBit]; // change the error resillence bit to 0;
+
+ /* Delete bit buffer */
+ bibDelete(buffer, &errorCode);
+ return ETrue;
+ }
+ else
+ {
+ /* Delete bit buffer */
+ bibDelete(buffer, &errorCode);
+ return EFalse;
+ }
+}
+
+/*
+* CMPEG4Transcoder
+*
+* Parameters:
+*
+* Function:
+* Constructor
+*
+*/
+CMPEG4Transcoder::CMPEG4Transcoder(const vdeInstance_t *aVDEInstance, bibBuffer_t *aInBuffer, bibBuffer_t *aOutBuffer)
+{
+ VDTASSERT(aVDEInstance);
+ VDTASSERT(aInBuffer);
+ VDTASSERT(aOutBuffer);
+
+ /* passing the arguments */
+ iVDEInstance = aVDEInstance;
+ iInBuffer = aInBuffer;
+ iOutBuffer = aOutBuffer;
+
+ /* Color Toning */
+ iMBType = NULL;
+ iCurQuant = 0;
+ iColorEffect = aVDEInstance->iColorEffect;
+ iColorToneU = aVDEInstance->iColorToneU;
+ iColorToneV = aVDEInstance->iColorToneV;
+ iRefQuant = aVDEInstance->iRefQp;
+ iDcScaler = GetMpeg4DcScalerUV(iRefQuant);
+
+ iDoModeTranscoding = EFalse;
+ iDoTranscoding = (iColorEffect || iDoModeTranscoding);
+ iTargetFormat = EVedVideoTypeMPEG4SimpleProfile;
+ iStuffingBitsUsed = 0;
+
+ /* default values */
+ iLastMBNum = -1;
+ iCurMBNum = 0;
+
+ /* initialize here but will be changed later to proper value */
+ iOutputMpeg4TimeIncResolution = KOutputMpeg4TimeIncResolution;
+
+ iNumMBsInOneVOP = (iVDEInstance->lumHeight * iVDEInstance->lumWidth) >> 8; // /256
+ iMBsinWidth = iVDEInstance->lumWidth >> 4;
+ iNumMBsInGOB = iVDEInstance->lumWidth >> 4;
+
+
+ iMBList = NULL;
+ iH263DCData = NULL;
+ h263mbi = NULL;
+
+
+ iH263MBVPNum = NULL;
+ iErrorResilienceStartByteIndex = KDataNotValid;
+ iErrorResilienceStartBitIndex = KDataNotValid;
+
+ iVideoPacketNumInMPEG4 = 0; // the video packet number this MB belongs to, NOTE: the first GOB doesn't have a GOB header
+ iCurMBNumInVP = -1;
+ fFirstFrameInH263 = EFalse;
+
+ return;
+}
+
+/*
+* ~CMPEG4Transcoder
+*
+* Parameters:
+*
+* Function:
+* Destructor
+*
+*/
+CMPEG4Transcoder::~CMPEG4Transcoder()
+{
+ if (iCurIMBinstance)
+ {
+ free(iCurIMBinstance);
+ }
+ if (iCurPMBinstance)
+ {
+ free(iCurPMBinstance);
+ }
+ if (bufEdit.editParams)
+ {
+ free(bufEdit.editParams);
+ }
+
+ // for H263
+ if (iH263MBVPNum)
+ {
+ free(iH263MBVPNum);
+ }
+
+ // for color toning
+ if (iMBType)
+ {
+ free(iMBType);
+ }
+
+
+
+ if (iH263DCData)
+ {
+ for (int i = 0; i < iNumMBsInOneVOP; i++)
+ {
+ free(iH263DCData[i]);
+ }
+ free(iH263DCData);
+ }
+
+ if ( ( (iTargetFormat == EVedVideoTypeH263Profile0Level10) ||
+ (iTargetFormat == EVedVideoTypeH263Profile0Level45) ) &&
+ iBitStreamMode != EVedVideoBitstreamModeMPEG4ShortHeader &&
+ iBitStreamMode != EVedVideoBitstreamModeH263 &&
+ h263mbi)
+ {
+ free(h263mbi);
+ }
+
+ if ( iOutBuffer )
+ {
+
+ PRINT((_L("CMPEG4Transcoder: finish one frame successfully, buffer size %d"),
+ iOutBuffer->getIndex));
+ }
+
+#ifdef _DEBUG
+ if (iOutBuffer->getIndex > KInitialBufferSize)
+ {
+ PRINT((_L("CMPEG4Transcoder: Output buffer size from engine is not big enough! check KInitialBufferSize")));
+
+ }
+#endif
+ if ( iOutBuffer )
+ {
+ VDTASSERT(iOutBuffer->getIndex < KInitialBufferSize);
+ }
+}
+
+/*
+* H263EscapeCoding
+*
+* Parameters:
+*
+* Function:
+* Indicates whether escape vlc coding is used in one block
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::H263EscapeCoding(int aIndex, int fEscapeCodeUsed)
+{
+ iEscapeCodeUsed[aIndex] = fEscapeCodeUsed;
+}
+
+/*
+* SetTranscoding
+*
+* Parameters:
+*
+* Function:
+* Indicates whether we need to do MPEG4 bitstream transcoding
+* Returns:
+* TX error codes
+* Error codes:
+* None
+*
+*/
+int CMPEG4Transcoder::SetTranscoding(vdeDecodeParamters_t *aDecoderInfo)
+{
+ iColorEffect = aDecoderInfo->aColorEffect;
+ iColorToneU = aDecoderInfo->aColorToneU;
+ iColorToneV = aDecoderInfo->aColorToneV;
+ iBitStreamMode = (TVedVideoBitstreamMode)aDecoderInfo->streamMode;
+
+ iTargetFormat = aDecoderInfo->aOutputVideoFormat;
+ iDoModeTranscoding = aDecoderInfo->fModeChanged ? ETrue: EFalse;
+ iDoTranscoding = (iColorEffect || iDoModeTranscoding);
+
+ /* set to proper value */
+ iOutputMpeg4TimeIncResolution = *(aDecoderInfo->aMPEG4TargetTimeResolution);
+
+ /* allocate buffer for MPEG4 - > H263 transcoding */
+ /* the following is used if spatial domain processing is not done */
+
+ if ( ( (iTargetFormat == EVedVideoTypeH263Profile0Level10) ||
+ (iTargetFormat == EVedVideoTypeH263Profile0Level45) ) &&
+ iBitStreamMode != EVedVideoBitstreamModeMPEG4ShortHeader &&
+ iBitStreamMode != EVedVideoBitstreamModeH263)
+ {
+ h263mbi = (tMBInfo*) malloc (sizeof(tMBInfo) * iNumMBsInOneVOP);
+ if (!h263mbi)
+ {
+ PRINT((_L("CMPEG4Transcoder::SetTranscoding - h263mbi creation failed")));
+ deb("CMPEG4Transcoder::SetTranscoding - h263mbi creation failed\n");
+
+ return TX_ERR;
+ }
+ memset(h263mbi, 0, sizeof(tMBInfo) * iNumMBsInOneVOP);
+ }
+
+ return TX_OK;
+}
+
+
+
+
+/*
+* BeginOneVideoPacket
+*
+* Parameters:
+*
+* Function:
+* Records the position before one Video packet is processed
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::BeginOneVideoPacket(dvpVPInParam_t *aVPin)
+{
+ VDTASSERT(iInBuffer);
+ VDTASSERT(aVPin);
+
+ iCurVPIn = aVPin;
+ iVPStartByteIndex = iInBuffer->getIndex;
+ iVPStartBitIndex = iInBuffer->bitIndex;
+
+ iCurMBNumInVP = -1;
+
+ iStuffingBitsUsed = 0;
+
+ iVopCodingType = aVPin->pictParam->pictureType;
+ iBitStreamMode = sGetMPEG4Mode(aVPin->pictParam->error_res_disable,
+ aVPin->pictParam->data_partitioned, aVPin->pictParam->reversible_vlc);
+}
+
+
+/*
+* sConstructH263PicHeader
+*
+* Parameters:
+* lBitOut output buffer
+* quant quant value to be put in header
+* picType VDX_VOP_TYPE_P or VDX_VOP_TYPE_I
+* tr time increament
+* Function:
+* Writes the pic header into bit-stream for one MPEG4 frame
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void sConstructH263PicHeader(bibBuffer_t *lBitOut, int picType, int quant, int tr, int aVOPNotCoded, int aFormat)
+
+{
+ if (aVOPNotCoded)
+ {
+ return;
+ }
+ /* ShortVideoStartMarker */
+ sPutBits(lBitOut, 22, SHORT_VIDEO_START_MARKER);
+ /* TemporalReference */
+ sPutBits(lBitOut, 8, (tr & 0x000000ff));
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* Zero Bit */
+ sPutBits(lBitOut, 1, 0);
+ /* SplitScreenIndicator = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* DocumentCameraIndicator = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* FullPictureFreezeRelease = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* Source Fromat */
+ sPutBits(lBitOut, 3, aFormat);
+ /* PictureCodingType 0 for intra, 1 for inter */
+ sPutBits(lBitOut, 1, picType == VDX_VOP_TYPE_P);
+ /* UMV= 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* SAC = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* Advanced Prediction = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* PB frame = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* VOPQuant */
+ sPutBits(lBitOut, 5, quant);
+ /* ZeroBIt */
+ sPutBits(lBitOut, 1, 0);
+ /* Pei = 0 */
+ sPutBits(lBitOut, 1, 0);
+}
+
+
+/*
+* VOPHeaderEnded
+*
+* Parameters:
+*
+* Function:
+* Copy the VOP Header to output buffer
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::VOPHeaderEnded(int aStartByteIndex, int aStartBitIndex,
+ int aQuant, int aPicType, int aFrameNum, int aVOPNotCoded)
+{
+ const int KNumMbInSqcif = 48;
+ const int KNumMbInQcif = 99;
+ const int KNumMbInCif = 396;
+
+ if (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45)
+ {
+ int sourceFormat = 2; // qcif
+ /* note: other formate not supported */
+ if (iNumMBsInOneVOP == KNumMbInSqcif) /* sqcif */
+ {
+ sourceFormat = 1; // sqcif
+ }
+ else if (iNumMBsInOneVOP == KNumMbInQcif) /* qcif */
+ {
+ sourceFormat = 2; // qcif
+ }
+ else if (iNumMBsInOneVOP == KNumMbInCif) /* cif */
+ {
+ sourceFormat = 3; // cif
+ }
+ sConstructH263PicHeader(iOutBuffer, aPicType, aQuant, 0, aVOPNotCoded, sourceFormat);
+ PRINT((_L("CMPEG4Transcoder: MPEG4 -> H263: picture header generated")));
+ }
+ /* Copy the VOP header */
+ else
+ {
+ bufEdit.copyMode = CopyWhole; // whole
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,aStartByteIndex,aStartBitIndex);
+ }
+ iPreQuant = aQuant;
+ iStuffingBitsUsed = 0;
+
+ iCurQuant = aQuant;
+ /* Color Toning */
+ if (!aFrameNum || !iRefQuant)
+ {
+ iRefQuant = iCurQuant;
+ iDcScaler = GetMpeg4DcScalerUV(iRefQuant);
+ }
+
+}
+
+
+/*
+* VOPEnded
+*
+* Parameters:
+*
+* Function:
+* This function is called when one VOP has ended
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::VOPEnded()
+{
+ /* check if MBs are lost */
+ int dataPartitioned = (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC
+ || iBitStreamMode == EVedVideoBitstreamModeMPEG4DP || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP);
+
+ if (iLastMBNum != iNumMBsInOneVOP - 1 && !(dataPartitioned && !iDoModeTranscoding))
+ {
+ for (int i = iLastMBNum+1; i < iNumMBsInOneVOP; i++)
+ {
+ /* output 1 bit COD */
+ sPutBits (iOutBuffer, 1, 1);
+ }
+ }
+
+ iLastMBNum = iNumMBsInOneVOP - 1;
+ /* bits need to be stuffed in the output buffer at the end VOP */
+ if (!dataPartitioned && iTargetFormat == EVedVideoTypeMPEG4SimpleProfile)
+ {
+ if (!iStuffingBitsUsed)
+ {
+ vdtStuffBitsMPEG4(iOutBuffer);
+ }
+ iStuffingBitsUsed = 1;
+ }
+ else if (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45)
+ {
+ sStuffBitsH263(iOutBuffer);
+ }
+
+ PRINT((_L("CMPEG4Transcoder: VOPEnded. color effect: %d, format convert %d, do transcoding: %d streammode: %d, outputformat: %d "),
+ iColorEffect, iDoModeTranscoding, iDoTranscoding, iBitStreamMode, iTargetFormat));
+}
+
+/*
+* AfterOneVideoPacketHeader
+*
+* Parameters:
+*
+* Function:
+* This function is called after retreiving the VP
+* Records the position before the content of the video packet is processed
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::AfterVideoPacketHeader(dvpVPInOutParam_t *aVPInfo)
+{
+ VDTASSERT(aVPInfo);
+ iCurVPInOut = aVPInfo;
+
+ iVPHeaderEndByteIndex = iInBuffer->getIndex;
+ iVPHeaderEndBitIndex = iInBuffer->bitIndex;
+
+ /* Color Toning */
+ iCurQuant = aVPInfo->quant;
+
+ /* Copy the VP header to output stream. Note; the first VP does not have a VP header */
+ if (iTargetFormat == EVedVideoTypeMPEG4SimpleProfile)
+ {
+ bufEdit.copyMode = CopyWhole; /* whole */
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,iVPStartByteIndex,iVPStartBitIndex);
+ }
+}
+
+
+/*
+* OneVPEnded
+*
+* Parameters:
+*
+* Function:
+* This function is called after one VP contents are retrieved
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::OneVPEnded()
+{
+ if (!iDoTranscoding)
+ {
+ /* no transcoding, copy whole content VP */
+ bufEdit.copyMode = CopyWhole;
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,iVPHeaderEndByteIndex,iVPHeaderEndBitIndex);
+ iStuffingBitsUsed = 1;// also stuffing is copied
+ }
+ else
+ {
+ int dataPartitioned = (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC
+ || iBitStreamMode == EVedVideoBitstreamModeMPEG4DP || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP);
+ int nextExpectedMBNum = iCurVPInOut->currMBNum;
+
+ if (dataPartitioned && !iDoModeTranscoding)
+ {
+ /* if data is partitioned and we are not doing format transcoding,
+ not coded MBs info is already in data partition 1
+ */
+ }
+ else
+ {
+ /* MBs are lost or not coded, */
+ for (int i = iLastMBNum+1; i < nextExpectedMBNum; i++)
+ {
+ /* output 1 bit COD */
+ sPutBits (iOutBuffer, 1, 1);
+ }
+ }
+
+ iLastMBNum = nextExpectedMBNum - 1;
+ /* bits need to be stuffed in the output buffer at the end of vp in all cases (bw or not) */
+ if (iTargetFormat == EVedVideoTypeMPEG4SimpleProfile)
+ {
+ if (!iStuffingBitsUsed)
+ {
+ vdtStuffBitsMPEG4(iOutBuffer);
+ }
+ iStuffingBitsUsed = 1;
+ }
+ }
+}
+
+
+
+/*
+* BeginOneMB
+*
+* Parameters:
+*
+* Function:
+* Records the position before one MB is processed
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::BeginOneMB(int aMBNum)
+{
+ VDTASSERT(iInBuffer);
+
+ iMBStartByteIndex = iInBuffer->getIndex;
+ iMBStartBitIndex = iInBuffer->bitIndex;
+ iCurMBNum = aMBNum;
+
+ // Color Toning
+ iCurMBNumInVP++;
+
+ if ((iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) && iDoModeTranscoding)
+ {
+ /* H263 -> MPEG4 */
+ VDTASSERT(iH263MBVPNum);
+ iH263MBVPNum[iCurMBNum]= iVideoPacketNumInMPEG4;
+ }
+}
+
+/*
+* BeginOneBlock
+*
+* Parameters:
+*
+* Function:
+* Records the position before one block in MB is processed
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::BeginOneBlock(int aBlockIndex)
+{
+ VDTASSERT(aBlockIndex >= 0 && aBlockIndex < 6);
+
+ iBlockStartByteIndex[aBlockIndex] = iInBuffer->getIndex;
+ iBlockStartBitIndex[aBlockIndex] = iInBuffer->bitIndex;
+}
+
+
+/*
+* OneIMBDataStarted
+*
+* Parameters:
+*
+* Function:
+* This function is called after the MB header is read; start one IMB,
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::OneIMBDataStarted(vdxIMBListItem_t *aMBInstance)
+{
+ VDTASSERT(aMBInstance);
+ VDTASSERT(iCurIMBinstance);
+ iMBCodingType = VDX_MB_INTRA;
+ iVopCodingType = VDX_VOP_TYPE_I;
+ iMBType[iCurMBNum] = iMBCodingType;
+
+
+ memcpy(iCurIMBinstance, aMBInstance, sizeof(vdxIMBListItem_t));
+}
+
+/*
+* OnePMBDataStarted
+*
+* Parameters:
+*
+* Function:
+* This function is called after the MB header is read; start one PMB,
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::OnePMBDataStarted(vdxPMBListItem_t *aMBInstance)
+{
+ VDTASSERT(aMBInstance);
+ VDTASSERT(iCurPMBinstance);
+
+ iMBCodingType = aMBInstance->mbClass;
+ iVopCodingType = VDX_VOP_TYPE_P;
+ iMBType[iCurMBNum] = iMBCodingType;
+
+ memcpy(iCurPMBinstance, aMBInstance, sizeof(vdxPMBListItem_t));
+}
+
+
+
+/*
+* OneIMBDataStartedDataPartitioned
+*
+* Parameters:
+*
+* Function:
+* Add one IMB instance, It is done after parsing Part1 and Part2 before the block data for current MB
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::OneIMBDataStartedDataPartitioned(vdxIMBListItem_t *aMBInstance, dlst_t *aMBList, int aCurrMBNumInVP, int aMBNum)
+{
+ VDTASSERT(aMBInstance); // at this point, the instance should not be null
+ VDTASSERT(aMBList);
+
+ memcpy(iCurIMBinstance, aMBInstance, sizeof(vdxIMBListItem_t));
+ iCurMBNumInVP = aCurrMBNumInVP;
+ iCurMBNum = aMBNum;
+ iMBList = aMBList;
+ iMBCodingType = VDX_MB_INTRA;
+ iVopCodingType = VDX_VOP_TYPE_I;
+ iMBType[iCurMBNum] = iMBCodingType;
+
+ if (!iCurMBNumInVP && iDoTranscoding)
+ {
+ if (!iDoModeTranscoding)
+ {
+ /* We are not doing bitstream transcoding,
+ we have color effect here and need to reconstruct data partitions.
+ */
+ ReconstructIMBPartitions();
+ }
+ }
+}
+
+/*
+* OnePMBDataStartedDataPartitioned
+*
+* Parameters:
+*
+* Function:
+* Add one IMB instance, It is done after parsing Part1 and Part2 before the block data for current MB
+* Note: PMB may be INTRA coded.
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::OnePMBDataStartedDataPartitioned(vdxPMBListItem_t *aMBInstance, dlst_t *aMBList, int aCurrMBNumInVP, int aMBNum)
+{
+ VDTASSERT(aMBInstance); /* at this point, the instance should not be null */
+ VDTASSERT(aMBList);
+
+ memcpy(iCurPMBinstance, aMBInstance, sizeof(vdxPMBListItem_t));
+ iCurMBNumInVP = aCurrMBNumInVP;
+ iCurMBNum = aMBNum;
+ iMBList = aMBList;
+ iMBCodingType = aMBInstance->mbClass;
+ iVopCodingType = VDX_VOP_TYPE_P;
+ iMBType[iCurMBNum] = iMBCodingType;
+
+ if (!aMBInstance->fCodedMB && iDoModeTranscoding)
+ {
+ /* this MB is not coded and need to be converted to target mode,
+ out put the possible MB stuffing bits and COD
+ */
+ /* MB stuffing bits if they exsit */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ aMBInstance->DataItemStartByteIndex[11], aMBInstance->DataItemStartBitIndex[11],
+ aMBInstance->DataItemEndByteIndex[11], aMBInstance->DataItemEndBitIndex[11]);
+ /* It is a not-coded MB, output 1 bit COD (it always exists in P frame) */
+ sPutBits (iOutBuffer, 1, 1);
+ iLastMBNum = iCurMBNum;
+ }
+ else if (!iCurMBNumInVP && iDoTranscoding)
+ {
+ if (!iDoModeTranscoding)
+ {
+ /* We are not doing bitstream transcoding,
+ we have color effect here and need to reconstruct data partitions.
+ */
+ ReconstructPMBPartitions();
+ }
+ }
+}
+
+
+
+/*
+* TranscodingOneMB
+*
+* Parameters:
+*
+* Function:
+* Transcoding one MB, which may include dequantization, requantization , and re-encoding
+* Returns:
+* DMD error codes since called from decmbdct
+*
+*/
+int CMPEG4Transcoder::TranscodingOneMB(dmdPParam_t *aParam = NULL)
+{
+/* Because it has block data, this MB must be a coded MB,
+which means the position indicated by iMBStartByteIndex and iMBStartBitIndex starts with a MCBPC
+ */
+ VDTASSERT(!(!iCurPMBinstance->fCodedMB && iMBCodingType == VDX_MB_INTER));
+
+ if (!iDoTranscoding)
+ {
+ iLastMBNum = iCurMBNum; // need to update the variable to avoid marking this as noncoded MB
+ return TX_OK;
+ }
+
+ int dataPartitioned = (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC
+ || iBitStreamMode == EVedVideoBitstreamModeMPEG4DP || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP);
+
+ if (dataPartitioned)
+ {
+ /* since we need to handle MB stuffing bits, which are handle outside the transcoder in other modes,
+ not coded MBs and MB stuffing bits are handled in OnePMBDataStartedDataPartitioned,
+ ReconstuctI/PMBPartitios or ConstructRegularMPEG4MBData
+ */
+ }
+ else if(iCurMBNum != iLastMBNum + 1 )
+ {
+ /* if previous MBs are lost or not coded, we copy one MB with COD = 1; */
+ for (int i = 0 ; i < iCurMBNum - iLastMBNum - 1; i++)
+ {
+ /* output 1 bit COD */
+ sPutBits (iOutBuffer, 1, 1);
+ }
+ }
+
+ int newMCBPCLen = 0;
+ int newMCBPC = 0;
+ int oldMCBPCLen = 0;
+
+ /* determine whether to change mcbpc */
+ if (iColorEffect)
+ {
+ if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ oldMCBPCLen = vdtGetPMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, iCurPMBinstance->mcbpc);
+ }
+ else
+ {
+ oldMCBPCLen = vdtGetIMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, iCurIMBinstance->mcbpc);
+ }
+ }
+
+
+
+ if (iDoModeTranscoding && ( (iTargetFormat == EVedVideoTypeH263Profile0Level10) ||
+ (iTargetFormat == EVedVideoTypeH263Profile0Level45) ) )
+ {
+ if ( ConstructH263MBData(aParam, newMCBPCLen, newMCBPC) != VDC_OK )
+ {
+ return TX_ERR;
+ }
+ }
+ else /* possible H263->MPEG4 transcoding */
+
+ {
+ /* MPEG4 with VDT_RESYN and VDT_REGULAR, we only do bitstream copying */
+ if ( iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn || iBitStreamMode == EVedVideoBitstreamModeMPEG4Regular ||
+ ((iBitStreamMode ==EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) && !iDoModeTranscoding) )
+ {
+ /* the MB stuffing is taken card of outside in file viddemux.cpp
+ we only need to output COD, MCBPC
+ */
+ int mcbpcStartByteIndex, mcbpcStartBitIndex;
+
+ if (iVopCodingType == VDX_VOP_TYPE_I)
+ {
+ mcbpcStartByteIndex = iCurIMBinstance->DataItemStartByteIndex[0];
+ mcbpcStartBitIndex = iCurIMBinstance->DataItemStartBitIndex[0];
+ }
+ else
+ {
+ mcbpcStartByteIndex = iCurPMBinstance->DataItemStartByteIndex[0];
+ mcbpcStartBitIndex = iCurPMBinstance->DataItemStartBitIndex[0];
+ /* It is a coded MB, output 1 bit COD (it always exists in P frame) */
+ sPutBits (iOutBuffer, 1, 0);
+ }
+
+ if (!iColorEffect)
+ {
+ bufEdit.copyMode = CopyWhole; /* whole */
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,mcbpcStartByteIndex,mcbpcStartBitIndex);
+ }
+ else
+ {
+ /* modify mcbpc and copy only the Y data */
+ bufEdit.copyMode = CopyWithEdit; // copy with edit
+ bufEdit.editParams[0].StartByteIndex = mcbpcStartByteIndex;
+ bufEdit.editParams[0].StartBitIndex = mcbpcStartBitIndex;
+ bufEdit.editParams[0].curNumBits = oldMCBPCLen;
+ bufEdit.editParams[0].newNumBits = newMCBPCLen;
+ bufEdit.editParams[0].newValue = newMCBPC;
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,mcbpcStartByteIndex,mcbpcStartBitIndex);
+
+ /* disgard the UV data */
+ int16 errorCode = 0;
+ int bitsToRewind = ((iInBuffer->getIndex << 3) + 7 - iInBuffer->bitIndex)
+ - ((iBlockStartByteIndex[4] << 3) + 7 - iBlockStartBitIndex[4]);
+ bibRewindBits(bitsToRewind, iOutBuffer, &errorCode );
+
+ if (iMBCodingType == VDX_MB_INTRA)
+ {
+ if (iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263)
+ {
+ sResetH263IntraDcUV(iOutBuffer, iColorToneU, iColorToneV);
+ }
+ else
+ {
+ ResetMPEG4IntraDcUV();
+ }
+ }
+ }
+ }
+
+ else if ((iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) && iDoModeTranscoding)
+ {
+ H263ToMPEG4MBData(newMCBPCLen, newMCBPC);
+ }
+
+ else /* data partitioned */
+ {
+ if (iDoModeTranscoding)
+ {
+ /* for data partitioned bitstream, we do the bitstream rearrangement */
+ ConstructRegularMPEG4MBData(newMCBPCLen, newMCBPC);
+ }
+ else
+ {
+ /* copy the ACs or DCTs */
+ bufEdit.copyMode = CopyWhole; // whole
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,iBlockStartByteIndex[0],iBlockStartBitIndex[0]);
+ if (iColorEffect)
+ {
+ /* discard U V data */
+ int16 errorCode = 0;
+ int bitsToRewind = ((iInBuffer->getIndex << 3) + 7 - iInBuffer->bitIndex)
+ - ((iBlockStartByteIndex[4] << 3) + 7 - iBlockStartBitIndex[4]);
+ bibRewindBits(bitsToRewind, iOutBuffer, &errorCode );
+ }
+ }
+ }
+
+ }
+ iLastMBNum = iCurMBNum;
+ return TX_OK;
+}
+
+
+
+
+/*
+* ReconstructIMBPartitions
+*
+* Parameters:
+*
+* Function:
+* Recontruct the partitions for color effect when we are not doing format transcoding
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::ReconstructIMBPartitions()
+{
+ vdxIMBListItem_t *MBinstance;
+ int *dataItemStartByteIndex;
+ int *dataItemStartBitIndex;
+ int *dataItemEndByteIndex;
+ int *dataItemEndBitIndex;
+ int newMCBPCLen = 0;
+ int newMCBPC = 0;
+
+ VDTASSERT(iMBList);
+
+ for (dlstHead(iMBList, (void **) &MBinstance);
+ MBinstance != NULL;
+ dlstNext(iMBList, (void **) &MBinstance))
+ {
+ dataItemStartByteIndex = MBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = MBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = MBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = MBinstance->DataItemEndBitIndex;
+ // MB stuffing bits if they exsit
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11],
+ dataItemEndByteIndex[11], dataItemEndBitIndex[11]);
+
+ /* MCBPC */
+ if (iColorEffect)
+ {
+ /* MCBPC Changed. Ignore the old value (not used) */
+ vdtGetIMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, MBinstance->mcbpc);
+ sPutBits(iOutBuffer, newMCBPCLen, newMCBPC);
+ }
+ else
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[0], dataItemStartBitIndex[0],
+ dataItemEndByteIndex[0], dataItemEndBitIndex[0]);
+ }
+
+ /* DQUANT, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[1], dataItemStartBitIndex[1],
+ dataItemEndByteIndex[1], dataItemEndBitIndex[1]);
+
+ /* INTRA DCs */
+ if (!iColorEffect)
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[4], dataItemStartBitIndex[4],
+ dataItemEndByteIndex[4], dataItemEndBitIndex[4]);
+ }
+ else
+ {
+ if (!(VDT_NO_DATA(dataItemStartByteIndex[4], dataItemStartBitIndex[4],
+ dataItemEndByteIndex[4], dataItemEndBitIndex[4])))
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[4], dataItemStartBitIndex[4],
+ dataItemStartByteIndex[8], dataItemStartBitIndex[8]);
+ ResetMPEG4IntraDcUV();
+ }
+ }
+ }
+
+ /* DC marker */
+ sPutBits(iOutBuffer, DC_MARKER_LENGTH, DC_MARKER);
+
+ for (dlstHead(iMBList, (void **) &MBinstance);
+ MBinstance != NULL;
+ dlstNext(iMBList, (void **) &MBinstance))
+ {
+ dataItemStartByteIndex = MBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = MBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = MBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = MBinstance->DataItemEndBitIndex;
+
+ /* ac_pred_flag */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[3], dataItemStartBitIndex[3],
+ dataItemEndByteIndex[3], dataItemEndBitIndex[3]);
+
+ /* CBPY */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[2], dataItemStartBitIndex[2],
+ dataItemEndByteIndex[2], dataItemEndBitIndex[2]);
+ }
+
+ /* make sure the head of the list is reset */
+ dlstHead(iMBList, (void **) &MBinstance);
+}
+
+/*
+* ReconstructPMBPartitions
+*
+* Parameters:
+*
+* Function:
+* Recontruct the partitions for color effect when we are not doing format transcoding
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::ReconstructPMBPartitions()
+{
+ vdxPMBListItem_t *MBinstance;
+ int *dataItemStartByteIndex;
+ int *dataItemStartBitIndex;
+ int *dataItemEndByteIndex;
+ int *dataItemEndBitIndex;
+ int newMCBPCLen = 0;
+ int newMCBPC = 0;
+
+ VDTASSERT(iMBList);
+
+ for (dlstHead(iMBList, (void **) &MBinstance);
+ MBinstance != NULL;
+ dlstNext(iMBList, (void **) &MBinstance))
+ {
+ dataItemStartByteIndex = MBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = MBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = MBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = MBinstance->DataItemEndBitIndex;
+
+ /* MB stuffing bits if they exsit */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11],
+ dataItemEndByteIndex[11], dataItemEndBitIndex[11]);
+
+ if (MBinstance->fCodedMB)
+ {
+ /* output 1 bit COD, coded */
+ sPutBits (iOutBuffer, 1, 0);
+
+ /* MCBPC */
+ if (iColorEffect)
+ {
+ /* MCBPC Changed, ignore the return value */
+ vdtGetPMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, MBinstance->mcbpc);
+ sPutBits(iOutBuffer, newMCBPCLen, newMCBPC);
+ }
+ else
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[0], dataItemStartBitIndex[0],
+ dataItemEndByteIndex[0], dataItemEndBitIndex[0]);
+ }
+
+ /* MVs, if they exist */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[10], dataItemStartBitIndex[10],
+ dataItemEndByteIndex[10], dataItemEndBitIndex[10]);
+ }
+ else
+ {
+ /* output 1 bit COD, not coded */
+ sPutBits (iOutBuffer, 1, 1);
+ }
+ }
+
+ /* MM marker */
+ sPutBits(iOutBuffer, MOTION_MARKER_LENGTH, MOTION_MARKER);
+
+ for (dlstHead(iMBList, (void **) &MBinstance);
+ MBinstance != NULL;
+ dlstNext(iMBList, (void **) &MBinstance))
+ {
+ if (MBinstance->fCodedMB)
+ {
+ dataItemStartByteIndex = MBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = MBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = MBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = MBinstance->DataItemEndBitIndex;
+
+ /* ac_pred_flag, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[3], dataItemStartBitIndex[3],
+ dataItemEndByteIndex[3], dataItemEndBitIndex[3]);
+
+ /* CBPY, */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[2], dataItemStartBitIndex[2],
+ dataItemEndByteIndex[2], dataItemEndBitIndex[2]);
+ /* DQUANT, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[1], dataItemStartBitIndex[1],
+ dataItemEndByteIndex[1], dataItemEndBitIndex[1]);
+
+ /* INTRA DCs, if they exsit */
+ if (!iColorEffect)
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[4], dataItemStartBitIndex[4],
+ dataItemEndByteIndex[4], dataItemEndBitIndex[4]);
+ }
+ else
+ {
+ if (!(VDT_NO_DATA(dataItemStartByteIndex[4], dataItemStartBitIndex[4],
+ dataItemEndByteIndex[4], dataItemEndBitIndex[4])))
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[4], dataItemStartBitIndex[4],
+ dataItemStartByteIndex[8], dataItemStartBitIndex[8]);
+ ResetMPEG4IntraDcUV();
+ }
+ }
+ }
+ }
+
+ /* make sure the head of the list is reset */
+ dlstHead(iMBList, (void **) &MBinstance);
+}
+
+/*
+* ResetMPEG4IntraDcUV
+*
+* Parameters:
+*
+* Function:
+* This function resets the DCc for U V block in INTRA MB.
+* Inputs are valid only with Color Effect
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::ResetMPEG4IntraDcUV()
+{
+ /* set INTRADC for u,v in the output buffer */
+ TInt sizeU, sizeCodeU, sizeCodeLengthU, valueU, valueCodeU, valueCodeLengthU;
+ TInt sizeV, sizeCodeV, sizeCodeLengthV, valueV, valueCodeV, valueCodeLengthV;
+ TInt curDcScaler, delta;
+ TReal realDelta, realVal;
+ TInt mbh, mbv, mbd; // previous MB in the horizontal, vertical and diagonal directions
+ TInt codeMB;
+
+ // initialize for codewords
+ sizeU = sizeCodeU = sizeCodeLengthU = valueCodeU = valueCodeLengthU = 0;
+ sizeV = sizeCodeV = sizeCodeLengthV = valueCodeV = valueCodeLengthV = 0;
+
+ // initialize for prediction
+ mbh = mbv = mbd = VDX_MB_INTER;
+ codeMB = 0;
+
+ // NOTE: VDX_MB_INTER=1, VDX_MB_INTRA=2, NOT-CODED MB has a value of 0
+ if (iVopCodingType == VDX_VOP_TYPE_I)
+ {
+ /* encode intra DC coefficients for INTRA MBs of I-VOP if
+ either of the following is true:
+ -
+ -
+ else, do not encode intra DC
+ (because rest of MBs have differential intra DC, which is zero)
+ */
+ if (!iCurMBNumInVP ||
+ (!(iCurMBNum%iMBsinWidth) && (iCurMBNumInVP<iMBsinWidth)))
+ {
+ codeMB = 1;
+ }
+ }
+ else if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ if (iCurMBNumInVP>iMBsinWidth)
+ {
+ if (iCurMBNum%iMBsinWidth)
+ {
+ mbh = iMBType[iCurMBNum-1];
+ mbd = iMBType[iCurMBNum-iMBsinWidth-1];
+ }
+ mbv = iMBType[iCurMBNum-iMBsinWidth];
+ }
+ else if (iCurMBNumInVP==iMBsinWidth)
+ {
+ if (iCurMBNum%iMBsinWidth)
+ {
+ mbh = iMBType[iCurMBNum-1];
+ }
+ mbv = iMBType[iCurMBNum-iMBsinWidth];
+ }
+ else if (iCurMBNumInVP>0)
+ {
+ if (iCurMBNum%iMBsinWidth)
+ {
+ mbh = iMBType[iCurMBNum-1];
+ }
+ }
+
+ //
+ if ((mbh<VDX_MB_INTRA && mbv<VDX_MB_INTRA) ||
+ (mbd==VDX_MB_INTRA && ((mbh==VDX_MB_INTRA && mbv<VDX_MB_INTRA) ||
+ (mbh<VDX_MB_INTRA && mbv==VDX_MB_INTRA))))
+ {
+ codeMB = 1;
+ }
+ }
+
+ if (codeMB) // if IntraDC need to be coded
+ {
+ // color-toned U,V values
+ valueU = iColorToneU;
+ valueV = iColorToneV;
+
+ // compensate for different QP than original
+ if (iCurQuant != iRefQuant)
+ {
+ // calculate change in dc value
+ curDcScaler = GetMpeg4DcScalerUV(iCurQuant);
+ realDelta = TReal(iDcScaler-curDcScaler)/TReal(curDcScaler);
+ if (realDelta != 0.0)
+ {
+ // U
+ realVal = realDelta*TReal(valueU);
+ delta = TInt(realVal + ((realVal<0) ? (-0.5) : (0.5)));
+ valueU += delta;
+ // V
+ realVal = realDelta*TReal(valueV);
+ delta = TInt(realVal + ((realVal<0) ? (-0.5) : (0.5)));
+ valueV += delta;
+ }
+ }
+
+ // get codewords
+ GetMPEG4IntraDcCoeffUV(valueU, sizeU, sizeCodeU, sizeCodeLengthU,
+ valueCodeU, valueCodeLengthU);
+ GetMPEG4IntraDcCoeffUV(valueV, sizeV, sizeCodeV, sizeCodeLengthV,
+ valueCodeV, valueCodeLengthV);
+
+ // code codewords
+ // U
+ sPutBits(iOutBuffer, sizeCodeLengthU, sizeCodeU); // dct_dc_coeff size
+ if (sizeCodeU != 3) // size=0
+ {
+ sPutBits(iOutBuffer, valueCodeLengthU, valueCodeU); // dct_dc_coeff differential
+ if (valueCodeLengthU>8)
+ sPutBits(iOutBuffer, 1, 1); // marker bit
+ }
+
+ // V
+ sPutBits(iOutBuffer, sizeCodeLengthV, sizeCodeV); // dct_dc_coeff size
+ if (sizeCodeV != 3) // size=0
+ {
+ sPutBits(iOutBuffer, valueCodeLengthV, valueCodeV); // dct_dc_coeff differential
+ if (valueCodeLengthV>8)
+ sPutBits(iOutBuffer, 1, 1); // marker bit
+ }
+ }
+ else
+ {
+ sPutBits (iOutBuffer, 2, 3); /* U */
+ sPutBits (iOutBuffer, 2, 3); /* V */
+ }
+}
+
+
+/*
+* GetMPEG4IntraDcCoeffUV
+*
+* Parameters:
+* aValue coefficient value
+* aDCAC pointer the reconstructed coefficients
+* Function:
+* This function fills the reconstructed DCAC values for INTRA block.
+* Inputs are valid only with Color Effect
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::GetMPEG4IntraDcCoeffUV(TInt aValue, TInt& aSize,
+ TInt& aSizeCode, TInt& aSizeCodeLength, TInt& aValueCode, TInt& aValueCodeLength)
+{
+ int absVal = (aValue>=0 ? aValue : -aValue);
+ // size of aValueCode
+ for (aSize=0; absVal|0; absVal>>=1, aSize++) ;
+ if (aSize)
+ {
+ // codeword for aSize
+ if (aSize==1)
+ {
+ aSizeCode = 2;
+ aSizeCodeLength = 2;
+ }
+ else
+ {
+ aSizeCode = 1;
+ aSizeCodeLength = aSize;
+ }
+
+ // codeword for aValue
+ aValueCode = aValue;
+ if (aValue<0)
+ aValueCode += ((1<<aSize)-1);
+ aValueCodeLength = aSize;
+ }
+ else
+ {
+ // codeword for aSize
+ aSizeCode = 3; // codeword for size=0
+ aSizeCodeLength = 2;
+ // no codeword for aValue
+ aValueCode = aValueCodeLength = 0;
+ }
+}
+
+
+/*
+* AddOneBlockDCACrecon
+*
+* Parameters:
+* aIndex block index
+* aDCAC pointer the reconstructed coefficients
+* Function:
+* This function fills the reconstructed DCAC values for INTRA block.
+* Inputs are valid only with Color Effect
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::AddOneBlockDCACrecon(int aIndex, int *aDCAC)
+{
+ VDTASSERT(aIndex >= 0 && aIndex < 6);
+
+ if (aDCAC && iDoModeTranscoding && (iTargetFormat == EVedVideoTypeH263Profile0Level10 ||
+ iTargetFormat == EVedVideoTypeH263Profile0Level45))
+ {
+ /* we only need the reconstructed DCACs for MPEG4 -> H263 */
+ /* It is a coded block */
+ memcpy(iDCTBlockData + (aIndex << 6), aDCAC, sizeof(int) * BLOCK_COEFF_SIZE);
+ }
+}
+
+/*
+* ConstructH263MBData
+*
+* Parameters:
+* aNewMCBPCLen new length of mcbpc
+* aNewMCBPC new mcbpc
+* Function:
+* This function creates a new H263 MB
+* Inputs are valid only with Color Effect
+* Returns:
+* VDC error codes
+*
+*/
+int CMPEG4Transcoder::ConstructH263MBData(dmdPParam_t *aParam, int /*aNewMCBPCLen*/, int /*aNewMCBPC*/)
+{
+ /* MB data part1: output MCBPC, CBPY, DQuant, MV, intra DC etc */
+ int *dataItemStartByteIndex;
+ int *dataItemStartBitIndex;
+ int *dataItemEndByteIndex;
+ int *dataItemEndBitIndex;
+ int quant, dquant;
+ int codedBlockPattern = 0;
+
+ const unsigned int sDquant[5] =
+ {
+ 1, 0, (unsigned int)65536, 2, 3
+ };
+
+ if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ dataItemStartByteIndex = iCurPMBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = iCurPMBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = iCurPMBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = iCurPMBinstance->DataItemEndBitIndex;
+ quant = iCurPMBinstance->quant;
+ dquant = iCurPMBinstance->dquant;
+ }
+ else
+ {
+ dataItemStartByteIndex = iCurIMBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = iCurIMBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = iCurIMBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = iCurIMBinstance->DataItemEndBitIndex;
+ quant = iCurIMBinstance->quant;
+ dquant = iCurIMBinstance->dquant;
+ }
+
+ if (iPreQuant != quant - dquant)
+ {
+ /* last quant in MPEG4 and H263 is different, dquant and VLCs may not be reused */
+ if (abs(quant - iPreQuant) > 2)
+ {
+ /* VLCs cannot be reused, obtain the new ones */
+ sQuantizeMB(iDCTBlockData, quant, iPreQuant,
+ iMBCodingType, iColorEffect);
+ quant = iPreQuant;
+ dquant = 0;
+ }
+ else
+ {
+ /* VLCs can be reused, but need to change dquant and MCBPC */
+ dquant = quant - iPreQuant;
+ }
+ }
+
+ /* MB stuffing bits if they exsit */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11],
+ dataItemEndByteIndex[11], dataItemEndBitIndex[11]);
+
+ if (iMBCodingType == VDX_MB_INTER)
+ {
+ VDTASSERT(aParam);
+ tMBPosition mbPos;
+ tMotionVector mvTestOutside;
+ mbPos.x = aParam->xPosInMBs * 16;
+ mbPos.y = aParam->yPosInMBs * 16;
+ mbPos.LeftBound = 0;
+ mbPos.RightBound = iVDEInstance->lumWidth << 1;
+ mbPos.TopBound = 0;
+ mbPos.BottomBound = iVDEInstance->lumHeight << 1;
+ mvTestOutside.mvx = (int16) ((aParam->mvx[0] << 1) / 10);
+ mvTestOutside.mvy = (int16) ((aParam->mvy[0] << 1) / 10);
+
+ /* Three cases for MVs. 1): 4MVs -> need mapping 2). 1 outside frame MV 3) rounding type = 1 */
+ vdcInstance_t * vdcTemp = (vdcInstance_t *)(iVDEInstance->vdcHInstance);
+
+ /* Two cases for MVs. 1): 4MVs -> need mapping 2). 1 outside frame MV */
+ if (iCurPMBinstance->numMVs == 4 || (iCurPMBinstance->numMVs == 1 &&
+ vbmMVOutsideBound(&mbPos, &mvTestOutside, 1)) || vdcTemp->pictureParam.rtype)
+ {
+ int32 numTextureBits;
+ int32 searchRange = 16;
+ tMotionVector *initPred;
+ (h263mbi+iCurMBNum)->QuantScale = (int16) quant;
+ (h263mbi+iCurMBNum)->dQuant = (int16) dquant;
+
+ /* note: this buffer is also used in the diamond search and half-pixel search !!!!!
+ which needs at least 8 points
+ */
+ initPred = (tMotionVector*) malloc(8 * sizeof (tMotionVector));
+ if(!initPred)
+ {
+ //Memory not available
+ return TX_ERR;
+ }
+
+
+ for (int i = 0; i < iCurPMBinstance->numMVs ; i++)
+ {
+ (initPred + i)->mvx = (int16) (aParam->mvx[i] / 10); /* the recorded mv is multipied by 10, */
+ (initPred + i)->mvy = (int16) (aParam->mvy[i] / 10); /* the recorded mv is multipied by 10, */
+ }
+ int32 noOfPredictors = iCurPMBinstance->numMVs;
+
+ /* perform the 4MVs -> 1MV mapping, and output this MB */
+ vbmPutInterMB(&mbPos,
+ iOutBuffer,aParam,
+ initPred, noOfPredictors,
+ (u_int32) iVDEInstance->lumWidth, (u_int32) iVDEInstance->lumHeight,
+ searchRange, iCurMBNum, &numTextureBits,
+ (int16)iColorEffect, h263mbi);
+ /* the MVs buffer is updated inside vbmPutInterMB */
+
+ if (initPred)
+ free(initPred);
+ }
+ else
+ {
+ /* Here, for Inter MB with One inside Frame MV, we simply reuse the DCTs */
+ VDTASSERT(iCurPMBinstance->numMVs == 1);
+
+ /* It is a coded MB, output 1 bit COD (it always exists in P frame) */
+ sPutBits (iOutBuffer, 1, 0);
+ int cbpy;
+ int mcbpcVal;
+ int len;
+
+ codedBlockPattern = sFindCBP(iDCTBlockData, OFF);
+ mcbpcVal = iColorEffect? 0 : (codedBlockPattern & 3);
+ cbpy = ((codedBlockPattern >> 2) & 0xf);
+ vbmGetH263PMCBPC(dquant, iColorEffect, cbpy, mcbpcVal, len);
+ sPutBits(iOutBuffer, len, mcbpcVal); //MCBPC, CBPY
+
+ /* DQUANT, if it exsits */
+ if (dquant)
+ {
+ sPutBits(iOutBuffer, 2, sDquant[dquant + 2]);
+ }
+ /* recode MVs, one more indice exists in the MV VLC table in MPEG4
+ moreover, vop_fcode can be larger than 1 (although it may rarely happens),
+ so it is better to redo the VLC coding
+ */
+ /* the recorded mv is multipied by 10, in pixel unit */
+ int16 mvx = (int16) ((aParam->mvx[0] << 1) / 10);
+ int16 mvy = (int16) ((aParam->mvy[0] << 1) / 10);
+
+ tMotionVector lPredMV[4];
+ tMBInfo *mbi = h263mbi + iCurMBNum;
+
+ /* get the new predicted MV */
+ vbmMvPrediction(mbi, iCurMBNum, lPredMV, (u_int32)iMBsinWidth);
+
+ vbmEncodeMVDifferential(mvx - lPredMV[0].mvx, mvy - lPredMV[0].mvy, 1, iOutBuffer);
+ cbpy = 32;
+ /* following is the block level data */
+ for (int i = 0; i < (iColorEffect? 4 : 6); i++)
+ {
+ int fBlockCoded = cbpy & codedBlockPattern;
+ if (fBlockCoded)
+ {
+ /* here we do the VLC coding again */
+ int numTextureBits = 0;
+ vdtPutInterMBCMT(iOutBuffer,0, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, ON);
+ }
+ cbpy >>= 1;
+ }
+
+ /* update the MVs buffer */
+ (h263mbi + iCurMBNum)->MV[0][0] = (int16) ((aParam->mvx[0] << 1) / 10); /* the recorded mv is multipied by 10 */
+ (h263mbi + iCurMBNum)->MV[0][1] = (int16) ((aParam->mvy[0] << 1) / 10); /* the recorded mv is multipied by 10 */
+
+ } /* end of if 4MVs */
+ }
+ else /* INTRA MB */
+ {
+ /* update the MVs buffer */
+ (h263mbi + iCurMBNum)->MV[0][0] = 0;
+ (h263mbi + iCurMBNum)->MV[0][1] = 0;
+ /* MPEG4 and H263 use different methods for INTRA MB, redo the VLC coding */
+ int cbpy;
+ int mcbpcVal;
+ int len;
+
+ codedBlockPattern = sFindCBP(iDCTBlockData, ON);
+ mcbpcVal = iColorEffect? 0 : (codedBlockPattern & 3);
+ cbpy = ((codedBlockPattern >> 2) & 0xf);
+ vbmGetH263IMCBPC(dquant, (iVopCodingType == VDX_VOP_TYPE_P), iColorEffect, cbpy, mcbpcVal, len);
+ sPutBits(iOutBuffer, len, mcbpcVal); //COD, MCBPC, CBPY
+
+ /* DQUANT, if it exsits */
+ if (dquant)
+ {
+ sPutBits(iOutBuffer, 2, sDquant[dquant + 2]);
+ }
+ cbpy = 32;
+
+ /* following is the block level data */
+ for (int i = 0; i < (iColorEffect? 4 : 6); i++)
+ {
+ /* requantize INTRA DC */
+ /* DC Quantization */
+ int coeff = (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0] >> 3;
+
+ if(coeff < 1) coeff = 1;
+ if(coeff > 254) coeff = 254;
+ if(coeff == 128)
+ {
+ sPutBits(iOutBuffer, 8, 255);
+ }
+ else
+ {
+ sPutBits(iOutBuffer, 8, coeff);
+ }
+
+ (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0] = coeff;
+ if(cbpy & codedBlockPattern)
+ {
+ int numTextureBits = 0;
+ vdtPutInterMBCMT(iOutBuffer,1, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, ON);
+ }
+ cbpy >>= 1;
+ }
+ }
+
+ if (iColorEffect && (iMBCodingType == VDX_MB_INTRA))
+ {
+ ResetH263IntraDcUV(iOutBuffer, iColorToneU, iColorToneV);
+ }
+ iPreQuant = quant;
+
+ return TX_OK;
+}
+
+/*
+* ConstructRegularMPEG4MBData
+*
+* Parameters:
+* aNewMCBPCLen new length of mcbpc
+* aNewMCBPC new mcbpc
+* Function:
+* This function rearranges the data for bitstream with data partitioning
+* Only valid in Data Partitioned mode
+* Inputs are valid only with Color Effect
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::ConstructRegularMPEG4MBData(int aNewMCBPCLen, int aNewMCBPC)
+{
+ /* MB data part1: output MCBPC, CBPY, DQuant, MV, intra DC etc */
+ int *dataItemStartByteIndex;
+ int *dataItemStartBitIndex;
+ int *dataItemEndByteIndex;
+ int *dataItemEndBitIndex;
+
+ if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ dataItemStartByteIndex = iCurPMBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = iCurPMBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = iCurPMBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = iCurPMBinstance->DataItemEndBitIndex;
+ }
+ else
+ {
+ dataItemStartByteIndex = iCurIMBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = iCurIMBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = iCurIMBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = iCurIMBinstance->DataItemEndBitIndex;
+ }
+
+ /* MB stuffing bits if they exsit */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11],
+ dataItemEndByteIndex[11], dataItemEndBitIndex[11]);
+
+ if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ /* It is a coded MB, output 1 bit COD (it always exists in P frame) */
+ sPutBits (iOutBuffer, 1, 0);
+ }
+
+ /* MCBPC. NOTE: the positions do not include MCBPC stuffing bits !! */
+ if (iColorEffect)
+ {
+ /* MCBPC Changed */
+ sPutBits(iOutBuffer, aNewMCBPCLen, aNewMCBPC);
+ }
+ else
+ {
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[0], dataItemStartBitIndex[0],
+ dataItemEndByteIndex[0], dataItemEndBitIndex[0]);
+ }
+ /* ac_pred_flag, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[3], dataItemStartBitIndex[3],
+ dataItemEndByteIndex[3], dataItemEndBitIndex[3]);
+
+ /* CBPY */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[2], dataItemStartBitIndex[2],
+ dataItemEndByteIndex[2], dataItemEndBitIndex[2]);
+
+ /* DQUANT, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[1], dataItemStartBitIndex[1],
+ dataItemEndByteIndex[1], dataItemEndBitIndex[1]);
+
+ if (iMBCodingType == VDX_MB_INTER)
+ {
+ /* MVs, if they exsit */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[10], dataItemStartBitIndex[10],
+ dataItemEndByteIndex[10], dataItemEndBitIndex[10]);
+ }
+
+ /* following is the block level data */
+ for (int i = 0; i < (iColorEffect? 4 : 6); i++)
+ {
+ /* INTRA DC, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[i + 4], dataItemStartBitIndex[i + 4],
+ dataItemEndByteIndex[i + 4], dataItemEndBitIndex[i + 4]);
+
+ /* block data part2, AC or DCT coefficients */
+ if (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC)
+ {
+ /* remember for data partitioning, the positions only indicate the
+ AC or DCTs coefficients
+ */
+ if (VDT_NO_DATA(iBlockStartByteIndex[i], iBlockStartBitIndex[i],
+ iBlockEndByteIndex[i], iBlockEndBitIndex[i]))
+ {
+ /* no coefficients,skip this block */
+ continue;
+ }
+ else
+ {
+ /* for RVLC coding, we transform the block data back to VLC */
+ int numTextureBits = 0;
+ /* redo the entropy coding, RVLC -> VLC
+ only for AC (IMB) or DCT (PMB) coefficients
+ */
+ if (iMBCodingType == VDX_MB_INTRA)
+ {
+ vdtPutIntraMBCMT(iOutBuffer,iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, i, 1, 0);
+ }
+ else
+ {
+ vdtPutInterMBCMT(iOutBuffer,0, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, OFF);
+ }
+ }
+ }
+ else /* ouput the AC or DCT coefficients */
+ {
+ bufEdit.copyMode = CopyWhole; /* CopyWhole */
+ vdtCopyBuffer(iInBuffer,iOutBuffer,
+ iBlockStartByteIndex[i],iBlockStartBitIndex[i],
+ iBlockEndByteIndex[i],iBlockEndBitIndex[i]);
+ }
+ }
+ if (iColorEffect && (iMBCodingType == VDX_MB_INTRA))
+ {
+ ResetMPEG4IntraDcUV();
+ }
+}
+
+
+
+/*
+* AddOneBlockDataToMB
+*
+* Parameters:
+* blockData block data before VLC coding, in ZigZag order
+* Function:
+* This function input one block data to current MB
+* only here the whole MB data is retrieved (COD=0)
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::AddOneBlockDataToMB(int aBlockIndex, int *aBlockData)
+{
+ VDTASSERT(aBlockIndex >= 0 && aBlockIndex < 6);
+
+
+ if (aBlockData && iDoModeTranscoding)
+ {
+ /* iDCTBlockData is only used when we need to convert the bitstream to MPEG4_RESYN
+ It is a coded block
+ */
+ if (iMBCodingType == VDX_MB_INTRA && (iTargetFormat == EVedVideoTypeH263Profile0Level10 ||
+ iTargetFormat == EVedVideoTypeH263Profile0Level45))
+ {
+ /* we only need the reconstructed DCACs, skipped */
+ }
+ else
+ {
+ memcpy(iDCTBlockData + (aBlockIndex << 6), aBlockData, sizeof(int) * BLOCK_COEFF_SIZE);
+ }
+ }
+ else
+ {
+ memset(iDCTBlockData + (aBlockIndex << 6), 0, sizeof(int) * BLOCK_COEFF_SIZE);
+ }
+
+
+
+ iBlockEndByteIndex[aBlockIndex] = iInBuffer->getIndex;
+ iBlockEndBitIndex[aBlockIndex] = iInBuffer->bitIndex;
+}
+
+/*
+* ErrorResilienceInfo
+*
+* Parameters:
+* header VOL Header data
+* Function:
+* This function records the position of resnc_marker_disable bit
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::ErrorResilienceInfo(vdxVolHeader_t *header, int aByte, int aBit)
+{
+ if (header)
+ {
+
+ memcpy(&iVOLHeader, header, sizeof(vdxVolHeader_t)); // save the header info
+
+ }
+ else
+ {
+ iErrorResilienceStartByteIndex = aByte; /* save the bits position */
+ iErrorResilienceStartBitIndex = aBit;
+ }
+}
+
+
+
+/*
+* MPEG4TimerResolution
+*
+* Parameters:
+*
+* Function:
+* This function records the position of vop_time_increment_resolution bit
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::MPEG4TimerResolution(int aStartByteIndex, int aStartBitIndex)
+{
+ iTimeResolutionByteIndex = aStartByteIndex;
+ iTimeResolutionBitIndex = aStartBitIndex;
+}
+
+
+
+void CMPEG4Transcoder::ConstructVOSHeader(int aMPEG4, vdeDecodeParamters_t *aDecoderInfo)
+{
+ if (!aMPEG4 )
+ {
+ /* for H263 and MPEG4 shortheader, no vos generated */
+ if (iErrorResilienceStartByteIndex == KDataNotValid &&
+ iErrorResilienceStartBitIndex == KDataNotValid)
+ {
+ iBitStreamMode = EVedVideoBitstreamModeH263; // pure H.263
+ aDecoderInfo->vosHeaderSize = aDecoderInfo->fModeChanged? KH263ToMpeg4VosSize : 0;
+ }
+ else
+ {
+ /* we went into the VOL layer. It is a MPEG4 bitstream with short header */
+ iBitStreamMode = EVedVideoBitstreamModeMPEG4ShortHeader; /* MPEG4 shortheader */
+ iShortHeaderEndByteIndex = iInBuffer->getIndex;
+ iShortHeaderEndBitIndex = iInBuffer->bitIndex;
+ aDecoderInfo->vosHeaderSize = aDecoderInfo->fModeChanged? KH263ToMpeg4VosSize : KShortHeaderMpeg4VosSize;
+ }
+ fFirstFrameInH263 = ETrue;
+ }
+ else
+ {
+ iNumMBsInOneVOP = (iVDEInstance->lumHeight * iVDEInstance->lumWidth) / 256;
+
+ /* even iBitStreamMode is given outside, we renew it here anyway */
+ iBitStreamMode = sGetMPEG4Mode(iVOLHeader.error_res_disable,
+ iVOLHeader.data_partitioned, iVOLHeader.reversible_vlc);
+
+ if (iTargetFormat != EVedVideoTypeH263Profile0Level10 &&
+ iTargetFormat != EVedVideoTypeH263Profile0Level45) /* EVedVideoTypeMPEG4SimpleProfile or None */
+ {
+ /* copy from the begining of the input buffer */
+ vdtCopyBuffer(iInBuffer,iOutBuffer,0,7, iTimeResolutionByteIndex, iTimeResolutionBitIndex);
+ /* it is 16 bits */
+ sPutBits (iOutBuffer, KMpeg4VopTimeIncrementResolutionLength, *aDecoderInfo->aMPEG4TargetTimeResolution);
+
+ int startByteIndex, startBitIndex;
+ startByteIndex = iTimeResolutionByteIndex + 2;
+ startBitIndex = iTimeResolutionBitIndex;
+
+ sPutBits(iOutBuffer, 1, MARKER_BIT);
+ /* close fixed_vop_rate */
+ sPutBits (iOutBuffer, 1, 0); /* it is 1 bit */
+
+ int num_bits = 0;
+ vdcInstance_t * vdcTemp = (vdcInstance_t *)(iVDEInstance->vdcHInstance);
+ if (vdcTemp->pictureParam.fixed_vop_rate)
+ {
+ for (num_bits = 1; ((vdcTemp->pictureParam.time_increment_resolution-1) >> num_bits) != 0; num_bits++)
+ {
+ }
+ }
+ num_bits += 2;
+
+ /* following is to skip the fixed_vop_rate */
+ int bitsRemain, bitShift = 0;
+ int bitsToMove = 0 ;
+ /* complete the byte */
+ if (startBitIndex != 7)
+ {
+ bitShift = startBitIndex + 1;
+ bitsToMove = (num_bits < bitShift) ? num_bits : bitShift;
+ /* update statistics to take care of bit addition or byte completion */
+ if (num_bits < bitShift)
+ {
+ /* bits skipped but byte not completed */
+ startBitIndex -= bitsToMove;
+ }
+ else
+ {
+ /* byte completed */
+ startByteIndex ++;
+ startBitIndex = 7;
+ }
+ }
+ /* full bytes to skip */
+ startByteIndex += ((num_bits - bitsToMove) >> 3);
+ bitsRemain = (num_bits - bitsToMove) % 8;
+
+ /* the remaining bits */
+ startBitIndex = ( bitsRemain != 0) ? 7 - bitsRemain : startBitIndex;
+
+
+ /* check if we have user data in the end of VOL; it cannot be copied as such but needs to be byte aligned */
+ /* first need to rewind the input buffer to be able to seek in it */
+ int16 error = 0;
+ int curByteIndex = iInBuffer->getIndex;
+ int curBitIndex = iInBuffer->bitIndex;
+ int bits = ((curByteIndex - iTimeResolutionByteIndex)<<3) + (7-curBitIndex);
+ bibRewindBits(bits, iInBuffer, &error);
+ int sncCode = sncSeekMPEGStartCode(iInBuffer,
+ vdcTemp->pictureParam.fcode_forward, 1 /* don't check VOPs */, 1 /* check for user data*/, &error);
+
+ /* record next resync position */
+ int resyncByteIndex = iInBuffer->getIndex;
+
+ int stuffBits = 0;
+ int userDataExists = 0;
+ if ( sncCode == SNC_USERDATA )
+ {
+ /* copy only until this sync code, and copy the rest separately in the end. */
+ userDataExists = 1;
+ }
+ else
+ {
+ /* No UD */
+ /* restore the original pointers in iInBuffer */
+ iInBuffer->getIndex = curByteIndex;
+ iInBuffer->bitIndex = curBitIndex;
+ }
+
+ if (iDoModeTranscoding || aDecoderInfo->fHaveDifferentModes)
+ {
+ /* close the error resilience tools, change the bitstream to regular MPEG4 with resyn marker */
+ int numBits = iVOLHeader.data_partitioned ? 3 : 2;
+
+ bufEdit.copyMode = CopyWithEdit;
+ bufEdit.editParams[0].StartByteIndex = iErrorResilienceStartByteIndex;
+ bufEdit.editParams[0].StartBitIndex = iErrorResilienceStartBitIndex;
+ bufEdit.editParams[0].curNumBits = numBits;
+ bufEdit.editParams[0].newNumBits = 2;
+ bufEdit.editParams[0].newValue = 0; /* new codeword: resyn, no dp, no rvlc */
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit, startByteIndex,startBitIndex); /* copy from vop_time_increment_resolution */
+
+ /* rewind stuffing bits */
+ int16 error;
+ sncRewindStuffing(iOutBuffer, &error);
+
+ // stuff bits in outbuffer for next start code
+ vdtStuffBitsMPEG4(iOutBuffer);
+ }
+ else
+ {
+
+ /* rewind stuffing bits */
+ sncRewindStuffing(iInBuffer, &error);
+
+ /* record the number of bits rewinded - can be from 0 to 8 */
+ /* note that iInBuffer must be byte aligned before rewinding */
+ if (iInBuffer->bitIndex == 7) // full byte rewind
+ {
+ stuffBits = ( (int)(iInBuffer->getIndex) < resyncByteIndex) ? 8 : 0;
+ }
+ else
+ {
+ stuffBits = iInBuffer->bitIndex + 1;
+ }
+
+ /* copy the rest of VOS until the first VOP (or UD) */
+ bufEdit.copyMode = CopyWhole;
+ vdtCopyBuffer(iInBuffer,iOutBuffer, startByteIndex,startBitIndex,
+ resyncByteIndex, iInBuffer->bitIndex);
+
+ // stuff bits in outbuffer for next start code
+ vdtStuffBitsMPEG4(iOutBuffer);
+
+ // move inbuffer pointer back to original value
+ bibForwardBits(stuffBits, iInBuffer);
+ }
+
+
+ if ( userDataExists )
+ {
+ /* seek for VOP start code */
+ int sncCode = sncSeekMPEGStartCode(iInBuffer,
+ vdcTemp->pictureParam.fcode_forward, vdcTemp->pictureParam.error_res_disable, 0, &error);
+
+ /* rewind stuffing bits */
+ sncRewindStuffing(iInBuffer, &error);
+
+ // record the number of bits rewinded - can be from 0 to 8
+ // note that iInBuffer must be byte aligned before rewinding
+ if (iInBuffer->bitIndex == 7) // full byte rewind
+ {
+ stuffBits = ( (int)(iInBuffer->getIndex) < resyncByteIndex) ? 8 : 0;
+ }
+ else
+ {
+ stuffBits = iInBuffer->bitIndex + 1;
+ }
+
+ bufEdit.copyMode = CopyWhole;
+ vdtCopyBuffer(iInBuffer,iOutBuffer, resyncByteIndex, 7,
+ iInBuffer->getIndex, iInBuffer->bitIndex);
+
+ // stuff bits in outbuffer for next start code
+ vdtStuffBitsMPEG4(iOutBuffer);
+
+ // move inbuffer pointer back to original value
+ bibForwardBits(stuffBits, iInBuffer);
+
+
+
+ }
+
+ aDecoderInfo->vosHeaderSize = iOutBuffer->getIndex;
+ }
+
+ PRINT((_L("CMPEG4Transcoder: ConstructVOSHeader. resyn: %d, data partitioned: %d, rvlc: %d, resolution: %d"),
+ iVOLHeader.error_res_disable, iVOLHeader.data_partitioned, iVOLHeader.reversible_vlc,
+ aDecoderInfo->iTimeIncrementResolution));
+ }
+ PRINT((_L("CMPEG4Transcoder: streammode: %d, outputformat: %d, vos size : %d"),
+ iBitStreamMode, iTargetFormat, aDecoderInfo->vosHeaderSize));
+}
+
+
+
+
+/****************************************************************
+* *
+* Functions for H.263, or H.263 -> MPEG4 (only baseline H.263) *
+* *
+*****************************************************************/
+
+
+/* Luminance block dc-scaler value corresponding to QP values of 0-31 */
+const u_int8 sLumDCScalerTbl[32] =
+{
+ 0, 8, 8, 8, 8, 10, 12, 14,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 34, 36, 38, 40, 42, 44, 46
+};
+
+/* Chrominance block dc-scaler value corresponding to QP values of 0-31 */
+const u_int8 sChrDCScalerTbl[32] =
+{
+ 0, 8, 8, 8, 8, 9, 9, 10,
+ 10, 11, 11, 12, 12, 13, 13, 14,
+ 14, 15, 15, 16, 16, 17, 17, 18,
+ 18, 19, 20, 21, 22, 23, 24, 25
+};
+
+/*
+* sGetMPEG4INTRADCValue
+*
+* Parameters:
+* intraDC reconstructed intra DC from H263
+* QP quantion factor
+* blockNum block number (0 to 5)
+* currMBNum current MB number
+* mbinWidth number of MBs in picure width
+* dcData matrix to store the INTRA DC values
+* mbVPNumber matrix recording the video packet number for each MB
+*
+* Function:
+* This function gets the new intra DC for MPEG4
+* Returns:
+* INTRA DC to put into MPEG4 bitstream
+* Error codes:
+* None
+*
+*/
+int sGetMPEG4INTRADCValue(int intraDC, int blockNum, int currMBNum,
+ int32 QP, int32 mbinWidth, int **dcData, int *mbVPNumber)
+{
+ int tempDCScaler;
+ int blockA = 0, blockB = 0, blockC = 0;
+ int gradHor, gradVer, predDC;
+
+ VDTASSERT(currMBNum >= 0);
+ VDTASSERT(QP <= 31);
+
+ /* Prediction blocks A (left), B (above-left), and C (above) */
+ switch (blockNum)
+ {
+ case 0:
+ case 4:
+ case 5:
+ /* Y0, U, and V blocks */
+ if (((currMBNum % mbinWidth) == 0) || /* Left edge */
+ (mbVPNumber[currMBNum - 1] != mbVPNumber[currMBNum]))
+ {
+ blockA = 1024; /* fixed value for H263 */
+ }
+ else
+ {
+ blockA = dcData[currMBNum - 1][blockNum > 3? blockNum : 1];
+ }
+
+ if (((currMBNum / mbinWidth) == 0) || /* Top Edge */
+ ((currMBNum % mbinWidth) == 0) || /* Left Edge */
+ (mbVPNumber[currMBNum - mbinWidth - 1] != mbVPNumber[currMBNum]))
+ {
+ blockB = 1024;
+ }
+ else
+ {
+ blockB = dcData[currMBNum - mbinWidth - 1][blockNum > 3? blockNum : 3];
+ }
+
+ if (((currMBNum / mbinWidth) == 0) || /* Top Edge */
+ (mbVPNumber[currMBNum - mbinWidth] != mbVPNumber[currMBNum]))
+ {
+ blockC = 1024;
+ }
+ else
+ {
+ blockC = dcData[currMBNum - mbinWidth][blockNum > 3? blockNum : 2];
+ }
+ break;
+
+ case 1:
+ /* Y1 block */
+ blockA = dcData[currMBNum][0];
+
+ if (((currMBNum / mbinWidth) == 0) || /* Top Edge */
+ (mbVPNumber[currMBNum - mbinWidth] != mbVPNumber[currMBNum]))
+ {
+ blockB = 1024;
+ blockC = 1024;
+ }
+ else
+ {
+ blockB = dcData[currMBNum - mbinWidth][2];
+ blockC = dcData[currMBNum - mbinWidth][3];
+ }
+ break;
+
+ case 2:
+ /* Y2 block */
+
+ if (((currMBNum % mbinWidth) == 0) || /* Left Edge */
+ (mbVPNumber[currMBNum - 1] != mbVPNumber[currMBNum]))
+ {
+ blockA = 1024;
+ blockB = 1024;
+ }
+ else
+ {
+ blockA = dcData[currMBNum - 1][3];
+ blockB = dcData[currMBNum - 1][1];
+ }
+
+ blockC = dcData[currMBNum][0];
+ break;
+
+ case 3:
+ /* Y3 block */
+
+ blockA = dcData[currMBNum][2];
+ blockB = dcData[currMBNum][0];
+ blockC = dcData[currMBNum][1];
+ break;
+
+ default:
+ break;
+ }
+
+ gradHor = blockB - blockC;
+ gradVer = blockA - blockB;
+
+ if ((abs(gradVer)) < (abs(gradHor)))
+ {
+ /* Vertical prediction (from C) */
+ predDC = blockC;
+ }
+ else
+ {
+ /* Horizontal prediction (from A) */
+ predDC = blockA;
+ }
+
+ /* DC quantization */
+ if (blockNum < 4) /* Luminance Block */
+ {
+ intraDC += (sLumDCScalerTbl[QP] >> 1);
+ intraDC /= sLumDCScalerTbl[QP];
+
+ /* update the DC data matrix
+ note: for INTER MB, the entry is already preset to 1024!!
+ */
+ dcData[currMBNum][blockNum] = intraDC * sLumDCScalerTbl[QP];
+ }
+ else /* Chrominance block */
+ {
+ intraDC += (sChrDCScalerTbl[QP] >> 1);
+ intraDC /= sChrDCScalerTbl[QP];
+ /* update the DC data matrix
+ note: for INTER MB, the entry is already preset to 1024!!
+ */
+ dcData[currMBNum][blockNum] = intraDC * sChrDCScalerTbl[QP];
+ }
+ /* DC prediction */
+ tempDCScaler = (blockNum<4)? sLumDCScalerTbl[QP] : sChrDCScalerTbl[QP];
+
+ return (intraDC - ((predDC + tempDCScaler/2) / tempDCScaler));
+}
+
+/*
+* sPutVOLHeader
+*
+* Parameters:
+* bitOut pointer to the output buffer
+* aWidth picture width
+* aHeight picture height
+* aTimerResolution timer resolution for MPEG4
+*
+* Function:
+* This function writes the VOL header into bit-stream
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+inline void sPutVOLHeader(bibBuffer_t* bitOut, int aWidth, int aHeight, int aTimerResolution)
+{
+ bibBuffer_t *lBitOut;
+ uint32 vop_time_increment_resolution;
+
+ lBitOut = bitOut;
+ WRITE32(lBitOut, (uint32)VIDEO_OBJECT_LAYER_START_CODE);
+ /* RandomAccessibleVol == 1 means all VOP's can be decoded independently */
+ sPutBits(lBitOut, 1, 0);
+ /* VideoObjectTypeIndication = SIMPLE OBJECT */
+ sPutBits(lBitOut, 8, SIMPLE_OBJECT);
+ /* IsObjectLayerIdentifier */
+ sPutBits(lBitOut, 1, 0);
+ /* AspectRatioInfo */
+ sPutBits(lBitOut, 4, ASPECT_RATIO_INFO);
+ /* vol_control_parameters = 1 */
+ sPutBits(lBitOut, 1, 1);
+ /* Chroma Format */
+ sPutBits(lBitOut, 2, CHROMA_FORMAT);
+ /* LowDelay = 1; */
+ sPutBits(lBitOut, 1, 1);
+ /* vbvParameters = 0; */
+ sPutBits(lBitOut, 1, 0);
+ /* VideoObjectLayerShape == RECTANGULAR */
+ sPutBits(lBitOut, 2, RECTANGULAR);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* VopTimeIncrementResolution */
+ vop_time_increment_resolution = aTimerResolution;
+ sPutBits(lBitOut, 16, vop_time_increment_resolution);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* FixedVOPRate = 0, not fixed */
+ sPutBits(lBitOut, 1, 0);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* VideoObjectLayerWidth */
+ sPutBits(lBitOut, 13, aWidth);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* VideoObjectLayerHeight */
+ sPutBits(lBitOut, 13, aHeight);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* Interlaced = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* ObmcDisable= 1 */
+ sPutBits(lBitOut, 1, 1);
+ /* SpriteEnable = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* Not8Bit = 0 */
+ sPutBits(lBitOut, 1, 0);
+ /* QuantType = H263 (0) */
+ sPutBits(lBitOut, 1, H263);
+ /* Complexity Estimation Disable = 1 */
+ sPutBits(lBitOut, 1, 1);
+ /* ResyncMarkerDisable */
+ sPutBits(lBitOut, 1, 0); /* H263 is converted to resyn_marker MPEG4 in video editor */
+ /* DataPartioned */
+ sPutBits(lBitOut, 1, 0); /* always 0 for H263 */
+ /* Reversible VLC closed */
+ /* Scalability = 0 */
+ sPutBits(lBitOut, 1, 0);
+ vdtStuffBitsMPEG4(lBitOut);
+
+ return;
+}
+
+
+/*
+* sPutGOVHeader
+*
+* Parameters:
+* bitOut pointer to the output buffer
+* aModuloTimeBase time base for MPEG4
+*
+* Function:
+* This function writes the group of VOP(GOV) header into bit-stream
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+inline void sPutGOVHeader(bibBuffer_t *bitOut, int aModuloTimeBase)
+{
+ int32 time_code_hours;
+ int32 time_code_minutes;
+ int32 time_code_seconds;
+
+ WRITE32(bitOut, (uint32)GROUP_OF_VOP_START_CODE);
+ time_code_seconds = aModuloTimeBase;
+ time_code_minutes = time_code_seconds / 60;
+ time_code_hours = time_code_minutes / 60;
+ time_code_minutes = time_code_minutes - (time_code_hours * 60);
+ time_code_seconds = time_code_seconds - (time_code_minutes * 60)
+ - (time_code_hours * 3600);
+
+ sPutBits(bitOut, 5, time_code_hours);
+ sPutBits(bitOut, 6, time_code_minutes);
+ sPutBits(bitOut, 1, MARKER_BIT);
+ sPutBits(bitOut, 6, time_code_seconds);
+
+ /* ClosedGov */
+ sPutBits(bitOut, 1, 0);
+ /* Broken Link */
+ sPutBits(bitOut, 1, 0);
+
+ /* Stuff bits */
+ vdtStuffBitsMPEG4(bitOut);
+
+ return;
+}
+
+/*
+* sConstructMPEG4VOSHeaderForH263
+*
+* Parameters:
+* bitOut pointer to the output buffer
+* aWidth picture width
+* aHeight picture height
+*
+* Function:
+* This function writes the MPEG4 VOS header into bit-stream
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void sConstructMPEG4VOSHeaderForH263(bibBuffer_t *bitOut, int aWidth, int aHeight, int aOutputMpeg4TimeRes)
+{
+ /* visual object sequence header */
+ WRITE32(bitOut, (uint32)VISUAL_OBJECT_SEQUENCE_START_CODE);
+
+ /* This is for testing for level 0,3 */
+ uint32 level = 8; /* level 0 for QCIF or less */
+ if(aWidth > 176 || aHeight > 144) /* level 2 for greater than QCIF */
+ level = 2;
+ sPutBits(bitOut, 8, level); /* simple profile, level 0 for H263 */
+
+ /* visual object header begins */
+ WRITE32(bitOut, (uint32)VISUAL_OBJECT_START_CODE);
+ /* IsVisualObjectIdentifier = 0 */
+ sPutBits(bitOut, 1, 0);
+ /* VisualObjectType = VIDEO_OBJECT */
+ sPutBits(bitOut, 4, VISUAL_OBJECT);
+ /* VideoSignalType = 0 */
+ sPutBits(bitOut, 1, 0);
+
+ vdtStuffBitsMPEG4(bitOut);
+ WRITE32(bitOut, (uint32)VIDEO_OBJECT_START_CODE);
+
+ /* Writes the VOL header into bit-stream , for baseline H263 TR is marked with 29.97fps. ->? */
+ sPutVOLHeader(bitOut, aWidth, aHeight, aOutputMpeg4TimeRes);
+
+ /* Writes GOV , time base is 0 */
+ sPutGOVHeader(bitOut, 0);
+
+ return;
+}
+
+
+/*
+* sPutVideoPacketHeader
+*
+* Parameters:
+* lBitOut output buffer
+* mbNo Macroblock number
+* quantiserScale quant value to be put in header
+* aMBsInVOP # of MBs in one VOP
+*
+* Function:
+* This function writes the video packet header information into bit-stream
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+inline void sPutVideoPacketHeader(bibBuffer_t *lBitOut, int32 mbNo,
+ int16 quantiserScale,
+ int aMBsInVOP)
+{
+ int32 lResyncMarkerLength = 17;
+ int32 lMBNoResolution;
+
+ /* ResyncMarker */
+ int fCode = 1; /*always 1 for H263 */
+ lResyncMarkerLength = 16 + fCode;
+ sPutBits(lBitOut, lResyncMarkerLength, 1);
+
+ --aMBsInVOP;
+ lMBNoResolution = 1;
+ while( (aMBsInVOP =
+ aMBsInVOP >> 1) > 0 )
+ {
+ lMBNoResolution++;
+ }
+ sPutBits(lBitOut, lMBNoResolution, mbNo);
+
+ /* QuantScale */
+ sPutBits(lBitOut, 5, quantiserScale);
+ /* HEC */
+ sPutBits(lBitOut, 1, 0); /* always 0 for H263 */
+
+ return;
+}
+
+/*
+* sConstructVOPHeaderForH263
+*
+* Parameters:
+* lBitOut output buffer
+* prevQuant quant value to be put in header
+* aVOPType picture coding type
+* aVOPTimeIncrement time increament
+*
+* Function:
+* This function writes the VOP header into bit-stream for one H263 frame
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+
+void sConstructVOPHeaderForH263(bibBuffer_t *lBitOut, int prevQuant, int aVOPType, int aVOPTimeIncrement,int aOutputMpeg4TimeRes)
+{
+ WRITE32(lBitOut, (uint32)VOP_START_CODE);
+ /* VOPType, 0 for Intra and 1 for inter */
+ sPutBits(lBitOut, 2, aVOPType);
+
+ /* H263 TR is marked with 29.97fps */
+ /* Modulo Time Base */
+ int outputTimerResolution = aOutputMpeg4TimeRes;
+ while ((unsigned)aVOPTimeIncrement >= (unsigned) outputTimerResolution)
+ {
+ sPutBits(lBitOut, 1, 1);
+ aVOPTimeIncrement -= outputTimerResolution;
+ }
+ sPutBits(lBitOut, 1, 0);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* VopTimeIncrement */
+ int numOutputTrBits;
+ for (numOutputTrBits = 1; ((outputTimerResolution-1) >> numOutputTrBits) != 0; numOutputTrBits++)
+ {
+ }
+ int VOPIncrementResolutionLength = numOutputTrBits;
+ sPutBits(lBitOut, VOPIncrementResolutionLength, aVOPTimeIncrement);
+ /* Marker Bit */
+ sPutBits(lBitOut, 1, MARKER_BIT);
+ /* VOPCoded */
+ sPutBits(lBitOut, 1, 1); /* always 1 for H263 */
+ /* VOPRoundingType */
+ if(aVOPType == P_VOP)
+ {
+ sPutBits(lBitOut, 1, 0); /* always 0 for H263 */
+ }
+ /* IntraDCVLCThreshold */
+ sPutBits(lBitOut, 3, 0); /* always 0 for H263 */
+ /* VOPQuant */
+ sPutBits(lBitOut, 5, prevQuant);
+ /* VOPFcodeForwad */
+ if(aVOPType == P_VOP)
+ {
+ sPutBits(lBitOut, 3, 1); /* always 1 for H263 */
+ }
+
+ return;
+}
+
+
+
+/*
+* H263PictureHeaderEndedL
+*
+* Parameters:
+*
+* Function:
+* This function is called after one H263 picture header is parsed
+* Note: the input header is only valid inside this function
+* Returns:
+* VDC error codes
+* Error codes:
+* None
+*
+*/
+int CMPEG4Transcoder::H263PictureHeaderEnded(dphOutParam_t *aH263PicHeader, dphInOutParam_t *aInfo)
+{
+ VDTASSERT(aH263PicHeader);
+
+ // asad
+ if (!aInfo->vdcInstance->frameNum || !iRefQuant)
+ {
+ iRefQuant = aH263PicHeader->pquant;
+ iDcScaler = GetMpeg4DcScalerUV(iRefQuant);
+ }
+
+ if (!iDoModeTranscoding )
+ {
+
+ /* Copy the header to output stream */
+ bufEdit.copyMode = CopyWhole; /* CopyWhole */
+
+ if ( (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45) &&
+ fFirstFrameInH263 && iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader)
+ {
+ /* we don't need the VOS header, remove it */
+ PRINT((_L("CMPEG4Transcoder: MPEG4 shortheader VOS removed")));
+
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,iShortHeaderEndByteIndex,iShortHeaderEndBitIndex);
+ fFirstFrameInH263 = EFalse;
+ }
+ else
+ {
+ /* copy from the begining of the input buffer,
+ including the VOS header for MPEG4 shortheader if its mode is not being changed
+ */
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,0,7);
+ }
+ }
+
+
+
+ else
+ {
+ /* H263 Picture Header -> MPEG4 VOP Header mapping
+ information about this frame
+ */
+ iMBsinWidth = aInfo->vdcInstance->pictureParam.lumWidth >> 4;
+
+ iNumMBsInOneVOP = (aInfo->vdcInstance->pictureParam.lumWidth >> 4) *
+ (aInfo->vdcInstance->pictureParam.lumHeight >> 4);
+
+ iNumMBsInGOB = aInfo->vdcInstance->pictureParam.numMBsInGOB;
+
+ /* create the intraDC matrix for DC prediction */
+ VDTASSERT(!iH263DCData);
+ VDTASSERT(!iH263MBVPNum);
+
+ iH263DCData = (int **)malloc(iNumMBsInOneVOP * sizeof(int));
+ if (!iH263DCData)
+ {
+ deb("CMPEG4Transcoder::ERROR - iH263DCData creation failed\n");
+ return TX_ERR;
+ }
+
+ for (int i = 0; i < iNumMBsInOneVOP; i++)
+ {
+ iH263DCData[i] = (int *) malloc(6 * sizeof(int)); /* six blocks in one MB */
+ VDTASSERT(iH263DCData[i]);
+ if (!iH263DCData[i])
+ {
+ deb("CMPEG4Transcoder::ERROR - iH263DCData[i] creation failed\n");
+
+ for(int k=0; k<i; k++)
+ {
+ free (iH263DCData[k]);
+ }
+ if (iH263DCData)
+ {
+ free(iH263DCData);
+ }
+
+ return TX_ERR;
+ }
+
+
+ /* initialize each entry to 1024 for DC prediction */
+ for (int j = 0; j < 6; j++)
+ {
+ iH263DCData[i][j] = 1024;
+ }
+ }
+
+ iH263MBVPNum = (int *) malloc(iNumMBsInOneVOP * sizeof(int));
+ if (!iH263MBVPNum)
+ {
+ deb("CMPEG4Transcoder::ERROR - iH263MBVPNum creation failed\n");
+ return TX_ERR;
+ }
+
+ memset(iH263MBVPNum, 0, iNumMBsInOneVOP * sizeof(int));
+ int pictureType = aInfo->vdcInstance->pictureParam.pictureType == VDX_PIC_TYPE_I? I_VOP : P_VOP;
+
+ if (fFirstFrameInH263)
+ {
+ /* first frame, construct the VOS header */
+ sConstructMPEG4VOSHeaderForH263(iOutBuffer,
+ aInfo->vdcInstance->pictureParam.lumWidth,
+ aInfo->vdcInstance->pictureParam.lumHeight,
+ iOutputMpeg4TimeIncResolution);
+ fFirstFrameInH263 = EFalse;
+
+ PRINT((_L("CMPEG4Transcoder: H263 -> MPEG VOS generated")));
+ }
+ sConstructVOPHeaderForH263(iOutBuffer, aH263PicHeader->pquant, pictureType, aH263PicHeader->trp == -1 ? 0 : aH263PicHeader->trp,iOutputMpeg4TimeIncResolution);
+
+
+ PRINT((_L("CMPEG4Transcoder: H263 -> MPEG4: transcoding one picture")));
+ }
+
+
+ PRINT((_L("CMPEG4Transcoder: H263PictureHeaderEndedL. color effect: %d, format convert %d, do transcoding: %d streammode: %d, outputformat: %d "),
+ iColorEffect, iDoModeTranscoding, iDoTranscoding,
+ iBitStreamMode, iTargetFormat));
+
+ return TX_OK;
+}
+
+/*
+* H263GOBSliceHeaderEnded
+*
+* Parameters:
+*
+* Function:
+* This function is called after one H263 GOB or Slice header is parsed
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::H263GOBSliceHeaderEnded(vdxGOBHeader_t *aH263GOBHeader, vdxSliceHeader_t */*aH263SliceHeader*/)
+{
+ iGOBSliceHeaderEndByteIndex = iInBuffer->getIndex;
+ iGOBSliceHeaderEndBitIndex = iInBuffer->bitIndex;
+
+ if (aH263GOBHeader)
+ {
+ /* not the first GOB (no header), we have stuffing bits ahead
+ since we only store the position of GBSC not including
+ the stuffing bits, we may need to insert the stuffing bits here
+ if we have color effect, we have done the stuffing at the end of last GOB
+ see functin: H263OneGOBSliceWithHeaderEnded
+ */
+ sStuffBitsH263(iOutBuffer);
+ }
+
+ if (!iDoModeTranscoding)
+ {
+ /* Copy the header to output stream */
+ bufEdit.copyMode = CopyWhole; // whole
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,iGOBSliceStartByteIndex,iGOBSliceStartBitIndex);
+
+ }
+
+ else
+ {
+ /* H263 GOB (Slice) Header -> MPEG4 VP Header mapping */
+ if (!VDT_NO_DATA((int)iInBuffer->getIndex, iInBuffer->bitIndex, iGOBSliceStartByteIndex, iGOBSliceStartBitIndex) &&
+ aH263GOBHeader)
+ {
+ /* sPutVideoPacketHeader */
+ sPutVideoPacketHeader(iOutBuffer, aH263GOBHeader->gn * iNumMBsInGOB, (short)aH263GOBHeader->gquant, iNumMBsInOneVOP);
+ }
+ }
+
+ // one slice ended, new video packet starting
+ iCurMBNumInVP = -1;
+
+}
+
+
+/*
+* H263GOBSliceHeaderBegin
+*
+* Parameters:
+*
+* Function:
+* This function is called before one H263 GOB or Slice header is parsed
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::H263GOBSliceHeaderBegin()
+{
+ /* position not include the stuffing bits ahead of the GBSC ! */
+ iGOBSliceStartByteIndex = iInBuffer->getIndex;
+ iGOBSliceStartBitIndex = iInBuffer->bitIndex;
+ iStuffingBitsUsed = 0;
+}
+
+
+/*
+* H263GOBSliceHeaderBegin
+*
+* Parameters:
+*
+* Function:
+* This function is called after one H263 GOB or Slice ends
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::H263OneGOBSliceEnded(int nextExpectedMBNum)
+{
+ if (iDoTranscoding)
+ {
+ /* MBs are lost or not coded, for H263 and H263->MPEG4 both */
+ for (int i = iLastMBNum+1; i < nextExpectedMBNum; i++)
+ {
+ /* output 1 bit COD */
+ sPutBits (iOutBuffer, 1, 1);
+ }
+ iLastMBNum = nextExpectedMBNum - 1;
+ }
+}
+
+
+/*
+* H263OneGOBSliceWithHeaderEnded
+*
+* Parameters:
+*
+* Function:
+* This function is called after GOB (Slice) that has GOB header (except the first GOB) ends
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::H263OneGOBSliceWithHeaderEnded()
+{
+ if (!iDoTranscoding)
+ {
+ bufEdit.copyMode = CopyWhole; /* CopyWhole */
+ CopyStream(iInBuffer,iOutBuffer,&bufEdit,
+ iGOBSliceHeaderEndByteIndex,iGOBSliceHeaderEndBitIndex);
+ }
+ else
+ {
+
+ if (iDoModeTranscoding)
+ {
+ /* for H263 to MPEG4, it implies that one video packet is finished */
+ vdtStuffBitsMPEG4(iOutBuffer);
+ }
+ else
+
+ {
+ /* stuffing occurs outside at the end of one GOB/slice withe header or end of frame, check in file core.cpp */
+ sStuffBitsH263(iOutBuffer);
+ }
+ iVideoPacketNumInMPEG4 ++;
+ }
+
+ // one slice ended, new video packet starting
+ iCurMBNumInVP = -1; // 0
+
+}
+
+
+
+/*
+* H263ToMPEG4MBData
+*
+* Parameters:
+*
+* Function:
+* This function transcodes one H263 MB to one MPEG4 MB
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::H263ToMPEG4MBData(int aNewMCBPCLen, int aNewMCBPC)
+{
+ /* MB data part1: output MCBPC, CBPY, DQuant, MV, intra DC etc */
+ int *dataItemStartByteIndex;
+ int *dataItemStartBitIndex;
+ int *dataItemEndByteIndex;
+ int *dataItemEndBitIndex;
+ int quant, cbpy, cbpc;
+
+ if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ dataItemStartByteIndex = iCurPMBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = iCurPMBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = iCurPMBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = iCurPMBinstance->DataItemEndBitIndex;
+ quant = iCurPMBinstance->quant;
+ cbpy = iCurPMBinstance->cbpy;
+ cbpc = iCurPMBinstance->cbpc;
+ }
+ else
+ {
+ dataItemStartByteIndex = iCurIMBinstance->DataItemStartByteIndex;
+ dataItemStartBitIndex = iCurIMBinstance->DataItemStartBitIndex;
+ dataItemEndByteIndex = iCurIMBinstance->DataItemEndByteIndex;
+ dataItemEndBitIndex = iCurIMBinstance->DataItemEndBitIndex;
+ quant = iCurIMBinstance->quant;
+ cbpy = iCurIMBinstance->cbpy;
+ cbpc = iCurIMBinstance->cbpc;
+ }
+
+ /* COD and MCBPC, (for I frame, it is MCBPC, for P frame it is COD and MCBPC) */
+ if (iVopCodingType == VDX_VOP_TYPE_P)
+ {
+ /* It is a coded MB, output 1 bit COD (it always exists in P frame) */
+ sPutBits (iOutBuffer, 1, 0);
+ }
+
+ if (iColorEffect)
+ {
+ /* MCBPC Changed */
+ sPutBits(iOutBuffer, aNewMCBPCLen, aNewMCBPC);
+ }
+ else
+ {
+ /* remember the positions do not include the possible stuffing MCBPC bits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[0], dataItemStartBitIndex[0],
+ dataItemEndByteIndex[0], dataItemEndBitIndex[0]);
+ }
+
+ /* ac_pred_flag */
+ if (iMBCodingType == VDX_MB_INTRA)
+ {
+ sPutBits(iOutBuffer, 1, 0);// it is closed for H263 INTRA MB
+ }
+
+ /* CBPY */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[2], dataItemStartBitIndex[2],
+ dataItemEndByteIndex[2], dataItemEndBitIndex[2]);
+
+ /* DQUANT, if it exsits */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[1], dataItemStartBitIndex[1],
+ dataItemEndByteIndex[1], dataItemEndBitIndex[1]);
+
+ if (iMBCodingType == VDX_MB_INTER)
+ {
+ /* MVs, if they exsit */
+ vdtCopyBuffer(iInBuffer, iOutBuffer,
+ dataItemStartByteIndex[10], dataItemStartBitIndex[10],
+ dataItemEndByteIndex[10], dataItemEndBitIndex[10]);
+ }
+
+ /* following is the block level data */
+ for (int i = 0; i < (iColorEffect? 4 : 6); i++)
+ {
+ if (iMBCodingType == VDX_MB_INTRA)
+ {
+ int fBlockCoded = 0;
+ if (i < 4)
+ {
+ fBlockCoded = vdxIsYCoded(cbpy, i + 1);
+ }
+ else if (i == 4)
+ {
+ fBlockCoded = vdxIsUCoded(cbpc);
+ }
+ else
+ {
+ fBlockCoded = vdxIsVCoded(cbpc);
+ }
+
+ /* Difference between H263 and MPEG4 :
+ 0. DC quantization is different, DC need to be dequantized and requantized
+ Note: for ACs, here we only support H263 quantization in MPEG4, we can copy them
+ 1. DC prediction is used in MPEG4
+ 2. They use different VLC table for INTRA AC coefficient
+ */
+ /* reconstuct INTRA DC */
+ int intraDC = (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0]; /* it is already dequantized in funcion vdxGetIntraDCTBlock */
+
+ /* INTRA quantization and prediction */
+ (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0] = sGetMPEG4INTRADCValue(intraDC,
+ i, iCurMBNum, quant, iMBsinWidth,iH263DCData, iH263MBVPNum);
+
+ /* recoding the INTRA block */
+ int numTextureBits = 0;
+
+ vdtPutIntraMBCMT(iOutBuffer,iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, i, 0, 1); /* DC coding */
+
+ if (fBlockCoded)
+ {
+ vdtPutIntraMBCMT(iOutBuffer,iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, i, 1, 0); /*encode ACs */
+ }
+
+ }
+
+ else if (!(VDT_NO_DATA(iBlockStartByteIndex[i], iBlockStartBitIndex[i],
+ iBlockEndByteIndex[i], iBlockEndBitIndex[i])))
+ {
+
+ /* 4. same VLC table for DCTs in H263 and MPEG4, but with different Escape Coding type.
+ see 7.4.1.3. in MPEG4 draft
+ */
+ if (iEscapeCodeUsed[i])
+ {
+ int numTextureBits = 0;
+ vdtPutInterMBCMT(iOutBuffer,0, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, OFF);
+ }
+ else
+ {
+ bufEdit.copyMode = CopyWhole; /* CopyWhole */
+ vdtCopyBuffer(iInBuffer,iOutBuffer,
+ iBlockStartByteIndex[i],iBlockStartBitIndex[i],
+ iBlockEndByteIndex[i],iBlockEndBitIndex[i]);
+ }
+ }
+ }
+
+ if (iColorEffect && (iMBCodingType == VDX_MB_INTRA))
+ {
+ ResetMPEG4IntraDcUV();
+ }
+}
+
+
+
+/*
+* NeedDecodedYUVFrame
+*
+* Parameters:
+*
+* Function:
+* This function indicates if whether we need the decoded frame
+* Returns:
+* ETrue if we need the decoded frame
+* Error codes:
+* None
+*
+*/
+int CMPEG4Transcoder::NeedDecodedYUVFrame()
+{
+ if ( (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45) &&
+ iBitStreamMode !=EVedVideoBitstreamModeMPEG4ShortHeader && iBitStreamMode != EVedVideoBitstreamModeH263)
+ return ETrue;
+ else
+ return EFalse;
+}
+
+/*
+* NewL
+*
+* Parameters:
+*
+* Function:
+* Symbian two-phased constructor
+* Returns:
+* pointer to constructed object, or NULL
+* Error codes:
+* None
+*
+*/
+CMPEG4Transcoder* CMPEG4Transcoder::NewL(const vdeInstance_t *aVDEInstance, bibBuffer_t *aInBuffer, bibBuffer_t *aOutBuffer)
+{
+ CMPEG4Transcoder *self = new (ELeave) CMPEG4Transcoder(aVDEInstance, aInBuffer, aOutBuffer);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ return self;
+}
+
+
+/*
+* ConstructL
+*
+* Parameters:
+*
+* Function:
+* Symbian 2nd phase constructor (can leave)
+* Returns:
+* None
+* Error codes:
+* None
+*
+*/
+void CMPEG4Transcoder::ConstructL()
+{
+
+ /* Create one IMB Instance */
+ iCurIMBinstance = (vdxIMBListItem_t *) malloc(sizeof(vdxIMBListItem_t));
+ if (!iCurIMBinstance)
+ {
+ deb("CMPEG4Transcoder::ERROR - iCurIMBinstance creation failed\n");
+ User::Leave(KErrNoMemory);
+
+ }
+ memset(iCurIMBinstance, 0, sizeof(vdxIMBListItem_t));
+
+ /* Create one PMBInstance */
+ iCurPMBinstance = (vdxPMBListItem_t *) malloc(sizeof(vdxPMBListItem_t));
+ if (!iCurPMBinstance)
+ {
+ deb("CMPEG4Transcoder::ERROR - iCurPMBinstance creation failed\n");
+ User::Leave(KErrNoMemory);
+
+ }
+ memset(iCurPMBinstance, 0, sizeof(vdxPMBListItem_t));
+
+ /* initialize the edit buffer */
+ bufEdit.editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
+ VDTASSERT(bufEdit.editParams);
+ if (!bufEdit.editParams)
+ {
+ deb("CMPEG4Transcoder::ERROR - bufEdit.editParams creation failed\n");
+ User::Leave(KErrNoMemory);
+
+ }else{
+ bufEdit.numChanges = 1;
+ }
+
+ if (!iMBType)
+ {
+ iMBType = (u_char *) malloc(iNumMBsInOneVOP * sizeof(u_char));
+ if (!iMBType)
+ {
+ deb("CMPEG4Transcoder::ERROR - iMBType creation failed\n");
+ User::Leave(KErrNoMemory);
+ }
+ memset(iMBType, VDX_MB_INTER, iNumMBsInOneVOP * sizeof(u_char));
+ }
+
+}
+
+
+/*
+* GetMpeg4DcScaler
+*
+* Parameters:
+*
+* aQP Quantization parameter
+*
+* Function:
+* Evaluates Chrominance DC Scaler from QP for MPEG4
+* Returns:
+* int DC scaler value
+* Error codes:
+* None
+*
+*/
+int CMPEG4Transcoder::GetMpeg4DcScalerUV(int aQP)
+{
+ if (aQP>=1 && aQP<=4)
+ return (8);
+ else if (aQP>=5 && aQP<=24)
+ return ((aQP+13)/2);
+ else if (aQP>=25 && aQP<=31)
+ return (aQP-6);
+ else
+ return (0); // error
+}
+
+
+void CMPEG4Transcoder::AfterMBLayer(int aUpdatedQp)
+{
+ iCurQuant = aUpdatedQp;
+}
+
+
+
+
+/* End of File */