aboutsummaryrefslogblamecommitdiffstats
blob: cd10b71c2936dbd081538f14f2e5238c0ba24155 (plain) (tree)








































































                                                                                               









                      
















                                                                                                                       









                                                                                                                              



                                                
                                            








                                                                                                 
                                                                                                                          

                                                                                                                                         


                                                                                                                                        

                               


                                                               

                                                                                            









                                                     





                                                                                             
 
                             
                                         
 
                                 














                                                                          
 




                                 




                                                                                         











                                   
 
















                                                                                          

                                               

                                             

                                              
 

                                                                                           


                                                                               
                                       
                                                                                   
                                                                                           
 




                                                                                            


                                                                                               
                                                 


                                                                

                                                                                                        

                                                  
                                                                           

                                                                         
                                                                                     
 


                                          

                                                     



                                                      











                                                                          


                                                

                                                                 
                                                                                           






                                                       
                     



















                                                                                             
                                         
                                            
                                          




                                                


                                                                                     
 
                                            

                                                          


                                                                                                 



                                                                                            
                                                  
                                                                          



                                                                                    
     

                                                


















                                                                                                      


                                         




                                                   
                                                          



                                                                                          



                                                                                          





                                                       
     
                    
 




















                                                                                                           




                                           




                                                   
                                        
                                                                           
                                               
                                                                           
     
                                                      

                                                          


                                                                                          



                                                                                          
 
                                                                
                                                                                                                        





                                                       
     
                    


                                  

                       


                  
                 

                      

                    



















                                                                                
                                                                                  
                                         
                                        









                                                        


                                                           




                                                                                         
                                                                                                 
                                                                                                           








                                                                                                  





                                                                                                     
                                                                                 
                                                                                                     
                                                                              
                                                   
                                                                                        
                                                                                                     
                                                                              


         
                        
                                                                  
                                                                                                                 
                                                                                 
                                                                                  
                                                                                                       



                                                                              
                                                        
                                                                                  
                                                                                                       











                                                                                                   























                                                                                


                                               
                                                          


                                                                                          






                                                       






























































































                                                                                    
/*
 * Copyright (c) 2013, Texas Instruments Incorporated
 * All rights reserved.
 *
 * 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.
 */

/*
********************************** Notes ******************************************
*******
********************************* Memory *****************************************
*
*******
********************************* IPC 3.x *****************************************
* Two approaches are followed for IPC MmRpc calls.
* 1. All the parameters which need to be sent and received to/from IPU are coupled in a struct
*     allocated from Shared Memory. Only the adrress of the struct is passed to MmRpc
*     as a pointer argument. This approach is useful as MmRpc in some cases to avoid multiple
*     translations.
*     This approach is followed for :
*     Engine_open(), Engine_close(), create(), control(), delete()
*     For understanding refer to the Mmrpc_test.c in IPC 3.x
* 2. All the parameters which need to be sent are given as separate arguments to
*     MmRpc. This appraoch is needed when you need to translate an address which is
*     ofsetted from a pointer which in itself needs to be translated.
*     This apporach is followed for : process()
*     For understanding, take the example of inbufs argument in process call(). Inbufs
*     allocated in Shared memory and needs to be translated, has the address of Input
*     buffer (allocated from Tiler). It is not possible to give the Input buffer as an argument
*     to Mmrpc for translation until inbufs is given as a parameter to Mmrpc. Therefore inbuf
*     can't be populated inside another Shared memory struct.
* 3. This approach is a workaround to use approach [1] by solving the issue posed by [2].
*     This approach is followed for : get_version()
*     Taking the example of inbufs to explain, the Input buffer address will be one of the
*     parameters of the struct (explained in [1]) along with inbufs address. Therefore the
*     Input buffer address will get translated here. At the IPU, this address needs to be
*     copied back to inbufs.
*********************************************************************************
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>

#include <xdc/std.h>

/* IPC Headers */
#include <MmRpc.h>

/*DCE Headers */
#include "libdce.h"
#include "dce_rpc.h"
#include "dce_priv.h"
#include "memplugin.h"


/********************* GLOBALS ***********************/
/* Hande used for Remote Communication                               */
static MmRpc_Handle       MmRpcHandle = NULL;
static pthread_mutex_t    mutex = PTHREAD_MUTEX_INITIALIZER;
static int                count = 0;


