/******************************************************************************
* FILE PURPOSE: Video transcode demo: decode+encode
******************************************************************************
* FILE NAME:   videoTranscodeDecEnc.c
*
* DESCRIPTION: Contains routines that support video transcode demo
*
* TABS: NONE
*
*
* (C) Copyright 2010, Texas Instruments Incorporated
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
*/
/* Standard C header files                                                    */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "siuVctCodecAPI.h"
#include "siuVctBufferManager.h"
#include "siuVctParse.h"
#include "siuVctTftp.h"
#include "ividmc/siuVidMc.h"
#include "common/siuloc.h"
#include "osal/siuFcOsal.h"
#include "osal/siuOsal.h"

#include "siuVctFileIO.h"
#include "targethw.h"
#include <ti/mas/tftp/tftp.h>

#include <xdc/std.h>
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/Diags.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Memory.h>

#include <ti/xdais/ires.h>
extern IALG_Handle ALG_create(IALG_Fxns *fxns, IALG_Handle p, IALG_Params *params, Bool second_inst);
extern Void ALG_delete(IALG_Handle alg, Bool second_inst);

/* Decoder input */
#pragma DATA_SECTION( decInpBuf, ".codec_input");
XDAS_Int8 decInpBuf[3447936];

/* YUV from decoder, which will also be the input to the encoder */
#define YUV_BUF_SIZE 3133440*5  /*1920*1088*1.5=3133440*/
#pragma DATA_SECTION(yuvData, ".transcode_yuv");
XDAS_Int8 yuvData[YUV_BUF_SIZE];
XDAS_Int8   *yuv_ptr_start;
XDAS_Int8   *yuv_ptr_working;
XDAS_Int32  yuv_numValidBytes;
XDAS_UInt32 yuv_memorySizeLimit;

/* Encoder ouput */
#define CORE_OUTPUT_BUF_SIZE  (9 * 32768)
volatile XDAS_UInt32 max_output_bufsize = 0;
XDAS_Int8  outputData[CORE_OUTPUT_BUF_SIZE];
#pragma DATA_SECTION(outputData, ".codec_output")

/* Decoder instance, handle, and API table*/
#define MAX_DEC_INST_SIZE 5000
XDAS_Int8 decInst[MAX_DEC_INST_SIZE];
vidDecoderAPI_t         *decAPI;
IALG_Handle             decHandle;
XDAS_UInt32 first_time;

/* Decoder instance, handle, and API table*/
#define MAX_ENC_INST_SIZE 5000
XDAS_Int8 encInst2[MAX_ENC_INST_SIZE];
IALG_Handle     encHandle;
vidEncoderAPI_t *encAPI;

extern cregister volatile unsigned int TSCL;
extern cregister volatile unsigned int DNUM;

//PC--
XDAS_Int32 useHyperLink = 0;
XDAS_Int32 numChips = 0;

/* Functions */
XDAS_Void siuVctDecode_WriteYUVData(IVIDEO1_BufDesc *displayBufs);
XDAS_Int32 createEncoder(const char* encCodecname);
XDAS_Int32 createDecoder(const char* decCodecname,
                         XDM1_BufDesc *decInputBufDesc, XDM_BufDesc *decOutputBufDesc);
XDAS_Int32 frameEncode(XDAS_UInt32 *processCycles);
XDAS_Int32 frameDecode(XDM1_BufDesc *decInputBufDesc, XDM_BufDesc *decOutputBufDesc,
                     IVIDDEC2_InArgs *decInArgs, IVIDDEC2_OutArgs *decOutArgs,
                     XDAS_UInt32 BytesRead, XDAS_UInt32 *processCycles);
XDAS_Int32 frameDecFlush(XDM1_BufDesc *decInputBufDesc, XDM_BufDesc *decOutputBufDesc,
                     IVIDDEC2_InArgs *decInArgs, IVIDDEC2_OutArgs *decOutArgs,
                     XDAS_UInt32 *processCycles);
XDAS_Int32 frameEncFlush(XDAS_UInt32 *processCycles);
XDAS_UInt32 xdm2p0_vid_enc_buf_query(XDAS_Int32* numInBufs, XDAS_Int32 *bufSizes);



XDAS_Void transcodeYuvMgrInit()
{
    yuv_ptr_start        = (XDAS_Int8 *)&yuvData[0];
    yuv_ptr_working      = (XDAS_Int8 *)&yuvData[0];
    yuv_numValidBytes    = 0;
    yuv_memorySizeLimit  = YUV_BUF_SIZE;
}

