Example #1
0
DvevmStRetCode
dvtb_MPEG4Enc1Control(DvevmStMPEG4Enc1Info *ve)
{
    int status = -1, i = 0;
    DvevmStRetCode retCode = DVEVM_ST_SUCCESS;

    ASSERT(ve != NULL);
    ASSERT(ve->ceHdl != NULL);

    status = VIDENC1_control(ve->venc1Hdl, ve->venc1Cmd, (IVIDENC1_DynamicParams *) (&ve->venc1DynParams), (IVIDENC1_Status *) (&ve->venc1Status));
    if (VIDENC1_EOK != status)
    {
        SYS_ERROR("Error (%d), Codec Error (%d) in Video Encoder Control\n", status, (int) ve->venc1Status.videncStatus.extendedError);
        retCode = DVEVM_ST_FAIL;
    }
    else
    {
        if (XDM_GETBUFINFO == ve->venc1Cmd)
        {
            ve->inBuf.numBufs = ve->venc1Status.videncStatus.bufInfo.minNumInBufs;
            for (i = 0; i < ve->inBuf.numBufs; i++)
                ve->inBuf.bufSizes[i] = ve->venc1Status.videncStatus.bufInfo.minInBufSize[i];

            ve->outBuf.numBufs = ve->venc1Status.videncStatus.bufInfo.minNumOutBufs;
            for (i = 0; i < ve->outBuf.numBufs; i++)
                ve->outBuf.bufSizes[i] = ve->venc1Status.videncStatus.bufInfo.minOutBufSize[i];

        }
        else if(XDM_GETSTATUS == ve->venc1Cmd)
        {
            if(ve->venc1Status.videncStatus.extendedError)
            {
                if(XDM_ISFATALERROR(ve->venc1Status.videncStatus.extendedError))
                {
                    SYS_ERROR("Exiting: Encode Failed with a Codec fatal error %x.\n", (int) ve->venc1Status.videncStatus.extendedError);
                    retCode = DVEVM_ST_FAIL;
                }
                else
                    SYS_DEBUG("Continue: Codec generated an non fatal error %x.\n", (int) ve->venc1Status.videncStatus.extendedError);
            }
        }
    }
    return retCode;
}
Example #2
0
XDAS_Int32 ALG_vidEncSetDynamicParams(ALG_VidEncObj *pObj)
{
  XDAS_Int32 status;

  if(pObj==NULL)
    return OSA_EFAIL;

  //test only
  pObj->createPrm.qpinit 		= 36;
  pObj->createPrm.qpmin 		= 30;
  pObj->createPrm.qpmax 		= 50;
  pObj->createPrm.packetsize 	= 100;
  
  if(pObj->createPrm.codec==ALG_VID_CODEC_MJPEG) {

	OSA_mutexLock(&vnf_imcop_lock);
	OSA_mutexLock(&vicp_imcop_lock);
    ALG_jpgEncSetQvalue(pObj->hJpgEncode, pObj->createPrm.qValue);
    OSA_mutexUnlock(&vnf_imcop_lock);
	OSA_mutexUnlock(&vicp_imcop_lock);

    return OSA_SOK;
  }

  if(pObj->createPrm.codec==ALG_VID_CODEC_H264)
  {
    memcpy(&pObj->dynamicParams_h264, &H264VENC_TI_IH264VENC_DYNAMICPARAMS, sizeof(pObj->dynamicParams_h264));
    pObj->dynamicParams.size = sizeof(pObj->dynamicParams_h264);
  }
  else if(pObj->createPrm.codec==ALG_VID_CODEC_MPEG4)
  {
	pObj->dynamicParams.size = sizeof(pObj->dynamicParams_mpeg4);
  }
  else
  {
    pObj->dynamicParams.size = sizeof(pObj->dynamicParams);
  }

  pObj->dynamicParams.inputHeight         = pObj->createPrm.height;
  pObj->dynamicParams.inputWidth          = pObj->createPrm.width;
  pObj->dynamicParams.targetBitRate       = pObj->createPrm.bitrate < 0 ? 0 : pObj->createPrm.bitrate;
  pObj->dynamicParams.generateHeader      = XDM_ENCODE_AU;
  pObj->dynamicParams.captureWidth        = pObj->createPrm.offsetH;
  pObj->dynamicParams.targetFrameRate     = pObj->createPrm.framerate;
  pObj->dynamicParams.refFrameRate        = pObj->createPrm.framerate;
  pObj->dynamicParams.interFrameInterval  = 0;
  pObj->dynamicParams.mbDataFlag		  = XDAS_FALSE;

  switch(pObj->createPrm.codec) {
    case ALG_VID_CODEC_H264:
 	  pObj->dynamicParams.intraFrameInterval  				  	= 0;
  	  pObj->dynamicParams.forceFrame 		  				  	= IVIDEO_NA_FRAME;//(pObj->createPrm.forceKeyFrame==TRUE)?IVIDEO_IDR_FRAME:IVIDEO_NA_FRAME;

	  pObj->dynamicParams_h264.sliceSize					  	= ((pObj->createPrm.height/16)*pObj->createPrm.packetsize)/100;
	  pObj->dynamicParams_h264.airRate						  	= 0;
      pObj->dynamicParams_h264.intraFrameQP					  	= pObj->createPrm.qpinit;
      pObj->dynamicParams_h264.interPFrameQP				  	= pObj->createPrm.qpinit;
      pObj->dynamicParams_h264.initQ						  	= pObj->createPrm.qpinit;
      pObj->dynamicParams_h264.rcQMax						  	= (pObj->createPrm.qpmax>51)?51:pObj->createPrm.qpmax;
      pObj->dynamicParams_h264.rcQMin						  	= (pObj->createPrm.qpmin<=0)?1:pObj->createPrm.qpmin;
      pObj->dynamicParams_h264.rcQMaxI						  	= (pObj->createPrm.qpmax>51)?51:pObj->createPrm.qpmax;
      pObj->dynamicParams_h264.rcQMinI						  	= (pObj->createPrm.qpmin<=0)?1:pObj->createPrm.qpmin;
	  pObj->dynamicParams_h264.maxDelay						  	= 2000;
	  pObj->dynamicParams_h264.aspectRatioX 				  	= 1;
	  pObj->dynamicParams_h264.aspectRatioY 				  	= 1;
	  pObj->dynamicParams_h264.lfDisableIdc					  	= 0;
   	  pObj->dynamicParams_h264.enableBufSEI					  	= 0;    /*!< Enable Buffering period SEI */
  	  pObj->dynamicParams_h264.enablePicTimSEI				  	= 1;  	/*!< Enable Picture Timing SEI */
 	  pObj->dynamicParams_h264.perceptualRC                   	= 1;
      pObj->dynamicParams_h264.idrFrameInterval               	= 100;//pObj->createPrm.keyFrameInterval;
      pObj->dynamicParams_h264.mvSADoutFlag 				  	= pObj->createPrm.mbMvOutEnable;
	  pObj->dynamicParams_h264.resetHDVICPeveryFrame		  	= pObj->createPrm.resetHDVICP;
      pObj->dynamicParams_h264.enableROI					  	= 1;
	  pObj->dynamicParams_h264.metaDataGenerateConsume        	= 0;
	  pObj->dynamicParams_h264.maxBitrateCVBR				  	= 0;
	  pObj->dynamicParams_h264.interlaceRefMode				  	= 0;
	  pObj->dynamicParams_h264.enableGDR						= 0;
	  pObj->dynamicParams_h264.GDRduration						= 0;
	  pObj->dynamicParams_h264.GDRinterval						= 0;
	  pObj->dynamicParams_h264.LongTermRefreshInterval			= 0;
	  pObj->dynamicParams_h264.UseLongTermFrame					= 0;
	  pObj->dynamicParams_h264.SetLongTermFrame					= 0;
	  pObj->dynamicParams_h264.CustomScaleMatrix_Buffer			= NULL;
	  pObj->dynamicParams_h264.CVBRsensitivity					= 0;
	  pObj->dynamicParams_h264.CVBRminbitrate					= 0;
	  pObj->dynamicParams_h264.LBRmaxpicsize					= 0;
	  pObj->dynamicParams_h264.LBRminpicsize					= 0;
	  pObj->dynamicParams_h264.LBRskipcontrol					= 0x050004;
	  pObj->dynamicParams_h264.maxHighCmpxIntCVBR			  	= 0;
	  pObj->dynamicParams_h264.disableMVDCostFactor			  	= 0;
	  pObj->dynamicParams_h264.putDataGetSpaceFxn			  	= NULL;
	  pObj->dynamicParams_h264.dataSyncHandle				  	= NULL;

	  pObj->dynamicParams_h264.VUI_Buffer->timingInfoPresentFlag= 1;
	  pObj->dynamicParams_h264.VUI_Buffer->timeScale 			= 240*(pObj->createPrm.framerate/1000);
	  pObj->dynamicParams_h264.VUI_Buffer->numUnitsInTicks 		= 120;

	  /* these three fields are not set as they are reserved */
	  /* intraSliceNum, meMultiPart and intraThrQF */
	  switch(pObj->createPrm.rateControlType) {
		case ALG_VID_ENC_RATE_CONTROL_CBR:
		  pObj->dynamicParams_h264.rcAlgo     = 5;
		  break;
		default:
		case ALG_VID_ENC_RATE_CONTROL_VBR:
		  pObj->dynamicParams_h264.rcAlgo     = 5;//1;
		  break;
		case ALG_VID_ENC_RATE_CONTROL_RCOFF:
		  pObj->dynamicParams_h264.rcAlgo     = 2;
		  break;
	  }
	  if( pObj->dynamicParams_h264.sliceSize > (pObj->createPrm.height/16) )
	  {
		pObj->dynamicParams_h264.sliceSize = (pObj->createPrm.height/16);
	  }

      break;

    case ALG_VID_CODEC_MPEG4:

	  pObj->dynamicParams.inputHeight 		  	= pObj->createPrm.height;
	  pObj->dynamicParams.inputWidth		  	= pObj->createPrm.offsetH;
	  pObj->dynamicParams.captureWidth        	= 0;
 	  pObj->dynamicParams.intraFrameInterval  	= pObj->createPrm.keyFrameInterval;
  	  pObj->dynamicParams.forceFrame 		  	= (pObj->createPrm.forceKeyFrame==TRUE)?IVIDEO_I_FRAME:IVIDEO_NA_FRAME;

	  pObj->dynamicParams_mpeg4.numMBRows      	= ((pObj->createPrm.height/16)*pObj->createPrm.packetsize)/100;
	  pObj->dynamicParams_mpeg4.initQ          	= pObj->createPrm.qpinit;
	  pObj->dynamicParams_mpeg4.rcQMin         	= (pObj->createPrm.qpmin<=1)?2:pObj->createPrm.qpmin;
	  pObj->dynamicParams_mpeg4.rcQMax         	= (pObj->createPrm.qpmax>31)?31:pObj->createPrm.qpmax;
	  pObj->dynamicParams_mpeg4.rateFix        	= 0;
	  pObj->dynamicParams_mpeg4.rateFixRange   	= 2;
	  pObj->dynamicParams_mpeg4.interFrameQP   	= 0;
	  pObj->dynamicParams_mpeg4.intraFrameQP   	= 0;
	  if( pObj->dynamicParams_mpeg4.numMBRows > (pObj->createPrm.height/16) )
	  {
		pObj->dynamicParams_mpeg4.numMBRows = (pObj->createPrm.height/16);
	  }

	  if((pObj->createPrm.encodePreset&ALG_VID_ENC_PRESET_MASK) == ALG_VID_ENC_PRESET_AUTO)
	  {
		  pObj->dynamicParams_mpeg4.intraAlgo      	= IMP4VENC_INTRA_INTER_DECISION_LQ_HP;
		  pObj->dynamicParams_mpeg4.skipMBAlgo     	= IMP4VENC_SKIP_MB_LQ_HP;
		  pObj->dynamicParams_mpeg4.unrestrictedMV 	= IMP4VENC_UMV_LQ_HP; //(pObj->createPrm.mode == ALG_VID_ENC_MODE_FAST_FPS) ? IMP4VENC_UMV_LQ_HP:IMP4VENC_UMV_HQ_LP;
		  if(pObj->createPrm.width<=720) // for D1 or QVGA
			pObj->dynamicParams_mpeg4.meAlgo		= IMP4VENC_ME_MQ_MP;
		  else if(pObj->createPrm.width==1280) // for 720P or SXVGA
			pObj->dynamicParams_mpeg4.meAlgo		= IMP4VENC_ME_HQ_MP;
		  else // 1080P or others.
			pObj->dynamicParams_mpeg4.meAlgo		= IMP4VENC_ME_LQ_HP;
	  }
	  else {
		  pObj->dynamicParams_mpeg4.intraAlgo      	= IMP4VENC_INTRA_INTER_DECISION_HQ_LP;
		  pObj->dynamicParams_mpeg4.skipMBAlgo     	= IMP4VENC_SKIP_MB_HQ_LP;
		  pObj->dynamicParams_mpeg4.unrestrictedMV 	= IMP4VENC_UMV_LQ_HP; //switched off due to UMV bug
		  pObj->dynamicParams_mpeg4.meAlgo			= IMP4VENC_ME_HQ_LP;
	  }

	  pObj->dynamicParams_mpeg4.mvDataEnable = pObj->createPrm.mbMvOutEnable;

      break;
    case ALG_VID_CODEC_MJPEG:
			pObj->createPrm.mbMvOutEnable = 0;
      break;
  }

  #ifdef ALG_VID_ENC_DEBUG
  OSA_printf(" ALG: VidEnc: DynamicParams: bitrate = %ld bps, Key-frame-interval = %ld\n",
    	pObj->dynamicParams.targetBitRate,
    	pObj->dynamicParams_h264.idrFrameInterval
    );
  #endif

  if(pObj->createPrm.codec!=ALG_VID_CODEC_H264) {
	 OSA_mutexLock(&vnf_imcop_lock);
	 OSA_mutexLock(&vicp_imcop_lock);
  }
  else {
    if (pObj->params_h264.enableDDRbuff==0)
      OSA_mutexLock(&vicp_imcop_lock);
  }

  /* Set video encoder dynamic parameters */
  pObj->encStatus.size = sizeof(VIDENC1_Status);
  pObj->encStatus.data.buf = NULL;
  status = VIDENC1_control(pObj->hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)&pObj->dynamicParams, &pObj->encStatus);

  if (status != VIDENC1_EOK) {
    OSA_ERROR("XDM_SETPARAMS failed, status=%ld\n", status);
    return OSA_EFAIL;
  }

  pObj->encStatus.data.buf = NULL;

  status = VIDENC1_control(pObj->hEncode, XDM_GETBUFINFO, (VIDENC1_DynamicParams*)&pObj->dynamicParams, &pObj->encStatus);

  if (status != VIDENC1_EOK) {
      OSA_ERROR("XDM_GETBUFINFO failed, status=%ld\n", status);
      return OSA_EFAIL;
  }

  #ifdef ALG_VID_ENC_DEBUG
  	OSA_printf(" ALG: VidEnc: mbMvOutEnable =%d \n",(int)pObj->createPrm.mbMvOutEnable);
	OSA_printf(" ALG: VidEnc: encStatus.bufInfo.minNumOutBufs is %d\n", (int)pObj->encStatus.bufInfo.minNumOutBufs);					//2
	OSA_printf(" ALG: VidEnc: encStatus.bufInfo.minOutBufSize[0] is %d\n", (int)pObj->encStatus.bufInfo.minOutBufSize[0]);
	OSA_printf(" ALG: VidEnc: encStatus.bufInfo.minOutBufSize[1] is %d\n", (int)pObj->encStatus.bufInfo.minOutBufSize[1]);
  	OSA_printf(" ALG: VidEnc: XDM_GETBUFINFO: min in bufs:%ld buf(0):%ld buf(1):%ld\n", pObj->encStatus.bufInfo.minNumInBufs,  																																										pObj->encStatus.bufInfo.minInBufSize[0],  																																										pObj->encStatus.bufInfo.minInBufSize[1]);
  #endif

	if( pObj->createPrm.mbMvOutEnable )
	{
		if( pObj->encStatus.bufInfo.minNumOutBufs > 1 )
		{
			if( pObj->MV_Size == 0 )
			{

				pObj->MV_Size = pObj->encStatus.bufInfo.minOutBufSize[1];
				pObj->MV_Addr = OSA_cmemAlloc(pObj->MV_Size,32);
				if( pObj->MV_Addr == NULL )
				{
					OSA_ERROR("OSA_cmemAlloc failed \n");
		      		return OSA_EFAIL;
				}

				#ifdef ALG_VID_ENC_DEBUG
				OSA_printf(" ALG: VidEnc: pObj->MV algName =%s \n",pObj->algName);
			    OSA_printf(" ALG: VidEnc: pObj->MV_Size =%d \n",(int)pObj->MV_Size);
				OSA_printf(" ALG: VidEnc: Default is Disable MV data output \n");
				#endif
				/* Default is Disable MV data output */
 				pObj->createPrm.mbMvOutEnable = 0;
 				switch(pObj->createPrm.codec)
 				{
 					case ALG_VID_CODEC_H264:
						pObj->dynamicParams_h264.mvSADoutFlag = 0;
 					break;
 					case ALG_VID_CODEC_MPEG4:
 						pObj->dynamicParams_mpeg4.mvDataEnable = 0;
 					break;
 				}
 				status = VIDENC1_control(pObj->hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)&pObj->dynamicParams, &pObj->encStatus);
				if (status != VIDENC1_EOK) {
					OSA_ERROR("XDM_SETPARAMS failed, status=%ld\n", status);
					return OSA_EFAIL;
				}
			}
		}else{
			OSA_ERROR("pObj->encStatus.bufInfo.minNumOutBufs is incorrect for MV_DATA \n");
	    	return OSA_EFAIL;
		}
	}

	/* Reset Force Frame Flag */
	pObj->createPrm.forceKeyFrame = FALSE;

	if(pObj->createPrm.codec!=ALG_VID_CODEC_H264){
		OSA_mutexUnlock(&vnf_imcop_lock);
		OSA_mutexUnlock(&vicp_imcop_lock);
	} else {
	  if (pObj->params_h264.enableDDRbuff== 0)
      	OSA_mutexUnlock(&vicp_imcop_lock);
   }

   return OSA_SOK;
}
Example #3
0
/*
 *  ======== encode_decode ========
 */