/****************** INLINE FUNCTIONS ********************/

static inline void Fill_MmRpc_fxnCtx(MmRpc_FxnCtx *fxnCtx, int fxn_id, int num_params, int num_xlts, MmRpc_Xlt *xltAry)
{
    fxnCtx->fxn_id = fxn_id;
    fxnCtx->num_params = num_params;
    fxnCtx->num_xlts = num_xlts;
    fxnCtx->xltAry = xltAry;
}

static inline void Fill_MmRpc_fxnCtx_OffPtr_Params(MmRpc_Param *mmrpc_params, int size, void *base, int offset, size_t handle)
{
    mmrpc_params->type = MmRpc_ParamType_OffPtr;
    mmrpc_params->param.offPtr.size = (size_t)size;
    mmrpc_params->param.offPtr.base = (size_t)base;
    mmrpc_params->param.offPtr.offset = (size_t)offset;
    mmrpc_params->param.offPtr.handle = handle;
}

static inline void Fill_MmRpc_fxnCtx_Ptr_Params(MmRpc_Param *mmrpc_params, int size, void *addr, size_t handle)
{
    mmrpc_params->type = MmRpc_ParamType_Ptr;
    mmrpc_params->param.ptr.size = size;
    mmrpc_params->param.ptr.addr = (size_t)addr;
    mmrpc_params->param.ptr.handle = handle;
}

static inline void Fill_MmRpc_fxnCtx_Scalar_Params(MmRpc_Param *mmrpc_params, int size, int data)
{
    mmrpc_params->type = MmRpc_ParamType_Scalar;
    mmrpc_params->param.scalar.size = size;
    mmrpc_params->param.scalar.data = (size_t)data;
}

static inline void Fill_MmRpc_fxnCtx_Xlt_Array(MmRpc_Xlt *mmrpc_xlt, int index, int32_t base, int32_t addr, size_t handle)
{
    /* index : index of params filled in FxnCtx                                                                                        */
    /* offset : calculated from address of index                                                                                      */
    mmrpc_xlt->index = index;
    mmrpc_xlt->offset = MmRpc_OFFSET(base, addr);
    mmrpc_xlt->base = handle;
    mmrpc_xlt->handle = handle;
}

/************************ FUNCTIONS **************************/
/* Interface for QNX for parameter buffer allocation                                      */
/* These interfaces are implemented to maintain Backward Compatability          */
void *dce_alloc(int sz)
{
    return (memplugin_alloc(sz, 0, TILER_1D_BUFFER));
}

void dce_free(void *ptr)
{
    memplugin_free(ptr, TILER_1D_BUFFER);
}

/*=====================================================================================*/
/** dce_ipc_init            : Initialize MmRpc. This function is called within Engine_open().
 *
 * @ return                 : Error Status.
 */
static int dce_ipc_init(void)
{
    MmRpc_Params        args;
    dce_error_status    eError = DCE_EOK;

    printf(" >> dce_ipc_init\n");

    pthread_mutex_lock(&mutex);

    count++;
    /* Check if already Initialized */
    _ASSERT(count == 1, DCE_EOK);

    /* Create remote server insance */
    MmRpc_Params_init(&args);

    eError = MmRpc_create(DCE_DEVICE_NAME, &args, &MmRpcHandle);

    _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CREATE_FAIL, count--);

    printf("open(/dev/" DCE_DEVICE_NAME ") -> 0x%x\n", (int)MmRpcHandle);

EXIT:
    pthread_mutex_unlock(&mutex);
    return (eError);
}

/*=====================================================================================*/
/** dce_ipc_deinit            : DeInitialize MmRpc. This function is called within
 *                              Engine_close().
 */
static void dce_ipc_deinit()
{
    pthread_mutex_lock(&mutex);

    count--;
    if( count > 0 ) {
        goto EXIT;
    }

    if( MmRpcHandle != NULL ) {
        MmRpc_delete(&MmRpcHandle);
    }
    MmRpcHandle = NULL;

EXIT:
    pthread_mutex_unlock(&mutex);
    return;
}