/******************************************************************************
* FUNCTION PURPOSE: Main Function acting as a client for Video Transcode Call
******************************************************************************
* DESCRIPTION: Main Function acting as a client for Video Transcode Call
*
* XDAS_Int32 videoTranscode (
*    const char *decCodecname        - name of the decoder
*    const char *encCodecname        - name of the encoder
*    XDAS_UInt32 framesToEncode      - # of frames to transcode
*    void *decCodecParams            - codec parameters for decoder
*    void *encCodecParams            - codec parameters for encoder
* )
*****************************************************************************/
XDAS_Int32 videoTranscode (const char* decCodecname,
                           const char* encCodecname,
                           tulong framesToDecode)
{
    /* Decoder parameters     */
    IVIDDEC2_InArgs            *decInArgs;
    IVIDDEC2_OutArgs           *decOutArgs;
    XDM1_BufDesc                decInputBufDesc;
    XDM_BufDesc                 decOutputBufDesc;

    XDAS_UInt32 bytesConsumed=0, bytesGenerated=0;   /* bytes consumed/generated */
    XDAS_UInt32 BytesRead=0;     /* bytes read by the decoder from tftp */
    XDAS_Int32  frameCount=0, displayFrame=0, encFrameCount = 0, encDisplayFrame=0; /* frame count and display frame count */

    XDAS_UInt32 processCycles;
    XDAS_Int32 outputSize;

    int jj;

   /* DDR init and start Filer I/O */
    siuVct_DDR_Init();

    siuVct_FileIO_Start();

    /*-----------------------------------------------------------------------*/
    /*  Initialize the first time flag to 1 which will get used for the      */
    /*  condition check for reinitializing the buffers after the first       */
    /*  decode call.                                                         */
    /*-----------------------------------------------------------------------*/
    first_time = 1;

    /* Create and configure decoder & encoder */
    createDecoder(decCodecname, &decInputBufDesc, &decOutputBufDesc);
    createEncoder(encCodecname);

    /* Decoder in and out args */
    decInArgs                = (IVIDDEC2_InArgs *)decAPI->decGetInArgs((void *)decInst);
    decOutArgs               = (IVIDDEC2_OutArgs *)decAPI->decGetOutArgs((void *)decInst);
    /* Resetting variables                                                   */
    decOutArgs->bytesConsumed = 0;
    decInArgs->numBytes = 0;
    /*-----------------------------------------------------------------------*/
    /*  The outBufsInUseFlag tells us whether the previous input buffer given*/
    /*  by the application to the algorithm is still in use or not. Since    */
    /*  this is before the first decode call, assign this flag to 0. The     */
    /*  algorithm will take care to initialize this flag appropriately from  */
    /*  hereon for the current configuration.                                */
    /*-----------------------------------------------------------------------*/
    decOutArgs->outBufsInUseFlag     = 0;

    transcodeYuvMgrInit();

    /* Do-While Loop for Decode Call                                         */
    do
    {
        /* Decoder read input data from TFTP */
        BytesRead = siuVct_ReadInputData(decInputBufDesc.descs[0].buf,decInputBufDesc.descs[0].bufSize, decOutArgs->bytesConsumed);

        /* Check for Break off condition                                       */
        if (BytesRead <=0) 
        {
            printf("\n Bitstream Ended...  ");
            break; /* Bitstream ended: Break off the while loop                  */
        }

        /* Decode frame */
        frameDecode(&decInputBufDesc, &decOutputBufDesc, decInArgs, decOutArgs, BytesRead, &processCycles);

        /* Check for frame ready via display buffer pointers                   */
        jj = 0;

        /* Write YUV data to DDR */
        while(decOutArgs->outputID[jj] && (displayFrame < framesToDecode))
        {
            printf("\n Decode frame #%d, Cycles consumed = %d, BytesConsumed = %d ",displayFrame, processCycles, decOutArgs->bytesConsumed);
            /* Write the decoder YUV output to DDR                     */
            siuVctDecode_WriteYUVData(&decOutArgs->displayBufs[jj]);

            displayFrame++;
            jj++;
        }

        /* Encoder frame */
        outputSize = frameEncode(&processCycles);
        if (outputSize > 0) 
        {
            printf("\n Encode frame #%d, Cycles consumed = %d, BytesGenerated = %d ", encDisplayFrame, processCycles, outputSize);
            /* Write the encoder output frame and tftp back to PC */
            siuVct_WriteOutputData((XDAS_Int8 *)&outputData[0], outputSize);
            bytesGenerated += outputSize;
            encDisplayFrame++;
            encFrameCount++;
        } 
        if (outputSize==0) encFrameCount++;

        bytesConsumed          += decOutArgs->bytesConsumed;
        frameCount++;

        if (frameCount >= framesToDecode)
        {
            break;
        }
    }  while(1);  /* end of Do-While loop                                    */

    /* Flush decoded frame */
    if((displayFrame < framesToDecode) && (displayFrame < frameCount) )
    {
        printf("\n Decoder flush ...  ");
        /* Decoder flush */
        frameDecFlush(&decInputBufDesc, &decOutputBufDesc, decInArgs, decOutArgs, &processCycles);
        jj = 0;

        /* Write the decoder output YUV in the display order                    */
        while(decOutArgs->outputID[jj] && (displayFrame < framesToDecode))
        {
            printf("\n Decode frame #%d, Cycles consumed = %d, BytesConsumed = %d ", displayFrame, processCycles, decOutArgs->bytesConsumed);
            siuVctDecode_WriteYUVData(&decOutArgs->displayBufs[jj]);
            displayFrame++;
            jj++;
        }

        do {
            /* Encode frame */            
            outputSize = frameEncode(&processCycles);
            if (outputSize > 0) 
            {
                printf("\n Encode frame #%d, Cycles consumed = %d, BytesGenerated = %d ",encDisplayFrame, processCycles, outputSize);
                /* Write the encoder output frame and tftp back to PC */
                siuVct_WriteOutputData((XDAS_Int8 *)&outputData[0], outputSize);
                encDisplayFrame++;
                encFrameCount++;
            }
            if (outputSize==0) encFrameCount++;
            if (encFrameCount >= framesToDecode)
            {
                break;
            }
        } while (1);
    }

    /* Flush frames for encoder */
    printf("\n Encoder flush ...  ");
    do{
        outputSize = frameEncFlush(&processCycles);
        if (outputSize > 0) 
        {
            printf("\n Encode frame #%d, Cycles consumed = %d, BytesGenerated = %d ",encDisplayFrame, processCycles, outputSize);
            /* Write the encoder output frame and tftp back to PC */
            siuVct_WriteOutputData((XDAS_Int8 *)&outputData[0], outputSize);
            encDisplayFrame++;
            encFrameCount++;
            bytesGenerated += outputSize;
        }
        if (encDisplayFrame >= framesToDecode)
            break;
    } while (1);

    /*-----------------------------------------------------------------------*/
    /*  The algorithm currently does not guarantee to set freebufid of       */
    /*  all buffers in use when the framecount exceeds framestoDecode.       */
    /*  This is managed for now by an application function. Note that        */
    /*  doing this has significance only when running multiple streams.      */
    /*-----------------------------------------------------------------------*/
    BUFFMGR_ReleaseAllBuffers();
    BUFFMGR_DeInit(MAX_BUFF_ELEMENTS, MAX_BUFS_IN_FRAME);

    /* Delete the Algorithm instance object specified by handle */
    ALG_delete (decHandle, 1);
    ALG_delete (encHandle, 0);

    if(frameCount == 0)
    {
        frameCount = 1; /* To avoid division with zero */
    }

    siuVct_FileIO_Stop();

    printf("\n --------------  SUMMARY --------------------\n");
    printf("\t Total number of Frames              = %d\n",
        (XDAS_UInt32)frameCount);
    printf("\t Decoder Bit Rate at 30 frames/Sec           = %d Kbps\n",
        (XDAS_UInt32)(((bytesConsumed*8*30)/frameCount)/1000));
    printf("\t Encoder Bit Rate at 30 frames/Sec           = %d Kbps\n",
        (XDAS_UInt32)(((bytesGenerated*8*30)/frameCount)/1000));

    printf (" --------------    END   --------------------\n");

    printf("\n End of execution\n");

    return(0);

} /* tvct_test_entry_decode_xdm1p0_encode_xdm0p9 */

/*
 *  ===== Remove padding when writing YUV data by the decoder  =====
 */
