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.

ipnc rdk 5.0 h264 decode problem

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

  • Hi,

    What kind of stream it is? does it have B frames and what is height? If height is not multiple of 16 decoder will pad and decode it. Do you handling this case?.

    I suggest you to run standalone testapp provided with decoder to confirm decoder functionality for given stream.

    Thanks,

    Veeranna

  • Whether the economy is in great or poor shape, having a great credit score can save you hundreds of thousands over the life of a mortgage. It can save you thousands in credit card interest payments, thousands in car payments, and even thousands in student loan payments. There is a reason credit restoration will always be needed and that is the sheer number or errors contained on reports themselves and the amount of time it takes to dispute such errors.