/*===============================================================*/
/** Engine_open        : Open Codec Engine.
 *
 * @ param attrs  [in]       : Engine Attributes. This param is not passed to Remote core.
 * @ param name [in]       : Name of Encoder or Decoder codec.
 * @ param ec [out]         : Error returned by Codec Engine.
 * @ return : Codec Engine Handle is returned to be used to create codec.
 *                 In case of error, NULL is returned as Engine Handle.
 */
Engine_Handle Engine_open(String name, Engine_Attrs *attrs, Engine_Error *ec)
{
    MmRpc_FxnCtx        fxnCtx;
    dce_error_status    eError = DCE_EOK;
    dce_engine_open    *engine_open_msg = NULL;
    Engine_Attrs       *engine_attrs = NULL;
    Engine_Handle       engine_handle = NULL;

    _ASSERT(name != '\0', DCE_EINVALID_INPUT);

    /* Initialize IPC. In case of Error Deinitialize them */
    _ASSERT_AND_EXECUTE(dce_ipc_init() == DCE_EOK, DCE_EIPC_CREATE_FAIL, dce_ipc_deinit());

    printf(">> Engine_open Params::name = %s size = %d\n", name, strlen(name));
    /* Allocate Shared memory for the engine_open rpc msg structure*/
    /* Tiler Memory preferred in QNX */
    engine_open_msg = memplugin_alloc(sizeof(dce_engine_open), 0, TILER_1D_BUFFER);
    _ASSERT_AND_EXECUTE(engine_open_msg != NULL, DCE_EOUT_OF_MEMORY, engine_handle = NULL);

    if( attrs ) {
        engine_attrs = memplugin_alloc(sizeof(Engine_Attrs), 0, TILER_1D_BUFFER);
        _ASSERT_AND_EXECUTE(engine_attrs != NULL, DCE_EOUT_OF_MEMORY, engine_handle = NULL);
        *engine_attrs = *attrs;
    }
    /* Populating the msg structure with all the params */
    /* Populating all params into a struct avoid individual address translations of name, ec */
    strncpy(engine_open_msg->name, name, strlen(name));
    engine_open_msg->engine_attrs = engine_attrs;

    /* Marshall function arguments into the send buffer */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_ENGINE_OPEN, 1, 0, NULL);
    Fill_MmRpc_fxnCtx_OffPtr_Params(fxnCtx.params, GetSz(engine_open_msg), (void *)P2H(engine_open_msg),
                                    sizeof(MemHeader), memplugin_share(engine_open_msg));

    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, (int32_t *)(&engine_handle));

    /* In case of Error, the Application will get a NULL Engine Handle */
    _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CALL_FAIL, engine_handle = NULL);

    if( ec ) {
        *ec = engine_open_msg->error_code;
    }
EXIT:
    memplugin_free(engine_open_msg, TILER_1D_BUFFER);
    if( engine_attrs ) {
        memplugin_free(engine_attrs, TILER_1D_BUFFER);
    }
    return ((Engine_Handle)engine_handle);
}

/*===============================================================*/
/** Engine_close           : Close Engine.
 *
 * @ param engine  [in]    : Engine Handle obtained in Engine_open() call.
 */
Void Engine_close(Engine_Handle engine)
{
    MmRpc_FxnCtx        fxnCtx;
    int32_t             fxnRet;
    dce_error_status    eError = DCE_EOK;

    _ASSERT(engine != NULL, DCE_EINVALID_INPUT);

    /* Marshall function arguments into the send buffer */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_ENGINE_CLOSE, 1, 0, NULL);
    Fill_MmRpc_fxnCtx_Scalar_Params(fxnCtx.params, sizeof(Engine_Handle), (int32_t)engine);

    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet);

    _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);

EXIT:
    dce_ipc_deinit();
    return;
}

/*===============================================================*/
/** Functions create(), control(), get_version(), process(), delete() are common codec
 * glue function signatures which are same for both encoder and decoder
 */
/*===============================================================*/
/** create         : Create Encoder/Decoder codec.
 *
 * @ param engine  [in]    : Engine Handle obtained in Engine_open() call.
 * @ param name [in]       : Name of Encoder or Decoder codec.
 * @ param params [in]     : Static parameters of codec.
 * @ param codec_id [in]  : To differentiate between Encoder and Decoder codecs.
 * @ return : Codec Handle is returned to be used for control, process, delete calls.
 *                 In case of error, NULL is returned.
 */