XDAS_Void siuVctDecode_WriteYUVData(IVIDEO1_BufDesc *displayBufs)
{
  XDAS_Int32 YWidth, YHeight, availableSize;
  XDAS_Int32 row,oddwidth=0,oddheight=0;
  XDAS_Int8 *output;

  siu_invalidate_cache();

  /* Align valid data to base of the buffer */
  if(yuv_ptr_start != yuv_ptr_working) {
      memcpy(yuv_ptr_start, yuv_ptr_working, yuv_numValidBytes);
      yuv_ptr_working = yuv_ptr_start;
  }

  availableSize = (yuv_memorySizeLimit - yuv_numValidBytes);

  output  = &displayBufs->bufDesc[0].buf[0];
  YWidth    = displayBufs->frameWidth;
  YHeight    = displayBufs->frameHeight;

  if(displayBufs->chromaFormat == 4)
  {
    for ( row=0; row < YHeight; row++ )
    {
      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, YWidth*2);
      yuv_numValidBytes += YWidth*2;
      availableSize -= YWidth*2;
      if (availableSize <= 0) goto error;
      output += displayBufs->framePitch;
    }
  }
  else if (displayBufs->chromaFormat == 1)
  {
    for ( row=0; row < YHeight; row++ )
    {
      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, YWidth);
      yuv_numValidBytes += YWidth;
      availableSize -= YWidth;
      if (availableSize <= 0) goto error;
      output += displayBufs->framePitch;
    }

    output      = &displayBufs->bufDesc[1].buf[0];

    for ( row=0; row < YHeight>>1; row++ )
    {
      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, YWidth>>1);
      yuv_numValidBytes += YWidth>>1;
      availableSize -= YWidth>>1;
      if (availableSize <= 0) goto error;

      if(oddwidth) {
          /* Copy decoder output to YUV data buffer */
          memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1)-1);
          yuv_numValidBytes += (YWidth>>1)-1;
          availableSize -= (YWidth>>1)-1;
          if (availableSize <= 0) goto error;
      }
      output +=    (displayBufs->framePitch>> 1);
    }

    if(oddheight)
    {
      output -=    (displayBufs->framePitch>> 1);

      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1));
      yuv_numValidBytes += (YWidth>>1);
      availableSize -= (YWidth>>1);
      if (availableSize <= 0) goto error;

      if(oddwidth) {
         /* Copy decoder output to YUV data buffer */
          memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1)-1);
          yuv_numValidBytes += (YWidth>>1)-1;
          availableSize -= (YWidth>>1)-1;
          if (availableSize <= 0) goto error;
      }
    }

    output     = &displayBufs->bufDesc[2].buf[0];

    for ( row=0; row < YHeight>>1; row++ )
    {
      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1));
      yuv_numValidBytes += (YWidth>>1);
      availableSize -= (YWidth>>1);
      if (availableSize <= 0) goto error;

      if(oddwidth) {
        /* Copy decoder output to YUV data buffer */
        memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1)-1);
        yuv_numValidBytes += (YWidth>>1)-1;
        availableSize -= (YWidth>>1)-1;
        if (availableSize <= 0) goto error;
      }
      output +=    (displayBufs->framePitch >> 1);
    }

    if(oddheight)
    {
      output -=    (displayBufs->framePitch>> 1);

      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1));
      yuv_numValidBytes += (YWidth>>1);
      availableSize -= (YWidth>>1);
      if (availableSize <= 0) goto error;

      if(oddwidth) {
        /* Copy decoder output to YUV data buffer */
        memcpy(&yuv_ptr_working[yuv_numValidBytes], output, (YWidth>>1)-1);
        yuv_numValidBytes += (YWidth>>1)-1;
        availableSize -= (YWidth>>1)-1;
        if (availableSize <= 0) goto error;
      }
    }
  }
  else if (displayBufs->chromaFormat == 2)
  {
    for ( row=0; row < YHeight; row++ )
    {
      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, YWidth);
      yuv_numValidBytes += YWidth;
      availableSize -= YWidth;
      if (availableSize <= 0) goto error;
      output += displayBufs->framePitch;
    }

    output      = &displayBufs->bufDesc[1].buf[0];
    /* Copy decoder output to YUV data buffer */
    memcpy(&yuv_ptr_working[yuv_numValidBytes], output, displayBufs->bufDesc[1].bufSize);
    yuv_numValidBytes += displayBufs->bufDesc[1].bufSize;
    availableSize -= displayBufs->bufDesc[1].bufSize;
    if (availableSize <= 0) goto error;
    output     = &displayBufs->bufDesc[2].buf[0];
    /* Copy decoder output to YUV data buffer */
    memcpy(&yuv_ptr_working[yuv_numValidBytes], output, displayBufs->bufDesc[2].bufSize);
    yuv_numValidBytes += displayBufs->bufDesc[2].bufSize;
    availableSize -= displayBufs->bufDesc[2].bufSize;
    if (availableSize <= 0) goto error;

  }
  else if (displayBufs->chromaFormat == 6)
  {
    for ( row=0; row < YHeight; row++ )
    {
      /* Copy decoder output to YUV data buffer */
      memcpy(&yuv_ptr_working[yuv_numValidBytes], output, YWidth);
      yuv_numValidBytes += YWidth;
      availableSize -= YWidth;
      if (availableSize <= 0) goto error;
      output += displayBufs->framePitch;
    }
    output      = &displayBufs->bufDesc[1].buf[0];
    /* Copy decoder output to YUV data buffer */
    memcpy(&yuv_ptr_working[yuv_numValidBytes], output, displayBufs->bufDesc[1].bufSize);
    yuv_numValidBytes += displayBufs->bufDesc[1].bufSize;
    availableSize -= displayBufs->bufDesc[1].bufSize;
    if (availableSize <= 0) goto error;
    output     = &displayBufs->bufDesc[2].buf[0];
    /* Copy decoder output to YUV data buffer */
    memcpy(&yuv_ptr_working[yuv_numValidBytes], output, displayBufs->bufDesc[2].bufSize);
    yuv_numValidBytes += displayBufs->bufDesc[2].bufSize;
    availableSize -= displayBufs->bufDesc[2].bufSize;
    if (availableSize <= 0) goto error;

  }
  siu_osal_wbinv_cache_all();

  return;
error: 
  printf("\n Overflow when writing decoded YUV data into the buffer ...");
  return;
}


/*
 *  ======== Create, initialize, and configure encoder ========
 */
