#include <alg_priv.h>
#include <alg_vidEnc.h>
#include <alg_jpgEnc.h>
#include <osa_cmem.h>
#include <osa_file.h>
#include <ti/sdo/codecs/mpeg4enc/imp4venc.h>
#include <ti/sdo/codecs/h264enc/ih264venc.h>
#include <alg_vidDec.h>

  OSA_PrfHndl prfVid;
//#define ALG_VID_ENC_DEBUG
//#define ALG_VID_ENC_TEST_DEBUG
#define ALG_VID_ENC_TEST_FILESYS  "./"
#define ALG_VID_ENC_TEST_CHANNELS   (2)


typedef struct {

  VIDENC1_Handle   hEncode;
  ALG_VidEncCreate createPrm;
  char             algName[20];
  
  VIDENC1_Params          params;
  IH264VENC_Params        h264Params;
  IMP4VENC_Params         mpeg4Params;
  
  IH264VENC_DynamicParams h264dynamicParams;
  IMP4VENC_DynamicParams  mpeg4dynamicParams;
  IVIDENC1_DynamicParams  dynamicParams;
  VIDENC1_Status          encStatus;

  void *hJpgEncode;
  
  XDAS_UInt8 *MV_Addr;		
  XDAS_UInt32 MV_Size;
  
} ALG_VidEncObj;


int ALG_vidEncSetDynamicParams(ALG_VidEncObj *pObj);

void *ALG_vidEncCreate(ALG_VidEncCreate *create)
{
  int maxbitrate = 0 ;

  XDAS_Int32              status;
  ALG_VidEncObj           *pObj;
  
  if(gALG_hEngine==NULL)
    return NULL;

  pObj = OSA_memAlloc(sizeof(ALG_VidEncObj));
  if(pObj==NULL)
    return NULL;

  memset(pObj, 0, sizeof(ALG_VidEncObj)); 

  switch(create->codec) {
    case ALG_VID_CODEC_H264:
      strcpy(pObj->algName, ALG_VID_CODEC_H264_ENC_NAME);
      break;
    case ALG_VID_CODEC_MPEG4:
      strcpy(pObj->algName, ALG_VID_CODEC_MPEG4_ENC_NAME);
      break;
    case ALG_VID_CODEC_MJPEG:
      strcpy(pObj->algName, ALG_VID_CODEC_JPEG_ENC_NAME);
      break;
    default:
      OSA_memFree(pObj);
      return NULL;
  }
   
  memcpy(&pObj->createPrm, create, sizeof(pObj->createPrm)); 
  
  if(create->codec==ALG_VID_CODEC_MJPEG)
  {
    ALG_JpgEncCreate jpgCreate;
    
    jpgCreate.dataFormat = create->dataFormat;
    jpgCreate.width      = create->width;
    jpgCreate.height     = create->height;
    jpgCreate.offsetH    = create->offsetH;
    jpgCreate.offsetV    = create->offsetV;                                            
    jpgCreate.encDataFormat = ALG_VID_DATA_FORMAT_YUV420;
    jpgCreate.qValue     = create->qValue;
    
    pObj->hJpgEncode = ALG_jpgEncCreate(&jpgCreate);
    
    if(pObj->hJpgEncode==NULL) {
      OSA_memFree(pObj);
      return NULL;
    }
  
    return pObj;
  }
  
  pObj->params.size                  = sizeof(VIDENC1_Params);

#ifdef DM368_CONFIG
  pObj->params.encodingPreset        = XDM_HIGH_SPEED;
//  pObj->params.encodingPreset        = XDM_USER_DEFINED;
#else
  pObj->params.encodingPreset        = XDM_HIGH_QUALITY;
#endif

  pObj->MV_Size = 0; //Initialization
  
  switch(create->rateControlType) {
    case ALG_VID_ENC_RATE_CONTROL_CBR:
      pObj->params.rateControlPreset     = IVIDEO_LOW_DELAY;
      break;
    case ALG_VID_ENC_RATE_CONTROL_VBR:
      pObj->params.rateControlPreset     = IVIDEO_NONE;
      break;
    default:
    case ALG_VID_ENC_RATE_CONTROL_CVBR:
      pObj->params.rateControlPreset     = IVIDEO_STORAGE;
      break;
  }

  if(create->width == 704)
  {
//      maxbitrate = 3000000 ;
      maxbitrate = 10000000 ;
  }
  else
  {
//      maxbitrate = 1000000 ;
      maxbitrate = 4000000 ;
  }
  pObj->params.maxHeight             = create->height;
  pObj->params.maxWidth              = create->width;
  pObj->params.maxFrameRate          = 30000 ;
  pObj->params.maxBitRate            = maxbitrate ;
  pObj->params.inputChromaFormat     = XDM_YUV_420SP;
  pObj->params.dataEndianness        = XDM_BYTE;


  pObj->params.maxInterFrameInterval = 0;

if(pObj->createPrm.enableInterlaced)
  pObj->params.inputContentType      = IVIDEO_INTERLACED;
else
  pObj->params.inputContentType      = IVIDEO_PROGRESSIVE;    


  pObj->params.reconChromaFormat     = XDM_YUV_420SP;
  
  switch(create->codec) {
    case ALG_VID_CODEC_H264:
    
      memcpy(&pObj->h264Params, &IH264VENC_PARAMS, sizeof(IH264VENC_PARAMS));
      memcpy(&pObj->h264Params.videncParams, &pObj->params, sizeof(pObj->params));
      
      pObj->h264Params.videncParams.size = sizeof(pObj->h264Params);
      pObj->h264Params.levelIdc = IH264VENC_LEVEL_30;

#ifdef DM368_CONFIG
      pObj->h264Params.encQuality = 2 ; // 2010 2.5 light codec 
#endif
      
      pObj->hEncode = VIDENC1_create(gALG_hEngine, pObj->algName, (VIDENC1_Params*)&pObj->h264Params);      
      break;
    default:
      pObj->hEncode = VIDENC1_create(gALG_hEngine, pObj->algName, &pObj->params);          
      break;
  }

  if(pObj->hEncode == NULL) {
    OSA_ERROR("Failed to open video encode algorithm: %s (0x%x)\n", pObj->algName, Engine_getLastError(gALG_hEngine));
    OSA_memFree(pObj);
    return NULL; 
  }
  
  pObj->params.maxBitRate            = create->bitrate < 0 ? 0 : create->bitrate;

  status = ALG_vidEncSetDynamicParams(pObj);
  if(status!=OSA_SOK) {
    ALG_vidEncDelete(pObj);
    return NULL;
  }

  
  return pObj;
}