static void *create(Engine_Handle engine, String name, void *params, dce_codec_type codec_id)
{
    MmRpc_FxnCtx        fxnCtx;
    dce_error_status    eError = DCE_EOK;
    void               *codec_handle = NULL;
    char               *codec_name = NULL;

    _ASSERT(name != '\0', DCE_EINVALID_INPUT);
    _ASSERT(engine != NULL, DCE_EINVALID_INPUT);
    _ASSERT(params != NULL, DCE_EINVALID_INPUT);

    /* Allocate shared memory for translating codec name to IPU */
    codec_name = memplugin_alloc(MAX_NAME_LENGTH * sizeof(char), 0, TILER_1D_BUFFER);
    _ASSERT_AND_EXECUTE(codec_name != NULL, DCE_EOUT_OF_MEMORY, codec_handle = NULL);

    strncpy(codec_name, name, strlen(name));

    /* Marshall function arguments into the send buffer */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_CREATE, 4, 0, NULL);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[0]), sizeof(int32_t), codec_id);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[1]), sizeof(Engine_Handle), (int32_t)engine);
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[2]), GetSz(codec_name), P2H(codec_name),
                                    sizeof(MemHeader), memplugin_share(codec_name));
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[3]), GetSz(params), P2H(params),
                                    sizeof(MemHeader),  memplugin_share(params));
    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, (int32_t *)(&codec_handle));

    /* In case of Error, the Application will get a NULL Codec Handle */
    _ASSERT_AND_EXECUTE(eError == DCE_EOK, DCE_EIPC_CALL_FAIL, codec_handle = NULL);

EXIT:
    memplugin_free(codec_name, TILER_1D_BUFFER);
    return ((void *)codec_handle);
}

/*===============================================================*/
/** control               : Codec control call.
 *
 * @ param codec  [in]     : Codec Handle obtained in create() call.
 * @ param id [in]            : Command id for XDM control operation.
 * @ param dynParams [in] : Dynamic input parameters to Codec.
 * @ param status [out]    : Codec returned status parameters.
 * @ param codec_id [in]  : To differentiate between Encoder and Decoder codecs.
 * @ return : Status of control() call is returned.
 *                #XDM_EOK                  [0]   :  Success.
 *                #XDM_EFAIL                [-1] :  Failure.
 *                #IPC_FAIL                   [-2] : MmRpc Call failed.
 *                #XDM_EUNSUPPORTED [-3] :  Unsupported request.
 *                #OUT_OF_MEMORY       [-4] :  Out of Shared Memory.
 */
static XDAS_Int32 control(void *codec, int id, void *dynParams, void *status, dce_codec_type codec_id)
{
    MmRpc_FxnCtx        fxnCtx;
    int32_t             fxnRet;
    dce_error_status    eError = DCE_EOK;

    _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
    _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT);
    _ASSERT(status != NULL, DCE_EINVALID_INPUT);

    /* Marshall function arguments into the send buffer */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_CONTROL, 5, 0, NULL);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[0]), sizeof(int32_t), codec_id);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[1]), sizeof(int32_t), (int32_t)codec);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[2]), sizeof(int32_t), (int32_t)id);
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[3]), GetSz(dynParams), P2H(dynParams),
                                    sizeof(MemHeader), memplugin_share(dynParams));
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[4]), GetSz(status), P2H(status),
                                    sizeof(MemHeader), memplugin_share(status));

    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet);

    _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);

EXIT:
    return (fxnRet);

}

/*===============================================================*/
/** get_version        : Codec control call to get the codec version. This call has been made
 *                                     separate from control call because it involves an additional version
 *                                     buffer translation.
 *
 * @ param codec  [in]     : Codec Handle obtained in create() call.
 * @ param id [in]            : Command id for XDM control operation.
 * @ param dynParams [in] : Dynamic input parameters to Codec.
 * @ param status [out]    : Codec returned status parameters.
 * @ param codec_id [in]  : To differentiate between Encoder and Decoder codecs.
 * @ return : Status of control() call is returned.
 *                #XDM_EOK                  [0]   :  Success.
 *                #XDM_EFAIL                [-1] :  Failure.
 *                #IPC_FAIL                   [-2] : MmRpc Call failed.
 *                #XDM_EUNSUPPORTED [-3] :  Unsupported request.
 *                #OUT_OF_MEMORY       [-4] :  Out of Shared Memory.
 */