XDAS_Int32 createEncoder(const char* encCodecname)
{

    void            *encFxns;
    IVIDENC2_Params *staticParams;
    IVIDMC_t         mcVidEncParams;
    IRES_Fxns       *resFxns;
    void *encCodecParams    = (void *)&(siuVctCodecParams.staticParamsCh1[0]);
    void *encCodecDynParams = (void *)&(siuVctCodecParams.dynamicParamsCh1[0]);

    XDAS_UInt32 bufSizeTotal = 0;
    XDAS_Int32 numBufs, numRefBufs, bufSizes[MAX_BUFS_IN_FRAME];
    
    /* Get encoder API table */
    encAPI = getVidEncoderAPI(encCodecname);

    if (encAPI == NULL){
       printf("\nEncoder is not installed .. exiting \n");
       return -1;
    }

    if(encAPI->encInstanceSize >= MAX_ENC_INST_SIZE) {
       printf("\nEncoder Instance Size Exceeds allocated value.. exiting \n");
       return -1;
    }
    encAPI->encInitInstance((void *)encInst2);

    /* Initialization of multi-core params. Do this before encSetStaticParams
        so that it can be populated to StaticParams */
    siuVidMc_Init_ShmemTab(DNUM);
    mcVidEncParams.swbarr        = siuVidMc_Swbarr;
    mcVidEncParams.shmmap        = siuVidMc_Map_Shmem;
    mcVidEncParams.shmmunmap     = siuVidMc_Unmap_Shmem;
    mcVidEncParams.shmmap_sync   = siuVidMc_Shmem_Sync;
    mcVidEncParams.Lock          = NULL;
    mcVidEncParams.UnLock        = NULL;
    mcVidEncParams.ncores        = 1;
    mcVidEncParams.core_task_ID  = IVIDMC_TASK_MASTER;
    mcVidEncParams.coreID        = DNUM;

    encAPI->encSetMcParams((void *)encInst2, &mcVidEncParams);

    /* Initialization of parameters needed for Algorithm Instance create */
    encAPI->encSetStaticParams((void *)encInst2, (void *)encCodecParams, 0);

    /* Get XDM0.9 pointers from the codec */
    encFxns               =  encAPI->encGetFxns((void *)encInst2);
    staticParams          = (IVIDENC2_Params *)encAPI->encGetStaticParams((void *)encInst2);

    /* Create codec instance */
    if ((encHandle =  (IALG_Handle)ALG_create (
        (IALG_Fxns *) encFxns,
        (IALG_Handle) NULL,
        (IALG_Params *) staticParams,
         1)) == NULL)
    {
        printf("\nFailed to Create Encoder Instance... Exiting for this configuration..");
        return -1;
    }

    printf("\nEncoder Algorithm Instance Creation Done...\n");

    /* Set run time dynamic parameters */
    encAPI->encSetDynamicParams((void *)encInst2, (void *)encCodecDynParams);

    /* Assign resources to the algorithm: check if any changes are needed here */
    resFxns = encAPI->encGetIresFxns();

    /* Activate the Algorithm                                               */
    encHandle->fxns->algActivate(encHandle);
    if (siu_osal_fc_assign_resources((void *)encHandle, (void *)resFxns, SIU_FC_USER_GROUP0) == FALSE) {
        printf("Assign Resource Failed \n");
        return (-1);
    }
    /* Deactivate the Algorithm                                              */
    encHandle->fxns->algDeactivate(encHandle);
    siu_osal_wbinv_cache_all();

    bufSizeTotal = xdm2p0_vid_enc_buf_query(&numBufs, bufSizes);

    if(bufSizeTotal > 0) {
        if(BUFFMGR_Init(numBufs, &bufSizes[0], BUFFMGR_1) == -1)
        {
            printf("\n Buffer Init Fails ... ");
            return -1;
        }

        numRefBufs = MAX_BUFF_ELEMENTS;
        if(BUFFMGR_ReInit(numRefBufs, numBufs, &bufSizes[0], BUFFMGR_1) == -1)
        {
            printf("\n Buffer ReInit Fails ... ");
            return -1;
        }
   }

   return 0;
}

/*
 *  ======== Create, initialize, and configure decoder ========
 */
XDAS_Int32 participating_cores_all[1] = {0};
XDAS_Int32 createDecoder(const char* decCodecname,
                         XDM1_BufDesc *decInputBufDesc, XDM_BufDesc *decOutputBufDesc)
{
	IVIDMC3_t                mcVid3Params;
    void                    *decFxns;
    IVIDDEC2_Params         *decStaticParams;
    IVIDDEC2_DynamicParams  *decDynamicParams;
    IVIDDEC2_Status         *decStatus;
    IVIDDEC2_Fxns           *ividDecFxns;
    IRES_Fxns               *resFxns;
    void *decCodecParams    = (void *)&(siuVctCodecParams.staticParams[0]);
    void *decCodecDynParams = (void *)&(siuVctCodecParams.dynamicParams[0]);

    XDAS_Int32              ii, ret_val;

    /* Get decoder API table */
    decAPI = getVidDecoderAPI(decCodecname);

    if (decAPI == NULL){
       printf("Decoder is not installed .. exiting \n");
       return -1;
    }

    if(decAPI->decInstanceSize >= MAX_DEC_INST_SIZE) {
       printf("Decoder Instance Size Exceeds allocated value.. exiting \n");
       return -1;
    }
    decAPI->decInitInstance((void *)decInst);

    /* Initialization of multi-core params. Do this before decSetStaticParams
        so that it can be populated to static params */
    siuVidMc3Init(0, 1);
    mcVid3Params.keyCreate      = siuVidMc3KeyCreate;
    mcVid3Params.barrWait       = siuVidMc3BarrWait;
    mcVid3Params.shmMap         = siuVidMc3ShmMap;
    mcVid3Params.shmSync        = siuVidMc3ShmSync;
    mcVid3Params.shmSyncWait    = siuVidMc3ShmSyncWait;
    mcVid3Params.lockAcquire    = siuVidMc3LockAcquire;
    mcVid3Params.lockRelease    = siuVidMc3LockRelease;
    mcVid3Params.lockCheck      = siuVidMc3LockCheck;
    mcVid3Params.mailBoxOpen    = siuVidMc3MailBoxOpen;
    mcVid3Params.mailBoxWrite   = siuVidMc3MailBoxWrite;
    mcVid3Params.mailBoxRead    = siuVidMc3MailBoxRead;
    mcVid3Params.mailBoxQuery   = siuVidMc3MailBoxQuery;
    mcVid3Params.num_users      = 1;
    mcVid3Params.task_ID        = IVIDMC3_TASK_MASTER;
    mcVid3Params.user_id        = 0;

    decAPI->decSetMcParams((void *)decInst,  (void *)&mcVid3Params);

    /* Initialization of parameters needed for Algorithm Instance create */
    decAPI->decSetStaticParams((void *)decInst, decCodecParams);

    /* Get XDM1.0 pointers from the codec */
    decFxns                  =  decAPI->decGetFxns((void *)decInst);
    decStaticParams          = (IVIDDEC2_Params *)decAPI->decGetStaticParams((void *)decInst);
    decDynamicParams         = (IVIDDEC2_DynamicParams *)decAPI->decGetDynamicParams((void *)decInst);
    decStatus                = (IVIDDEC2_Status *)decAPI->decGetStatus((void *)decInst);

    /* Create the Decoder Algorithm object (instance)                                */
    printf("\nCreating Decoder Algorithm Instance...");

    if ((decHandle =  (IALG_Handle)ALG_create (
        (IALG_Fxns *) decFxns,
        (IALG_Handle) NULL,
        (IALG_Params *) decStaticParams,
         0)) == NULL)
    {
        printf( "\nFailed to Create Instance... Exiting for this configuration..");
        return(-1);
    }
    printf("\nAlgorithm Instance Creation Done...\n");

    decHandle->fxns->algActivate((IALG_Handle)decHandle);

    /* Assign resources to the algorithm */
    resFxns = decAPI->decGetIresFxns();
    if (siu_osal_fc_assign_resources((void *)decHandle, (void *)resFxns, SIU_FC_USER_GROUP0) == FALSE) {
        printf("Assign Resource Failed \n");
        return (-1);
    }

    /* Assigning Algorithm handle fxns field to ividDecfxns                  */
    ividDecFxns = (IVIDDEC2_Fxns *)decHandle->fxns;

    /* Set run time dynamic parameters */
    decAPI->decSetDynamicParams((void *)decInst, (void *)decCodecDynParams);

    /*-----------------------------------------------------------------------*/
    /*  The XDM_RESET call gives resets all the internal data structures and */
    /*  context for the new stream that is to be decoded.                    */
    /*-----------------------------------------------------------------------*/
    ividDecFxns->control((IVIDDEC2_Handle)decHandle, XDM_RESET,     decDynamicParams, decStatus);
    ividDecFxns->control((IVIDDEC2_Handle)decHandle, XDM_SETPARAMS, decDynamicParams, decStatus);

    decHandle->fxns->algDeactivate((IALG_Handle)decHandle);
    siu_osal_wbinv_cache_all();

    /*-----------------------------------------------------------------------*/
    /*  The GETBUFINFO call gives information for number and size of input   */
    /*  and output buffers. For this first call, the actual width and height */
    /*  of the picture is not known hence, this control call returns the out */
    /*  buffer sizes based on the maxHeight and maxWidth provided as part    */
    /*  of the input params from testparams file.                            */
    /*-----------------------------------------------------------------------*/
    decHandle->fxns->algActivate((IALG_Handle)decHandle);
    ividDecFxns->control((IVIDDEC2_Handle)decHandle, XDM_GETBUFINFO, decDynamicParams, decStatus);
    decHandle->fxns->algDeactivate((IALG_Handle)decHandle);

    /*-----------------------------------------------------------------------*/
    /*  The buffermanager init function call allocates the memory for the    */
    /*  number of buffers of the corresponding sizes as passed in arguments  */
    /*  to it. This function initializes the output/reference bufs based on  */
    /*  the outBuf parameters returned from the GETBUFINFO call above. This  */
    /*  call will allocate each of the numOutbufs memory equal to (specified */
    /*  bufsize). The initialization and allocation of buff ptr will take    */
    /*  place only for the first ref buffer. For the remaining ref buffers,  */
    /*  allocation will happen after the first decode call, when actual      */
    /*  height and width of picture are known.                               */
    /*  Note that the allocation of output/ref buffers will happen each time */
    /*  for the entire bunch of configuration sets provided in the testvecs  */
    /*  config file.                                                         */
    /*-----------------------------------------------------------------------*/
    ret_val = BUFFMGR_Init(decStatus->bufInfo.minNumOutBufs,
                        decStatus->bufInfo.minOutBufSize, BUFFMGR_0);

    if (ret_val)
    {
        printf ("\nMemory could not get allocated for output buffers\n");
        return -1;
    }
    /*-----------------------------------------------------------------------*/
    /*  Initialize the input buffer properties as required by algorithm      */
    /*  based on info received by preceding GETBUFINFO call. First init the  */
    /*  number of input bufs.                                                */
    /*-----------------------------------------------------------------------*/

    decInputBufDesc->numBufs          = decStatus->bufInfo.minNumInBufs ;
    decInputBufDesc->descs[0].bufSize = decStatus->bufInfo.minInBufSize[0];

    for(ii=0; ii<(decStatus->bufInfo.minNumInBufs-1);ii++ )
    {
        decInputBufDesc->descs[ii+1].buf = decInputBufDesc->descs[ii].buf +
            decStatus->bufInfo.minInBufSize[ii];
        decInputBufDesc->descs[ii+1].bufSize =
            decStatus->bufInfo.minInBufSize[ii +1];
    }

    /*-----------------------------------------------------------------------*/
    /*  Initialize the output buffer properties as required by algorithm     */
    /*  based on info received by preceding GETBUFINFO call.                 */
    /*-----------------------------------------------------------------------*/
    decOutputBufDesc->numBufs = decStatus->bufInfo.minNumOutBufs;

    /* set space for buffer descriptors                                      */
    decInputBufDesc->descs[0].buf     = decInpBuf;

    return 0;

}