static Void encode_decode(VIDENC1_Handle enc, VIDDEC2_Handle dec, FILE *in,
    FILE *out)
{
    Int                         n;
    Int32                       status;

    VIDDEC2_InArgs              decInArgs;
    VIDDEC2_OutArgs             decOutArgs;
    VIDDEC2_DynamicParams       decDynParams;
    VIDDEC2_Status              decStatus;

    VIDENC1_InArgs              encInArgs;
    VIDENC1_OutArgs             encOutArgs;
    VIDENC1_DynamicParams       encDynParams;
    VIDENC1_Status              encStatus;

    IVIDEO1_BufDescIn           encInBufDesc;

    XDM_BufDesc                 encOutBufDesc;
    XDAS_Int8                  *encoded[XDM_MAX_IO_BUFFERS];
    XDAS_Int32                  encBufSizes[XDM_MAX_IO_BUFFERS];

    XDM1_BufDesc                decInBufDesc;

    XDM_BufDesc                 decOutBufDesc;
    XDAS_Int8                  *dst[XDM_MAX_IO_BUFFERS];
    XDAS_Int32                  outBufSizes[XDM_MAX_IO_BUFFERS];

    /* clear and initialize the buffer descriptors */
    memset(encoded, 0, sizeof(encoded[0]) * XDM_MAX_IO_BUFFERS);
    memset(dst,     0, sizeof(dst[0])     * XDM_MAX_IO_BUFFERS);

    encoded[0] = encodedBuf;
    dst[0]     = outBuf;

    encInBufDesc.numBufs = encOutBufDesc.numBufs = decInBufDesc.numBufs =
        decOutBufDesc.numBufs = 1;

    encOutBufDesc.bufSizes  = encBufSizes;
    decOutBufDesc.bufSizes  = outBufSizes;

    encInBufDesc.bufDesc[0].bufSize = encBufSizes[0] =
        decInBufDesc.descs[0].bufSize = outBufSizes[0] = NSAMPLES;

    encInBufDesc.bufDesc[0].buf = inBuf;
    encOutBufDesc.bufs = encoded;
    decInBufDesc.descs[0].buf = encoded[0];
    decOutBufDesc.bufs     = dst;

    encInBufDesc.frameWidth     = 0;  /* TODO */
    encInBufDesc.frameHeight    = 0;  /* TODO */
    encInBufDesc.framePitch     = 0;  /* TODO */

    /* initialize all "sized" fields */
    encInArgs.size    = sizeof(encInArgs);
    decInArgs.size    = sizeof(decInArgs);
    encOutArgs.size   = sizeof(encOutArgs);
    decOutArgs.size   = sizeof(decOutArgs);
    encDynParams.size = sizeof(encDynParams);
    decDynParams.size = sizeof(decDynParams);
    encStatus.size    = sizeof(encStatus);
    decStatus.size    = sizeof(decStatus);

    /*
     * Note that we use versionBuf in both the encoder and decoder.  In this
     * application, this is okay, as there is always only one user of
     * the buffer.  Not all applications can make this assumption.
     */
    encStatus.data.buf     = decStatus.data.buf     = versionBuf;
    encStatus.data.bufSize = decStatus.data.bufSize = MAXVERSIONSIZE;

    /* if the codecs support it, dump their versions */
    status = VIDDEC2_control(dec, XDM_GETVERSION, &decDynParams, &decStatus);
    Log_print1(Diags_USER1, "[+1] Decoder version:  %s",
            (IArg)((status == VIDDEC2_EOK ? ((char *)decStatus.data.buf) :
            "[unknown]")));

    status = VIDENC1_control(enc, XDM_GETVERSION, &encDynParams, &encStatus);
    Log_print1(Diags_USER1, "[+1] Encoder version:  %s",
            (IArg)((status == VIDENC1_EOK ? ((char *)encStatus.data.buf) :
            "[unknown]")));

    /*
     * This app expects the encoder to provide 1 buf in and get 1 buf out,
     * and the buf sizes of the in and out buffer must be able to handle
     * NSAMPLES bytes of data.
     */
    status = VIDENC1_control(enc, XDM_GETSTATUS, &encDynParams, &encStatus);
    if (status != VIDENC1_EOK) {
        /* failure, report error and exit */
        Log_print1(Diags_USER7, "[+7] encode control status = %ld",
                (IArg)status);
        return;
    }

    /* Validate this encoder codec will meet our buffer requirements */
    if ((encInBufDesc.numBufs < encStatus.bufInfo.minNumInBufs) ||
        (IFRAMESIZE < encStatus.bufInfo.minInBufSize[0]) ||
        (encOutBufDesc.numBufs < encStatus.bufInfo.minNumOutBufs) ||
        (EFRAMESIZE < encStatus.bufInfo.minOutBufSize[0])) {

        /* failure, report error and exit */
        Log_print0(Diags_USER7, "[+7] Error:  encoder codec feature conflict");
        return;
    }

    status = VIDDEC2_control(dec, XDM_GETSTATUS, &decDynParams, &decStatus);
    if (status != VIDDEC2_EOK) {
        /* failure, report error and exit */
        Log_print1(Diags_USER7, "[+7] decode control status = %ld",
                (IArg)status);
        return;
    }

    /* Validate this decoder codec will meet our buffer requirements */
    if ((decInBufDesc.numBufs < decStatus.bufInfo.minNumInBufs) ||
        (EFRAMESIZE < decStatus.bufInfo.minInBufSize[0]) ||
        (decOutBufDesc.numBufs < decStatus.bufInfo.minNumOutBufs) ||
        (OFRAMESIZE < decStatus.bufInfo.minOutBufSize[0])) {

        /* failure, report error and exit */
        Log_print0(Diags_USER7,
                "[+7] App-> ERROR: decoder does not meet buffer requirements.");
        return;
    }

    /*
     * Read complete frames from in, encode, decode, and write to out.
     */
    for (n = 0; fread(inBuf, IFRAMESIZE, 1, in) == 1; n++) {

#ifdef CACHE_ENABLED
#if defined(xdc_target__isaCompatible_64P) || \
    defined(xdc_target__isaCompatible_64T)
        /*
         *  fread() on this processor is implemented using CCS's stdio, which
         *  is known to write into the cache, not physical memory.  To meet
         *  XDAIS DMA Rule 7, we must writeback the cache into physical
         *  memory.  Also, per DMA Rule 7, we must invalidate the buffer's
         *  cache before providing it to any xDAIS algorithm.
         */
        Memory_cacheWbInv(inBuf, IFRAMESIZE);
#else
#error Unvalidated config - add appropriate fread-related cache maintenance
#endif
        /* Per DMA Rule 7, our output buffer cache lines must be cleaned */
        Memory_cacheInv(encodedBuf, EFRAMESIZE);
#endif

        Log_print1(Diags_USER1, "[+1] App-> Processing frame %d...", (IArg)n);

        /*
         * Encode the frame.
         *
         * Note, inputID == 0 is an error.  This example doesn't account
         * for the case where 'n + 1' wraps to zero.
         */
        encInArgs.inputID = n + 1;
        status = VIDENC1_process(enc, &encInBufDesc, &encOutBufDesc, &encInArgs,
            &encOutArgs);

        Log_print2(Diags_USER2,
                "[+2] App-> Encoder frame %d process returned - 0x%x)",
                (IArg)n, (IArg)status);

        if (status != VIDENC1_EOK) {
            Log_print3(Diags_USER7,
                    "[+7] App-> Encoder frame %d processing FAILED, status = 0x%x, "
                    "extendedError = 0x%x",
                    (IArg)n, (IArg)status, (IArg)(encOutArgs.extendedError));
            break;
        }

        /*
         * So far, so good.  Validate our assumption that the encoder
         * provided encodedBuf as it's encOutArgs->encodedBuf.buf.  If
         * that's not the case, we may be dealing with a codec that's
         * giving us out of order frames... and this simple app
         * doesn't support that.
         */
        if (encOutArgs.encodedBuf.buf != encodedBuf) {
            Log_print0(Diags_USER7,
                    "[+7] App-> Internal error.  Unsupported encoder");
            break;
        }

#ifdef CACHE_ENABLED
        /*
         * Conditionally writeback the encoded buf from the previous
         * call.  Also, as encodedBuf is an inBuf to the next process
         * call, conditionally invalidate it as well.
         */
        if (XDM_ISACCESSMODE_WRITE(encOutArgs.encodedBuf.accessMask)) {
            Memory_cacheWbInv(encodedBuf, EFRAMESIZE);
        }

        /*
         * Per DMA Rule 7, our output buffer cache lines (for the
         * upcoming decoder) must be cleaned.
         */
        Memory_cacheInv(outBuf, OFRAMESIZE);
#endif

        /* decode the frame */
        decInArgs.numBytes = EFRAMESIZE;
        decInArgs.inputID = 1;  /* typically this varies by each frame */
        status = VIDDEC2_process(dec, &decInBufDesc, &decOutBufDesc,
            &decInArgs, &decOutArgs);

        Log_print2(Diags_USER2,
                "[+2] App-> Decoder frame %d process returned - 0x%x)",
                (IArg)n, (IArg)status);

        if (status != VIDDEC2_EOK) {
            Log_print2(Diags_USER7,
                    "[+7] App-> Decoder frame %d processing FAILED, status ="
                    " 0x%x", (IArg)n, (IArg)status);
            break;
        }

        /* again, validate our assumption that we don't get out-of-order bufs */
        if (decOutArgs.decodedBufs.bufDesc[0].buf != outBuf) {
            Log_print0(Diags_USER7,
                    "[+7] App-> Internal error.  Unsupported decoder");
            break;
        }

#ifdef CACHE_ENABLED
        /* Conditionally writeback the decoded buf */
        if (XDM_ISACCESSMODE_WRITE(
                decOutArgs.decodedBufs.bufDesc[0].accessMask)) {
            Memory_cacheWb(outBuf, OFRAMESIZE);
        }
#endif

        /* write to file */
        fwrite(dst[0], OFRAMESIZE, 1, out);
    }

    Log_print1(Diags_USER1, "[+1] %d frames encoded/decoded", (IArg)n);
}
/*
 *  ======== call ========
 */