static XDAS_Int32 get_version(void *codec, void *dynParams, void *status, dce_codec_type codec_id)
{
    MmRpc_FxnCtx        fxnCtx;
    MmRpc_Xlt           xltAry;
    void             * *version_buf = NULL;
    int32_t             fxnRet;
    dce_error_status    eError = DCE_EOK;

    _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
    _ASSERT(dynParams != NULL, DCE_EINVALID_INPUT);
    _ASSERT(status != NULL, DCE_EINVALID_INPUT);

    if( codec_id == OMAP_DCE_VIDDEC3 ) {
        version_buf = (void * *)(&(((IVIDDEC3_Status *)status)->data.buf));
    } else if( codec_id == OMAP_DCE_VIDENC2 ) {
        version_buf = (void * *)(&(((IVIDENC2_Status *)status)->data.buf));
    }
    _ASSERT(*version_buf != NULL, DCE_EINVALID_INPUT);

    /* Marshall function arguments into the send buffer */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_GET_VERSION, 4, 1, &xltAry);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[0]), sizeof(int32_t), codec_id);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[1]), sizeof(int32_t), (int32_t)codec);
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[2]), GetSz(dynParams), P2H(dynParams),
                                    sizeof(MemHeader), memplugin_share(dynParams));
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[3]), GetSz(status), P2H(status),
                                    sizeof(MemHeader), memplugin_share(status));

    /* Address Translation needed for buffer for version Info */
    Fill_MmRpc_fxnCtx_Xlt_Array(fxnCtx.xltAry, 3, (int32_t)status, (int32_t)version_buf, memplugin_share(*version_buf));

    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet);

    _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);

EXIT:
    return (fxnRet);
}

typedef enum process_call_params {
    CODEC_ID_INDEX = 0,
    CODEC_HANDLE_INDEX,
    INBUFS_INDEX,
    OUTBUFS_INDEX,
    INARGS_INDEX,
    OUTARGS_INDEX
} process_call_params;

#define LUMA_BUF 0
#define CHROMA_BUF 1
/*===============================================================*/
/** process               : Encode/Decode process.
 *
 * @ param codec  [in]     : Codec Handle obtained in create() call.
 * @ param inBufs [in]     : Input buffer details.
 * @ param outBufs [in]    : Output buffer details.
 * @ param inArgs [in]     : Input arguments.
 * @ param outArgs [out]  : Output arguments.
 * @ param codec_id [in]  : To differentiate between Encoder and Decoder codecs.
 * @ return : Status of the process call.
 *                #XDM_EOK                  [0]   :  Success.
 *                #XDM_EFAIL                [-1] :  Failure.
 *                #IPC_FAIL                   [-2] :  MmRpc Call failed.
 *                #XDM_EUNSUPPORTED [-3] :  Unsupported request.
 */
