diff -r 000000000000 -r 951a5db380a0 videoeditorengine/h263decoder/src/decpich_mpeg.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/h263decoder/src/decpich_mpeg.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,417 @@ +/* +* 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: +* Picture header decoding functions (MPEG-4). +* +*/ + + + +#include "h263dConfig.h" +#include "mpegcons.h" +#include "sync.h" +#include "decpich.h" +#include "debug.h" +#include "vdeims.h" +#include "vdeimb.h" +#include "viddemux.h" + + +/* + * Global functions + */ + +/* + * dphGetMPEGVolHeader + * + * + * Parameters: + * hInstance instance data + * + * Function: + * This function decodes the Video Object Header and the VOL Header + * and initializes the fields of vdcInstance which are set in these + * headers. Check and reports (generating error messages) if the header + * shows a configuration on feature which is not supported by the + * Simple Video Object Profile of MPEG4 + * + * Returns: + * VDE_OK if the function was successful + * VDE_ERROR if a fatal error, from which the decoder + * cannot be restored, has occured + * + */ + +int dphGetMPEGVolHeader(dphInOutParam_t *inOutParam, CMPEG4Transcoder *hTranscoder) +{ + vdcInstance_t *instance = inOutParam->vdcInstance; + bibBuffer_t *inBuffer = inOutParam->inBuffer; + int bitErrorIndication = 0; + vdxVolHeader_t volHeader; + + /* read the Stream headers from the bitstream */ + if ((vdxGetVolHeader(inBuffer, &volHeader, &bitErrorIndication, 0, 0, 0, hTranscoder) != VDX_OK) || + (bitErrorIndication != 0)) { + return DPH_ERR; + } + + /* copy the useful VOL parameters to pictureParam or the core data structure */ + instance->pictureParam.vo_id = volHeader.vo_id; + instance->pictureParam.vol_id = volHeader.vol_id; + instance->pictureParam.time_increment_resolution = volHeader.time_increment_resolution; + + /* MVE */ + instance->pictureParam.fixed_vop_rate = volHeader.fixed_vop_rate; + + instance->pictureParam.lumWidth = volHeader.lumWidth; + instance->pictureParam.lumHeight = volHeader.lumHeight; + + if (volHeader.lumWidth%16) + instance->pictureParam.lumMemWidth = (((volHeader.lumWidth >>4/*/16*/) + 1) <<4/** 16*/); + else + instance->pictureParam.lumMemWidth = volHeader.lumWidth; + + if (volHeader.lumHeight%16) + instance->pictureParam.lumMemHeight = (((volHeader.lumHeight >>4/*/16*/) + 1) <<4/** 16*/); + else + instance->pictureParam.lumMemHeight = volHeader.lumHeight; + + instance->pictureParam.error_res_disable = volHeader.error_res_disable; + instance->pictureParam.data_partitioned = volHeader.data_partitioned; + instance->pictureParam.reversible_vlc = volHeader.reversible_vlc; + + /* copy the got user data to the core data structure */ + if (volHeader.user_data != NULL) { + instance->user_data = (char *) malloc(MAX_USER_DATA_LENGTH); + + volHeader.user_data_length = + ((instance->user_data_length + volHeader.user_data_length) >= MAX_USER_DATA_LENGTH) ? + (MAX_USER_DATA_LENGTH - instance->user_data_length) : volHeader.user_data_length; + + memcpy( + instance->user_data + instance->user_data_length, + volHeader.user_data, + volHeader.user_data_length); + + instance->user_data_length += volHeader.user_data_length; + + free(volHeader.user_data); + } + + return DPH_OK; +} + +/* {{-output"dphGetMPEGVopHeader.txt"}} */ +/* + * dphGetMPEGVopHeader + * + * + * Parameters: + * inOutParam input/output parameters, these parameters + * may be modified in the function + * outParam output parameters + * bitErrorIndication bit error indication, see biterr.h for + * the possible values + * + * Function: + * This function gets and decodes an MPEG Vop header which should start + * with a VOP start_code at the current position of the bit buffer. + * At first, the function reads the picture header fields from the bitstream. + * Then, it checks whether the values of the fields are supported. + * An unsupported value is interpreted as a bit error. Finally, + * the function updates VDC instance data and output parameters + * (according to the new picture header). + * + * Returns: + * >= 0 the function was successful + * < 0 an error occured + * + */ + +int dphGetMPEGVopHeader( + const dphInParam_t *inParam, + dphInOutParam_t *inOutParam, + dphOutParam_t *outParam, + int *bitErrorIndication) +/* {{-output"dphGetMPEGVopHeader.txt"}} */ +{ + bibBuffer_t *inBuffer = inOutParam->inBuffer; + u_char fPrevIntraGot; /* Non-zero if an INTRA frame has been decoded + before the current frame */ + vdxGetVopHeaderInputParam_t picHdrIn; + vdxVopHeader_t picHeader; + vdcInstance_t *instance = inOutParam->vdcInstance; + vdcPictureParam_t *pictureParam = &instance->pictureParam; + int fInterFrame; /* non-zero = INTER frame, 0 = INTRA frame */ + int ret = DPH_OK, curr_mod_time_base=0; + int16 error = 0; + int32 currFrameNum=0; + + /* In normal case read the picture header from the bitstream. + This function can be also called just to initialize the default + picture header parameters and allocate image buffers, but not read + the picture header from bitstream. This is used when the picture + header has been lost (e.g. packet loss) but decoding is continued */ + + if (inParam->fReadBits) { + + /* + * Get picture header + */ + + picHdrIn.time_increment_resolution = pictureParam->time_increment_resolution; + + /* MVE */ + int dummy1, dummy2, dummy3, dummy4; /* not used for processing */ + ret = vdxGetVopHeader(inBuffer, &picHdrIn, &picHeader, + &dummy1, &dummy2, &dummy3, &dummy4, + bitErrorIndication); + + if ( ret < 0 ) + return DPH_ERR; + else if ( ret > 0 ) { + ret = DPH_OK_BUT_BIT_ERROR; + goto updateInstanceData; + } else { + ret = DPH_OK; + } + + /* + * Check picture header validity + */ + + /* Local parameters needed in validity check (and possibly afterwards) */ + fPrevIntraGot = instance->fIntraGot; + fInterFrame = (picHeader.coding_type == VDX_VOP_TYPE_P); + + + if (picHeader.time_base_incr < 0 || picHeader.time_base_incr > 60) { + if ( *bitErrorIndication ) { + ret = DPH_OK_BUT_BIT_ERROR; + goto updateInstanceData; + } + } + + curr_mod_time_base = pictureParam->mod_time_base + picHeader.time_base_incr; + + currFrameNum = (int) ((curr_mod_time_base + + ((double) picHeader.time_inc) / ((double) pictureParam->time_increment_resolution)) * + 30.0 + 0.001); + + if ((currFrameNum <= instance->frameNum) && + (instance->frameNum > 0)) { + if (*bitErrorIndication) { + ret = DPH_OK_BUT_BIT_ERROR; + goto updateInstanceData; + } else { + /* this can happen if a previous picture header is lost and it had + mod_time_base increase information. */ + int i; + int32 tryFrameNum=0; + for (i=1;i<5;i++) { + tryFrameNum = (int) (((curr_mod_time_base+i) + + ((double) picHeader.time_inc) / ((double) pictureParam->time_increment_resolution)) * + 30.0 + 0.001); + if (tryFrameNum > instance->frameNum) { + currFrameNum = tryFrameNum; + curr_mod_time_base += i; + ret = DPH_OK; + break; + } + } + if (i==5) { + ret = DPH_OK_BUT_BIT_ERROR; + goto updateInstanceData; + } + } + } + + /* If no INTRA frame has ever been decoded and the current frame is INTER */ + if (!fPrevIntraGot && fInterFrame) { + deb("ERROR. No I-vop before a P-vop\n"); + return DPH_ERR_NO_INTRA; + + } + + /* fcode can have only the valid values 1..7 */ + if(picHeader.fcode_forward == 0) { + ret = DPH_OK_BUT_BIT_ERROR; + goto updateInstanceData; + } + + /* quant can not be zero */ + if(picHeader.quant == 0) { + ret = DPH_OK_BUT_BIT_ERROR; + goto updateInstanceData; + } + + } /* end fReadBits */ + + /* Now, the picture header is considered to be error-free, + and its contents are used to manipulate instance data */ + +updateInstanceData: + + /* + * Update instance data and output parameters + */ + + /* some parameters need to be set if error has been detected, for initializing */ + if (!inParam->fReadBits || (ret == DPH_OK_BUT_BIT_ERROR)) { + picHeader.rounding_type = 0; + picHeader.fcode_forward = 1; + picHeader.coding_type = 1; + } else { + /* Update frame numbers */ + pictureParam->time_base_incr = picHeader.time_base_incr; + pictureParam->mod_time_base = curr_mod_time_base; + pictureParam->time_inc = picHeader.time_inc; + instance->frameNum = currFrameNum; + } + + /* Update picture parameters */ + pictureParam->trd = (instance->frameNum % 256) - pictureParam->tr; + pictureParam->tr = instance->frameNum % 256; + + pictureParam->pictureType = picHeader.coding_type; + + if (!picHeader.vop_coded) { + return DPH_OK_BUT_NOT_CODED; + } + + /* NO reference picture selection */ + outParam->trp = -1; + + /* No PB Frames allowed */ + instance->frameNumForBFrame = -1; + + /* Note: If no INTRA has been got the function has already returned */ + instance->fIntraGot = 1; + + pictureParam->intra_dc_vlc_thr = picHeader.intra_dc_vlc_thr; + pictureParam->fcode_forward = picHeader.fcode_forward; + + outParam->pquant = picHeader.quant; + + /* Initialize for only 1 GOB */ + pictureParam->numMBLinesInGOB = pictureParam->lumMemHeight / 16; + pictureParam->numMBsInMBLine = pictureParam->lumMemWidth / 16; + + pictureParam->numGOBs = 1; + pictureParam->fLastGOBSizeDifferent = 0; + pictureParam->numMBsInGOB = + pictureParam->numMBsInMBLine * pictureParam->numMBLinesInGOB; + pictureParam->numMBsInLastGOB = pictureParam->numMBsInGOB; + + /* Rounding type */ + pictureParam->rtype = picHeader.rounding_type; + + /* NO channel Multiplexing */ + pictureParam->fSplitScreenIndicator = 0; + pictureParam->fDocumentCameraIndicator = 0; + pictureParam->fFullPictureFreezeRelease = 0; + pictureParam->fPLUSPTYPE = 0; + pictureParam->cpm = 0; + + /* All the Annexes are switched off */ + pictureParam->fSAC = 0; + pictureParam->fRPR = 0; + pictureParam->fRRU = 0; + pictureParam->fCustomSourceFormat = 0; + pictureParam->fAIC = 0; + pictureParam->fDF = 0; + pictureParam->fSS = 0; + pictureParam->fRPS = 0; + pictureParam->fISD = 0; + pictureParam->fAIV = 0; + pictureParam->fMQ = 0; + pictureParam->fUMVLimited = 0; + + /* Unrestricted MV allowed + OBMC NOT allowed */ + pictureParam->fUMV = 1; + pictureParam->fAP = 0; + pictureParam->fMVsOverPictureBoundaries = 1; + + /* Initialize motion vector count module */ + mvcStart( &instance->mvcData, + ((instance->pictureParam.lumMemWidth >>4 /*/ 16*/) - 1), + pictureParam->lumWidth, + pictureParam->lumHeight, &error); + /* Note: This assumes that the memory for frame->mvcData is filled with 0 + in the first time the function is called. + (This is ensured by setting the instance data to zero when it is + initialized in vdcOpen.) */ + if (error) { + deb("mvcStart failed.\n"); + return DPH_ERR; + } + + /* Initialize once to count parameters for the mvc module */ + { + int r_size, scale_factor; + + instance->mvcData.f_code = pictureParam->fcode_forward; + r_size = pictureParam->fcode_forward - 1; + scale_factor = (1 << r_size); + instance->mvcData.range = 160 * scale_factor; + } + + /* Start, initialize the Advanced Intra Coding module */ + aicStart(&instance->aicData, pictureParam->numMBsInMBLine, &error); + if (error) { + deb("aicStart failed.\n"); + return DPH_ERR; + } + + /* Get image buffers */ + { + vdeIms_t *store = instance->imageStore; + vdeImsItem_t *imsItem; + vdeImb_t *imb; + int width, height; + + vdeImsSetYUVNeed(store, inParam->fNeedDecodedFrame); + + if (vdeImsGetFree(store, instance->pictureParam.lumMemWidth, + instance->pictureParam.lumMemHeight, + &instance->currFrame) < 0) + goto errGetFreeP; + imsItem = instance->currFrame; + + if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) + goto errAfterGetFreeP; + + if (vdeImbYUV(imb, &outParam->currYFrame, + &outParam->currUFrame, &outParam->currVFrame, + &width, &height) < 0) + goto errAfterGetFreeP; + } + + return ret; + + /* Error condition handling, + release everything in reverse order */ + errAfterGetFreeP: + + vdeImsPutFree(instance->imageStore, instance->currFrame); + errGetFreeP: + + instance->currFrame = NULL; + instance->bFrame = NULL; + + return DPH_ERR; +} +// End of File