This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

dm365平台, 720P解码h264文件, 图像质量问题



专家好, 我遇到如下问题: 

软件架构为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帧): 

  • 代码: ( 已经根据网上其他资料修改过.)

    //----------- 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;
    }

  • //-------------解压功能

    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;
    }

  • 解码的文件是什么编码得来的,解365的编码文件怎样?

  • Hi Feng Dong,

    这个264文件就是dm365本机自身编码过来的.