static XDAS_Int32 process(void *codec, void *inBufs, void *outBufs,
                          void *inArgs, void *outArgs, dce_codec_type codec_id)
{
    MmRpc_FxnCtx        fxnCtx;
    MmRpc_Xlt           xltAry[MAX_TOTAl_BUF];
    int                 fxnRet, count, total_count, numInBufs = 0, numOutBufs = 0;
    dce_error_status    eError = DCE_EOK;
    void             * *data_buf = NULL;

    _ASSERT(codec != NULL, DCE_EINVALID_INPUT);
    _ASSERT(inBufs != NULL, DCE_EINVALID_INPUT);
    _ASSERT(outBufs != NULL, DCE_EINVALID_INPUT);
    _ASSERT(inArgs != NULL, DCE_EINVALID_INPUT);
    _ASSERT(outArgs != NULL, DCE_EINVALID_INPUT);

    if( codec_id == OMAP_DCE_VIDDEC3 ) {
        numInBufs = ((XDM2_BufDesc *)inBufs)->numBufs;
        numOutBufs = ((XDM2_BufDesc *)outBufs)->numBufs;
    } else if( codec_id == OMAP_DCE_VIDENC2 ) {
        numInBufs = ((IVIDEO2_BufDesc *)inBufs)->numPlanes;
        numOutBufs = ((XDM2_BufDesc *)outBufs)->numBufs;
    }

    /* marshall function arguments into the send buffer                       */
    /* Approach [2] as explained in "Notes" used for process               */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_PROCESS, 6, numInBufs + numOutBufs, xltAry);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[CODEC_ID_INDEX]), sizeof(int32_t), codec_id);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[CODEC_HANDLE_INDEX]), sizeof(int32_t), (int32_t)codec);

    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[INBUFS_INDEX]), GetSz(inBufs), P2H(inBufs),
                                    sizeof(MemHeader), memplugin_share(inBufs));
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[OUTBUFS_INDEX]), GetSz(outBufs), P2H(outBufs),
                                    sizeof(MemHeader), memplugin_share(outBufs));
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[INARGS_INDEX]), GetSz(inArgs), P2H(inArgs),
                                    sizeof(MemHeader), memplugin_share(inArgs));
    Fill_MmRpc_fxnCtx_OffPtr_Params(&(fxnCtx.params[OUTARGS_INDEX]), GetSz(outArgs), P2H(outArgs),
                                    sizeof(MemHeader), memplugin_share(outArgs));

    /* InBufs, OutBufs, InArgs, OutArgs buffer need translation but since they have been */
    /* individually mentioned as fxnCtx Params, they need not be mentioned below again */
    /* Input and Output Buffers have to be mentioned for translation                               */
    for( count = 0, total_count = 0; count < numInBufs; count++, total_count++ ) {
        if( codec_id == OMAP_DCE_VIDDEC3 ) {
            data_buf = (void * *)(&(((XDM2_BufDesc *)inBufs)->descs[count].buf));
            Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), INBUFS_INDEX, (int32_t)inBufs,
                                        (int32_t)data_buf, (size_t)*data_buf);
        } else if( codec_id == OMAP_DCE_VIDENC2 ) {
            data_buf = (void * *)(&(((IVIDEO2_BufDesc *)inBufs)->planeDesc[count].buf));
            Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), INBUFS_INDEX, (int32_t)inBufs,
                                        (int32_t)data_buf, (size_t)*data_buf);
        }
    }

    /* Output Buffers */
    for( count = 0; count < numOutBufs; count++, total_count++ ) {
        if(((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].buf != ((XDM2_BufDesc *)outBufs)->descs[CHROMA_BUF].buf ) {
            /* Either Encode usecase or MultiPlanar Buffers for Decode usecase */
            data_buf = (void * *)(&(((XDM2_BufDesc *)outBufs)->descs[count].buf));
            Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), OUTBUFS_INDEX, (int32_t)outBufs,
                                        (int32_t)data_buf, (size_t)*data_buf);
        }
#if defined(BUILDOS_LINUX)
        else {
            /* SinglePlanar Buffers for Decode usecase*/
            data_buf = (void * *)(&(((XDM2_BufDesc *)outBufs)->descs[count].buf));
            Fill_MmRpc_fxnCtx_Xlt_Array(&(fxnCtx.xltAry[total_count]), OUTBUFS_INDEX, (int32_t)outBufs,
                                        (int32_t)data_buf, (size_t)*data_buf);
            if( count == CHROMA_BUF ) {
                if(((XDM2_BufDesc *)outBufs)->descs[count].memType == XDM_MEMTYPE_RAW ||
                   ((XDM2_BufDesc *)outBufs)->descs[count].memType == XDM_MEMTYPE_TILEDPAGE ) {
                    *data_buf += ((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].bufSize.bytes;
                } else {
                    *data_buf += ((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].bufSize.tileMem.width *
                                 ((XDM2_BufDesc *)outBufs)->descs[LUMA_BUF].bufSize.tileMem.height;
                }
            }
        }
#endif
    }

    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet);

    _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);

    eError = (dce_error_status)(fxnRet);
EXIT:
    return (eError);
}

/*===============================================================*/
/** delete                : Delete Encode/Decode codec instance.
 *
 * @ param codec  [in]     : Codec Handle obtained in create() call.
 * @ param codec_id [in]  : To differentiate between Encoder and Decoder codecs.
 * @ return : NIL.
 */