int ALG_vidEncSetDynamicParams(ALG_VidEncObj *pObj)
{
  XDAS_Int32 status;
  
  if(pObj==NULL)
    return OSA_EFAIL;

  if(pObj->createPrm.codec==ALG_VID_CODEC_MJPEG) {
    ALG_jpgEncSetQvalue(pObj->hJpgEncode, pObj->createPrm.bitrate);
    return OSA_SOK;
  }
    
  if(pObj->createPrm.codec==ALG_VID_CODEC_H264) {
    memcpy(&pObj->h264dynamicParams, &H264VENC_TI_IH264VENC_DYNAMICPARAMS, sizeof(H264VENC_TI_IH264VENC_DYNAMICPARAMS));
    pObj->dynamicParams.size                = sizeof(pObj->h264dynamicParams);    
  } 
  else if(pObj->createPrm.codec==ALG_VID_CODEC_MPEG4) {
    pObj->dynamicParams.size                = sizeof(pObj->mpeg4dynamicParams);    
  }
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.intraFrameInterval  = pObj->createPrm.keyFrameInterval;
  pObj->dynamicParams.generateHeader      = XDM_ENCODE_AU;
if(pObj->createPrm.enableInterlaced)  
  pObj->dynamicParams.captureWidth        = pObj->createPrm.offsetH*2;
else
  pObj->dynamicParams.captureWidth        = pObj->createPrm.offsetH;    
  pObj->dynamicParams.targetFrameRate     = 30000;
  pObj->dynamicParams.refFrameRate        = 30000;

  /* Set video encoder dynamic parameters */
  pObj->encStatus.size = sizeof(VIDENC1_Status);
  pObj->encStatus.data.buf = NULL;
  
  switch(pObj->createPrm.codec) {
    case ALG_VID_CODEC_H264:
      pObj->dynamicParams.forceFrame = IVIDEO_NA_FRAME;
      memcpy(&pObj->h264dynamicParams.videncDynamicParams, &pObj->dynamicParams, sizeof(pObj->dynamicParams));
      
      pObj->h264dynamicParams.idrFrameInterval               = pObj->createPrm.keyFrameInterval;    
      pObj->h264dynamicParams.resetHDVICPeveryFrame = TRUE;      

      if(pObj->createPrm.mode == ALG_VID_ENC_MODE_FAST_FPS)
      {
        pObj->h264dynamicParams.perceptualRC                   = 0;
      }
      pObj->h264dynamicParams.mvSADoutFlag = pObj->createPrm.mbMvOutEnable;
      pObj->h264dynamicParams.rcQMin       = pObj->createPrm.enableROI ? 2:8;
      pObj->h264dynamicParams.rcQMax       = pObj->createPrm.enableROI ? 51:40;
      pObj->h264dynamicParams.rcQMinI      = pObj->createPrm.enableROI ? 2:8;
      pObj->h264dynamicParams.rcQMaxI      = pObj->createPrm.enableROI ? 51:40;
      pObj->h264dynamicParams.enableROI    = pObj->createPrm.enableROI;

	  status = VIDENC1_control(pObj->hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)&pObj->h264dynamicParams, &pObj->encStatus);

	  if (status != VIDENC1_EOK) {
	      OSA_ERROR("XDM_SETPARAMS failed, status=%ld\n", status);
		  OSA_ERROR("VIDENC1_control() failed with error (%d ext: 0x%x)\n",
                  (int)status, (unsigned int) pObj->encStatus.extendedError);
	      return OSA_EFAIL;
	  }

	  pObj->encStatus.data.buf = NULL;

	  status = VIDENC1_control(pObj->hEncode, XDM_GETBUFINFO, (VIDENC1_DynamicParams*)&pObj->h264dynamicParams, &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: DynamicParams: bitrate = %ld bps, Key-frame-interval = %ld\n",
    pObj->h264dynamicParams.videncDynamicParams.targetBitRate,
    pObj->h264dynamicParams.idrFrameInterval    
    );
  #endif

	      break;

    case ALG_VID_CODEC_MPEG4:
          memcpy(&pObj->mpeg4dynamicParams.videncDynamicParams, &pObj->dynamicParams, sizeof(pObj->dynamicParams));

	  pObj->mpeg4dynamicParams.intraAlgo      = IMP4VENC_INTRA_INTER_DECISION_HQ_LP;
	  pObj->mpeg4dynamicParams.numMBRows      = (pObj->createPrm.height>960) ? 1:30;
	  pObj->mpeg4dynamicParams.initQ          = 4;
	  pObj->mpeg4dynamicParams.rcQMax         = 25;
	  pObj->mpeg4dynamicParams.rcQMin         = 4;
	  pObj->mpeg4dynamicParams.rateFix        = 0;
	  pObj->mpeg4dynamicParams.rateFixRange   = 2;
	  pObj->mpeg4dynamicParams.skipMBAlgo     = IMP4VENC_SKIP_MB_LQ_HP;
	  pObj->mpeg4dynamicParams.unrestrictedMV = IMP4VENC_UMV_LQ_HP;
         pObj->mpeg4dynamicParams.interFrameQP = 0;
         pObj->mpeg4dynamicParams.intraFrameQP = 0;            
	  if(pObj->dynamicParams.inputWidth<720)
	  	pObj->mpeg4dynamicParams.meAlgo	= IMP4VENC_ME_LQ_HP;
  	  else
  	  	pObj->mpeg4dynamicParams.meAlgo	= (pObj->createPrm.mode == ALG_VID_ENC_MODE_FAST_FPS) ? IMP4VENC_ME_LQ_HP:IMP4VENC_ME_HQ_MP;

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

        if(pObj->mpeg4dynamicParams.numMBRows > (pObj->createPrm.height/16))
            pObj->mpeg4dynamicParams.numMBRows = (pObj->createPrm.height/16);
  
         status = VIDENC1_control(pObj->hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)&pObj->mpeg4dynamicParams, &pObj->encStatus);

          if (status != VIDENC1_EOK) {
      		OSA_ERROR("XDM_SETPARAMS failed, status=%ld\n", status);
	  	OSA_ERROR("VIDENC1_control() failed with error (%d ext: 0x%x)\n",
                  (int)status, (unsigned int) pObj->encStatus.extendedError);
      		return OSA_EFAIL;
  	}

	  pObj->encStatus.data.buf = NULL;

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

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

	  break;
    case ALG_VID_CODEC_MJPEG:
         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);
	  OSA_ERROR("VIDENC1_control() failed with error (%d ext: 0x%x)\n",
                  (int)status, (unsigned int) pObj->encStatus.extendedError);
      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;
  }
      break;
  }    


 


  if( pObj->createPrm.mbMvOutEnable )
  {
      if( pObj->encStatus.bufInfo.minNumOutBufs > 1 )
      {
//    		OSA_printf(" ALG: VidEnc: pObj->MV_Size =%d \n",(int)pObj->MV_Size);
	  if( pObj->MV_Size == 0 )
	  {
	      pObj->MV_Size = pObj->encStatus.bufInfo.minOutBufSize[1] ;
	      pObj->MV_Addr = OSA_cmemAlloc(pObj->MV_Size*(2<<pObj->createPrm.enableInterlaced),32);
//Anshuman - Making the below change to overcome the problem in codec where it asks for more memory
//	      pObj->MV_Addr = OSA_cmemAlloc((pObj->MV_Size)>>pObj->createPrm.enableInterlaced,32);

    		OSA_printf(" ALG: VidEnc: pObj->MV_Size =%d \n",(int)pObj->MV_Size);

	      if( pObj->MV_Addr == NULL )
	      {
		  OSA_ERROR("OSA_cmemAlloc failed \n");
		  return OSA_EFAIL;
	      }
				
    	      /* Default is Disable MV data output */

//    	      pObj->createPrm.mbMvOutEnable = 0;
              switch(pObj->createPrm.codec)
              {
 	          case ALG_VID_CODEC_H264:
		  pObj->h264dynamicParams.mvSADoutFlag = 0;
     	          status = VIDENC1_control(pObj->hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)&pObj->h264dynamicParams, &pObj->encStatus);
 		  break;
 		  case ALG_VID_CODEC_MPEG4:
		  pObj->mpeg4dynamicParams.mvDataEnable = 0;
     	          status = VIDENC1_control(pObj->hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)&pObj->mpeg4dynamicParams, &pObj->encStatus);

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

  return OSA_SOK;
}

int ALG_vidEncSetKeyFrameInterval(void *hndl, int keyFrameInterval)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  int status;

  if(pObj==NULL)
    return OSA_EFAIL;

  pObj->createPrm.keyFrameInterval = keyFrameInterval;
//  pObj->createPrm.bitrate--; // since keyFrameInterval does not take effect unless there is change in bitrate
  
  status = ALG_vidEncSetDynamicParams(pObj);
  
//  pObj->createPrm.bitrate++; // restore original bitrate
//  status = ALG_vidEncSetDynamicParams(pObj);
      
  return status;
}