XDAS_UInt32 xdm2p0_vid_enc_buf_query(XDAS_Int32* numInBufs, XDAS_Int32 *bufSizes)
{
  IVIDENC2_Fxns           *ividEncfxns=(IVIDENC2_Fxns *)encHandle->fxns;
  IVIDENC2_DynamicParams  *dynamicParams;
  IVIDENC2_Status         *status; 
  XDAS_Int32               i;
  XDAS_UInt32              totalSize = 0;

  dynamicParams         = (IVIDENC2_DynamicParams *)encAPI->encGetDynamicParams((void *)encInst2);
  status                = (IVIDENC2_Status *)encAPI->encGetStatus((void *)encInst2);

  encHandle->fxns->algActivate((IALG_Handle)encHandle);
  ividEncfxns->control((IVIDENC2_Handle)encHandle, XDM_GETBUFINFO, dynamicParams, status);
  encHandle->fxns->algDeactivate((IALG_Handle)encHandle);

  *numInBufs = status->bufInfo.minNumInBufs;
  for(i=0;i<status->bufInfo.minNumInBufs;i++) {
    bufSizes[i] = status->bufInfo.minInBufSize[i].bytes;
    totalSize += bufSizes[i];
  }

  return totalSize;
}

XDAS_Int32 xdm2p0_vid_set_iobufdesc(IVIDEO2_BufDesc *pInputBufDesc, XDM2_BufDesc *pOutputBufDesc, BUFFMGR_buffEleHandle buffEleEnc)
{
  XDAS_Int32 retVal, i, bytesConsumed;
  XDAS_UInt32 captureWidth, captureHeight;
  IVIDENC2_Fxns           *ividEncfxns;
  IVIDENC2_Params         *staticParams;
  IVIDENC2_DynamicParams  *dynamicParams;
  IVIDENC2_Status         *status; 

  /* Get XDM2.0 pointers from the codec */
  ividEncfxns           = (IVIDENC2_Fxns *)encHandle->fxns;
  staticParams          = (IVIDENC2_Params *)encAPI->encGetStaticParams((void *)encInst2);
  dynamicParams         = (IVIDENC2_DynamicParams *)encAPI->encGetDynamicParams((void *)encInst2);
  status                = (IVIDENC2_Status *)encAPI->encGetStatus((void *)encInst2);

  captureWidth   =  (dynamicParams->captureWidth + 15) & ~15;
  if(captureWidth == 0)
  {
    captureWidth =  (dynamicParams->inputWidth + 15) & ~15;
  }
  captureHeight   = (dynamicParams->inputHeight + 15) & ~15 ;

  encHandle->fxns->algActivate((IALG_Handle)encHandle);
  retVal= ividEncfxns->control((IVIDENC2_Handle)encHandle, XDM_GETBUFINFO, dynamicParams, status);
  encHandle->fxns->algDeactivate((IALG_Handle)encHandle);

  if(retVal == XDM_EFAIL)
  {
    printf("\n XDM_GETBUFINFO Control function returned an Error...  exiting");
    return -1; 
  }

    /*------------------------------------------------------------------------*/
    /*  Initialize the input buffer properties as required by algorithm       */
    /*  based on info received by preceding GETBUFINFO call.                  */
    /*------------------------------------------------------------------------*/
    pInputBufDesc->numPlanes = status->bufInfo.minNumInBufs;
    pInputBufDesc->numMetaPlanes = 0;

    /*------------------------------------------------------------------------*/
    /* Set entire Image region in the buffer  by using config parameters      */
    /*------------------------------------------------------------------------*/
    pInputBufDesc->imageRegion.topLeft.x = 0;
    pInputBufDesc->imageRegion.topLeft.y = 0;
    pInputBufDesc->imageRegion.bottomRight.x = captureWidth;
    pInputBufDesc->imageRegion.bottomRight.y = captureHeight;

    /*------------------------------------------------------------------------*/
    /* Image pitch is capture width                                           */
    /*------------------------------------------------------------------------*/
    pInputBufDesc->imagePitch[0] = dynamicParams->captureWidth;
    pInputBufDesc->imagePitch[1] = dynamicParams->captureWidth;

    /*------------------------------------------------------------------------*/
    /* Set Content type and chroma format from encoder parameters             */
    /*------------------------------------------------------------------------*/
    pInputBufDesc->contentType = staticParams->inputContentType;
    pInputBufDesc->chromaFormat = staticParams->inputChromaFormat;

    /*------------------------------------------------------------------------*/
    /* Assign memory pointers and sizes for all the input buffers         */
    /*------------------------------------------------------------------------*/
    pInputBufDesc->numPlanes = 0;

    for(i = 0; i < status->bufInfo.minNumInBufs; i++)
    {
      pInputBufDesc->numPlanes++;
      pInputBufDesc->planeDesc[i].memType = (XDAS_Int16)(status->bufInfo.inBufMemoryType[i]);
      pInputBufDesc->planeDesc[i].bufSize.bytes = status->bufInfo.minInBufSize[i].bytes;
      if (buffEleEnc!=NULL) {
          if(i == 0)
            pInputBufDesc->planeDesc[i].buf = (XDAS_Int8*)buffEleEnc->buf[0];
          else
            pInputBufDesc->planeDesc[i].buf = pInputBufDesc->planeDesc[i-1].buf + 
                                          status->bufInfo.minInBufSize[i-1].bytes;
      } else {
          pInputBufDesc->planeDesc[i].buf = 0;
      }
    }
    fflush(stdout);    

    pInputBufDesc->dataLayout         = 0; //encoderParams->dataLayout;
    pInputBufDesc->topFieldFirstFlag  = 0; //encoderParams->topFieldFirstFlag;

    if(staticParams->metadataType[pInputBufDesc->numMetaPlanes]== 258) // IH264_USER_DEFINED_SCALINGMATRIX
    {
      pInputBufDesc->metadataPlaneDesc[pInputBufDesc->numMetaPlanes].buf = (XDAS_Int8 *)(encAPI->metaDataPlane);
      pInputBufDesc->metadataPlaneDesc[pInputBufDesc->numMetaPlanes].bufSize.bytes = encAPI->metaDataSize;
      pInputBufDesc->numMetaPlanes++;
    }

    /*------------------------------------------------------------------------*/
    /* Initialise output descriptors                                          */
    /*------------------------------------------------------------------------*/
    pOutputBufDesc->numBufs = 0;
    for(i = 0; i < status->bufInfo.minNumOutBufs; i++)
    {
      pOutputBufDesc->numBufs++;
      pOutputBufDesc->descs[i].memType = status->bufInfo.outBufMemoryType[i];
      pOutputBufDesc->descs[i].bufSize.bytes = status->bufInfo.minOutBufSize[i].bytes;
      if(i == 0)
        pOutputBufDesc->descs[0].buf = (XDAS_Int8*)&outputData[0];
      else
        pOutputBufDesc->descs[i].buf = pOutputBufDesc->descs[i-1].buf + 
                                      status->bufInfo.minOutBufSize[i-1].bytes;
    } 

    /* Get encoder input: YUV data output by the decoder */
    for(i=0; i < status->bufInfo.minNumInBufs; i++)
    {
        if (yuv_numValidBytes < pInputBufDesc->planeDesc[i].bufSize.bytes) {
            return -1;
        }
        if(pInputBufDesc->planeDesc[i].buf != NULL) {
            memcpy(pInputBufDesc->planeDesc[i].buf, yuv_ptr_working, pInputBufDesc->planeDesc[i].bufSize.bytes);        
            bytesConsumed = pInputBufDesc->planeDesc[i].bufSize.bytes;            
            yuv_numValidBytes -= bytesConsumed;
            yuv_ptr_working   += bytesConsumed;
        }
    }
    return 0;
}


