hi,
I use ipnc rdk 5.0 ”moduletest.out alg_vidDec“ to decode h264 stream. some of the decoded YUV sequence is incorrect. see the following attached picture:
the green portion is incorrect. please give me some suggestion about this problem.
my code:
void *ALG_vidDecCreate(ALG_VidDecCreate *create) { ALG_VidDecObj *pObj; pObj = OSA_memAlloc(sizeof(*pObj)); 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; } pObj->params.size = sizeof(VIDDEC2_Params); pObj->params.maxHeight = create->maxHeight; pObj->params.maxWidth = create->maxWidth; pObj->params.maxFrameRate = 30000; pObj->params.maxBitRate = ALG_VID_DEC_MAX_BITRATE; pObj->params.dataEndianness = XDM_BYTE; //pObj->params.forceChromaFormat = 9; //by parry pObj->params.forceChromaFormat = XDM_YUV_420SP; #if 1 // by parry memcpy(&pObj->h264Params, &IH264VDEC_PARAMS, sizeof(pObj->h264Params)); pObj->h264Params.displayDelay = 2; pObj->h264Params.hdvicpHandle = (void*) NULL; pObj->h264Params.disableHDVICPeveryFrame = 1; pObj->h264Params.viddecParams = pObj->params; pObj->h264Params.viddecParams.size = sizeof(pObj->h264Params); #endif /* Create video decoder instance */ //pObj->hDecode = VIDDEC2_create(gALG_hEngine, pObj->algName, &pObj->params); //by parry 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; //by parry 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; //by parry 2010.0908 pObj->dynamicParams.frameOrder = IVIDDEC2_DECODE_ORDER; #if 1 //pObj->dynamicParams.mbDataFlag = 1; this flag is not used by the version of decoder //pObj->dynamicParams.newFrameFlag = 1; this flag is not used by the version of decoder h264DynParams.viddecDynamicParams = pObj->dynamicParams; h264DynParams.resetHDVICPeveryFrame=1; #endif pObj->decStatus.size = sizeof(VIDDEC2_Status); pObj->decStatus.data.buf = NULL; // by parry h264DynParams.viddecDynamicParams = pObj->dynamicParams; h264DynParams.resetHDVICPeveryFrame = 1; //status = VIDDEC2_control(pObj->hDecode, XDM_SETPARAMS, &pObj->dynamicParams, &pObj->decStatus); //by parry 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); #if 1 status = VIDDEC2_control(pObj->hDecode, XDM_GETBUFINFO, &h264DynParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_GETBUFINFO failed, status=%ld\n", status); return OSA_EFAIL; } #ifdef ALG_VID_DEC_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 #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.numBufs = 1; inBufDesc.descs[0].bufSize = prm->inDataSize; inBufDesc.descs[0].buf = (XDAS_Int8 *)prm->inAddr; outBufPtrs[0] = (XDAS_Int8 *)prm->outAddr; outBufPtrs[1] = (XDAS_Int8 *)(prm->outAddr + outBufSizeArray[0]) ; outBufDesc.numBufs = 2; outBufDesc.bufSizes = outBufSizeArray; outBufDesc.bufs = (XDAS_Int8 **) &outBufPtrs; inArgs.size = sizeof(VIDDEC2_InArgs); inArgs.numBytes = prm->inDataSize; inArgs.inputID = prm->inputBufId+1; // must be greater than 0 OSA_printf("/******************/\n " "inArgs.numBytes: %d \n" "inArgs.size: %d\n" "inArgs.inputID: %d\n", inArgs.numBytes ,inArgs.size,inArgs.inputID); //by parry outArgs.size = sizeof(VIDDEC2_OutArgs); outArgs.outBufsInUseFlag = 0; status = VIDDEC2_process(pObj->hDecode, &inBufDesc, &outBufDesc, &inArgs, &outArgs); if (status != VIDDEC2_EOK) { OSA_ERROR("VIDDEC2_process, status=%ld\n", status); //return OSA_EFAIL; } #if 1 status = VIDDEC2_control(pObj->hDecode, XDM_GETSTATUS, &h264DynParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_GETSTATUS failed, status=%ld\n", status); return OSA_EFAIL; } #endif runStatus->bytesUsed = outArgs.bytesConsumed; //by parry must add if (status != VIDDEC2_EOK) { OSA_ERROR("status=%ld\n", status); return OSA_EFAIL; } OSA_printf("outArgs.displayBufs[0].frameType :%d,extendedError:%08x\n",outArgs.displayBufs[0].frameType,pObj->decStatus.extendedError); 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; } #if 1 status = VIDDEC2_control(pObj->hDecode, XDM_GETSTATUS, &h264DynParams, &pObj->decStatus); if (status != VIDDEC2_EOK) { OSA_ERROR("XDM_GETSTATUS failed, status=%ld\n", status); return OSA_EFAIL; } #endif runStatus->frameWidth = pObj->decStatus.outputWidth; runStatus->frameHeight = pObj->decStatus.outputHeight; 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++; #if 0 //save to file yv12 if(pObj->decStatus.extendedError ==0) { char *pBuffer; char *tmpBuf[2]; int size; static char filename1[80]; static FILE* file=NULL; static int count=0; int fWriteSize; int i; char *Luma_data; char *CbCr_data; Luma_data = outArgs.displayBufs[0].bufDesc[0].buf; CbCr_data = outArgs.displayBufs[0].bufDesc[1].buf; //OSA_printBytes(CbCr_data, 512); size = runStatus->frameHeight*runStatus->frameWidth; tmpBuf[0] = gBuffer; tmpBuf[1] =tmpBuf[0]+(size>> 2); OSA_printf("Luma_data:%08x,CbCr_data:%08x,outBufPtrs[0]:%08x,outBufPtrs[1]:%08x,h:%d,w:%d,count:%d\n", Luma_data,CbCr_data,outBufPtrs[0],outBufPtrs[1],outArgs.displayBufs[0].frameHeight, outArgs.displayBufs[0].frameWidth,count); separateCbCrPixels1(CbCr_data, tmpBuf, (runStatus->frameHeight>>1), runStatus->frameWidth, outArgs.displayBufs[0].framePitch); OSA_printf("1\n"); if(file==NULL) { sprintf(filename1, "IMG_%d_%dx%d.YUV420",count, runStatus->frameWidth,runStatus->frameHeight); file = fopen(filename1,"wb"); if(file==NULL) printf("fopen fail\n"); } OSA_printf("2\n"); for(i=0;i<outArgs.displayBufs[0].frameHeight;i++) { fWriteSize=fwrite(Luma_data,1,outArgs.displayBufs[0].frameWidth,file); Luma_data+=outArgs.displayBufs[0].framePitch; } OSA_printf("3\n"); fWriteSize=fwrite(tmpBuf[0],1,(size>>2),file); fWriteSize=fwrite(tmpBuf[1],1,(size>>2),file); //fclose(file); count++; } #endif return OSA_SOK; } int ALG_vidDecTestMain(int argc, char **argv) { int status, bufId, count, whOffset, frameWidth, frameHeight; Uint8 *inVirtAddr=NULL, *inPhysAddr, *outVirtAddr[2], *outPhysAddr[2], *curInAddr; OSA_PrfHndl prfVidDec; Uint32 size=10*MB, fileSize, totalDecSize; void *algVidDecHndl; ALG_VidDecCreate createPrm; ALG_VidDecRunPrm runPrm; ALG_VidDecRunStatus runStatus; char filename[100]; int runCount=0; if(argc>0) { status = DRV_init(); if(status!=OSA_SOK) { OSA_ERROR("DRV_init()\n"); return status; } status = ALG_sysInit(); if(status!=OSA_SOK) { DRV_exit(); return status; } } strcpy(filename, "test.264"); frameWidth = 384; frameHeight = 240; if(argc > 2) { strcpy(filename, argv[2]); if(argc>3) frameWidth = atoi(argv[3]); if(argc>4) frameHeight = atoi(argv[4]); } if(frameWidth==0||frameHeight==0) { OSA_ERROR("Illegal parameters!!!\n"); } inVirtAddr = OSA_cmemAlloc(size, 32); outVirtAddr[0] = OSA_cmemAlloc(2*MB, 32); outVirtAddr[1] = OSA_cmemAlloc(2*MB, 32); inPhysAddr = OSA_cmemGetPhysAddr(inVirtAddr); outPhysAddr[0] = OSA_cmemGetPhysAddr(outVirtAddr[0]); outPhysAddr[1] = OSA_cmemGetPhysAddr(outVirtAddr[1]); memset(outVirtAddr[0], 0xFF, 2*MB); memset(outVirtAddr[1], 0xFF, 2*MB); if( inVirtAddr==NULL || outVirtAddr[0] == NULL || outVirtAddr[1] == NULL || inPhysAddr==NULL || outPhysAddr[0] == NULL || outPhysAddr[1] == NULL ) { OSA_ERROR("OSA_cmemAlloc()\n"); goto error_exit; } status = OSA_fileReadFile(filename, inVirtAddr, size, &fileSize); if(status!=OSA_SOK) { OSA_ERROR("OSA_fileReadFile()\n"); goto error_exit; } //test_again: OSA_prfReset(&prfVidDec); createPrm.codec = ALG_VID_CODEC_H264; createPrm.dataFormat = DRV_DATA_FORMAT_YUV420; createPrm.maxWidth = frameWidth; createPrm.maxHeight = frameHeight; OSA_printf("width:%d,height:%d\n",createPrm.maxWidth,createPrm.maxHeight); algVidDecHndl = ALG_vidDecCreate(&createPrm); if(algVidDecHndl==NULL) { OSA_ERROR("ALG_vidDecCreate()\n"); goto error_exit; } curInAddr = inVirtAddr; totalDecSize = 0; bufId=0; count=0; ALG_vidDecTestDisplayCreate(); whOffset = 0; if(createPrm.codec==ALG_VID_CODEC_H264) whOffset = 48; OSA_printf(" ALG: VidDec: Decode in progress!!!\n"); while(totalDecSize < fileSize) { runPrm.inAddr = curInAddr; runPrm.outAddr = outVirtAddr[bufId]; runPrm.inDataSize = 100*KB; runPrm.outOffsetH = OSA_align(createPrm.maxWidth+whOffset, 32); runPrm.outOffsetV = createPrm.maxHeight+whOffset; runPrm.inputBufId = bufId; OSA_prfBegin(&prfVidDec); status = ALG_vidDecRun(algVidDecHndl, &runPrm, &runStatus); OSA_prfEnd(&prfVidDec, 1); #ifdef ALG_VID_DEC_TEST_DEBUG OSA_printf(" ALG: VidDec: %ld:%ld:%ld:%dx%d:%ld: %ld bytes (%ld, %ld),bob,offsetH:%d,offsetV:%d,totalDecSize:%d,fileSize:%d\n", runStatus.freeBufId, runPrm.inputBufId, runStatus.outputBufId, runStatus.frameWidth, runStatus.frameHeight, runStatus.isKeyFrame, runStatus.bytesUsed, runStatus.outStartX, runStatus.outStartY, runPrm.outOffsetH, runPrm.outOffsetV, totalDecSize, fileSize ); #endif if(status==OSA_SOK) { //runStatus.bytesUsed += 3; curInAddr += runStatus.bytesUsed; totalDecSize += runStatus.bytesUsed; } else { OSA_printf(" ALG: VidDec: ALG_vidDecRun() ERROR !!!\n"); break; } #if 1 ALG_vidDecTestDisplayCopy( outVirtAddr[runStatus.outputBufId], outPhysAddr[runStatus.outputBufId], &runStatus ); #endif bufId ^= 1; count++; if(count>10000) break; } OSA_printf(" ALG: VidDec: Decode DONE!!!\n"); //ALG_vidDecTestDisplayDelete(); ALG_vidDecDelete(algVidDecHndl); OSA_prfPrint(&prfVidDec, "VID DEC", 0); runCount++; //if(runCount<10) // goto test_again; error_exit: if(inVirtAddr) OSA_cmemFree(inVirtAddr); if(outVirtAddr[0]) OSA_cmemFree(outVirtAddr[0]); if(outVirtAddr[1]) OSA_cmemFree(outVirtAddr[1]); if(argc>0) { ALG_sysExit(); DRV_exit(); } return status; }