VIDDEC2_process is blocked by H.264 decoder instance on the DM368 IPNC EVM.

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

 

4 Replies