/*
 *  ======== Encode a frame ========
 */
XDAS_Int32 frameEncode(XDAS_UInt32 *processCycles)
{
    IVIDENC2_Fxns *ividEncfxns;
    XDAS_Int32   i, RetVal;
    XDAS_UInt32  TSCL_Begin, TSCL_End;

    IVIDENC2_DynamicParams *dynamicParams;
    IVIDENC2_InArgs        *inArgs;
    IVIDENC2_OutArgs       *outArgs;
    IVIDENC2_Status        *status;

    /* Input/Output Buffer Descriptor variables */
    IVIDEO2_BufDesc  inputBufDesc;
    XDM2_BufDesc     outputBufDesc;
    BUFFMGR_buffEleHandle buffEleEnc;

    buffEleEnc = BUFFMGR_GetFreeBuffer(BUFFMGR_1);    

    inArgs                = (IVIDENC2_InArgs *)encAPI->encGetInArgs((void *)encInst2);
    outArgs               = (IVIDENC2_OutArgs *)encAPI->encGetOutArgs((void *)encInst2);
    dynamicParams         = (IVIDENC2_DynamicParams *)encAPI->encGetDynamicParams((void *)encInst2);
    status                = (IVIDENC2_Status *)encAPI->encGetStatus((void *)encInst2);

    /* Assigning Encoder Algorithm handle fxns field to ividEncfxns */
    ividEncfxns = (IVIDENC2_Fxns *)encHandle->fxns ;

    /* Activate the Algorithm                                               */
    encHandle->fxns->algActivate(encHandle);

    /* Optional: Set Run time parameters in the Algorithm via control()     */
    RetVal = ividEncfxns->control((IVIDENC2_Handle)encHandle, XDM_SETPARAMS,
        (IVIDENC2_DynamicParams *)dynamicParams, (IVIDENC2_Status *)status);

    if(RetVal == XDM_EFAIL)
    {
        printf("\n Encoder control function returned an Error...  ");
        return -1; /* Error Condition: Application may want to break off          */
    }

    RetVal= ividEncfxns->control((IVIDENC2_Handle)encHandle,
        XDM_GETBUFINFO,
        (IVIDENC2_DynamicParams *)dynamicParams,
        (IVIDENC2_Status *)status);

    if(RetVal == XDM_EFAIL)
    {
        printf("\n Encoder control function returned an Error...  ");
        return -2; /* Error Condition: Application may want to break off          */
    }

    encHandle->fxns->algDeactivate(encHandle);

    if(xdm2p0_vid_set_iobufdesc(&inputBufDesc, &outputBufDesc, buffEleEnc) == -1)
        return -3; /*no yuv to encode*/

    encHandle->fxns->algActivate(encHandle);
    
    inArgs->inputID = buffEleEnc->bufId;

    TSCL_Begin = TSCL;
    /* Basic Algorithm process() call */
    RetVal = ividEncfxns->process((IVIDENC2_Handle)encHandle,
        (IVIDEO2_BufDesc *)&inputBufDesc,
        (XDM2_BufDesc *)&outputBufDesc,
        (IVIDENC2_InArgs *)inArgs,
        (IVIDENC2_OutArgs *)outArgs);
    TSCL_End   = TSCL;
    *processCycles = TSCL_End - TSCL_Begin;

    if (outArgs->bytesGenerated > max_output_bufsize)
        max_output_bufsize = outArgs->bytesGenerated;
    if (outArgs->bytesGenerated > CORE_OUTPUT_BUF_SIZE)
    {
        printf("\n Encoder overflow on local output buffer...  ");
        return -1; /* Error Condition: Application may want to break off   */
    }

    if(RetVal == XDM_EFAIL)
    {
      printf("\n Process function returned an Error...  %d", outArgs->extendedError);
    }
    /* Optional: Read status via control()                                  */
    ividEncfxns->control((IVIDENC2_Handle)encHandle,
        XDM_GETSTATUS,
        (IVIDENC2_DynamicParams *)dynamicParams,
        (IVIDENC2_Status *)status);

    /* DeActivate the Algorithm                                             */
    encHandle->fxns->algDeactivate(encHandle);
    siu_osal_wbinv_cache_all();

    i=0;
    while ( outArgs->freeBufID[i] != 0 ) {
        BUFFMGR_ReleaseBuffer((XDAS_UInt32 *)&outArgs->freeBufID[i], BUFFMGR_1);
        i++;
    }

    return (outArgs->bytesGenerated);
    /* Encoder process call: end */
}

