专家好, 我遇到如下问题:
软件架构为ipnc2.6, 在dm365平台实现解码功能,视频文件为 720P, 25fps, 发现仅有关键帧(I-frame) 解出的图像是很好质量的,其他帧(p-frame, b-frame) 解出来的帧是有马赛克的。
视频文件来源于本机自身。解码库已经更新到最新的了: dm365_h264dec_02_00_00_13_production.
该视频文件在电脑端用 ffplay 检查,发现是可以正常播放的,不存在马赛克现象。
我阅读了相关资料,觉得 p-frame 和 b-frame解出来的图像应该是依赖于 I-frame的(为了达到高压缩比率),猜测是通过某种方式叠加到之前的 I-frame去,但是具体怎么实现还没有头绪。不清楚是需要手工叠加还是解码库已经做了这个功能?
关键帧 (225帧):
非关键帧(224帧):
Ricky Xian:
代码: ( 已经根据网上其他资料修改过.)
//———– create —————————————————
void *ALG_vidDecCreate(ALG_VidDecCreate *create){ ALG_VidDecObj *pObj;
pObj = OSA_memAlloc(sizeof(ALG_VidDecObj));
if(pObj==NULL) return NULL;
memset(pObj, 0, sizeof(*pObj));
memcpy(&pObj->createPrm, create, sizeof(pObj->createPrm));
switch(create->codec) { case ALG_VID_CODEC_H264: strcpy(pObj->algName, ALG_VID_CODEC_H264_DEC_NAME); break; case ALG_VID_CODEC_MPEG4: strcpy(pObj->algName, ALG_VID_CODEC_MPEG4_DEC_NAME); break; case ALG_VID_CODEC_MJPEG: { ALG_JpgDecCreate jpgDecCreate;
jpgDecCreate.dataFormat = create->dataFormat; jpgDecCreate.maxWidth = create->maxWidth; jpgDecCreate.maxHeight = create->maxHeight;
pObj->hJpgDecode = ALG_jpgDecCreate(&jpgDecCreate);
if(pObj->hJpgDecode==NULL) return NULL;
return pObj; } break; default: OSA_memFree(pObj); return NULL; }
memcpy(&pObj->h264Params, &IH264VDEC_PARAMS, sizeof(pObj->h264Params)); pObj->params.size = sizeof(VIDDEC2_Params); pObj->params.maxHeight = create->maxHeight; pObj->params.maxWidth = create->maxWidth; pObj->params.maxFrameRate = 30000; //0 pObj->params.maxBitRate = ALG_VID_DEC_MAX_BITRATE; pObj->params.dataEndianness = XDM_BYTE; //pObj->params.forceChromaFormat = 9; pObj->params.forceChromaFormat = XDM_YUV_420SP;
pObj->h264Params.displayDelay = 0; pObj->h264Params.hdvicpHandle = NULL;// pObj->h264Params.resetHDVICPeveryFrame = TRUE; pObj->h264Params.disableHDVICPeveryFrame = 0; pObj->h264Params.frame_closedloop_flag = 1; pObj->h264Params.inputDataMode = 1; pObj->h264Params.sliceFormat = 1; pObj->h264Params.viddecParams = pObj->params; pObj->h264Params.viddecParams.size = sizeof(pObj->h264Params);
/* Create video decoder instance */ pObj->hDecode = VIDDEC2_create(gALG_hEngine, pObj->algName, &pObj->h264Params); if (pObj->hDecode == NULL) { OSA_ERROR("Failed to open video decode algorithm (%s)\n", pObj->algName); OSA_memFree(pObj); return NULL; }
return (void*)pObj;}
Ricky Xian:
//————-解压功能
int ALG_vidDecRun(void *hndl, ALG_VidDecRunPrm *prm, ALG_VidDecRunStatus *runStatus){ VIDDEC2_InArgs inArgs; VIDDEC2_OutArgs outArgs; XDM1_BufDesc inBufDesc; XDM_BufDesc outBufDesc; XDAS_Int32 outBufSizeArray[2]; XDAS_Int32 status; XDAS_Int8 *outBufPtrs[2]; ALG_VidDecObj *pObj; IH264VDEC_DynamicParams h264DynParams; pObj = (ALG_VidDecObj *)hndl;
if(pObj==NULL) return OSA_EFAIL;
if(pObj->createPrm.codec == ALG_VID_CODEC_MJPEG) {
ALG_JpgDecRunPrm jpgDecRun; ALG_JpgDecRunStatus jpgDecStatus;
jpgDecRun.inAddr = prm->inAddr; jpgDecRun.inDataSize = prm->inDataSize; jpgDecRun.outAddr = prm->outAddr; jpgDecRun.outOffsetH = prm->outOffsetH; jpgDecRun.outOffsetV = prm->outOffsetV; jpgDecRun.outStartX = 0; jpgDecRun.outStartY = 0;
status = ALG_jpgDecRun(pObj->hJpgDecode, &jpgDecRun, &jpgDecStatus); if(status!=OSA_SOK) return OSA_EFAIL;
runStatus->bytesUsed = jpgDecStatus.bytesUsed; runStatus->isKeyFrame = TRUE; runStatus->frameWidth = jpgDecStatus.frameWidth; runStatus->frameHeight= jpgDecStatus.frameHeight; runStatus->outputBufId= prm->inputBufId; runStatus->freeBufId = prm->inputBufId; runStatus->outStartX = jpgDecRun.outStartX; runStatus->outStartY = jpgDecRun.outStartY; runStatus->outOffsetH = jpgDecRun.outOffsetH; runStatus->outOffsetV = jpgDecRun.outOffsetV;
return OSA_SOK; }
if(pObj->hDecode==NULL) return OSA_EFAIL;
if(pObj->curFrameNum==0) { pObj->dynamicParams.size = sizeof(VIDDEC2_DynamicParams); pObj->dynamicParams.decodeHeader = XDM_DECODE_AU; pObj->dynamicParams.displayWidth = prm->outOffsetH; pObj->dynamicParams.frameSkipMode = IVIDEO_NO_SKIP;
// ricky: from web: // http://e2e.ti.com/support/embedded/multimedia_software_codecs/f/356/t/63637.aspx pObj->dynamicParams.frameOrder = IVIDDEC2_DECODE_ORDER;
pObj->decStatus.size = sizeof(VIDDEC2_Status); pObj->decStatus.data.buf = NULL; h264DynParams.viddecDynamicParams = pObj->dynamicParams; h264DynParams.viddecDynamicParams.size = sizeof(h264DynParams); h264DynParams.resetHDVICPeveryFrame = 1; h264DynParams.dataSyncHandle = NULL; h264DynParams.getDataFxn = NULL; status = VIDDEC2_control(pObj->hDecode, XDM_SETPARAMS, &h264DynParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_SETPARAMS failed, status=%ld\n", status); return OSA_EFAIL; }
/* Get buffer information from video decoder */ pObj->decStatus.size = sizeof(VIDDEC2_Status); pObj->decStatus.data.buf = NULL;
pObj->dynamicParams.size = sizeof(VIDDEC2_DynamicParams); status = VIDDEC2_control(pObj->hDecode, XDM_GETBUFINFO, &pObj->dynamicParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_GETBUFINFO failed, status=%ld\n", status); return OSA_EFAIL; }
#ifdef ALG_VID_DEC_TEST_DEBUG OSA_printf(" ALG: VidDec: XDM_GETBUFINFO: min out bufs:%ld,size:%ld %ld\n",pObj->decStatus.bufInfo.minNumOutBufs,pObj->decStatus.bufInfo.minOutBufSize[0], pObj->decStatus.bufInfo.minOutBufSize[1]); #endif }
pObj->dynamicParams.size = sizeof(VIDDEC2_DynamicParams); pObj->decStatus.size = sizeof(VIDDEC2_Status); pObj->decStatus.data.buf = NULL;
outBufSizeArray[0] = (prm->outOffsetH)*(prm->outOffsetV); outBufSizeArray[1] = outBufSizeArray[0]/2;
inBufDesc.descs[0].bufSize = prm->inDataSize; inBufDesc.descs[0].buf = (XDAS_Int8 *)prm->inAddr; inBufDesc.numBufs = 1;
outBufPtrs[0] = (XDAS_Int8 *)prm->outAddr; outBufPtrs[1] = (XDAS_Int8 *)(prm->outAddr + outBufSizeArray[0]) ;
outBufDesc.bufSizes = outBufSizeArray; outBufDesc.bufs = (XDAS_Int8 **) &outBufPtrs; outBufDesc.numBufs = 2;
inArgs.size = sizeof(VIDDEC2_InArgs); inArgs.numBytes = prm->inDataSize; inArgs.inputID = prm->inputBufId+1; // must be greater than 0
outArgs.size = sizeof(VIDDEC2_OutArgs); outArgs.outBufsInUseFlag=0; status = VIDDEC2_process(pObj->hDecode, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
status = VIDDEC2_control(pObj->hDecode, XDM_GETSTATUS, &pObj->dynamicParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_GETSTATUS failed, status=%ld\n", status); return OSA_EFAIL; }
runStatus->bytesUsed = outArgs.bytesConsumed;
if (status != VIDDEC2_EOK) { OSA_ERROR("status=%ld\n", status); return OSA_EFAIL; }
switch (outArgs.displayBufs[0].frameType) { case IVIDEO_I_FRAME: runStatus->isKeyFrame = TRUE; break; case IVIDEO_P_FRAME: runStatus->isKeyFrame = FALSE; break; case IVIDEO_B_FRAME: runStatus->isKeyFrame = FALSE; break; case IVIDEO_IDR_FRAME: runStatus->isKeyFrame = TRUE; break; case IVIDEO_II_FRAME: runStatus->isKeyFrame = TRUE; break; case IVIDEO_PP_FRAME: runStatus->isKeyFrame = FALSE; break; default: runStatus->isKeyFrame = FALSE; break; }
runStatus->frameWidth = pObj->decStatus.outputWidth; runStatus->frameHeight = pObj->decStatus.outputHeight;
if(outArgs.outBufsInUseFlag == 1){ inBufDesc.descs[0].buf = (XDAS_Int8 *)prm->inAddr + runStatus->bytesUsed;
status = VIDDEC2_process(pObj->hDecode, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
runStatus->bytesUsed += outArgs.bytesConsumed; if (status != VIDDEC2_EOK) { OSA_ERROR("status=%ld\n", status);// return OSA_EFAIL; }
VIDDEC2_control(pObj->hDecode, XDM_GETSTATUS, &pObj->dynamicParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_GETSTATUS failed with error code = 0x%x , status=%ld\n", pObj->decStatus.extendedError,status);// OSA_fileWriteFile("InputBitstream.dat", (XDAS_Int8 *)prm->inAddr, prm->inDataSize); OSA_printf("\r\n Bytes Consumed so far = %d ",runStatus->bytesUsed); return OSA_EFAIL; }} if(outArgs.displayBufs[0].bufDesc[0].buf == NULL) { return OSA_EFAIL; } else { runStatus->outputBufId = outArgs.outputID[0]-1; // to adjust for +1 done in inputID runStatus->freeBufId = outArgs.freeBufID[0]-1;
if(pObj->curFrameNum==0) { pObj->outStartY = ((Uint32)outArgs.displayBufs[0].bufDesc[0].buf – (Uint32)prm->outAddr)/prm->outOffsetH; pObj->outStartX = ((Uint32)outArgs.displayBufs[0].bufDesc[0].buf – (Uint32)prm->outAddr)%prm->outOffsetH; } runStatus->outStartX = pObj->outStartX; runStatus->outStartY = pObj->outStartY; runStatus->outOffsetH= prm->outOffsetH; runStatus->outOffsetV= prm->outOffsetV; } pObj->curFrameNum++; return OSA_SOK;}
Feng Dong:
解码的文件是什么编码得来的,解365的编码文件怎样?
Ricky Xian:
Hi Feng Dong,
这个264文件就是dm365本机自身编码过来的.