--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/decgob.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,508 @@
+/*
+* 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:
+* GOB decoding functions.
+*
+*/
+
+
+/*
+ * Includes
+ */
+#include "h263dConfig.h"
+#include "decgob.h"
+#include "block.h"
+#include "debug.h"
+#include "decmbs.h"
+#include "stckheap.h"
+#include "sync.h"
+#include "viddemux.h"
+#include "biblin.h"
+/* MVE */
+#include "MPEG4Transcoder.h"
+
+
+/*
+ * Global functions
+ */
+
+/* {{-output"dgobGetAndDecodeGOBSegment.txt"}} */
+/*
+ * dgobGetAndDecodeGOBSegment
+ *
+ *
+ * Parameters:
+ * inParam input parameters
+ * inOutParam input/output parameters, these parameters
+ * may be modified in the function
+ *
+ * Function:
+ * This function gets and decodes a GOB segment which should start
+ * with a GBSC at the current position of the bit buffer.
+ *
+ * Returns:
+ * >= 0 the function was successful
+ * < 0 an error occured
+ *
+ */
+
+int dgobGetAndDecodeGOBSegment(
+ const dgobGOBSegmentInParam_t *inParam,
+ dgobGOBSegmentInOutParam_t *inOutParam,
+ CMPEG4Transcoder *hTranscoder)
+/* {{-output"dgobGetAndDecodeGOBSegment.txt"}} */
+{
+ bibBuffer_t
+ *inBuffer; /* Input bit buffer instance */
+
+ int
+ retValue, /* Value returned from this function */
+
+ fGetNewReferenceFrame,
+ /* 1 if the reference picture has changed from
+ the previous one */
+
+ bitErrorIndication = 0,
+ /* Carries bit error indication information returned
+ by the video demultiplexer module */
+
+ intraGobsMissing = 0;
+ /* Flag to indicate if INTRA coded GOBs are missing */
+
+ u_int32
+ segmStart = bibNumberOfFlushedBits( inParam->inBuffer );
+ /* Start bit buffer position of the GOB segment */
+
+ vdxGetGOBHeaderInputParam_t
+ vdxParam; /* Input parameters for vdxGetGOBHeader */
+
+ vdxGOBHeader_t
+ header; /* GOB header data */
+
+ inBuffer = inParam->inBuffer;
+
+ /*
+ * Get GOB header
+ */
+
+ vdxParam.numStuffBits = inParam->numStuffBits;
+ vdxParam.fCustomPCF = inParam->pictParam->fCustomPCF;
+ vdxParam.fCPM = inParam->pictParam->cpm;
+ vdxParam.fRPS = inParam->pictParam->fRPS;
+
+ if (vdxGetGOBHeader(inBuffer, &vdxParam, &header, &bitErrorIndication,
+ inParam->iColorEffect, &inOutParam->StartByteIndex, &inOutParam->StartBitIndex, hTranscoder) < 0) {
+
+ deb("dgobGetAndDecodeGOBSegment: ERROR - vdxGetGOBHeader failed.\n");
+ goto unexpectedError;
+ }
+
+ /*
+ * Check header validity
+ */
+
+ if (header.gn >= inParam->pictParam->numGOBs) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - too big GN.\n");
+ goto unexpectedError;
+ }
+
+ /* If TRP present and TRP is not 8-bit if only 8-bit TRs have existed.
+ Note: The following condition assumes that only 8-bit TRs are allowed. */
+ if (header.trpi && header.trp > 255) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - too big TRP.\n");
+ goto unexpectedError;
+ }
+
+ /* If GFID is not as expected */
+ if (inOutParam->gfid >= 0 && bitErrorIndication != 0 &&
+ ((inParam->fGFIDShouldChange && inOutParam->gfid == header.gfid) ||
+ (!inParam->fGFIDShouldChange && inOutParam->gfid != header.gfid))) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - illegal GFID.\n");
+ goto unexpectedError;
+ }
+
+ inOutParam->prevGN = inOutParam->prevGNWithHeader = header.gn;
+ /* GFID was valid, and in the next GOB the gfidShouldChange flag should be 0 and GFID should be
+ the same as the current one */
+ inOutParam->gfid = header.gfid;
+
+ fGetNewReferenceFrame = 0;
+ if (inParam->pictParam->fRPS) {
+ /* If TRP has changed */
+ if ((header.trpi && header.trp != inOutParam->trp) ||
+ (!header.trpi && inOutParam->trp >= 0))
+ fGetNewReferenceFrame = 1;
+
+ if (header.trpi)
+ inOutParam->trp = header.trp;
+ else
+ inOutParam->trp = -1;
+ }
+
+ /* MVE */
+ hTranscoder->H263GOBSliceHeaderEnded(&header, NULL);
+
+
+ /*
+ * Decode GOB contents
+ */
+
+ retValue = dgobGetAndDecodeGOBSegmentContents(inParam, fGetNewReferenceFrame,
+ header.gquant, inOutParam, hTranscoder);
+
+ /* MVE */
+ hTranscoder->H263OneGOBSliceWithHeaderEnded();
+
+
+ if ( intraGobsMissing && retValue == 0 )
+ return DGOB_OK_BUT_BIT_ERROR;
+ else
+ return retValue;
+
+ unexpectedError:
+ return DGOB_ERR;
+}
+
+
+/* {{-output"dgobGetAndDecodeGOBSegmentContents.txt"}} */
+/*
+ * dgobGetAndDecodeGOBSegmentContents
+ *
+ *
+ * Parameters:
+ * inParam input parameters
+ * fGetNewReferenceFrame non-zero if a new reference frame must be
+ * requested from the image store, otherwise 0
+ * quant initial quantization parameter
+ * inOutParam input/output parameters, these parameters
+ * may be modified in the function
+ *
+ * Function:
+ * This function gets and decodes the contents of a GOB segment
+ * meaning that the header of the GOB (either GOB header or picture
+ * header) is already got and processed and the macroblocks belonging
+ * to the GOB segment are decoded.
+ *
+ * Returns:
+ * >= 0 the function was successful
+ * < 0 an error occured
+ *
+ */
+
+int dgobGetAndDecodeGOBSegmentContents(
+ const dgobGOBSegmentInParam_t *inParam,
+ int fGetNewReferenceFrame,
+ int quant,
+ dgobGOBSegmentInOutParam_t *inOutParam,
+ CMPEG4Transcoder *hTranscoder)
+/* {{-output"dgobGetAndDecodeGOBSegmentContents.txt"}} */
+{
+ bibBuffer_t
+ *inBuffer; /* Input bit buffer instance */
+
+
+ bibBuffer_t
+ *outBuffer; /* Output bit buffer instance */
+
+ bibBufferEdit_t
+ *bufEdit;
+
+ int colorEffect;
+ TBool getDecodedFrame;
+
+
+ /* decmbs input and output parameters */
+ dmbPFrameMBInParam_t dpmbi;
+ dmbPFrameMBInOutParam_t dpmbio;
+ dmbIFrameMBInParam_t dimbi;
+ dmbIFrameMBInOutParam_t dimbio;
+
+ int
+ *pYPosInMBs, /* Pointer to variable containing the y-position
+ of the current macroblock in macroblocks
+ (starting from zero in the top row) */
+ fSegmentCorrupted = 0;
+ /* Flag to indicate if the current GOB segment
+ is corrupted */
+
+ int16
+ error = 0; /* Used to pass error codes from snc and erd modules */
+
+ /* Pointers to pointers pointing to the top-left corner of the current
+ GOB (inside the current frame) */
+ u_char **pYGOB, **pUGOB, **pVGOB;
+
+ SOH_DEFINE(blcDiffMB_t, pDiffMB);
+ /* Storage for the previous difference blocks */
+
+ inBuffer = inParam->inBuffer;
+
+ outBuffer = inParam->outBuffer;
+ bufEdit = inParam->bufEdit;
+ colorEffect = inParam->iColorEffect;
+ getDecodedFrame = inParam->iGetDecodedFrame;
+
+
+ SOH_ALLOC(blcDiffMB_t, pDiffMB);
+
+ if (pDiffMB == NULL) {
+ deb("dgobGetAndDecodeGOBSegmentContents: SOH_ALLOC failed.\n");
+ goto unexpectedError;
+ }
+
+ pDiffMB->cbpy = 0;
+
+ /* If the reference frame changed */
+ if (fGetNewReferenceFrame) {
+ vdeIms_t *store = inOutParam->imageStore;
+ vdeImsItem_t *imsItem;
+ vdeImb_t *imb;
+ int width, height;
+
+ /* Get the reference frame */
+ if (inOutParam->trp >= 0) {
+ if (vdeImsGetReference(store, VDEIMS_REF_TR, inOutParam->trp, &imsItem) < 0) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsGetReference "
+ "failed.\n");
+ goto unexpectedError;
+ }
+ }
+
+ else {
+ if (vdeImsGetReference(store, VDEIMS_REF_LATEST, 0, &imsItem) < 0) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsGetReference "
+ "failed.\n");
+ goto unexpectedError;
+ }
+ }
+
+ /* If no reference frame available */
+ if (!imsItem) {
+
+ /* Treat the situation like a decoding error.
+ This should cause error concealment and
+ a NACK message if Annex N is used. */
+ deb("dgobGetAndDecodeGOBSegment: Warning - no reference frame "
+ "available.\n");
+
+ goto unexpectedError;
+ }
+
+ if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsStoreItemToImageBuffer "
+ "failed.\n");
+ goto unexpectedError;
+ }
+
+ inOutParam->rtr = imb->tr;
+
+ if (vdeImbYUV(imb, &inOutParam->refY, &inOutParam->refU,
+ &inOutParam->refV, &width, &height) < 0) {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImbYUV "
+ "failed.\n");
+ goto unexpectedError;
+ }
+ }
+
+ /* Preset structures for multiple macroblock decoding */
+ if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I) {
+ dimbi.inBuffer = inBuffer;
+
+
+ dimbi.outBuffer = outBuffer;
+ dimbi.bufEdit = bufEdit;
+ dimbi.iColorEffect = colorEffect;
+ dimbi.iGetDecodedFrame = getDecodedFrame;
+ dimbio.StartByteIndex = inOutParam->StartByteIndex;
+ dimbio.StartBitIndex = inOutParam->StartBitIndex;
+
+
+ dimbi.xPosInMBs = 0;
+ /* yPosInMBs set inside the loop (below) */
+ dimbi.pictParam = inParam->pictParam;
+ dimbi.fGOBHeaderPresent = 1;
+
+ dimbio.fCodedMBs = inOutParam->fCodedMBs;
+ dimbio.numOfCodedMBs = inOutParam->numOfCodedMBs;
+ dimbio.quant = quant;
+
+ /* YUV pointers set iside the loop (below) */
+
+ pYPosInMBs = &dimbi.yPosInMBs;
+ pYGOB = &dimbio.yMBInFrame;
+ pUGOB = &dimbio.uBlockInFrame;
+ pVGOB = &dimbio.vBlockInFrame;
+ }
+
+ else {
+ dpmbi.inBuffer = inBuffer;
+
+
+ dpmbi.outBuffer = outBuffer;
+ dpmbi.bufEdit = bufEdit;
+ dpmbi.iColorEffect = colorEffect;
+ dpmbi.iGetDecodedFrame = getDecodedFrame;
+ dpmbio.StartByteIndex = inOutParam->StartByteIndex;
+ dpmbio.StartBitIndex = inOutParam->StartBitIndex;
+
+
+ dpmbi.xPosInMBs = 0;
+ /* yPosInMBs set inside the loop (below) */
+ dpmbi.pictParam = inParam->pictParam;
+ dpmbi.fGOBHeaderPresent = 1;
+ dpmbi.refY = inOutParam->refY;
+ dpmbi.refU = inOutParam->refU;
+ dpmbi.refV = inOutParam->refV;
+ dpmbi.currPY = inOutParam->currPY;
+ dpmbi.currPU = inOutParam->currPU;
+ dpmbi.currPV = inOutParam->currPV;
+
+ dpmbio.fCodedMBs = inOutParam->fCodedMBs;
+ dpmbio.numOfCodedMBs = inOutParam->numOfCodedMBs;
+ dpmbio.quant = quant;
+
+ /* YUV pointers set iside the loop (below) */
+ dpmbio.mvcData = inOutParam->mvcData;
+ dpmbio.diffMB = pDiffMB;
+
+ pYPosInMBs = &dpmbi.yPosInMBs;
+ pYGOB = &dpmbio.yMBInFrame;
+ pUGOB = &dpmbio.uBlockInFrame;
+ pVGOB = &dpmbio.vBlockInFrame;
+ }
+
+ /* Loop forever (until the GOB segment ends) */
+ for (;;) {
+ int dmbsRetValue;
+ int numMBsInCurrGOB;
+ int sncCode;
+ int numStuffBits;
+ int mbNumberInScanOrder;
+
+ if ((inOutParam->prevGN == inParam->pictParam->numGOBs - 1) &&
+ (inParam->pictParam->fLastGOBSizeDifferent))
+ numMBsInCurrGOB = inParam->pictParam->numMBsInLastGOB;
+ else
+ numMBsInCurrGOB = inParam->pictParam->numMBsInGOB;
+
+ *pYPosInMBs = inOutParam->prevGN * inParam->pictParam->numMBLinesInGOB;
+
+ mbNumberInScanOrder = *pYPosInMBs * inParam->pictParam->numMBsInMBLine;
+
+ /* Set pointers for the GOB (inside frame(s)) */
+ if ( inOutParam->currPY != NULL )
+ {
+ int32 yOffset, uvOffset;
+
+ yOffset = *pYPosInMBs * 16 * inParam->pictParam->lumMemWidth;
+
+ *pYGOB = inOutParam->currPY + yOffset;
+
+ uvOffset = yOffset / 4;
+ *pUGOB = inOutParam->currPU + uvOffset;
+ *pVGOB = inOutParam->currPV + uvOffset;
+
+ }
+ else
+ {
+ *pYGOB = NULL;
+ *pUGOB = NULL;
+ *pVGOB = NULL;
+ }
+
+ /* Decode macroblocks of the current GOB */
+ if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I) {
+ dimbi.numMBsInSegment = numMBsInCurrGOB;
+ dmbsRetValue = dmbsGetAndDecodeIMBsInScanOrder(&dimbi,
+ &dimbio, &inOutParam->quantParams[mbNumberInScanOrder], hTranscoder);
+
+ inOutParam->StartByteIndex = dimbio.StartByteIndex;
+ inOutParam->StartBitIndex = dimbio.StartBitIndex;
+
+
+ }
+ else {
+ dpmbi.numMBsInSegment = numMBsInCurrGOB;
+ dmbsRetValue = dmbsGetAndDecodePMBsInScanOrder(&dpmbi,
+ &dpmbio, &inOutParam->quantParams[mbNumberInScanOrder], hTranscoder);
+
+ inOutParam->StartByteIndex = dpmbio.StartByteIndex;
+ inOutParam->StartBitIndex = dpmbio.StartBitIndex;
+ }
+
+ if (dmbsRetValue < 0)
+ goto unexpectedError;
+
+ /* Some bit errors were found inside the segment
+ (dpmbi/dimbi fSegmentCorrupted have the same address as fSegmentCorrupted)
+ Note that if no suspicious/corrupted blocks was found, but there was crc-error,
+ this flag is not set. However, that case will be checked if no sync code is found */
+ if ( fSegmentCorrupted )
+ break;
+
+ /* Check if there is a synchronization code in the current bitstream
+ position */
+ sncCode = sncCheckSync(inBuffer, &numStuffBits, &error);
+
+ /* If buffer ends (in one-frame-per-one-buffer case) */
+ if (error == ERR_BIB_NOT_ENOUGH_DATA)
+ break;
+
+ if (error)
+ goto unexpectedError;
+
+ /* If there is a synchronization code */
+ if (sncCode != SNC_NO_SYNC )
+ break;
+
+
+ if (inOutParam->prevGN + 1 < inParam->pictParam->numGOBs)
+ inOutParam->prevGN++;
+
+ else {
+ deb("dgobGetAndDecodeGOBSegment: ERROR - too much frame data.\n");
+ fSegmentCorrupted = 1;
+ break;
+ }
+
+ dpmbi.fGOBHeaderPresent = 0;
+ dimbi.fGOBHeaderPresent = 0;
+ }
+
+ /* Update coded macroblock counter */
+ if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I)
+ inOutParam->numOfCodedMBs = dimbio.numOfCodedMBs;
+ else
+ inOutParam->numOfCodedMBs = dpmbio.numOfCodedMBs;
+
+ if (!fSegmentCorrupted) {
+ SOH_DEALLOC(pDiffMB);
+ if (inOutParam->trp >= 0) {
+ }
+
+ return DGOB_OK;
+ }
+ else {
+
+ return DGOB_OK_BUT_BIT_ERROR;
+ }
+
+ unexpectedError:
+ SOH_DEALLOC(pDiffMB);
+ return DGOB_ERR;
+}
+
+
+// End of File