static void delete(void *codec, dce_codec_type codec_id)
{
    MmRpc_FxnCtx        fxnCtx;
    int32_t             fxnRet;
    dce_error_status    eError = DCE_EOK;

    _ASSERT(codec != NULL, DCE_EINVALID_INPUT);

    /* Marshall function arguments into the send buffer */
    Fill_MmRpc_fxnCtx(&fxnCtx, DCE_RPC_CODEC_DELETE, 2, 0, NULL);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[0]), sizeof(int32_t), codec_id);
    Fill_MmRpc_fxnCtx_Scalar_Params(&(fxnCtx.params[1]), sizeof(int32_t), (int32_t)codec);

    /* Invoke the Remote function through MmRpc */
    eError = MmRpc_call(MmRpcHandle, &fxnCtx, &fxnRet);

    _ASSERT(eError == DCE_EOK, DCE_EIPC_CALL_FAIL);

EXIT:
    return;
}

/*************** Deocder Codec Engine Functions ***********************/
VIDDEC3_Handle VIDDEC3_create(Engine_Handle engine, String name,
                              VIDDEC3_Params *params)
{
    VIDDEC3_Handle    codec;

    DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params);
    codec = create(engine, name, params, OMAP_DCE_VIDDEC3);
    DEBUG("<< codec=%p", codec);
    return (codec);
}

XDAS_Int32 VIDDEC3_control(VIDDEC3_Handle codec, VIDDEC3_Cmd id,
                           VIDDEC3_DynamicParams *dynParams, VIDDEC3_Status *status)
{
    XDAS_Int32    ret;

    DEBUG(">> codec=%p, id=%d, dynParams=%p, status=%p",
          codec, id, dynParams, status);
    if( id == XDM_GETVERSION ) {
        ret = get_version(codec, dynParams, status, OMAP_DCE_VIDDEC3);
    } else {
        ret = control(codec, id, dynParams, status, OMAP_DCE_VIDDEC3);
    }
    DEBUG("<< ret=%d", ret);
    return (ret);
}

XDAS_Int32 VIDDEC3_process(VIDDEC3_Handle codec,
                           XDM2_BufDesc *inBufs, XDM2_BufDesc *outBufs,
                           VIDDEC3_InArgs *inArgs, VIDDEC3_OutArgs *outArgs)
{
    XDAS_Int32    ret;

    DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p",
          codec, inBufs, outBufs, inArgs, outArgs);
    ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDDEC3);
    DEBUG("<< ret=%d", ret);
    return (ret);
}

Void VIDDEC3_delete(VIDDEC3_Handle codec)
{
    DEBUG(">> codec=%p", codec);
    delete(codec, OMAP_DCE_VIDDEC3);
    DEBUG("<<");
}

/*************** Enocder Codec Engine Functions ***********************/
VIDENC2_Handle VIDENC2_create(Engine_Handle engine, String name,
                              VIDENC2_Params *params)
{
    VIDENC2_Handle    codec;

    DEBUG(">> engine=%p, name=%s, params=%p", engine, name, params);
    codec = create(engine, name, params, OMAP_DCE_VIDENC2);
    DEBUG("<< codec=%p", codec);
    return (codec);
}

XDAS_Int32 VIDENC2_control(VIDENC2_Handle codec, VIDENC2_Cmd id,
                           VIDENC2_DynamicParams *dynParams, VIDENC2_Status *status)
{
    XDAS_Int32    ret;

    DEBUG(">> codec=%p, id=%d, dynParams=%p, status=%p",
          codec, id, dynParams, status);
    ret = control(codec, id, dynParams, status, OMAP_DCE_VIDENC2);
    DEBUG("<< ret=%d", ret);
    return (ret);
}

XDAS_Int32 VIDENC2_process(VIDENC2_Handle codec,
                           IVIDEO2_BufDesc *inBufs, XDM2_BufDesc *outBufs,
                           VIDENC2_InArgs *inArgs, VIDENC2_OutArgs *outArgs)
{
    XDAS_Int32    ret;

    DEBUG(">> codec=%p, inBufs=%p, outBufs=%p, inArgs=%p, outArgs=%p",
          codec, inBufs, outBufs, inArgs, outArgs);
    ret = process(codec, inBufs, outBufs, inArgs, outArgs, OMAP_DCE_VIDENC2);
    DEBUG("<< ret=%d", ret);
    return (ret);
}

Void VIDENC2_delete(VIDENC2_Handle codec)
{
    DEBUG(">> codec=%p", codec);
    delete(codec, OMAP_DCE_VIDENC2);
    DEBUG("<<");
}