Hi.
I have a problem on the DM368 IPNC EVM.
Using DVSDK version is below.
- DVSDK : 2_10_01_18
- H.264 Decoder : 2.0.0.13
The problem is that VIDDEC2_process() blocked at a first frame while h264 decoding.
H264 stream well decode on the windows S/W players.
I don't know why VIDDEC2_process() blocked.
can anybody help me?
Test stream information.
- H264 stream was encoded by same DM368 IPNC.
- resolution : 640x480
- Bit rate : 4.5Mbps
- Frame rate : 30fps
Used algorithem in the algorithm server.
- g711enc
-h264enc
-h264dec
-ktnf
-iprun
cmem structure.
insmod cmemk.ko phys_start=0x83000000 phys_end=0x88000000 allowOverlap=1 phys_start_1=0x00001000 phys_end_1=0x00008000 pools_1=1x28672
1. below is messages when CE_DEBUG=2.
**********************************************
@20,298,676us: [+0 T:0x47c15490] ti.sdo.ce.video2.VIDDEC2 - VIDDEC2_control> Enter (handle=0x484e50, id=1, dynParams=0x47c14d44 (size=0x28), status=0x484cd4 (size=0xb8)
@20,298,929us: [+5 T:0x47c15490] CV - VISA_enter(visa=0x484e50): algHandle = 0x4845e0
@20,299,050us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_activate> Enter(alg=0x4845e0)
@20,299,245us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_activate> Exit
@20,299,554us: [+5 T:0x47c15490] CV - VISA_exit(visa=0x484e50): algHandle = 0x4845e0
@20,299,669us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_deactivate> Enter(alg=0x4845e0)
@20,299,807us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_deactivate> Exit
@20,299,918us: [+0 T:0x47c15490] ti.sdo.ce.video2.VIDDEC2 - VIDDEC2_control> Exit (handle=0x484e50, retVal=0x0)
@20,300,030us: [+0 T:0x47c15490] ti.sdo.ce.video2.VIDDEC2 - VIDDEC2_control> Enter (handle=0x484e50, id=5, dynParams=0x484da8 (size=0x1c), status=0x484cd4 (size=0xb8)
@20,300,156us: [+5 T:0x47c15490] CV - VISA_enter(visa=0x484e50): algHandle = 0x4845e0
@20,300,254us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_activate> Enter(alg=0x4845e0)
@20,300,380us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_activate> Exit
@20,300,499us: [+5 T:0x47c15490] CV - VISA_exit(visa=0x484e50): algHandle = 0x4845e0
@20,300,602us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_deactivate> Enter(alg=0x4845e0)
@20,300,733us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_deactivate> Exit
@20,300,840us: [+0 T:0x47c15490] ti.sdo.ce.video2.VIDDEC2 - VIDDEC2_control> Exit (handle=0x484e50, retVal=0x0)
ALG: VidDec: XDM_GETBUFINFO: min out bufs:2,size:871424 435712
VIDDEC2_process() enter
@20,301,062us: [+0 T:0x47c15490] ti.sdo.ce.video2.VIDDEC2 - VIDDEC2_process> Enter (handle=0x484e50, inBufs=0x47c14c80, outBufs=0x47c14d80, inArgs=0x47c14d8c, outArgs=0x47c144e0)
@20,301,199us: [+5 T:0x47c15490] CV - VISA_enter(visa=0x484e50): algHandle = 0x4845e0
@20,301,297us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_activate> Enter(alg=0x4845e0)
@20,301,423us: [+0 T:0x47c15490] ti.sdo.ce.alg.Algorithm - Algorithm_activate> Exit
-- No more message. decoding thread is blocked .
======================================================================
2. My source code.
**********************************************
/* algorithem open */
ALG_VidDecCreate createPrm;
ALG_VidDecRunPrm runPrm;
ALG_VidDecRunStatus runStatus;
whOffset = 96;
maxWidth = 640;
maxHeight = 480;
algVidDecHndl = NULL;
ibufVirtAddr = OSA_cmemAlloc(0x00200000, 32); // 2MB
ibufPhysAddr = OSA_cmemGetPhysAddr(ibufVirtAddr);
if( ibufVirtAddr == NULL || ibufPhysAddr == NULL ) goto error_proc;
for( i=0; i<NUMOF_OUTBUF; i++ )
{
obufVirtAddr[i] = OSA_cmemAlloc(0x00400000, 32); // 4MB
obufPhysAddr[i] = OSA_cmemGetPhysAddr(obufVirtAddr[i]);
if( obufVirtAddr[i] == NULL || obufPhysAddr[i] == NULL )
goto error_proc;
}
createPrm.codec = ALG_VID_CODEC_H264;
createPrm.dataFormat = DRV_DATA_FORMAT_YUV420;
createPrm.maxWidth = maxWidth;
createPrm.maxHeight = maxHeight;
algVidDecHndl = ALG_vidDecCreate(&createPrm);
if( algVidDecHndl==NULL )
{
IVNET_error("ALG_vidDecCreate() failed!\n");
goto error_proc;
}
// -------------
/* run decoding */
// after read one frame stream from a file.
runPrm.inAddr = ibufVirtAddr;
runPrm.outAddr = obufVirtAddr[0] + VIDEO_BUF_HEADER_SIZE;
runPrm.inDataSize = streamSize;
runPrm.outOffsetH = OSA_align( 640+ whOffset, 32);
runPrm.outOffsetV = 480 + whOffset;
runPrm.inputBufId = 0;
status = ALG_vidDecRun(gAviPlayerParm.algVidDecHndl, &gAviPlayerParm.runPrm, &gAviPlayerParm.runStatus);
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;
}
memcpy(&pObj->h264Params, &IH264VDEC_PARAMS, sizeof(pObj->h264Params));
pObj->params.size = sizeof(VIDDEC2_Params);
pObj->params.maxHeight = 480;
pObj->params.maxWidth = 640;
pObj->params.maxFrameRate = 0;
pObj->params.maxBitRate = 0x800000; // 8 Mbit
pObj->params.dataEndianness = XDM_BYTE;
pObj->params.forceChromaFormat = XDM_YUV_420SP;
pObj->h264Params.displayDelay = 0;
pObj->h264Params.levelLimit = 0;
pObj->h264Params.hdvicpHandle = (void*) NULL;
pObj->h264Params.disableHDVICPeveryFrame = 0;
pObj->h264Params.frame_closedloop_flag = 1; //reduce memory use of decoder
pObj->h264Params.inputDataMode = 1; // 0: Processing of one slice, 1: Processing of entire frame data
pObj->h264Params.sliceFormat = 1; // 0: Output data in NAL stream format, 1: Output data in BYTE stream format
pObj->h264Params.viddecParams = pObj->params;
pObj->h264Params.viddecParams.size = sizeof(IH264VDEC_Params); /*sizeof(pObj->h264Params);*/
/* Create video decoder instance */
pObj->hDecode = VIDDEC2_create(gALG_hEngine, pObj->algName, (VIDDEC2_Params*)(&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;
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, (VIDDEC2_DynamicParams*)(&h264DynParams), &pObj->decStatus); // KDS 2012.2.2 M
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;
}
#if 1
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; // same as frame size.
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;
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", (unsigned int)pObj->decStatus.extendedError,status);
// OSA_fileWriteFile("InputBitstream.dat", (XDAS_Int8 *)prm->inAddr, prm->inDataSize);
OSA_printf("\r\n Bytes Consumed so far = %d ",(int)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;
}