diff -r 951a5db380a0 -r e0b5df5c0969 videoeditorengine/h263decoder/src/core_mpeg.cpp --- a/videoeditorengine/h263decoder/src/core_mpeg.cpp Fri Jan 29 14:08:33 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,671 +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: -* MPEG-4 decoder core functions. -* -*/ - - -/* - * Includes - */ -#include "h263dConfig.h" -#include "vdc263.h" -#include "core.h" -#include "debug.h" -#include "decblock.h" /* for dblFree and dblLoad */ -#include "decvp_mpeg.h" -#include "decpich.h" -#include "h263dapi.h" /* for H263D_BC_MUX_MODE_SEPARATE_CHANNEL and H263D_ERD_ */ -#include "stckheap.h" -#include "sync.h" -#include "vdeims.h" -#include "vdeimb.h" -#include "viddemux.h" -#include "biblin.h" -/* MVE */ -#include "MPEG4Transcoder.h" - - -/* - * Typedefs and structs - */ - -/* This structure is used to indicate the expected decoding position. */ -typedef enum { - EDP_START_OF_FRAME, - EDP_START_OF_VIDEO_PACKET, - EDP_END_OF_FRAME -} vdcExpectedDecodingPosition_t; - - -/* - * Local function prototypes - */ - -extern int vdcFillImageBuffers( - vdcInstance_t *instance, - int numOfCodedMBs, - vdeImb_t *imbP); - - -/* - * Global functions - */ - -/* {{-output"vdcDecodeMPEGVolHeader.txt"}} */ -/* - * vdcDecodeMPEGVolHeader - * - * - * Parameters: - * None. - * - * Function: - * This function reads the VOL Header and updates the instance data - * with the read parameters. - * - * Returns: - * >= 0 if succeeded - * < 0 if failed - * - */ - -int vdcDecodeMPEGVolHeader(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, CMPEG4Transcoder *hTranscoder) -/* {{-output"vdcDecodeMPEGVolHeader.txt"}} */ -{ - dphInOutParam_t pichInOut; - int headerSuccess = 0; - - pichInOut.vdcInstance = (vdcInstance_t *) hInstance; - pichInOut.inBuffer = inBuffer; - - headerSuccess = dphGetMPEGVolHeader(&pichInOut, hTranscoder); - if (headerSuccess != 0) - return VDC_ERR; - else - return VDC_OK; -} - - -/* {{-output"vdcDecodeMPEGVop.txt"}} */ -/* - * vdcDecodeMPEGVop - * - * - * Parameters: - * hInstance handle of instance data - * - * inBuffer pointer to bit buffer, the current position - * of the buffer must start with a PSC - * - * Function: - * The vdcDecodeMPEGVop function implements the decoding process of the MPEG-4 - * Simple Video Object described in ISO/IEC 14496-2. - * - * The function decodes the next frame in the buffer (inBuffer) meaning that - * the decoding continues until the next VOP start code or EOB is found or - * until the end of the buffer is not reached. - * - * Returns: - * VDC_OK if the function was succesful - * VDC_OK_BUT_BIT_ERROR if bit errors were detected but - * decoded frames are provided by concealing - * the errors - * VDC_OK_BUT_FRAME_USELESS if severe bit errors were detected - * (no concealment was possible) or - * the bitstream ended unexpectedly - * VDC_ERR if a processing error occured, - * the instance should be closed - * - */ -int vdcDecodeMPEGVop(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, bibBuffer_t *outBuffer, - bibBufferEdit_t *bufEdit, int aColorEffect, TBool aGetDecodedFrame, - int aStartByteIndex, int aStartBitIndex, - CMPEG4Transcoder *hTranscoder) -/* {{-output"vdcDecodeMPEGVop.txt"}} */ -{ - int sncCode; /* the latest synchronization code, see - sncCheckSync for the possible values */ - - int retValue = VDC_OK; /* return value of this function */ - - int16 error = 0; - - u_char - *currYFrame = NULL, /* current P frame */ - *currUFrame = NULL, - *currVFrame = NULL, - *refYFrame = NULL, /* reference frame */ - *refUFrame = NULL, - *refVFrame = NULL; - - u_char *fCodedMBs = NULL; /* Pointer to table, which indicates coded \ - macroblocks by non-zero value */ - int numOfCodedMBs = 0; /* The number of coded macroblocks */ - - int *quantParams = NULL; /* Pointer to table, in which the quantization - parameter for each macroblock is stored */ - - int currMBNum = 0; /* Current macro block */ - - int decStatus = 0; - int corruptedVPs = 0; - int numberOfVPs = 1; - int headerSuccess = 0; - u_char fVOPHeaderCorrupted = 0, fVOPHeaderLost = 0; - - vdcExpectedDecodingPosition_t expectedDecodingPosition; - /* Tells in which part of the bitstream - the decoding should be */ - - vdcInstance_t *instance = (vdcInstance_t *) hInstance; - /* instance data */ - - vdcAssert(instance != NULL); - - /* Initializations */ - - instance->currFrame = NULL; - expectedDecodingPosition = EDP_START_OF_FRAME; - - /* Main loop */ - for (;;) { - int bitErrorIndication = 0; - - sncCode = sncCheckMpegSync(inBuffer, instance->pictureParam.fcode_forward, &error); - - /* If sncCheckSync failed */ - if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { - deb1p("vdcDecodeMPEGVop: ERROR - sncCheckSync returned %d.\n", error); - retValue = VDC_ERR; - goto exitFunction; - } - - /* If EOS was got */ - if (sncCode == SNC_EOB) - instance->fEOS = 1; - - /* If frame ends appropriately */ - if (expectedDecodingPosition == EDP_END_OF_FRAME && - (sncCode == SNC_VOP || sncCode == SNC_GOV || sncCode == SNC_EOB || - sncCode == SNC_STUFFING || error == ERR_BIB_NOT_ENOUGH_DATA)) - goto exitFunction; - - /* Else if frame (or stream) data ends suddenly */ - else if (error == ERR_BIB_NOT_ENOUGH_DATA) { - retValue = VDC_OK_BUT_BIT_ERROR; - goto exitFunction; - } - - /* Else if EOS was reached */ - else if (sncCode == SNC_EOB) { - /* The current frame is useless since it ends before it is complete. - On the other hand, there is no point in concealing it since - it is the last frame of the sequence. */ - goto exitFunction; - } - - /* Else if frame starts as expected */ - else if (expectedDecodingPosition == EDP_START_OF_FRAME && - ((sncCode == SNC_GOV) || (sncCode == SNC_VOP) || fVOPHeaderLost)) { - - dphInParam_t pichIn; - dphInOutParam_t pichInOut; - dphOutParam_t pichOut; - - if (sncCode == SNC_GOV) { - vdxGovHeader_t govHeader; - - headerSuccess = vdxGetGovHeader(inBuffer, &govHeader, &bitErrorIndication); - if ( headerSuccess < 0) { - retValue = VDC_ERR; - goto exitFunction; - } else if (( headerSuccess > 0 ) || - (govHeader.time_stamp < instance->pictureParam.mod_time_base) || - (govHeader.time_stamp - instance->pictureParam.mod_time_base > 60)) { - - if(sncCheckMpegVOP(inBuffer, &error) != SNC_PSC) { - retValue = VDC_OK_BUT_FRAME_USELESS; - goto exitFunction; - } - - } else { - instance->pictureParam.mod_time_base = govHeader.time_stamp; - - /* copying the user data */ - if (govHeader.user_data != NULL) { - - if (!instance->user_data) - instance->user_data = (char *) vdcMalloc( - MAX_USER_DATA_LENGTH); - - govHeader.user_data_length = - ((instance->user_data_length + govHeader.user_data_length) >= MAX_USER_DATA_LENGTH) ? - (MAX_USER_DATA_LENGTH - instance->user_data_length) : govHeader.user_data_length; - memcpy( - instance->user_data + instance->user_data_length, - govHeader.user_data, - govHeader.user_data_length); - instance->user_data_length += govHeader.user_data_length; - - vdcDealloc(govHeader.user_data); - } - - } - } - - /* Start VOP decoding */ - pichIn.fReadBits = (fVOPHeaderLost ? 0 : 1); - pichIn.fNeedDecodedFrame = aGetDecodedFrame | hTranscoder->NeedDecodedYUVFrame(); - pichInOut.vdcInstance = instance; - pichInOut.inBuffer = inBuffer; - - /* Get VOP header */ - headerSuccess = dphGetMPEGVopHeader(&pichIn, &pichInOut, &pichOut, &bitErrorIndication); - - deb1p("vdcDecodeMPEGVop: frameNum %d.\n", instance->frameNum); - if ( headerSuccess < 0) { - retValue = VDC_ERR; - goto exitFunction; - } else if ( headerSuccess > 0 ) { - - if (headerSuccess == DPH_OK_BUT_BIT_ERROR) { - /* find the next resync marker, to get the number of MBs in the current VP */ - sncCode = sncRewindAndSeekNewMPEGSync(-1, inBuffer, instance->pictureParam.fcode_forward, &error); - if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { - retValue = VDC_ERR; - goto exitFunction; - } - - if (sncCode == SNC_VIDPACK) { - fVOPHeaderCorrupted = 1; - } else { - retValue = VDC_OK_BUT_FRAME_USELESS; - goto exitFunction; - } - - } else if (headerSuccess == DPH_OK_BUT_NOT_CODED) { - - /* MVE */ - /* copy VOP header to output buffer in case VOP is not coded, including the GOV */ - bufEdit->copyMode = CopyWhole; /* copyWhole */ - CopyStream(inBuffer,outBuffer,bufEdit, aStartByteIndex, aStartBitIndex); - - /* behaves the same as if the frame was useless, but it's just not coded */ - retValue = VDC_OK_BUT_NOT_CODED; - goto exitFunction; - } - } - - - currYFrame = pichOut.currYFrame; - currUFrame = pichOut.currUFrame; - currVFrame = pichOut.currVFrame; - - currMBNum = 0; - - numOfCodedMBs = 0; - fCodedMBs = renDriCodedMBs(instance->currFrame->imb->drawItem); - memset(fCodedMBs, 0, renDriNumOfMBs( - instance->currFrame->imb->drawItem) * sizeof(u_char)); - - /* Initialize quantization parameter array */ - quantParams = instance->currFrame->imb->yQuantParams; - memset(quantParams, 0, renDriNumOfMBs( - instance->currFrame->imb->drawItem) * sizeof(int)); - - /* If this is the first frame and callback function has been set, report frame size */ - if (instance->nOfDecodedFrames == 0 && instance->reportPictureSizeCallback) { - h263dReportPictureSizeCallback_t cb = - (h263dReportPictureSizeCallback_t)instance->reportPictureSizeCallback; - cb(instance->hParent, instance->pictureParam.lumWidth, instance->pictureParam.lumHeight); - } - - /* Decode the 1st VP segment */ - { - dvpVPInParam_t dvpi; - dvpVPInOutParam_t dvpio; - - dvpi.pictParam = &instance->pictureParam; - dvpi.inBuffer = inBuffer; - dvpi.outBuffer = outBuffer; - dvpi.bufEdit = bufEdit; - dvpi.iColorEffect = aColorEffect; - dvpi.iGetDecodedFrame = aGetDecodedFrame; - - if (fVOPHeaderLost) fVOPHeaderCorrupted = 1; - dvpi.fVOPHeaderCorrupted = fVOPHeaderCorrupted; - - dvpio.currMBNum = 0; - dvpio.quant = pichOut.pquant; - dvpio.fCodedMBs = fCodedMBs; - dvpio.numOfCodedMBs = numOfCodedMBs; - dvpio.quantParams = quantParams; - dvpio.mvcData = &instance->mvcData; - dvpio.aicData = &instance->aicData; - dvpio.imageStore = instance->imageStore; - dvpio.frameNum = instance->frameNum; - - dvpio.refY = refYFrame; - dvpio.refU = refUFrame; - dvpio.refV = refVFrame; - dvpio.currPY = currYFrame; - dvpio.currPU = currUFrame; - dvpio.currPV = currVFrame; - - /* MVE */ - hTranscoder->VOPHeaderEnded(aStartByteIndex, aStartBitIndex, - pichOut.pquant, instance->pictureParam.pictureType, - instance->frameNum, headerSuccess == DPH_OK_BUT_NOT_CODED); - /* VOP header parsing success, begin on VP */ - hTranscoder->BeginOneVideoPacket(&dvpi); - hTranscoder->AfterVideoPacketHeader(&dvpio); // the first VP does not have VPHeader - - decStatus = dvpGetAndDecodeVideoPacketContents(&dvpi, - instance->pictureParam.pictureType != VDX_PIC_TYPE_I, - &dvpio, hTranscoder); - - if (decStatus < 0) { - retValue = VDC_ERR; - goto exitFunction; - } else if (decStatus > 0 ) { - if (decStatus == DGOB_OK_BUT_FRAME_USELESS) { - retValue = VDC_OK_BUT_FRAME_USELESS; - goto exitFunction; - } - corruptedVPs ++; - } - - /* MVE */ - /* the first VP ends */ - hTranscoder->OneVPEnded(); - - currMBNum = dvpio.currMBNum; - numOfCodedMBs = dvpio.numOfCodedMBs; - refYFrame = dvpio.refY; - refUFrame = dvpio.refU; - refVFrame = dvpio.refV; - - - if ((decStatus == DGOB_OK && currMBNum == instance->pictureParam.numMBsInGOB) || - (decStatus == DGOB_OK_BUT_BIT_ERROR && sncCheckMpegVOP(inBuffer, &error) == SNC_PSC)) - expectedDecodingPosition = EDP_END_OF_FRAME; - else - expectedDecodingPosition = EDP_START_OF_VIDEO_PACKET; - } - } - - /* Else if Video Packet starts as expected */ - else if (expectedDecodingPosition == EDP_START_OF_VIDEO_PACKET && - sncCode == SNC_VIDPACK) { - - dvpVPInParam_t dvpi; - dvpVPInOutParam_t dvpio; - - dvpi.pictParam = &instance->pictureParam; - dvpi.inBuffer = inBuffer; - dvpi.outBuffer = outBuffer; - dvpi.bufEdit = bufEdit; - dvpi.iColorEffect = aColorEffect; - dvpi.iGetDecodedFrame = aGetDecodedFrame; - dvpi.fVOPHeaderCorrupted = fVOPHeaderCorrupted; - - dvpio.currMBNum = currMBNum; - dvpio.fCodedMBs = fCodedMBs; - dvpio.numOfCodedMBs = numOfCodedMBs; - dvpio.quantParams = quantParams; - dvpio.mvcData = &instance->mvcData; - dvpio.aicData = &instance->aicData; - dvpio.imageStore = instance->imageStore; - - dvpio.refY = refYFrame; - dvpio.refU = refUFrame; - dvpio.refV = refVFrame; - dvpio.currPY = currYFrame; - dvpio.currPU = currUFrame; - dvpio.currPV = currVFrame; - - /* MVE */ - /* VOP header parsing success, begin on VP */ - hTranscoder->BeginOneVideoPacket(&dvpi); - - /* if the VOP header data needs to be corrected from the HEC codes set - inParam->fVOPHeaderCorrupted and pictParam values will be set + read - inOutParam->frameNum into instance->frameNum */ - decStatus = dvpGetAndDecodeVideoPacketHeader(&dvpi, &dvpio); - - /* MVE */ - /* After parsing the VP header */ - hTranscoder->AfterVideoPacketHeader(&dvpio); - - if (decStatus < 0) { - retValue = VDC_ERR; - goto exitFunction; - } else if (decStatus > 0) { - - if (fVOPHeaderCorrupted) { - /* this is also true when the whole packet with the VOP header is lost */ - - if (dvpio.frameNum <= instance->frameNum) { - /* VOP header could not be recovered from HEC (there was no HEC) - or there was an error in the VP header: in this case should we try to recover - VOP header from the next VP instead of the exiting here? */ - retValue = VDC_OK_BUT_FRAME_USELESS; - goto exitFunction; - - } else { - /* VOP header was succesfully recovered from HEC, - the first VP is treated as corrupted or lost */ - instance->frameNum = dvpio.frameNum; - - } - } else if (currMBNum < dvpio.currMBNum) { - /* when there was no bit-error in the VP header and the MB counter shows difference - we know, that a whole VP was lost */ - - corruptedVPs++; - numberOfVPs++; - - - } - } - - numberOfVPs++; - - if (!decStatus) { - - - decStatus = dvpGetAndDecodeVideoPacketContents(&dvpi,0,&dvpio, hTranscoder); - if (decStatus < 0) { - retValue = VDC_ERR; - goto exitFunction; - } else if (decStatus > 0 ) { - if (decStatus == DGOB_OK_BUT_FRAME_USELESS) { - retValue = VDC_OK_BUT_FRAME_USELESS; - goto exitFunction; - } - corruptedVPs++; - } - - } - - /* MVE */ - hTranscoder->OneVPEnded(); - - currMBNum = dvpio.currMBNum; - numOfCodedMBs = dvpio.numOfCodedMBs; - - if ((decStatus == DGOB_OK && currMBNum == instance->pictureParam.numMBsInGOB) || - (decStatus == DGOB_OK_BUT_BIT_ERROR && sncCheckMpegVOP(inBuffer, &error) == SNC_PSC)) - expectedDecodingPosition = EDP_END_OF_FRAME; - else { - expectedDecodingPosition = EDP_START_OF_VIDEO_PACKET; - if (fVOPHeaderCorrupted) fVOPHeaderCorrupted=0; - } - } - - /* Else decoding is out of sync */ - else { - switch (expectedDecodingPosition) { - - case EDP_START_OF_FRAME: - if (sncCode == SNC_VIDPACK) { - /* VP start code instead of VOP start code -> - packet including VOP header is lost */ - fVOPHeaderLost = 1; - continue; - } else { - /* No start code */ - retValue = VDC_OK_BUT_FRAME_USELESS; - goto exitFunction; - } - - case EDP_START_OF_VIDEO_PACKET: - /* If the decoding gets out of sync, the next sync code is - seeked in dvpGetAndDecodeVideoPacketContents. Then, if - the frame ends instead of a new VP header, we are here. */ - - /* Mark the missing VP corrupted */ - { - numberOfVPs++; - corruptedVPs++; - - } - - retValue = VDC_OK_BUT_BIT_ERROR; - goto exitFunction; - - case EDP_END_OF_FRAME: - /* Too much data */ - retValue = VDC_OK_BUT_BIT_ERROR; - goto exitFunction; - } - } - } - - - -exitFunction: - - /* MVE */ - hTranscoder->VOPEnded(); - - if (sncCheckMpegSync(inBuffer, instance->pictureParam.fcode_forward, &error) == SNC_EOB) { - instance->fEOS = 1; - } - - /* If frame(s) not useless */ - if (retValue == VDC_OK || retValue == VDC_OK_BUT_BIT_ERROR) { - - /* If bit errors */ - if (corruptedVPs) { - retValue = VDC_OK_BUT_FRAME_USELESS; - } - - if ( retValue != VDC_OK_BUT_FRAME_USELESS ) { - - if ( instance->nOfDecodedFrames < 0xffffffff ) - instance->nOfDecodedFrames++; - if (vdcFillImageBuffers(instance, numOfCodedMBs, - instance->currFrame->imb) < 0) - retValue = VDC_ERR; - - } - } - - /* If a fatal error occurred */ - if (retValue < 0) { - /* Return frame buffers for decoded output images, - as they are useless for the caller and - as the caller cannot get a handle to return them */ - if (instance->currFrame) - vdeImsPutFree(instance->imageStore, instance->currFrame); - } - - return retValue; -} - - -/* {{-output"vdcIsMPEGINTRA.txt"}} */ -/* - * vdcIsMPEGINTRA - * - * - * Parameters: - * hInstance handle of instance data - * frameStart pointer to memory chunk containing a frame - * frameLength number of bytes in frame - * - * Function: - * This function returns 1 if the passed frame is an INTRA frame. - * Otherwise the function returns 0. - * - * Returns: - * See above. - * - * - */ - -int vdcIsMPEGINTRA( - vdcHInstance_t hInstance, - void *frameStart, - unsigned frameLength) -/* {{-output"vdcIsINTRA.txt"}} */ -{ - bibBuffer_t *tmpBitBuffer; - int fINTRA = 0, bitErrorIndication, syncCode, vdxStatus; - int16 error = 0; - vdcInstance_t *instance = (vdcInstance_t *) hInstance; - vdxGovHeader_t govHeader; - - vdcAssert(instance); - - tmpBitBuffer = bibCreate(frameStart, frameLength, &error); - if (!tmpBitBuffer || error) - return 0; - - syncCode = sncCheckMpegSync(tmpBitBuffer, instance->pictureParam.fcode_forward, &error); - - if ((syncCode == SNC_GOV || syncCode == SNC_VOP) && error == 0) { - vdxGetVopHeaderInputParam_t vopIn; - vdxVopHeader_t vopOut; - - if (syncCode == SNC_GOV) { - vdxStatus = vdxGetGovHeader(tmpBitBuffer, &govHeader, - &bitErrorIndication); - - if (vdxStatus < 0 || bitErrorIndication != 0) - return fINTRA; - } - - /* MVE */ - int dummy1, dummy2, dummy3, dummy4; /* not used for any processing */ - /* Get VOP header */ - vopIn.time_increment_resolution = instance->pictureParam.time_increment_resolution; - vdxStatus = vdxGetVopHeader(tmpBitBuffer, &vopIn, &vopOut, - &dummy1, &dummy2, &dummy3, &dummy4, - &bitErrorIndication); - - - if (vdxStatus >= 0 && bitErrorIndication == 0) - fINTRA = (vopOut.coding_type == VDX_VOP_TYPE_I); - } - - bibDelete(tmpBitBuffer, &error); - - return fINTRA; -} -// End of File