int ALG_vidEncSetBitrate(void *hndl, int bitrate)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  
  if(pObj==NULL)
    return OSA_EFAIL;

  printf("ALG_vidEncSetBitrate bitrate = %d\n",bitrate) ;
  pObj->createPrm.bitrate = bitrate;
//  pObj->MV_Size = 1 ;
  return ALG_vidEncSetDynamicParams(pObj);
}

int ALG_vidEncSetMVdataOut(void *hndl, int mbMvOutEnable)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  
  if(pObj==NULL)
  {
    return OSA_EFAIL;
  }
  pObj->createPrm.mbMvOutEnable = mbMvOutEnable;
  
  return ALG_vidEncSetDynamicParams(pObj);
}


int ALG_vidEncGetMVdataSize(void *hndl)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  
  if(pObj==NULL)
    return OSA_EFAIL;


  return pObj->MV_Size*(2<<pObj->createPrm.enableInterlaced);
}

void *ALG_vidEncGetMVdataAddr(void *hndl)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  
  if(pObj==NULL)
    return NULL;
  
  return pObj->MV_Addr;
}

int ALG_vidEncGetMVdataStatus(void *hndl)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  
  if(pObj==NULL)
    return OSA_EFAIL;
  
  return pObj->createPrm.mbMvOutEnable;
}