static VISA_Status call(VISA_Handle visaHandle, VISA_Msg visaMsg)
{
    _VIDENC1_Msg *msg  = (_VIDENC1_Msg *)visaMsg;
    VIDENC1_Handle handle = (VIDENC1_Handle)visaHandle;
    Int i;
    IVIDEO1_BufDescIn inBufs;
    XDM_BufDesc outBufs;
    IVIDENC1_OutArgs *pOutArgs;
    IVIDENC1_Status *pStatus;
    IVIDENC1_CodecClassConfig *codecClassConfig;
    Int numBufs;

    /* get stub/skeleton config data; can be NULL (for old codecs) */
    codecClassConfig = (IVIDENC1_CodecClassConfig *)
                        VISA_getCodecClassConfig( visaHandle );


    /* perform the requested VIDENC1 operation by parsing message. */
    switch (msg->visa.cmd) {

        case _VIDENC1_CPROCESS: {
            /* unmarshall inBufs and outBufs */
            inBufs           = msg->cmd.process.inBufs;

            outBufs.bufs     = msg->cmd.process.outBufs;
            outBufs.numBufs  = msg->cmd.process.numOutBufs;
            outBufs.bufSizes = msg->cmd.process.outBufSizes;

            if (SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB) {
                /* invalidate cache for all input buffers */
                for (i = 0, numBufs = 0; i < XDM_MAX_IO_BUFFERS; i++) {
                    if (inBufs.bufDesc[i].buf != NULL) {
                        /* valid member of sparse array,
                         * invalidate it unless user configured it not to
                         */
                        if (codecClassConfig != NULL &&
                                codecClassConfig->manageInBufsCache[i] ==
                                FALSE) {
                            /* do nothing, i.e. don't invalidate */
                        } else {
                            Memory_cacheInv(inBufs.bufDesc[i].buf,
                                    inBufs.bufDesc[i].bufSize);
                        }

                        if (++numBufs == inBufs.numBufs) {
                            break;
                        }
                    }
                }

                /* invalidate cache for all output buffers */
                for (i = 0, numBufs = 0; i < XDM_MAX_IO_BUFFERS; i++) {
                    if (outBufs.bufs[i] != NULL) {
                        /* valid member of sparse array,
                         * invalidate it unless user configured it not to
                         */
                        if (codecClassConfig != NULL &&
                                codecClassConfig->manageOutBufsCache[i] ==
                                FALSE) {
                            /* do nothing, i.e. don't invalidate */
                        } else {
                            Memory_cacheInv(outBufs.bufs[i],
                                    outBufs.bufSizes[i]);
                        }

                        if (++numBufs == outBufs.numBufs) {
                            break;
                        }
                    }
                }
            } /* SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB */

            /* unmarshall outArgs based on the "size" of inArgs */
            pOutArgs = (IVIDENC1_OutArgs *)((UInt)(&(msg->cmd.process.inArgs)) +
                msg->cmd.process.inArgs.size);

            /*
             * Note, there's no need to invalidate cache for
             * pOutArgs->encodedBuf bufs nor pOutArgs->reconBufs bufs as they're
             * not _really_ OUT buffers.  Rather they're references to
             * the _real_ OUT buffers that are provided in outBufs - which
             * were already invalidated above.
             */

            /* make the process call */
            msg->visa.status = VIDENC1_process(handle,
                &inBufs, &outBufs, &(msg->cmd.process.inArgs), pOutArgs);

            if (SKEL_cachingPolicy == SKEL_WBINVALL) {
                Memory_cacheWbInvAll();
            }
            else if (SKEL_cachingPolicy == SKEL_LOCALBUFFERINVWB) {
                /* writeback cache for encoded buffer */
                if ((pOutArgs->encodedBuf.buf != NULL) &&
                        (XDM_ISACCESSMODE_WRITE(pOutArgs->encodedBuf.accessMask))) {
                    Memory_cacheWb(pOutArgs->encodedBuf.buf,
                            pOutArgs->encodedBuf.bufSize);

                    /*
                     * Since we've cacheWb this buffer, we arguably should
                     * reflect this cache state and clear the WRITE bit in
                     * the .accessMask field.  However, we know the stub
                     * doesn't propogate this field to the calling app, so
                     * this extra buffer management detail isn't necessary:
                     *
                     * XDM_CLEARACCESSMODE_WRITE(pOutArgs->encodedBuf.accessMask);
                     */
                }

                /* writeback cache for recon buffers  */
                for (i = 0; ((i < pOutArgs->reconBufs.numBufs) &&
                             (i < IVIDEO_MAX_YUV_BUFFERS)); i++) {
                    if ((pOutArgs->reconBufs.bufDesc[i].buf != NULL) &&
                            (XDM_ISACCESSMODE_WRITE(
                                pOutArgs->reconBufs.bufDesc[i].accessMask))) {

                        Memory_cacheWb(pOutArgs->reconBufs.bufDesc[i].buf,
                                pOutArgs->reconBufs.bufDesc[i].bufSize);

                        /*
                         * Since we've cacheWb this buffer, we arguably should
                         * reflect this cache state and clear the WRITE bit in
                         * the .accessMask field.  However, we know the stub
                         * doesn't propogate this field to the calling app, so
                         * this extra buffer management detail isn't necessary:
                         *
                         * XDM_CLEARACCESSMODE_WRITE(
                         *         pOutArgs->reconBufs.bufDesc[i].accessMask);
                         */
                    }
                }
            }

            /*
             * Note that any changes to individual outBufs[i] values made by
             * the codec will automatically update msg->cmd.process.outBufs
             * as we pass the outBufs array by reference.
             */

            break;
        }

        case _VIDENC1_CCONTROL: {
            /* unmarshall status based on the "size" of params */
            pStatus = (IVIDENC1_Status *)((UInt)(&(msg->cmd.control.params)) +
                msg->cmd.control.params.size);

            /* invalidate data buffer */
            if (pStatus->data.buf != NULL) {
                Memory_cacheInv(pStatus->data.buf, pStatus->data.bufSize);
            }

            msg->visa.status = VIDENC1_control(handle, msg->cmd.control.id,
                &(msg->cmd.control.params), pStatus);

            /* writeback data buffer */
            if ((pStatus->data.buf != NULL) &&
                XDM_ISACCESSMODE_WRITE(pStatus->data.accessMask)) {

                Memory_cacheWb(pStatus->data.buf, pStatus->data.bufSize);

                /*
                 * Since we've cacheWb this buffer, we arguably should
                 * reflect this cache state and clear the WRITE bit in
                 * the .accessMask field.  However, we know the stub
                 * doesn't propogate this field to the calling app, so
                 * this extra buffer management detail isn't necessary:
                 *
                 * XDM_CLEARACCESSMODE_WRITE(pStatus->data.accessMask);
                 */
            }

            break;
        }

        default: {
            msg->visa.status = VISA_EFAIL;

            break;
        }
    }
    return (VISA_EOK);
}