/*
 *  ======== Decode a frame ========
 */
XDAS_Int32 frameDecode(XDM1_BufDesc *decInputBufDesc, XDM_BufDesc *decOutputBufDesc,
                     IVIDDEC2_InArgs *decInArgs, IVIDDEC2_OutArgs *decOutArgs,
                     XDAS_UInt32 BytesRead, XDAS_UInt32 *processCycles)
{
    XDAS_Int32               retVal, i;
    IVIDDEC2_Fxns           *ividDecFxns;
    IVIDDEC2_DynamicParams  *decDynamicParams;
    IVIDDEC2_Status         *decStatus;

    XDAS_UInt32             TSCL_Begin, TSCL_End;

    /*-------------------------------------------------------------------------*/
    /*  Handle to a buffer element allocated by the buffer manager module      */
    /*-------------------------------------------------------------------------*/
    BUFFMGR_buffEleHandle buffEleDec;

    /* Assign the number of bytes available                                */
    decInputBufDesc->descs[0].buf   = (XDAS_Int8 *)((XDAS_Int32) decInpBuf);
    decInArgs->numBytes =  BytesRead;

    /*---------------------------------------------------------------------*/
    /*  Check for the value of the outBufsInUseFlag. If the previous       */
    /*  decode call was for the first field of an interlaced frame, the    */
    /*  previous outbuf supplied by algorithm may still be required for    */
    /*  decoding second field. In that case, the algorithm will not need   */
    /*  a new buffer from the application. If above is not the case, call  */
    /*  the getfreebuffer() function of buffermanager to get the buffer    */
    /*  element to be supplied to algorithm for the next decode call.      */
    /*---------------------------------------------------------------------*/
    if (!decOutArgs->outBufsInUseFlag)
    {
        buffEleDec = BUFFMGR_GetFreeBuffer(BUFFMGR_0);
        if (buffEleDec==NULL) {
            printf("\n Decoder cannot get a free Buffer ");
        }
    }

    /*---------------------------------------------------------------------*/
    /*  Copy the output buffer size values and pointers from the buffer    */
    /*  element returned by getfreebuffer() function. Initialize the       */
    /*  numBufs to 2 as numoutbufs is always 2 for luma and chroma buffers.*/
    /*---------------------------------------------------------------------*/
    decOutputBufDesc->bufSizes    = (XDAS_Int32 *) buffEleDec->bufSize;
    decOutputBufDesc->bufs        = (XDAS_Int8 **) buffEleDec->buf;

    /*---------------------------------------------------------------------*/
    /*  Initialize the input ID in input arguments to the bufferid of the  */
    /*  buffer element returned from getfreebuffer() function.             */
    /*---------------------------------------------------------------------*/
    decInArgs->inputID           = buffEleDec->bufId;

    decDynamicParams         = (IVIDDEC2_DynamicParams *)decAPI->decGetDynamicParams((void *)decInst);
    decStatus                = (IVIDDEC2_Status *)decAPI->decGetStatus((void *)decInst);

    decHandle->fxns->algActivate((IALG_Handle)decHandle);

    /* Optional: Set Run time parameters in the Algorithm via control()    */
    ividDecFxns = (IVIDDEC2_Fxns *)decHandle->fxns;
    ividDecFxns->control((IVIDDEC2_Handle)decHandle, XDM_SETPARAMS, decDynamicParams, decStatus);

    decOutArgs->displayBufs->frameWidth =0;
    decOutArgs->displayBufs->frameHeight =0;

    TSCL_Begin = TSCL;
    /* Basic Algorithm process() call                                      */
    retVal = ividDecFxns->process((IVIDDEC2_Handle)decHandle,
        (XDM1_BufDesc *)decInputBufDesc,
        (XDM_BufDesc *)decOutputBufDesc,
        decInArgs,
        decOutArgs);
    TSCL_End   = TSCL;
    *processCycles = TSCL_End - TSCL_Begin;

    decHandle->fxns->algDeactivate((IALG_Handle)decHandle);

    if(retVal == XDM_EFAIL)
    {
        printf("\n Process function returned an Error for stream...\n");
        siuVct_FileIO_Stop();
        return(-1);
    }

    /*---------------------------------------------------------------------*/
    /*  If this is the first time in the stream, reinitialize all the      */
    /*  buffers based on the picture width and height.                     */
    /*---------------------------------------------------------------------*/
    if (first_time)
    {
        IVIDDEC2_DynamicParams  *decDynamicParams;
        IVIDDEC2_Status         *decStatus;

        decHandle->fxns->algActivate((IALG_Handle)decHandle);
        decDynamicParams         = (IVIDDEC2_DynamicParams *)decAPI->decGetDynamicParams((void *)decInst);
        decStatus                = (IVIDDEC2_Status *)decAPI->decGetStatus((void *)decInst);

        /*-----------------------------------------------------------------*/
        /*  The GETBUFINFO call will give information for number of        */
        /*  output buffers. This call is after the first decode call hence */
        /*  the outputbuffer sizes returned by this call is calculated     */
        /*  based on the actual pic width and height. Hence, there is need */
        /*  for buffer allocation and initializations which happens        */
        /*  immediately after this call.                                   */
        /*-----------------------------------------------------------------*/
        ividDecFxns->control((IVIDDEC2_Handle)decHandle,XDM_GETBUFINFO, decDynamicParams, decStatus);

        /*-----------------------------------------------------------------*/
        /*  Reinitialize the buffers using the actual buffer sizes for     */
        /*  luma and chroma. This call will allocate and initialize the    */
        /*  remaining buf ptrs for the max num of ref frames supplied by   */
        /*  the alg in maxNumDisplayBufs (max ref buffers required). The   */
        /*  first call to buffmgr_init() had allocated the first ref       */
        /*  buffers hence this reinit call will allocate and init the      */
        /*  remaining ref buffers' pointers. The 1st ref buf ptr will      */
        /*  continue to be the one which was allocated by the buffmgr_init */
        /*  call.                                                          */
        /*-----------------------------------------------------------------*/
        BUFFMGR_ReInit (decStatus->maxNumDisplayBufs,
            decStatus->bufInfo.minNumOutBufs, decStatus->bufInfo.minOutBufSize, BUFFMGR_0);

        /*-----------------------------------------------------------------*/
        /*  Reset the flag first_time to 0 since the buffers are correctly */
        /*  reinitialized.                                                 */
        /*-----------------------------------------------------------------*/
        first_time = 0;
        decHandle->fxns->algDeactivate((IALG_Handle)decHandle);
    }

    /*---------------------------------------------------------------------*/
    /*  Always release buffers - which are released from the algorithm     */
    /*  side   -back to the buffer manager. The freebufID array of outargs */
    /*  contains the sequence of bufferIds which need to be freed. This    */
    /*  gets populated by the algorithm. The following function will do    */
    /*  the job of freeing up the buffers.                                 */
    /*---------------------------------------------------------------------*/
    i = 0;
    while ( decOutArgs->freeBufID[i] != 0 ) {
        BUFFMGR_ReleaseBuffer((XDAS_UInt32 *)&decOutArgs->freeBufID[i], BUFFMGR_0);
        i++;
    }

    return 0;
}