int ALG_vidEncSetROI(void *hndl, int flag)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;

  if(pObj==NULL)
    return OSA_EFAIL;

  pObj->createPrm.enableROI = flag;
  
  return ALG_vidEncSetDynamicParams(pObj);
}
void CheckROIBoundary(XDM_Point *val, int xbound, int ybound)
{
	if(val->x<0) val->x=0;
	if(val->y<0) val->y=0;

	if(val->x>xbound) val->x=xbound;
	if(val->y>ybound) val->x=ybound;
}



int ALG_vidEncRun(void *hndl, ALG_VidEncRunPrm *prm, ALG_VidEncRunStatus *runStatus)
{
  ALG_VidEncObj *pObj = (ALG_VidEncObj*)hndl;
  IVIDEO1_BufDescIn  inBufDesc;
  XDM_BufDesc        outBufDesc;
  XDAS_Int32         status;
  VIDENC1_InArgs     inArgs;
  VIDENC1_OutArgs    outArgs;
  IH264VENC_InArgs     h264InArgs;
  XDAS_Int32         offset;
  XDAS_Int32         outBufSizeArray[2];
  XDAS_UInt8          *dst[2];
  XDAS_UInt8 * tmpAddr;
  XDAS_UInt8          i=0;

    
  runStatus->bytesGenerated = 0;
  runStatus->isKeyFrame     = FALSE;
  runStatus->numMB          = 0;

  if(pObj==NULL)
    return OSA_EFAIL;
    
  if(pObj->createPrm.codec==ALG_VID_CODEC_MJPEG)
  {
    ALG_JpgEncRunPrm jpgRun;
    ALG_JpgEncRunStatus jpgStatus;
    
    jpgRun.inStartX = prm->inStartX;
    jpgRun.inStartY = prm->inStartY;    
    jpgRun.inAddr   = prm->inAddr;
    jpgRun.outAddr  = prm->outAddr;    
    jpgRun.outDataMaxSize = prm->outDataMaxSize;
    
    status = ALG_jpgEncRun(pObj->hJpgEncode, &jpgRun, &jpgStatus);
    
    runStatus->isKeyFrame     = TRUE;    
    
    if(status!=OSA_SOK) {
        
      return OSA_EFAIL;
    }
    
    runStatus->bytesGenerated = jpgStatus.bytesGenerated;
    
    return OSA_SOK;  
  }

  offset = pObj->createPrm.offsetH * pObj->createPrm.offsetV;

  if(prm->outDataMaxSize==0)
    prm->outDataMaxSize = pObj->createPrm.width*pObj->createPrm.height*2;
    
  outBufSizeArray[0] = prm->outDataMaxSize;

  prm->inStartY = OSA_floor(prm->inStartY, 2);
  prm->inStartX = OSA_floor(prm->inStartX, 2);
  
  inBufDesc.numBufs       = 2;
  inBufDesc.frameWidth    = OSA_align(pObj->createPrm.width, 16);
  inBufDesc.frameHeight   = OSA_align(pObj->createPrm.height, 16);
  inBufDesc.framePitch    = pObj->createPrm.offsetH;

if(pObj->createPrm.enableInterlaced)    
  inBufDesc.bufDesc[0].bufSize = pObj->createPrm.offsetH*2*inBufDesc.frameHeight ;
else
  inBufDesc.bufDesc[0].bufSize = pObj->createPrm.offsetH*inBufDesc.frameHeight ;
  inBufDesc.bufDesc[0].buf     = (XDAS_Int8*)(prm->inAddr + prm->inStartY*pObj->createPrm.offsetH + prm->inStartX);
  inBufDesc.bufDesc[0].accessMask = 0;

if(pObj->createPrm.enableInterlaced)    
  inBufDesc.bufDesc[1].bufSize = pObj->createPrm.offsetH*2*inBufDesc.frameHeight/2;
else
  inBufDesc.bufDesc[1].bufSize = pObj->createPrm.offsetH*inBufDesc.frameHeight/2;    
  inBufDesc.bufDesc[1].buf     = (XDAS_Int8*)(prm->inAddr + offset + prm->inStartY*pObj->createPrm.offsetH/2 + prm->inStartX);
  inBufDesc.bufDesc[1].accessMask = 0;
  if( pObj->MV_Size == 0 )
  {
	  outBufDesc.numBufs  = 1;
	  outBufDesc.bufSizes = outBufSizeArray;
	  outBufDesc.bufs     = (XDAS_Int8 **) &prm->outAddr;
  }
  else
  {
	  dst[0]	     = prm->outAddr;    
	  dst[1]             = pObj->MV_Addr;
          outBufSizeArray[1] = pObj->MV_Size;
	
	  outBufDesc.numBufs  = 2;
	  outBufDesc.bufSizes = outBufSizeArray;
	  outBufDesc.bufs     = dst;
  }

  inArgs.size         = sizeof(VIDENC1_InArgs);

  inArgs.inputID = 1;
  inArgs.topFieldFirstFlag = 0;

//if(gALG_vidEnc_enableROI)
if(pObj->createPrm.enableROI)
{
	if(pObj->createPrm.codec==ALG_VID_CODEC_H264)
	{
		h264InArgs.videncInArgs 			= inArgs;
		h264InArgs.videncInArgs.size 		= sizeof(IH264VENC_InArgs);
		h264InArgs.roiParameters.numOfROI 	= (prm->roiPrm.numROI>=MAX_ROI)?MAX_ROI:prm->roiPrm.numROI;
//        printf("number of ROI:%d\n",h264InArgs.roiParameters.numOfROI);

		for(i=0;i<h264InArgs.roiParameters.numOfROI;i++)
		{
			h264InArgs.roiParameters.listROI[i].topLeft.x = prm->roiPrm.roiInfo[i].topLeft_x;
			h264InArgs.roiParameters.listROI[i].topLeft.y = prm->roiPrm.roiInfo[i].topLeft_y;
			h264InArgs.roiParameters.listROI[i].bottomRight.x = prm->roiPrm.roiInfo[i].bottomRight_x;
			h264InArgs.roiParameters.listROI[i].bottomRight.y = prm->roiPrm.roiInfo[i].bottomRight_y;
			h264InArgs.roiParameters.roiPriority[i] = prm->roiPrm.roiInfo[i].roiPriority;

			CheckROIBoundary(&h264InArgs.roiParameters.listROI[i].topLeft, pObj->createPrm.width, pObj->createPrm.height);
			CheckROIBoundary(&h264InArgs.roiParameters.listROI[i].bottomRight, pObj->createPrm.width, pObj->createPrm.height);

			switch(prm->roiPrm.roiInfo[i].roiType)
			{
				case ALG_VID_ENC_ROI_TYPE_FACE:
					h264InArgs.roiParameters.roiType[i] = FACE_OBJECT;
					break;
				case ALG_VID_ENC_ROI_TYPE_PRIVACYMASK:
					h264InArgs.roiParameters.roiType[i] = PRIVACY_MASK;
					break;
				case ALG_VID_ENC_ROI_TYPE_FOREGROUND:
					h264InArgs.roiParameters.roiType[i] = FOREGROUND_OBJECT;
					break;
				default: // No other Types currently supported
					h264InArgs.roiParameters.roiType[i] = DEFAULT_OBJECT;
					break;
			}

//			OSA_printf(" ROI Prm for %d - Top Left (%d,%d) - Bottom right - (%d,%d) - Priority - %d, Type - %d \r\n",i,h264InArgs.roiParameters.listROI[i].topLeft.x,h264InArgs.roiParameters.listROI[i].topLeft.y,	h264InArgs.roiParameters.listROI[i].bottomRight.x,h264InArgs.roiParameters.listROI[i].bottomRight.y,h264InArgs.roiParameters.roiPriority[i],h264InArgs.roiParameters.roiType[i]);
		}
			h264InArgs.timeStamp 			= 0;
			h264InArgs.insertUserData 		= XDAS_FALSE;
	       	h264InArgs.lengthUserData 		= 0;
			h264InArgs.numOutputDataUnits 	= 0;
	}
}

  outArgs.size        = sizeof(VIDENC1_OutArgs);
  OSA_prfBegin(&prfVid);

if(pObj->createPrm.enableROI)
{
    if(pObj->createPrm.codec==ALG_VID_CODEC_H264)
        status = VIDENC1_process(pObj->hEncode, &inBufDesc, &outBufDesc, &h264InArgs, &outArgs);
    else
        status = VIDENC1_process(pObj->hEncode, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
}
else
  status = VIDENC1_process(pObj->hEncode, &inBufDesc, &outBufDesc, &inArgs, &outArgs);

  OSA_prfEnd(&prfVid, 1);
        
  if (status != VIDENC1_EOK) 
  {
   OSA_ERROR("VIDENC1_process() failed with error (%d ext: 0x%x)\n",
                  (int)status, (unsigned int) outArgs.extendedError);
    return OSA_EFAIL;
  }
  
  runStatus->bytesGenerated = outArgs.bytesGenerated;


if(pObj->createPrm.enableInterlaced)  
{
  inBufDesc.bufDesc[0].buf     = (XDAS_Int8*)(prm->inAddr + prm->inStartY*pObj->createPrm.offsetH + prm->inStartX+pObj->createPrm.offsetH);
  inBufDesc.bufDesc[1].buf     = (XDAS_Int8*)(prm->inAddr + offset + prm->inStartY*pObj->createPrm.offsetH/2 + prm->inStartX+pObj->createPrm.offsetH);  
  tmpAddr = prm->outAddr+runStatus->bytesGenerated;

  if( pObj->MV_Size == 0 )
  {
         
  	outBufDesc.bufs     = (XDAS_Int8 **) &tmpAddr;  
  }
  else
  {
	  dst[0]	     = tmpAddr;    
	  dst[1]             = pObj->MV_Addr + (pObj->MV_Size);
         outBufSizeArray[1] = pObj->MV_Size;
	
	  outBufDesc.numBufs  = 2;
	  outBufDesc.bufSizes = outBufSizeArray;
	  outBufDesc.bufs     = dst;
  }
if(pObj->createPrm.enableROI)
//if(gALG_vidEnc_enableROI)
{
    if(pObj->createPrm.codec==ALG_VID_CODEC_H264)
        status = VIDENC1_process(pObj->hEncode, &inBufDesc, &outBufDesc, &h264InArgs, &outArgs);
    else
        status = VIDENC1_process(pObj->hEncode, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
}
else
  status = VIDENC1_process(pObj->hEncode, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
  
  if (status != VIDENC1_EOK) 
  {
   OSA_ERROR("VIDENC1_process() failed with error (%d ext: 0x%x)\n",
                  (int)status, (unsigned int) outArgs.extendedError);
    return OSA_EFAIL;
  }
  runStatus->bytesGenerated += outArgs.bytesGenerated;
}

  if(outArgs.encodedFrameType==IVIDEO_IP_FRAME || outArgs.encodedFrameType==IVIDEO_II_FRAME ||outArgs.encodedFrameType==IVIDEO_I_FRAME || outArgs.encodedFrameType==IVIDEO_IDR_FRAME)
runStatus->isKeyFrame = TRUE;

  return OSA_SOK;
}

int ALG_vidEncDelete(void *hndl)
{
  ALG_VidEncObj *pObj=(ALG_VidEncObj *)hndl;
  
  if(pObj==NULL)
    return OSA_EFAIL;

  if(pObj->createPrm.codec==ALG_VID_CODEC_MJPEG)
  {
    ALG_jpgEncDelete(pObj->hJpgEncode);
    
  } else {
  
    if(pObj->hEncode)  
    {
    	if( pObj->MV_Size != 0 )
    	{
		OSA_cmemFree(pObj->MV_Addr);

    	}              


      VIDENC1_delete(pObj->hEncode);
    }        
  }
    
  OSA_memFree(pObj);  
        
  return OSA_SOK;
}



int ALG_vidEncTestMain(int argc, char **argv)
{
  int status, i, k, numFrames=1000;
  Uint8 *inVirtAddr=NULL, *inPhysAddr, *outVirtAddr=NULL, *outPhysAddr, *curOutAddr;
  OSA_PrfHndl prfVidEnc[ALG_VID_ENC_TEST_CHANNELS];
  Uint32 size=4*MB, fileSize;
  void *algVidEncHndl[ALG_VID_ENC_TEST_CHANNELS];
  ALG_VidEncCreate createPrm;
  ALG_VidEncRunPrm runPrm;
  ALG_VidEncRunStatus runStatus;
  FILE *fileHndl[ALG_VID_ENC_TEST_CHANNELS];
  char filename[20];
    
  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;
  }
  
  inVirtAddr     = OSA_cmemAlloc(size, 32); 
  outVirtAddr    = OSA_cmemAlloc(size, 32);
  
  inPhysAddr     = OSA_cmemGetPhysAddr(inVirtAddr);
  outPhysAddr    = OSA_cmemGetPhysAddr(outVirtAddr);  
  
  memset(outVirtAddr, 0x0, size);
  
  if(   inVirtAddr==NULL || outVirtAddr == NULL 
     || inPhysAddr==NULL || outPhysAddr == NULL 
    ) {
    OSA_ERROR("OSA_cmemAlloc()\n");  
    goto error_exit;
  }
  
  memset(fileHndl, 0, sizeof(fileHndl));

  createPrm.codec           = ALG_VID_CODEC_H264;          
  createPrm.dataFormat      = DRV_DATA_FORMAT_YUV420;     
  createPrm.width           = 352;          
  createPrm.height          = 240;         
  createPrm.offsetH         = 352;        
  createPrm.offsetV         = 240;        
  createPrm.bitrate         = 1*1000*1000;        
  createPrm.mode            = ALG_VID_ENC_MODE_STANDARD;           
  createPrm.keyFrameInterval= 30;
  createPrm.mbMvOutEnable   = FALSE;  
  createPrm.qValue          = 75;
  createPrm.enableInterlaced= 1;
  createPrm.enableROI= 0;

  if(createPrm.dataFormat==DRV_DATA_FORMAT_YUV420)
    status = OSA_fileReadFile("videoQVGA.yuv420", inVirtAddr, size,0, &fileSize);
  else
    status = OSA_fileReadFile("video.yuv422", inVirtAddr, size,0, &fileSize);  
  if(status!=OSA_SOK) {
    OSA_ERROR("OSA_fileReadFile()\n");    
    goto error_exit;
  }

  memset(algVidEncHndl, 0, sizeof(algVidEncHndl));
  
  for(k=0; k<ALG_VID_ENC_TEST_CHANNELS; k++) {
    algVidEncHndl[k] = ALG_vidEncCreate(&createPrm);
    if(algVidEncHndl[k]==NULL) {
      OSA_ERROR("ALG_vidEncCreate()\n");
      goto error_exit;
    }
    
    OSA_prfReset(&prfVidEnc[k]);
    
    sprintf( filename, "%s/CH%02d.bits", ALG_VID_ENC_TEST_FILESYS, k);
    
    fileHndl[k] = fopen(filename, "wb");
    
    if(fileHndl[k]==NULL) {
      OSA_ERROR("fopen(%s)", filename);
      goto error_exit;
    }
  }
    
  curOutAddr = outVirtAddr;

  for(i=0; i<numFrames; i++) {

    runPrm.inStartX       = 0;      
    runPrm.inStartY       = 0;      
    runPrm.inAddr         = inVirtAddr;        
    runPrm.outAddr        = curOutAddr;       
    runPrm.mbMvInfo       = NULL;      
    runPrm.outDataMaxSize = size;
    runPrm.forceKeyFrame  = FALSE; 

    for(k=0; k<ALG_VID_ENC_TEST_CHANNELS; k++) {
      
      #if 1  
      OSA_prfBegin(&prfVidEnc[k]);     
      status = ALG_vidEncRun(algVidEncHndl[k], &runPrm, &runStatus);
      OSA_prfEnd(&prfVidEnc[k], 1);  
      #endif
      
      if(status==OSA_SOK) {
        #ifdef ALG_VID_ENC_TEST_DEBUG
        OSA_printf(" ALG: VidEnc: CH %d: %d: %ld bytes, key_frame = %ld, MB = %d\n", k, i, runStatus.bytesGenerated, runStatus.isKeyFrame, runStatus.numMB);
        
        fwrite(curOutAddr, runStatus.bytesGenerated, 1, fileHndl[k]);      
        #endif
                
      } else {
        OSA_printf(" ALG: VidEnc: ALG_vidEncRun() ERROR !!!\n");
        break;
      }
    }
    #if 0
    if((i%11)==0) {
      ALG_vidDecTestMain(0, NULL);
    }    
    #endif
  }
  
  #ifdef ALG_VID_ENC_TEST_DEBUG  
  for(k=0; k<ALG_VID_ENC_TEST_CHANNELS; k++) {    
    OSA_prfPrint(&prfVidEnc[k], "VID ENC", 0);   
  }
  #endif
  
error_exit:

  for(k=0; k<ALG_VID_ENC_TEST_CHANNELS; k++) {  
    ALG_vidEncDelete(algVidEncHndl[k]);
    if(fileHndl[k])
      fclose(fileHndl[k]);
  }

  if(inVirtAddr)  
    OSA_cmemFree(inVirtAddr);

  if(outVirtAddr)  
    OSA_cmemFree(outVirtAddr);
 
  ALG_sysExit();
  DRV_exit();
  
  return status;
}
