diff -r 951a5db380a0 -r d87d32eab1a9 videoeditorengine/h263decoder/src/decvp_mpeg.cpp --- a/videoeditorengine/h263decoder/src/decvp_mpeg.cpp Fri Jan 29 14:08:33 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,653 +0,0 @@ -/* -* 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: -* Video packet decoding module (MPEG-4). -* -*/ - - -/* - * Includes - */ -#include "h263dConfig.h" -#include "decvp_mpeg.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"dvpGetAndDecodeVideoPacketHeader.txt"}} */ -/* - * dvpGetAndDecodeVideoPacketHeader - * - * - * Parameters: - * inParam input parameters - * inOutParam input/output parameters, these parameters - * may be modified in the function - * - * Function: - * This function gets and decodes a Video Packet header at the - * current position of the bit buffer. It checks its correctness and - * if it fits to the sequence of VPs, and does the necessary actions for - * correction. - * - * Returns: - * >= 0 the function was successful - * < 0 an error occured - * - */ - -int dvpGetAndDecodeVideoPacketHeader( - const dvpVPInParam_t *inParam, - dvpVPInOutParam_t *inOutParam) -/* {{-output"dvpGetAndDecodeVideoPacketHeader.txt"}} */ -{ - int16 error = 0; - vdxGetVideoPacketHeaderInputParam_t vdxParam; - vdxVideoPacketHeader_t header; - bibBuffer_t *inBuffer = inParam->inBuffer; - int bitErrorIndication = 0, retVal, fLostSegment = FALSE; - - /* - * Get VP header - */ - - vdxParam.fcode_forward = inParam->pictParam->fcode_forward; - vdxParam.time_increment_resolution = inParam->pictParam->time_increment_resolution; - vdxParam.numOfMBs = inParam->pictParam->numMBsInGOB; - - retVal = vdxGetVideoPacketHeader(inBuffer, &vdxParam, &header, &bitErrorIndication); - if (retVal < 0) { - return DGOB_ERR; - } else if (retVal > 0) { - deb("dvpGetAndDecodeVideoPacketHeader: ERROR - vdxGetVideoPacketHeader failed.\n"); - goto headerFailure; - } - - - /* - * Check header validity - */ - - if (header.currMBNum == 0 || header.currMBNum >= inParam->pictParam->numMBsInGOB) { - deb("dvpGetAndDecodeVideoPacketHeader: ERROR - too big currMBNum.\n"); - goto headerFailure; - } - - /* quant can not be zero */ - if(header.quant == 0) { - goto headerFailure; - } - - if (header.fHEC) { - - if (header.time_base_incr < 0 || header.time_base_incr > 60) { - if (bitErrorIndication) { - goto headerFailure; - } - } - - /* fcode can have only the valid values 1..7 */ - if (header.coding_type == VDX_VOP_TYPE_P) - if (header.fcode_forward == 0) { - goto headerFailure; - } - - if (!inParam->fVOPHeaderCorrupted) { - - if ((inParam->pictParam->pictureType != header.coding_type) || - (inParam->pictParam->time_base_incr != header.time_base_incr) || - (inParam->pictParam->time_inc != header.time_inc)) { - deb("dvpGetAndDecodeVideoPacketHeader: ERROR - Parameter change VOP<->VP header.\n"); - goto headerFailure; - } - } - } - if (inParam->fVOPHeaderCorrupted) { - /* Get the coding type parameter since it is needed in the concealment before the other updates */ - if (header.fHEC) { - inParam->pictParam->pictureType = header.coding_type; - } - } - if (header.currMBNum != inOutParam->currMBNum) { - if ( header.currMBNum > inOutParam->currMBNum && bitErrorIndication == 0) { - - fLostSegment = TRUE; - goto headerFailure; - - } else if (header.currMBNum < inOutParam->currMBNum) { - deb("dvpGetAndDecodeVideoPacketHeader: ERROR - MB counting is out of sync.\n"); - goto headerFailure; - } - } - - /* - * Update parameters - */ - - inOutParam->currMBNum = header.currMBNum; - inOutParam->quant = header.quant; - - if (inParam->fVOPHeaderCorrupted) { - if (header.fHEC) { - inParam->pictParam->mod_time_base += inParam->pictParam->time_base_incr = header.time_base_incr; - - inParam->pictParam->time_inc = header.time_inc; - - inOutParam->frameNum = (int) ((inParam->pictParam->mod_time_base + - ((double) header.time_inc) / ((double) inParam->pictParam->time_increment_resolution)) * - 30.0 + 0.001); - - inParam->pictParam->tr = inOutParam->frameNum % 256; - inParam->pictParam->pictureType = header.coding_type; - - inParam->pictParam->intra_dc_vlc_thr = header.intra_dc_vlc_thr; - - if (header.coding_type == VDX_VOP_TYPE_P) - if (inParam->pictParam->fcode_forward != header.fcode_forward) { - /* Initialize once to count parameters for the mvc module */ - int r_size, scale_factor; - - inParam->pictParam->fcode_forward = header.fcode_forward; - - inOutParam->mvcData->f_code = inParam->pictParam->fcode_forward; - r_size = inParam->pictParam->fcode_forward - 1; - scale_factor = (1 << r_size); - inOutParam->mvcData->range = 160 * scale_factor; - } - } else { - /* seek next PSC, VP start code is not good enough */ - sncRewindAndSeekNewMPEGSync(-1, inBuffer, 0, &error); - return DGOB_OK_BUT_BIT_ERROR; - } - } - - if (fLostSegment) - return DGOB_OK_BUT_BIT_ERROR; - else - return DGOB_OK; - - headerFailure: - sncRewindAndSeekNewMPEGSync(-1, inBuffer, inParam->pictParam->fcode_forward, &error); - - if (error && error != ERR_BIB_NOT_ENOUGH_DATA) - return DGOB_ERR; - return DGOB_OK_BUT_BIT_ERROR; -} - - -/* {{-output"dvpGetAndDecodeVideoPacketContents.txt"}} */ -/* - * dvpGetAndDecodeVideoPacketContents - * - * - * Parameters: - * inParam input parameters - * fGetNewReferenceFrame non-zero if a new reference frame must be - * requested from the image store, otherwise 0 - * inOutParam input/output parameters, these parameters - * may be modified in the function - * - * Function: - * This function gets and decodes the contents of a Video Packet - * after the header of the VP (either VP header or picture - * header) is already got and processed. It works MB-by-MB or if VP - * is data partitioned calls the corresponding decoding functions. - * Error concealment for the missing (not decodable) MBs in a P-frame - * is called. - * - * Returns: - * >= 0 the function was successful - * < 0 an error occured - * - */ - -int dvpGetAndDecodeVideoPacketContents( - const dvpVPInParam_t *inParam, - int fGetNewReferenceFrame, - dvpVPInOutParam_t *inOutParam, CMPEG4Transcoder *hTranscoder) -/* {{-output"dvpGetAndDecodeVideoPacketContents.txt"}} */ -{ - int16 error = 0; - int bitErrorIndication = 0; - dmbPFrameMBInParam_t dpmbi; - dmbPFrameMBInOutParam_t dpmbio; - dmbIFrameMBInParam_t dimbi; - dmbIFrameMBInOutParam_t dimbio; - int yPosInMBs, xPosInMBs = 0; - bibBuffer_t *inBuffer; - bibBuffer_t - *outBuffer; /* Output bit buffer instance */ - - bibBufferEdit_t - *bufEdit; - - int colorEffect; - TBool getDecodedFrame; - - - int fSegmentCorrupted = 0; - - int dmbRetValue; - int sncCode = SNC_NO_SYNC; - int lastMBNumInVP = 0; - int startMB = inOutParam->currMBNum; - - SOH_DEFINE(blcDiffMB_t, pDiffMB); /* Storage for the previous difference blocks */ - - SOH_ALLOC(blcDiffMB_t, pDiffMB); - - if (pDiffMB == NULL) { - deb("dvpGetAndDecodeVideoPacketContents: SOH_ALLOC failed.\n"); - goto unexpectedError; - } - - pDiffMB->cbpy = 0; - - inBuffer = inParam->inBuffer; - outBuffer = inParam->outBuffer; - bufEdit = inParam->bufEdit; - colorEffect = inParam->iColorEffect; - getDecodedFrame = inParam->iGetDecodedFrame; - - /* If the reference frame changed */ - if (fGetNewReferenceFrame) { - vdeIms_t *store = inOutParam->imageStore; - vdeImsItem_t *imsItem; - vdeImb_t *imb; - int width, height; - - if (vdeImsGetReference(store, VDEIMS_REF_LATEST, 0, &imsItem) < 0) { - deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImsGetReference " - "failed.\n"); - goto unexpectedError; - } - - /* If no reference frame available */ - if (!imsItem) { - /* Treat the situation like a decoding error.*/ - deb("dvpGetAndDecodeVideoPacketContents: Warning - no reference frame " - "available.\n"); - goto headerFailure; - } - - if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) { - deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImsStoreItemToImageBuffer " - "failed.\n"); - goto unexpectedError; - } - - if (vdeImbYUV(imb, &inOutParam->refY, &inOutParam->refU, - &inOutParam->refV, &width, &height) < 0) { - deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImbYUV " - "failed.\n"); - goto unexpectedError; - } - } - - xPosInMBs = (inOutParam->currMBNum % inParam->pictParam->numMBsInMBLine); - yPosInMBs = (inOutParam->currMBNum / inParam->pictParam->numMBsInMBLine); - - /* if VOP header corrupted and first VP -> exit */ - if(inParam->fVOPHeaderCorrupted && inOutParam->currMBNum==0) { - fSegmentCorrupted = 1; - goto exitWhenVOPHeaderCorrupted; - } - - /* in case of an I-VOP */ - if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I) { - dimbi.inBuffer = inBuffer; - dimbi.outBuffer = outBuffer; - dimbi.bufEdit = bufEdit; - dimbi.iColorEffect = colorEffect; - dimbi.iGetDecodedFrame = getDecodedFrame; - - dimbi.pictParam = inParam->pictParam; - - dimbi.xPosInMBs = xPosInMBs; - dimbi.yPosInMBs = yPosInMBs; - - dimbio.currMBNum = inOutParam->currMBNum; - dimbio.currMBNumInVP = 0; - - dimbio.aicData = inOutParam->aicData; - - dimbio.fCodedMBs = inOutParam->fCodedMBs; - dimbio.numOfCodedMBs = inOutParam->numOfCodedMBs; - dimbio.quant = inOutParam->quant; - - /* YUV pointers */ - { - int32 yOffset, uvOffset; - - yOffset = inParam->pictParam->lumMemWidth * dimbi.yPosInMBs + dimbi.xPosInMBs; - uvOffset = (inParam->pictParam->lumMemWidth >> 1) * dimbi.yPosInMBs + dimbi.xPosInMBs; - - if ( inOutParam->currPY != NULL ) - { - dimbio.yMBInFrame = inOutParam->currPY + (yOffset << 4); - dimbio.uBlockInFrame = inOutParam->currPU + (uvOffset << 3); - dimbio.vBlockInFrame = inOutParam->currPV + (uvOffset << 3); - } - else - { - dimbio.yMBInFrame = NULL; - dimbio.uBlockInFrame = NULL; - dimbio.vBlockInFrame = NULL; - } - } - } - /* in case of a P-VOP */ - else { - dpmbi.inBuffer = inBuffer; - dpmbi.outBuffer = outBuffer; - dpmbi.bufEdit = bufEdit; - dpmbi.iColorEffect = colorEffect; - dpmbi.iGetDecodedFrame = getDecodedFrame; - - dpmbi.pictParam = inParam->pictParam; - - dpmbi.xPosInMBs = xPosInMBs; - dpmbi.yPosInMBs = yPosInMBs; - - 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.currMBNum = inOutParam->currMBNum; - dpmbio.currMBNumInVP = 0; - - dpmbio.fCodedMBs = inOutParam->fCodedMBs; - dpmbio.numOfCodedMBs = inOutParam->numOfCodedMBs; - dpmbio.quant = inOutParam->quant; - - dpmbio.aicData = inOutParam->aicData; - - dpmbio.mvcData = inOutParam->mvcData; - dpmbio.diffMB = pDiffMB; - - /* YUV pointers */ - { - int32 yOffset, uvOffset; - - yOffset = inParam->pictParam->lumMemWidth * dpmbi.yPosInMBs + dpmbi.xPosInMBs; - uvOffset = (inParam->pictParam->lumMemWidth >> 1) * dpmbi.yPosInMBs + dpmbi.xPosInMBs; - - if ( inOutParam->currPY != NULL ) - { - dpmbio.yMBInFrame = inOutParam->currPY + (yOffset << 4); - dpmbio.uBlockInFrame = inOutParam->currPU + (uvOffset << 3); - dpmbio.vBlockInFrame = inOutParam->currPV + (uvOffset << 3); - } - else - { - dimbio.yMBInFrame = NULL; - dimbio.uBlockInFrame = NULL; - dimbio.vBlockInFrame = NULL; - } - } - } - - /* Decode multiple Macroblocks until a resync_marker is found or error occurs */ - while (inParam->pictParam->numMBsInGOB != inOutParam->currMBNum && - sncCode != SNC_VIDPACK && sncCode != SNC_VOP) { - - /* MVE */ - hTranscoder->BeginOneMB((inParam->pictParam->pictureType == VDX_VOP_TYPE_I) ? dimbio.currMBNum : dpmbio.currMBNum ); - - /* decode an I-frame MB */ - if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I) { - - if(inParam->pictParam->data_partitioned) { - - dmbRetValue = dmbsGetAndDecodeIMBsDataPartitioned(&dimbi, &dimbio, - inOutParam->quantParams, hTranscoder); - - if (dmbRetValue < 0) - goto unexpectedError; - - inOutParam->currMBNum = dimbio.currMBNum; - - /* Video Packet corrupted */ - if ( fSegmentCorrupted ) - break; - - } else { - - dmbRetValue = dmbGetAndDecodeIFrameMB(&dimbi, &dimbio, 1, hTranscoder); - - if (dmbRetValue < 0) - goto unexpectedError; - else if (dmbRetValue == DMB_BIT_ERR ) { - /* Video Packet corrupted */ - fSegmentCorrupted = 1; - break; - } - - /* Store quantizer */ - inOutParam->quantParams[dimbio.currMBNum] = dimbio.quant; - - /* increment the frame pointers and MB counters */ - dimbio.currMBNum++; - dimbio.currMBNumInVP++; - - if ( dimbio.yMBInFrame != NULL ) - { - dimbio.yMBInFrame += 16; - dimbio.uBlockInFrame += 8; - dimbio.vBlockInFrame += 8; - } - dimbi.xPosInMBs++; - - if (dimbi.xPosInMBs == inParam->pictParam->numMBsInMBLine) { - if ( dimbio.yMBInFrame != NULL ) - { - dimbio.yMBInFrame += 15 * inParam->pictParam->lumMemWidth; - dimbio.uBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); - dimbio.vBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); - } - dimbi.xPosInMBs = 0; - dimbi.yPosInMBs++; - } - - inOutParam->currMBNum = dimbio.currMBNum; - } - - /* decode a P-frame MB */ - } else { - - if(inParam->pictParam->data_partitioned) { - - dmbRetValue = dmbsGetAndDecodePMBsDataPartitioned(&dpmbi, &dpmbio, - inOutParam->quantParams, hTranscoder); - - if (dmbRetValue < 0) - goto unexpectedError; - - inOutParam->currMBNum = dpmbio.currMBNum; - lastMBNumInVP = dpmbio.currMBNumInVP; - - /* Video Packet corrupted */ - if ( fSegmentCorrupted ) - break; - - } else { - - dmbRetValue = dmbGetAndDecodePFrameMB(&dpmbi, &dpmbio, 1, hTranscoder); - - if (dmbRetValue < 0) - goto unexpectedError; - else if (dmbRetValue == DMB_BIT_ERR ) { - /* Video Packet corrupted */ - fSegmentCorrupted = 1; - break; - } - - /* Store quantizer */ - inOutParam->quantParams[dpmbio.currMBNum] = dpmbio.quant; - - /* increment the frame pointers and MB counters */ - dpmbio.currMBNum++; - dpmbio.currMBNumInVP++; - - if ( dpmbio.yMBInFrame != NULL ) - { - dpmbio.yMBInFrame += 16; - dpmbio.uBlockInFrame += 8; - dpmbio.vBlockInFrame += 8; - } - dpmbi.xPosInMBs++; - - if (dpmbi.xPosInMBs == inParam->pictParam->numMBsInMBLine) { - if ( dpmbio.yMBInFrame != NULL ) - { - dpmbio.yMBInFrame += 15 * inParam->pictParam->lumMemWidth; - dpmbio.uBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); - dpmbio.vBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); - } - dpmbi.xPosInMBs = 0; - dpmbi.yPosInMBs++; - } - - inOutParam->currMBNum = dpmbio.currMBNum; - } - } - - /* check for a resync_marker */ - sncCode = sncCheckMpegSync(inBuffer, inParam->pictParam->fcode_forward, &error); - - /* If sncCheckMpegSync failed */ - if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { - deb1p("dvpGetAndDecodeVideoPacketContents: ERROR - sncCheckSync returned %d.\n", error); - goto unexpectedError; - - } else - /* If buffer ends (in one-frame-per-one-buffer case) */ - if (sncCode == SNC_EOB || - sncCode == SNC_STUFFING || - error == ERR_BIB_NOT_ENOUGH_DATA) { - break; - } - - } - - -// <-- - - inOutParam->numOfCodedMBs = (inParam->pictParam->pictureType != VDX_VOP_TYPE_I) ? - dpmbio.numOfCodedMBs : dimbio.numOfCodedMBs; - - if (fSegmentCorrupted) { - u_int32 nextVPBitPos; - - /* find the next resync marker, to get the number of MBs in the current VP */ - sncCode = sncRewindAndSeekNewMPEGSync(-1, inBuffer, inParam->pictParam->fcode_forward, &error); - if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { - goto unexpectedError; - } else if (sncCode == SNC_EOB) { - goto exitFunction; - } - - nextVPBitPos = bibNumberOfFlushedBits(inParam->inBuffer); - - /* if the lastMBNumInVP was not yet read */ - if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I || - !inParam->pictParam->data_partitioned || - lastMBNumInVP == 0) { - - /* if VP header is found: read it, and get last MB number in current vop */ - if (sncCode == SNC_VIDPACK) { - vdxVideoPacketHeader_t header; - vdxGetVideoPacketHeaderInputParam_t vdxParam; - int retValue; - - vdxParam.fcode_forward = inParam->pictParam->fcode_forward; - vdxParam.time_increment_resolution = inParam->pictParam->time_increment_resolution; - vdxParam.numOfMBs = inParam->pictParam->numMBsInGOB; - - retValue = vdxGetVideoPacketHeader(inParam->inBuffer, &vdxParam, &header, &bitErrorIndication); - if (retValue < 0) { - goto unexpectedError; - } else if (retValue == VDX_OK_BUT_BIT_ERROR) { - /* If bit error occurred */ - goto headerFailure; - } - - /* rewind the bits to the beginning of the VP header */ - bibRewindBits(bibNumberOfFlushedBits(inParam->inBuffer) - nextVPBitPos, - inParam->inBuffer, &error); - - lastMBNumInVP = header.currMBNum; - - } else { - lastMBNumInVP = inParam->pictParam->numMBsInGOB; - } - } - - /* if possibly the next VP header is damaged (it gives MB index which is smaller than the start of the current one */ - if (lastMBNumInVP <= startMB || lastMBNumInVP > inParam->pictParam->numMBsInGOB) - goto exitFunction; - - /* if the MB counting due to error overran the next VP header's value */ - if (inOutParam->currMBNum > lastMBNumInVP) - inOutParam->currMBNum = VDC_MAX(lastMBNumInVP-3,startMB); - - /* if not all the MBs have been predicted due to error */ - else if (inOutParam->currMBNum < lastMBNumInVP) - inOutParam->currMBNum = VDC_MAX(inOutParam->currMBNum-1,startMB); - - - inOutParam->currMBNum = lastMBNumInVP; - } - - exitFunction: - - - exitWhenVOPHeaderCorrupted: - - if (!fSegmentCorrupted) { - SOH_DEALLOC(pDiffMB); - return DGOB_OK; - } - else { - SOH_DEALLOC(pDiffMB); - return DGOB_OK_BUT_BIT_ERROR; - } - - headerFailure: - SOH_DEALLOC(pDiffMB); - sncRewindAndSeekNewMPEGSync(-1, inBuffer, 0, &error); - if (error && error != ERR_BIB_NOT_ENOUGH_DATA) - return DGOB_ERR; - return DGOB_OK_BUT_BIT_ERROR; - - unexpectedError: - SOH_DEALLOC(pDiffMB); - return DGOB_ERR; -} -// End of File