XDAS_Int32 frameDecFlush(XDM1_BufDesc *decInputBufDesc, XDM_BufDesc *decOutputBufDesc,
                     IVIDDEC2_InArgs *decInArgs, IVIDDEC2_OutArgs *decOutArgs,
                     XDAS_UInt32 *processCycles)
{
    IVIDDEC2_DynamicParams  *decDynamicParams;
    IVIDDEC2_Status         *decStatus;
    IVIDDEC2_Fxns           *ividDecFxns;
    XDAS_UInt32             TSCL_Begin, TSCL_End;

    decDynamicParams         = (IVIDDEC2_DynamicParams *)decAPI->decGetDynamicParams((void *)decInst);
    decStatus                = (IVIDDEC2_Status *)decAPI->decGetStatus((void *)decInst);
    ividDecFxns = (IVIDDEC2_Fxns *)decHandle->fxns;

    decHandle->fxns->algActivate((IALG_Handle)decHandle);

    /* Add logic for flushing display buffers */
    ividDecFxns->control((IVIDDEC2_Handle)decHandle,XDM_FLUSH, decDynamicParams, decStatus);

    decHandle->fxns->algDeactivate((IALG_Handle)decHandle);

    decHandle->fxns->algActivate((IALG_Handle)decHandle);

    /* Basic Algorithm process() call                                      */
    TSCL_Begin = TSCL;
    ividDecFxns->process((IVIDDEC2_Handle)decHandle,
        (XDM1_BufDesc *)decInputBufDesc,
        (XDM_BufDesc *)decOutputBufDesc,
        decInArgs,
        decOutArgs);
    TSCL_End   = TSCL;
    *processCycles = TSCL_End - TSCL_Begin;

    decHandle->fxns->algDeactivate((IALG_Handle)decHandle);

    return 0;
}


XDAS_Int32 frameEncFlush(XDAS_UInt32 *processCycles)
{
    IVIDENC2_Fxns *ividEncfxns;
    XDAS_Int32   i, RetVal;
    XDAS_UInt32  TSCL_Begin, TSCL_End;

    IVIDENC2_DynamicParams *dynamicParams;
    IVIDENC2_InArgs        *inArgs;
    IVIDENC2_OutArgs       *outArgs;
    IVIDENC2_Status        *status;

    /* Input/Output Buffer Descriptor variables */
    IVIDEO2_BufDesc  inputBufDesc;
    XDM2_BufDesc     outputBufDesc;

    inArgs                = (IVIDENC2_InArgs *)encAPI->encGetInArgs((void *)encInst2);
    outArgs               = (IVIDENC2_OutArgs *)encAPI->encGetOutArgs((void *)encInst2);
    dynamicParams         = (IVIDENC2_DynamicParams *)encAPI->encGetDynamicParams((void *)encInst2);
    status                = (IVIDENC2_Status *)encAPI->encGetStatus((void *)encInst2);

    /* Assigning Encoder Algorithm handle fxns field to ividEncfxns */
    ividEncfxns = (IVIDENC2_Fxns *)encHandle->fxns ;

    /* Activate the Algorithm                                               */
    encHandle->fxns->algActivate(encHandle);

    /* Set FLUSH via control()     */
    RetVal = ividEncfxns->control((IVIDENC2_Handle)encHandle, XDM_FLUSH,
        (IVIDENC2_DynamicParams *)dynamicParams, (IVIDENC2_Status *)status);

    if(RetVal == XDM_EFAIL)
    {
        printf("\n Encoder control function returned an Error...  ");
        return -1; /* Error Condition: Application may want to break off          */
    }

    encHandle->fxns->algDeactivate(encHandle);

    xdm2p0_vid_set_iobufdesc(&inputBufDesc, &outputBufDesc, NULL);

    inArgs->inputID    = 0;
    inputBufDesc.planeDesc[0].buf   = 0;
    inputBufDesc.planeDesc[1].buf   = 0;
    inputBufDesc.planeDesc[2].buf   = 0;

    outputBufDesc.numBufs = 1;
    outputBufDesc.descs[0].buf = (XDAS_Int8*)&outputData[0];
    outputBufDesc.descs[0].bufSize.bytes = status->bufInfo.minOutBufSize[0].bytes;

    encHandle->fxns->algActivate(encHandle);
    
    TSCL_Begin = TSCL;
    /* Basic Algorithm process() call */
    RetVal = ividEncfxns->process((IVIDENC2_Handle)encHandle,
        (IVIDEO2_BufDesc *)&inputBufDesc,
        (XDM2_BufDesc *)&outputBufDesc,
        (IVIDENC2_InArgs *)inArgs,
        (IVIDENC2_OutArgs *)outArgs);
    TSCL_End   = TSCL;
    *processCycles = TSCL_End - TSCL_Begin;

    if (outArgs->bytesGenerated > max_output_bufsize)
        max_output_bufsize = outArgs->bytesGenerated;
    if (outArgs->bytesGenerated > CORE_OUTPUT_BUF_SIZE)
    {
        printf("\n Encoder overflow on local output buffer...  ");
        return -1; /* Error Condition: Application may want to break off   */
    }

    /* DeActivate the Algorithm                                             */
    encHandle->fxns->algDeactivate(encHandle);
    siu_osal_wbinv_cache_all();

    i=0;
    while ( outArgs->freeBufID[i] != 0 ) {
        BUFFMGR_ReleaseBuffer((XDAS_UInt32 *)&outArgs->freeBufID[i], BUFFMGR_1);
        i++;
    }

    return (outArgs->bytesGenerated);
    /* Encoder flush call: end */
}

/* nothing past this point */
