/*--------------------------------------------------------------------------
Copyright (c) 2010-2021, Linux Foundation. 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 The Linux Foundation 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, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT 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.
--------------------------------------------------------------------------*/
/*============================================================================
                            O p e n M A X   w r a p p e r s
                             O p e n  M A X   C o r e

*//** @file omx_video_base.cpp
  This module contains the implementation of the OpenMAX core & component.

*//*========================================================================*/

//////////////////////////////////////////////////////////////////////////////
//                             Include Files
//////////////////////////////////////////////////////////////////////////////

#define __STDC_FORMAT_MACROS //enables the format specifiers in inttypes.h
#include <inttypes.h>
#include <string.h>
#include <qdMetaData.h>
#include "omx_video_base.h"
#include "fastcv.h"
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#ifdef _ANDROID_ICS_
#include <media/hardware/HardwareAPI.h>
#include <gralloc_priv.h>
#endif
#ifdef _USE_GLIB_
#include <glib.h>
#define strlcpy g_strlcpy
#endif
#define H264_SUPPORTED_WIDTH (480)
#define H264_SUPPORTED_HEIGHT (368)

#define VC1_SP_MP_START_CODE        0xC5000000
#define VC1_SP_MP_START_CODE_MASK   0xFF000000
#define VC1_AP_START_CODE           0x00000100
#define VC1_AP_START_CODE_MASK      0xFFFFFF00
#define VC1_STRUCT_C_PROFILE_MASK   0xF0
#define VC1_STRUCT_B_LEVEL_MASK     0xE0000000
#define VC1_SIMPLE_PROFILE          0
#define VC1_MAIN_PROFILE            1
#define VC1_ADVANCE_PROFILE         3
#define VC1_SIMPLE_PROFILE_LOW_LEVEL  0
#define VC1_SIMPLE_PROFILE_MED_LEVEL  2
#define VC1_STRUCT_C_LEN            4
#define VC1_STRUCT_C_POS            8
#define VC1_STRUCT_A_POS            12
#define VC1_STRUCT_B_POS            24
#define VC1_SEQ_LAYER_SIZE          36

#define SZ_4K                       0x1000
#define SZ_1M                       0x100000
#undef ALIGN
#define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))

#ifndef ION_FLAG_CP_BITSTREAM
#define ION_FLAG_CP_BITSTREAM 0
#endif

#ifndef ION_FLAG_CP_PIXEL
#define ION_FLAG_CP_PIXEL 0
#endif

#undef MEM_HEAP_ID

#ifdef SLAVE_SIDE_CP
#define MEM_HEAP_ID ION_CP_MM_HEAP_ID
#define SECURE_ALIGN SZ_1M
#define SECURE_FLAGS_INPUT_BUFFER ION_FLAG_SECURE
#define SECURE_FLAGS_OUTPUT_BUFFER ION_FLAG_SECURE
#else //MASTER_SIDE_CP
#define MEM_HEAP_ID ION_SECURE_HEAP_ID
#define SECURE_ALIGN SZ_4K
#define SECURE_FLAGS_INPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_PIXEL)
#define SECURE_FLAGS_OUTPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_BITSTREAM)
#endif

// Gralloc flag to indicate UBWC
#define GRALLOC1_CONSUMER_USAGE_UBWC_FLAG GRALLOC1_CONSUMER_USAGE_PRIVATE_0

typedef struct OMXComponentCapabilityFlagsType {
    ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS
    OMX_U32 nSize;
    OMX_VERSIONTYPE nVersion;
    OMX_BOOL iIsOMXComponentMultiThreaded;
    OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc;
    OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc;
    OMX_BOOL iOMXComponentSupportsMovableInputBuffers;
    OMX_BOOL iOMXComponentSupportsPartialFrames;
    OMX_BOOL iOMXComponentUsesNALStartCodes;
    OMX_BOOL iOMXComponentCanHandleIncompleteFrames;
    OMX_BOOL iOMXComponentUsesFullAVCFrames;

} OMXComponentCapabilityFlagsType;
#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347

void* message_thread_enc(void *input)
{
    omx_video* omx = reinterpret_cast<omx_video*>(input);
    int ret;

    DEBUG_PRINT_HIGH("omx_venc: message thread start");
    prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0);
    while (!omx->msg_thread_stop) {
        ret = omx->signal.wait(2 * 1000000000);
        if (ret == ETIMEDOUT || omx->msg_thread_stop) {
            continue;
        } else if (ret) {
            DEBUG_PRINT_ERROR("omx_venc: message_thread_enc wait on condition failed, exiting");
            break;
        }
        omx->process_event_cb(omx);
    }
    DEBUG_PRINT_HIGH("omx_venc: message thread stop");
    return 0;
}

void post_message(omx_video *omx, unsigned char id)
{
    DEBUG_PRINT_LOW("omx_venc: post_message %d", id);
    omx->signal.signal();
}

// omx_cmd_queue destructor
omx_video::omx_cmd_queue::~omx_cmd_queue()
{
    // Nothing to do
}

// omx cmd queue constructor
omx_video::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
{
    memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
}

// omx cmd queue insert
bool omx_video::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
{
    bool ret = true;
    if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
        m_q[m_write].id       = id;
        m_q[m_write].param1   = p1;
        m_q[m_write].param2   = p2;
        m_write++;
        m_size ++;
        if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
            m_write = 0;
        }
    } else {
        ret = false;
        DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full");
    }
    return ret;
}

// omx cmd queue pop
bool omx_video::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
{
    bool ret = true;
    if (m_size > 0) {
        *id = m_q[m_read].id;
        *p1 = m_q[m_read].param1;
        *p2 = m_q[m_read].param2;
        // Move the read pointer ahead
        ++m_read;
        --m_size;
        if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
            m_read = 0;
        }
    } else {
        ret = false;
    }
    return ret;
}

// Retrieve the first mesg type in the queue
unsigned omx_video::omx_cmd_queue::get_q_msg_type()
{
    return m_q[m_read].id;
}


/* ======================================================================
   FUNCTION
   omx_venc::omx_venc

   DESCRIPTION
   Constructor

   PARAMETERS
   None

   RETURN VALUE
   None.
   ========================================================================== */
omx_video::omx_video():
    c2d_opened(false),
    psource_frame(NULL),
    pdest_frame(NULL),
    secure_session(false),
#ifdef _UBWC_
    m_ubwc_supported(true),
#else
    m_ubwc_supported(false),
#endif
    mUsesColorConversion(false),
    mC2dSrcFmt(NO_COLOR_FORMAT),
    mC2dDestFmt(NO_COLOR_FORMAT),
    mC2DFrameHeight(0),
    mC2DFrameWidth(0),
    m_pInput_pmem(NULL),
    m_pOutput_pmem(NULL),
#ifdef USE_ION
    m_pInput_ion(NULL),
    m_pOutput_ion(NULL),
#endif
    m_error_propogated(false),
    m_state(OMX_StateInvalid),
    m_app_data(NULL),
    m_use_input_pmem(OMX_FALSE),
    m_use_output_pmem(OMX_FALSE),
    m_sExtraData(0),
    m_sParamConsumerUsage(0),
    m_input_msg_id(OMX_COMPONENT_GENERATE_ETB),
    m_nOperatingRate(0),
    m_inp_mem_ptr(NULL),
    m_out_mem_ptr(NULL),
    m_client_output_extradata_mem_ptr(NULL),
    input_flush_progress (false),
    output_flush_progress (false),
    input_use_buffer (false),
    output_use_buffer (false),
    pending_input_buffers(0),
    pending_output_buffers(0),
    allocate_native_handle(false),
    m_out_bm_count(0),
    m_client_out_bm_count(0),
    m_client_in_bm_count(0),
    m_inp_bm_count(0),
    m_out_extradata_bm_count(0),
    m_flags(0),
    m_etb_count(0),
    m_fbd_count(0),
    m_event_port_settings_sent(false),
    hw_overload(false),
    m_graphicbuffer_size(0),
    m_buffer_freed(0),
    profile_mode(false),
    profile_frame_count(0),
    profile_start_time(0),
    profile_last_time(0),
    m_fastCV_init_done(false)
{
    DEBUG_PRINT_HIGH("omx_video(): Inside Constructor()");
    memset(&m_cmp,0,sizeof(m_cmp));
    memset(&m_pCallbacks,0,sizeof(m_pCallbacks));
    async_thread_created = false;
    msg_thread_created = false;
    msg_thread_stop = false;
    is_stop_in_progress = false;

    OMX_INIT_STRUCT(&m_blurInfo, OMX_QTI_VIDEO_CONFIG_BLURINFO);
    m_blurInfo.nPortIndex == (OMX_U32)PORT_INDEX_IN;

    mMapPixelFormat2Converter.insert({
            {HAL_PIXEL_FORMAT_RGBA_8888, RGBA8888},
            {HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC, NV12_UBWC},
            {HAL_PIXEL_FORMAT_NV12_ENCODEABLE, NV12_128m},
            {HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS, NV12_128m},
                });

    pthread_mutex_init(&m_lock, NULL);
    pthread_mutex_init(&m_TimeStampInfo.m_lock, NULL);
    m_TimeStampInfo.deferred_inbufq.m_size=0;
    m_TimeStampInfo.deferred_inbufq.m_read = m_TimeStampInfo.deferred_inbufq.m_write = 0;
    sem_init(&m_cmd_lock,0,0);
    DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr);

    memset(m_platform, 0, sizeof(m_platform));
#ifdef _ANDROID_
    char property_value[PROPERTY_VALUE_MAX] = {0};
    property_get("ro.board.platform", property_value, "0");
    strlcpy(m_platform, property_value, sizeof(m_platform));
    property_get("vendor.vidc.enc.profile.in", property_value, "0");
    profile_mode = !!atoi(property_value);
#endif

    pthread_mutex_init(&m_buf_lock, NULL);
}


/* ======================================================================
   FUNCTION
   omx_venc::~omx_venc

   DESCRIPTION
   Destructor

   PARAMETERS
   None

   RETURN VALUE
   None.
   ========================================================================== */
omx_video::~omx_video()
{
    DEBUG_PRINT_HIGH("~omx_video(): Inside Destructor()");
    /*For V4L2 based drivers, pthread_join is done in device_close
     * so no need to do it here*/
    pthread_mutex_destroy(&m_lock);
    pthread_mutex_destroy(&m_TimeStampInfo.m_lock);
    sem_destroy(&m_cmd_lock);
    DEBUG_PRINT_HIGH("m_etb_count = %" PRIu64 ", m_fbd_count = %" PRIu64, m_etb_count,
            m_fbd_count);

    pthread_mutex_destroy(&m_buf_lock);
    if (profile_mode && (profile_start_time < profile_last_time)) {
        DEBUG_PRINT_HIGH("Input frame rate = %f",
            ((profile_frame_count - 1) * 1e6) / (profile_last_time - profile_start_time));
    }
    if (m_fastCV_init_done) {
        fcvMemDeInit();
        fcvCleanUp();
        m_fastCV_init_done = false;
    }
    DEBUG_PRINT_HIGH("omx_video: Destructor exit");
    DEBUG_PRINT_HIGH("Exiting OMX Video Encoder ...");
}

/* ======================================================================
   FUNCTION
   omx_venc::OMXCntrlProcessMsgCb

   DESCRIPTION
   IL Client callbacks are generated through this routine. The decoder
   provides the thread context for this routine.

   PARAMETERS
   ctxt -- Context information related to the self.
   id   -- Event identifier. This could be any of the following:
   1. Command completion event
   2. Buffer done callback event
   3. Frame done callback event

   RETURN VALUE
   None.

   ========================================================================== */
void omx_video::process_event_cb(void *ctxt)
{
    unsigned long p1; // Parameter - 1
    unsigned long p2; // Parameter - 2
    unsigned long ident;
    unsigned qsize=0; // qsize
    omx_video *pThis = (omx_video *) ctxt;

    if (!pThis) {
        DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out");
        return;
    }

    // Protect the shared queue data structure
    do {
        /*Read the message id's from the queue*/

        pthread_mutex_lock(&pThis->m_lock);
        qsize = pThis->m_cmd_q.m_size;
        if (qsize) {
            pThis->m_cmd_q.pop_entry(&p1,&p2,&ident);
        }

        if (qsize == 0) {
            qsize = pThis->m_ftb_q.m_size;
            if (qsize) {
                pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
            }
        }

        if (qsize == 0) {
            qsize = pThis->m_etb_q.m_size;
            if (qsize) {
                pThis->m_etb_q.pop_entry(&p1,&p2,&ident);
            }
        }

        pthread_mutex_unlock(&pThis->m_lock);

        /*process message if we have one*/
        if (qsize > 0) {
            switch (ident) {
                case OMX_COMPONENT_GENERATE_EVENT:
                    if (pThis->m_pCallbacks.EventHandler) {
                        switch (p1) {
                            case OMX_CommandStateSet:
                                pThis->m_state = (OMX_STATETYPE) p2;
                                DEBUG_PRINT_LOW("Process -> state set to %d", pThis->m_state);
                                if (pThis->m_state == OMX_StateLoaded) {
                                    m_buffer_freed = false;
                                }
                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                        OMX_EventCmdComplete, p1, p2, NULL);
                                break;

                            case OMX_EventError:
                                DEBUG_PRINT_ERROR("ERROR: OMX_EventError: p2 = %lu", p2);
                                if (p2 == (unsigned)OMX_ErrorHardware) {
                                    pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                            OMX_EventError,OMX_ErrorHardware,0,NULL);
                                } else {
                                    pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                            OMX_EventError, p2, 0, 0);

                                }
                                break;

                            case OMX_CommandPortDisable:
                                DEBUG_PRINT_LOW("Process -> Port %lu set to PORT_STATE_DISABLED" \
                                        "state", p2);
                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                        OMX_EventCmdComplete, p1, p2, NULL );
                                break;
                            case OMX_CommandPortEnable:
                                DEBUG_PRINT_LOW("Process ->Port %lu set PORT_STATE_ENABLED state" \
                                        , p2);
                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
                                        OMX_EventCmdComplete, p1, p2, NULL );
                                break;

                            default:
                                DEBUG_PRINT_LOW("process_event_cb forwarding EventCmdComplete %lu", p1);
                                pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                        OMX_EventCmdComplete, p1, p2, NULL );
                                break;

                        }
                    } else {
                        DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks");
                    }
                    break;
                case OMX_COMPONENT_GENERATE_ETB_OPQ:
                    if (pThis->empty_this_buffer_opaque((OMX_HANDLETYPE)p1,\
                                (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
                        DEBUG_PRINT_ERROR("ERROR: ETBProxy() failed!");
                        pThis->omx_report_error ();
                    }
                    break;
                case OMX_COMPONENT_GENERATE_ETB: {
                        OMX_ERRORTYPE iret;
                        DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB");
                        iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
                        if (iret == OMX_ErrorInsufficientResources) {
                            DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
                            pThis->omx_report_hw_overload ();
                        } else if (iret != OMX_ErrorNone) {
                            DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
                            pThis->omx_report_error ();
                        }
                    }
                    break;

                case OMX_COMPONENT_GENERATE_FTB:
                    if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
                                (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
                        DEBUG_PRINT_ERROR("ERROR: FTBProxy() failed!");
                        pThis->omx_report_error ();
                    }
                    break;

                case OMX_COMPONENT_GENERATE_COMMAND:
                    pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
                            (OMX_U32)p2,(OMX_PTR)NULL);
                    break;

                case OMX_COMPONENT_GENERATE_EBD:
                    if ( pThis->empty_buffer_done(&pThis->m_cmp,
                                (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
                        DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
                        pThis->omx_report_error ();
                    }
                    break;

                case OMX_COMPONENT_GENERATE_FBD:
                    if ( pThis->fill_buffer_done(&pThis->m_cmp,
                                (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
                        DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
                        pThis->omx_report_error ();
                    }
                    break;

                case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:

                    pThis->input_flush_progress = false;
                    DEBUG_PRINT_HIGH("m_etb_count at i/p flush = %" PRIu64, m_etb_count);
                    m_etb_count = 0;
                    if (pThis->m_pCallbacks.EventHandler) {
                        /*Check if we need generate event for Flush done*/
                        if (BITMASK_PRESENT(&pThis->m_flags,
                                    OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
                            BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                    OMX_EventCmdComplete,OMX_CommandFlush,
                                    PORT_INDEX_IN,NULL );
                        } else if (BITMASK_PRESENT(&pThis->m_flags,
                                    OMX_COMPONENT_IDLE_PENDING)) {
                            if (!pThis->output_flush_progress) {
                                DEBUG_PRINT_LOW("dev_stop called after input flush complete");
                                if (dev_stop() != 0) {
                                    DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in i/p flush!");
                                    pThis->omx_report_error ();
                                }
                            }
                        }
                    }

                    break;

                case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:

                    pThis->output_flush_progress = false;
                    DEBUG_PRINT_HIGH("m_fbd_count at o/p flush = %" PRIu64, m_fbd_count);
                    m_fbd_count = 0;
                    if (pThis->m_pCallbacks.EventHandler) {
                        /*Check if we need generate event for Flush done*/
                        if (BITMASK_PRESENT(&pThis->m_flags,
                                    OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
                            BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);

                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                    OMX_EventCmdComplete,OMX_CommandFlush,
                                    PORT_INDEX_OUT,NULL );
                        } else if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
                            DEBUG_PRINT_LOW("dev_stop called after Output flush complete");
                            if (!pThis->input_flush_progress) {
                                if (dev_stop() != 0) {
                                    DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in o/p flush!");
                                    pThis->omx_report_error ();
                                }
                            }
                        }
                    }
                    break;

                case OMX_COMPONENT_GENERATE_START_DONE:
                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE msg");

                    if (pThis->m_pCallbacks.EventHandler) {
                        DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
                            DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Move to \
                                    executing");
                            // Send the callback now
                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
                            pThis->m_state = OMX_StateExecuting;
                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                    OMX_EventCmdComplete,OMX_CommandStateSet,
                                    OMX_StateExecuting, NULL);
                        } else if (BITMASK_PRESENT(&pThis->m_flags,
                                    OMX_COMPONENT_PAUSE_PENDING)) {
                            if (dev_pause()) {
                                DEBUG_PRINT_ERROR("ERROR: dev_pause() failed in Start Done!");
                                pThis->omx_report_error ();
                            }
                        } else if (BITMASK_PRESENT(&pThis->m_flags,
                                    OMX_COMPONENT_LOADED_START_PENDING)) {
                            if (dev_loaded_start_done()) {
                                DEBUG_PRINT_LOW("successful loaded Start Done!");
                            } else {
                                DEBUG_PRINT_ERROR("ERROR: failed in loaded Start Done!");
                                pThis->omx_report_error ();
                            }
                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_START_PENDING);
                        } else {
                            DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags);
                        }
                    } else {
                        DEBUG_PRINT_LOW("Event Handler callback is NULL");
                    }
                    break;

                case OMX_COMPONENT_GENERATE_PAUSE_DONE:
                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE msg");
                    if (pThis->m_pCallbacks.EventHandler) {
                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
                            //Send the callback now
                            pThis->complete_pending_buffer_done_cbs();
                            DEBUG_PRINT_LOW("omx_video::process_event_cb() Sending PAUSE complete after all pending EBD/FBD");
                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
                            pThis->m_state = OMX_StatePause;
                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                    OMX_EventCmdComplete,OMX_CommandStateSet,
                                    OMX_StatePause, NULL);
                        }
                    }

                    break;

                case OMX_COMPONENT_GENERATE_RESUME_DONE:
                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_RESUME_DONE msg");
                    if (pThis->m_pCallbacks.EventHandler) {
                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
                            // Send the callback now
                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
                            pThis->m_state = OMX_StateExecuting;
                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                    OMX_EventCmdComplete,OMX_CommandStateSet,
                                    OMX_StateExecuting,NULL);
                        }
                    }

                    break;

                case OMX_COMPONENT_GENERATE_STOP_DONE:
                    DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE msg");
                    if (pThis->m_pCallbacks.EventHandler) {
                        pThis->complete_pending_buffer_done_cbs();
                        if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
                            // Send the callback now
                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
                            pThis->m_state = OMX_StateIdle;
                            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data,
                                    OMX_EventCmdComplete,OMX_CommandStateSet,
                                    OMX_StateIdle,NULL);
                        } else if (BITMASK_PRESENT(&pThis->m_flags,
                                    OMX_COMPONENT_LOADED_STOP_PENDING)) {
                            if (dev_loaded_stop_done()) {
                                DEBUG_PRINT_LOW("successful loaded Stop Done!");
                            } else {
                                DEBUG_PRINT_ERROR("ERROR: failed in loaded Stop Done!");
                                pThis->omx_report_error ();
                            }
                            BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_STOP_PENDING);
                        } else {
                            DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags);
                        }
                    }

                    is_stop_in_progress = false;
                    break;

                case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
                    DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!");
                    pThis->omx_report_error ();
                    break;
                case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
                    DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
                    pThis->omx_report_unsupported_setting();
                    break;

                case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
                    DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
                    pThis->omx_report_hw_overload();
                    break;

                default:
                    DEBUG_PRINT_LOW("process_event_cb unknown msg id 0x%02x", (unsigned int)ident);
                    break;
            }
        }

        pthread_mutex_lock(&pThis->m_lock);
        qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\
                pThis->m_etb_q.m_size;

        pthread_mutex_unlock(&pThis->m_lock);

    } while (qsize>0);
    DEBUG_PRINT_LOW("exited the while loop");

}




/* ======================================================================
   FUNCTION
   omx_venc::GetComponentVersion

   DESCRIPTION
   Returns the component version.

   PARAMETERS
   TBD.

   RETURN VALUE
   OMX_ErrorNone.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::get_component_version
(
 OMX_IN OMX_HANDLETYPE hComp,
 OMX_OUT OMX_STRING componentName,
 OMX_OUT OMX_VERSIONTYPE* componentVersion,
 OMX_OUT OMX_VERSIONTYPE* specVersion,
 OMX_OUT OMX_UUIDTYPE* componentUUID
 )
{
    (void)hComp;
    (void)componentName;
    (void)componentVersion;
    (void)componentUUID;
    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State");
        return OMX_ErrorInvalidState;
    }
    /* TBD -- Return the proper version */
    if (specVersion) {
        specVersion->nVersion = OMX_SPEC_VERSION;
    }
    return OMX_ErrorNone;
}
/* ======================================================================
   FUNCTION
   omx_venc::SendCommand

   DESCRIPTION
   Returns zero if all the buffers released..

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp,
        OMX_IN OMX_COMMANDTYPE cmd,
        OMX_IN OMX_U32 param1,
        OMX_IN OMX_PTR cmdData
        )
{
    (void)hComp;
    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
        return OMX_ErrorInvalidState;
    }

    if (cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) {
        if ((param1 != (OMX_U32)PORT_INDEX_IN) && (param1 != (OMX_U32)PORT_INDEX_OUT) && (param1 != (OMX_U32)PORT_INDEX_BOTH)) {
            DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index");
            return OMX_ErrorBadPortIndex;
        }
    }
    if (cmd == OMX_CommandMarkBuffer) {
        if (param1 != PORT_INDEX_IN) {
            DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index");
            return OMX_ErrorBadPortIndex;
        }
        if (!cmdData) {
            DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null");
            return OMX_ErrorBadParameter;
        }
    }

    post_event((unsigned long)cmd,(unsigned long)param1,OMX_COMPONENT_GENERATE_COMMAND);
    sem_wait(&m_cmd_lock);
    return OMX_ErrorNone;
}

/* ======================================================================
   FUNCTION
   omx_venc::SendCommand

   DESCRIPTION
   Returns zero if all the buffers released..

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
        OMX_IN OMX_COMMANDTYPE cmd,
        OMX_IN OMX_U32 param1,
        OMX_IN OMX_PTR cmdData
        )
{
    (void)hComp;
    (void)cmdData;

    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    OMX_STATETYPE eState = (OMX_STATETYPE) param1;
    int bFlag = 1;

    if (cmd == OMX_CommandStateSet) {
        /***************************/
        /* Current State is Loaded */
        /***************************/
        if (m_state == OMX_StateLoaded) {
            if (eState == OMX_StateIdle) {
                //if all buffers are allocated or all ports disabled
                if (allocate_done() ||
                        ( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE)) {
                    DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle");
                } else {
                    DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending");
                    BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
                    // Skip the event notification
                    bFlag = 0;
                }
            }
            /* Requesting transition from Loaded to Loaded */
            else if (eState == OMX_StateLoaded) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded");
                post_event(OMX_EventError,OMX_ErrorSameState,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorSameState;
            }
            /* Requesting transition from Loaded to WaitForResources */
            else if (eState == OMX_StateWaitForResources) {
                /* Since error is None , we will post an event
                   at the end of this function definition */
                DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources");
            }
            /* Requesting transition from Loaded to Executing */
            else if (eState == OMX_StateExecuting) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Loaded to Pause */
            else if (eState == OMX_StatePause) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Loaded to Invalid */
            else if (eState == OMX_StateInvalid) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid");
                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorInvalidState;
            } else {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled",\
                        eState);
                eRet = OMX_ErrorBadParameter;
            }
        }

        /***************************/
        /* Current State is IDLE */
        /***************************/
        else if (m_state == OMX_StateIdle) {
            if (eState == OMX_StateLoaded) {
                if (release_done()) {
                    /*
                       Since error is None , we will post an event at the end
                       of this function definition
                     */
                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded");
                    if (dev_stop() != 0) {
                        DEBUG_PRINT_ERROR("ERROR: dev_stop() failed at Idle --> Loaded");
                        eRet = OMX_ErrorHardware;
                    }
                } else {
                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending");
                    BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
                    // Skip the event notification
                    bFlag = 0;
                }
            }
            /* Requesting transition from Idle to Executing */
            else if (eState == OMX_StateExecuting) {
                if ( dev_start() ) {
                    DEBUG_PRINT_ERROR("ERROR: dev_start() failed in SCP on Idle --> Exe");
                    omx_report_error ();
                    eRet = OMX_ErrorHardware;
                } else {
                    BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing");
                    bFlag = 0;
                }

                dev_start_done();
            }
            /* Requesting transition from Idle to Idle */
            else if (eState == OMX_StateIdle) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle");
                post_event(OMX_EventError,OMX_ErrorSameState,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorSameState;
            }
            /* Requesting transition from Idle to WaitForResources */
            else if (eState == OMX_StateWaitForResources) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Idle to Pause */
            else if (eState == OMX_StatePause) {
                /*To pause the Video core we need to start the driver*/
                if ( dev_start() ) {
                    DEBUG_PRINT_ERROR("ERROR: dev_start() failed in SCP on Idle --> Pause");
                    omx_report_error ();
                    eRet = OMX_ErrorHardware;
                } else {
                    BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
                    DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause");
                    bFlag = 0;
                }
            }
            /* Requesting transition from Idle to Invalid */
            else if (eState == OMX_StateInvalid) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid");
                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorInvalidState;
            } else {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled",eState);
                eRet = OMX_ErrorBadParameter;
            }
        }

        /******************************/
        /* Current State is Executing */
        /******************************/
        else if (m_state == OMX_StateExecuting) {
            /* Requesting transition from Executing to Idle */
            if (eState == OMX_StateIdle) {
                /* Since error is None , we will post an event
                   at the end of this function definition
                 */
                DEBUG_PRINT_LOW("OMXCORE-SM: Executing --> Idle");
                //here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle
                BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
                execute_omx_flush(OMX_ALL);
                bFlag = 0;
            }
            /* Requesting transition from Executing to Paused */
            else if (eState == OMX_StatePause) {

                if (dev_pause()) {
                    DEBUG_PRINT_ERROR("ERROR: dev_pause() failed in SCP on Exe --> Pause");
                    post_event(OMX_EventError,OMX_ErrorHardware,\
                            OMX_COMPONENT_GENERATE_EVENT);
                    eRet = OMX_ErrorHardware;
                } else {
                    BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
                    DEBUG_PRINT_LOW("OMXCORE-SM: Executing-->Pause");
                    bFlag = 0;
                }
            }
            /* Requesting transition from Executing to Loaded */
            else if (eState == OMX_StateLoaded) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Loaded");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Executing to WaitForResources */
            else if (eState == OMX_StateWaitForResources) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> WaitForResources");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Executing to Executing */
            else if (eState == OMX_StateExecuting) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Executing");
                post_event(OMX_EventError,OMX_ErrorSameState,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorSameState;
            }
            /* Requesting transition from Executing to Invalid */
            else if (eState == OMX_StateInvalid) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Invalid");
                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorInvalidState;
            } else {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled",eState);
                eRet = OMX_ErrorBadParameter;
            }
        }
        /***************************/
        /* Current State is Pause  */
        /***************************/
        else if (m_state == OMX_StatePause) {
            /* Requesting transition from Pause to Executing */
            if (eState == OMX_StateExecuting) {
                DEBUG_PRINT_LOW("Pause --> Executing");
                if ( dev_resume() ) {
                    post_event(OMX_EventError,OMX_ErrorHardware,\
                            OMX_COMPONENT_GENERATE_EVENT);
                    eRet = OMX_ErrorHardware;
                } else {
                    BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
                    DEBUG_PRINT_LOW("OMXCORE-SM: Pause-->Executing");
                    post_event (0, 0, OMX_COMPONENT_GENERATE_RESUME_DONE);
                    bFlag = 0;
                }
            }
            /* Requesting transition from Pause to Idle */
            else if (eState == OMX_StateIdle) {
                /* Since error is None , we will post an event
                   at the end of this function definition */
                DEBUG_PRINT_LOW("Pause --> Idle");
                BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
                execute_omx_flush(OMX_ALL);
                bFlag = 0;
            }
            /* Requesting transition from Pause to loaded */
            else if (eState == OMX_StateLoaded) {
                DEBUG_PRINT_ERROR("ERROR: Pause --> loaded");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Pause to WaitForResources */
            else if (eState == OMX_StateWaitForResources) {
                DEBUG_PRINT_ERROR("ERROR: Pause --> WaitForResources");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from Pause to Pause */
            else if (eState == OMX_StatePause) {
                DEBUG_PRINT_ERROR("ERROR: Pause --> Pause");
                post_event(OMX_EventError,OMX_ErrorSameState,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorSameState;
            }
            /* Requesting transition from Pause to Invalid */
            else if (eState == OMX_StateInvalid) {
                DEBUG_PRINT_ERROR("ERROR: Pause --> Invalid");
                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorInvalidState;
            } else {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled",eState);
                eRet = OMX_ErrorBadParameter;
            }
        }
        /***************************/
        /* Current State is WaitForResources  */
        /***************************/
        else if (m_state == OMX_StateWaitForResources) {
            /* Requesting transition from WaitForResources to Loaded */
            if (eState == OMX_StateLoaded) {
                /* Since error is None , we will post an event
                   at the end of this function definition */
                DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded");
            }
            /* Requesting transition from WaitForResources to WaitForResources */
            else if (eState == OMX_StateWaitForResources) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources");
                post_event(OMX_EventError,OMX_ErrorSameState,
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorSameState;
            }
            /* Requesting transition from WaitForResources to Executing */
            else if (eState == OMX_StateExecuting) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from WaitForResources to Pause */
            else if (eState == OMX_StatePause) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause");
                post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
                        OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorIncorrectStateTransition;
            }
            /* Requesting transition from WaitForResources to Invalid */
            else if (eState == OMX_StateInvalid) {
                DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid");
                post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
                eRet = OMX_ErrorInvalidState;
            }
            /* Requesting transition from WaitForResources to Loaded -
               is NOT tested by Khronos TS */

        } else {
            DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)",m_state,eState);
            eRet = OMX_ErrorBadParameter;
        }
    }
    /********************************/
    /* Current State is Invalid */
    /*******************************/
    else if (m_state == OMX_StateInvalid) {
        /* State Transition from Inavlid to any state */
        if ((eState == OMX_StateLoaded) || (eState == OMX_StateWaitForResources) ||
                (eState == OMX_StateIdle) || (eState == OMX_StateExecuting) ||
                (eState == OMX_StatePause) || (eState == OMX_StateInvalid)) {
            DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded");
            post_event(OMX_EventError,OMX_ErrorInvalidState,\
                    OMX_COMPONENT_GENERATE_EVENT);
            eRet = OMX_ErrorInvalidState;
        }
    } else if (cmd == OMX_CommandFlush) {
        if (0 == param1 || OMX_ALL == param1) {
            BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
        }
        if (1 == param1 || OMX_ALL == param1) {
            //generate output flush event only.
            BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
        }

        execute_omx_flush(param1);
        bFlag = 0;
    } else if ( cmd == OMX_CommandPortEnable) {
        if (param1 == PORT_INDEX_IN || param1 == OMX_ALL) {
            m_sInPortDef.bEnabled = OMX_TRUE;

            if ( (m_state == OMX_StateLoaded &&
                        !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
                    || allocate_input_done()) {
                post_event(OMX_CommandPortEnable,PORT_INDEX_IN,
                        OMX_COMPONENT_GENERATE_EVENT);
            } else {
                DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending");
                BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
                // Skip the event notification
                bFlag = 0;
            }
        }
        if (param1 == PORT_INDEX_OUT || param1 == OMX_ALL) {
            m_sOutPortDef.bEnabled = OMX_TRUE;

            if ( (m_state == OMX_StateLoaded &&
                        !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
                    || (allocate_output_done())) {
                post_event(OMX_CommandPortEnable,PORT_INDEX_OUT,
                        OMX_COMPONENT_GENERATE_EVENT);

            } else {
                DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending");
                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
                // Skip the event notification
                bFlag = 0;
            }
        }
    } else if (cmd == OMX_CommandPortDisable) {
        if (param1 == PORT_INDEX_IN || param1 == OMX_ALL) {
            m_sInPortDef.bEnabled = OMX_FALSE;
            if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
                    && release_input_done()) {
                post_event(OMX_CommandPortDisable,PORT_INDEX_IN,
                        OMX_COMPONENT_GENERATE_EVENT);
            } else {
                BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
                if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
                    execute_omx_flush(PORT_INDEX_IN);
                }

                // Skip the event notification
                bFlag = 0;
            }
        }
        if (param1 == PORT_INDEX_OUT || param1 == OMX_ALL) {
            m_sOutPortDef.bEnabled = OMX_FALSE;

            if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
                    && release_output_done()) {
                post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\
                        OMX_COMPONENT_GENERATE_EVENT);
            } else {
                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
                if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
                    execute_omx_flush(PORT_INDEX_OUT);
                }
                // Skip the event notification
                bFlag = 0;

            }
        }
    } else {
        DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)",cmd);
        eRet = OMX_ErrorNotImplemented;
    }
    if (eRet == OMX_ErrorNone && bFlag) {
        post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
    }
    sem_post(&m_cmd_lock);
    return eRet;
}

/* ======================================================================
   FUNCTION
   omx_venc::ExecuteOmxFlush

   DESCRIPTION
   Executes the OMX flush.

   PARAMETERS
   flushtype - input flush(1)/output flush(0)/ both.

   RETURN VALUE
   true/false

   ========================================================================== */
bool omx_video::execute_omx_flush(OMX_U32 flushType)
{
    bool bRet = false;
    DEBUG_PRINT_LOW("execute_omx_flush -  %u", (unsigned int)flushType);
    /* XXX: The driver/hardware does not support flushing of individual ports
     * in all states. So we pretty much need to flush both ports internally,
     * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
     * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
     * we automatically omit sending the FLUSH done for the "opposite" port. */

    input_flush_progress = true;
    output_flush_progress = true;
    bRet = execute_flush_all();
    return bRet;
}
/*=========================================================================
FUNCTION : execute_output_flush

DESCRIPTION
Executes the OMX flush at OUTPUT PORT.

PARAMETERS
None.

RETURN VALUE
true/false
==========================================================================*/
bool omx_video::execute_output_flush(void)
{
    unsigned long p1 = 0; // Parameter - 1
    unsigned long p2 = 0; // Parameter - 2
    unsigned long ident = 0;
    bool bRet = true;

    /*Generate FBD for all Buffers in the FTBq*/
    DEBUG_PRINT_LOW("execute_output_flush");
    pthread_mutex_lock(&m_lock);
    while (m_ftb_q.m_size) {
        m_ftb_q.pop_entry(&p1,&p2,&ident);

        if (ident == OMX_COMPONENT_GENERATE_FTB ) {
            pending_output_buffers++;
            VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
        } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
        }
    }

    pthread_mutex_unlock(&m_lock);
    /*Check if there are buffers with the Driver*/
    if (dev_flush(PORT_INDEX_OUT)) {
        DEBUG_PRINT_ERROR("ERROR: o/p dev_flush() Failed");
        return false;
    }

    return bRet;
}
/*=========================================================================
FUNCTION : execute_input_flush

DESCRIPTION
Executes the OMX flush at INPUT PORT.

PARAMETERS
None.

RETURN VALUE
true/false
==========================================================================*/
bool omx_video::execute_input_flush(void)
{
    unsigned long p1 = 0; // Parameter - 1
    unsigned long p2 = 0; // Parameter - 2
    unsigned long ident = 0;
    bool bRet = true;

    /*Generate EBD for all Buffers in the ETBq*/
    DEBUG_PRINT_LOW("execute_input_flush");

    pthread_mutex_lock(&m_lock);
    while (m_etb_q.m_size) {
        m_etb_q.pop_entry(&p1,&p2,&ident);
        if (ident == OMX_COMPONENT_GENERATE_ETB) {
            pending_input_buffers++;
            VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
        } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
        } else if (ident == OMX_COMPONENT_GENERATE_ETB_OPQ) {
            print_omx_buffer("Flush ETB_OPQ", (OMX_BUFFERHEADERTYPE *)p2);
            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2);
        }
    }
    while (m_TimeStampInfo.deferred_inbufq.m_size) {
        m_TimeStampInfo.deferred_inbufq.pop_entry(&p1,&p2,&ident);
        m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p1);
    }
    if (mUseProxyColorFormat) {
        if (psource_frame) {
            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame);
            psource_frame = NULL;
        }
        while (m_opq_meta_q.m_size) {
            unsigned long p1,p2,id;
            m_opq_meta_q.pop_entry(&p1,&p2,&id);
            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,
                    (OMX_BUFFERHEADERTYPE  *)p1);
        }
        if (pdest_frame) {
            m_opq_pmem_q.insert_entry((unsigned long)pdest_frame,0,0);
            pdest_frame = NULL;
        }
    }
    pthread_mutex_unlock(&m_lock);
    /*Check if there are buffers with the Driver*/
    if (dev_flush(PORT_INDEX_IN)) {
         DEBUG_PRINT_ERROR("ERROR: i/p dev_flush() Failed");
         return false;
    }

    return bRet;
}


/*=========================================================================
FUNCTION : execute_flush

DESCRIPTION
Executes the OMX flush at INPUT & OUTPUT PORT.

PARAMETERS
None.

RETURN VALUE
true/false
==========================================================================*/
bool omx_video::execute_flush_all(void)
{
    unsigned long p1 = 0; // Parameter - 1
    unsigned long p2 = 0; // Parameter - 2
    unsigned long ident = 0;
    bool bRet = true;

    DEBUG_PRINT_LOW("execute_flush_all");

    /*Generate EBD for all Buffers in the ETBq*/
    pthread_mutex_lock(&m_lock);
    while (m_etb_q.m_size) {
        m_etb_q.pop_entry(&p1,&p2,&ident);
        if (ident == OMX_COMPONENT_GENERATE_ETB) {
            pending_input_buffers++;
            VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
        } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
            empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
        } else if(ident == OMX_COMPONENT_GENERATE_ETB_OPQ) {
            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2);
        }
    }

    while (m_TimeStampInfo.deferred_inbufq.m_size) {
        m_TimeStampInfo.deferred_inbufq.pop_entry(&p1,&p2,&ident);
        m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p1);
    }

    if(mUseProxyColorFormat) {
        if(psource_frame) {
            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame);
            psource_frame = NULL;
        }
        while(m_opq_meta_q.m_size) {
            unsigned long p1,p2,id;
            m_opq_meta_q.pop_entry(&p1,&p2,&id);
            m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,
                (OMX_BUFFERHEADERTYPE  *)p1);
        }
        if(pdest_frame){
            m_opq_pmem_q.insert_entry((unsigned long)pdest_frame,0,0);
            pdest_frame = NULL;
        }
    }

    /*Generate FBD for all Buffers in the FTBq*/
    DEBUG_PRINT_LOW("execute_output_flush");
    while (m_ftb_q.m_size) {
        m_ftb_q.pop_entry(&p1,&p2,&ident);

        if (ident == OMX_COMPONENT_GENERATE_FTB ) {
            pending_output_buffers++;
            VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
        } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
            fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
        }
    }

    pthread_mutex_unlock(&m_lock);
    /*Check if there are buffers with the Driver*/
    if (dev_flush(PORT_INDEX_BOTH)) {
         DEBUG_PRINT_ERROR("ERROR: dev_flush() Failed");
         return false;
    }

    return bRet;
}

/* ======================================================================
   FUNCTION
   omx_venc::SendCommandEvent

   DESCRIPTION
   Send the event to decoder pipe.  This is needed to generate the callbacks
   in decoder thread context.

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
bool omx_video::post_event(unsigned long p1,
        unsigned long p2,
        unsigned long id)
{
    bool bRet =  false;

    pthread_mutex_lock(&m_lock);

    if ((id == OMX_COMPONENT_GENERATE_FTB) ||
            (id == OMX_COMPONENT_GENERATE_FBD) ||
            (id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH)) {
        m_ftb_q.insert_entry(p1,p2,id);
    } else if ((id == OMX_COMPONENT_GENERATE_ETB) ||
            (id == OMX_COMPONENT_GENERATE_EBD) ||
            (id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH)) {
        m_etb_q.insert_entry(p1,p2,id);
    } else {
        m_cmd_q.insert_entry(p1,p2,id);
    }

    bRet = true;
    post_message(this, id);
    pthread_mutex_unlock(&m_lock);

    return bRet;
}

/* ======================================================================
   FUNCTION
   omx_venc::GetParameter

   DESCRIPTION
   OMX Get Parameter method implementation

   PARAMETERS
   <TBD>.

   RETURN VALUE
   Error None if successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
        OMX_IN OMX_INDEXTYPE paramIndex,
        OMX_INOUT OMX_PTR     paramData)
{
    (void)hComp;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    unsigned int height=0,width = 0;

    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State");
        return OMX_ErrorInvalidState;
    }
    if (paramData == NULL) {
        DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData");
        return OMX_ErrorBadParameter;
    }

    switch ((int)paramIndex) {
        case OMX_IndexParamPortDefinition:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;

                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition: port %d", portDefn->nPortIndex);
                if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
                    dev_get_buf_req (&m_sInPortDef.nBufferCountMin,
                        &m_sInPortDef.nBufferCountActual,
                        &m_sInPortDef.nBufferSize,
                        m_sInPortDef.nPortIndex);

                    memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef));
#ifdef _ANDROID_ICS_
                    if (meta_mode_enable) {
                        // request size of largest metadata (happens to be NativeHandleSource) since
                        // we do not know the exact metadata-type yet
                        portDefn->nBufferSize = sizeof(LEGACY_CAM_METADATA_TYPE);
                    }
                    if (mUseProxyColorFormat) {
                        portDefn->format.video.eColorFormat =
                            (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque;
                    }
#endif
                } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
                    if (m_state != OMX_StateExecuting) {
                        dev_get_buf_req (&m_sOutPortDef.nBufferCountMin,
                            &m_sOutPortDef.nBufferCountActual,
                            &m_sOutPortDef.nBufferSize,
                            m_sOutPortDef.nPortIndex);
                        dev_get_dimensions(m_sOutPortDef.nPortIndex,
                            &m_sOutPortDef.format.video.nFrameWidth,
                            &m_sOutPortDef.format.video.nFrameHeight);
                    }

                    memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef));
                    // Tiling in HW expects output port def to be aligned to tile size
                    // At the same time, FWK needs original WxH for various purposes
                    // Sending input WxH as output port def WxH to FWK
                    if (m_sOutPortDef.format.video.eCompressionFormat ==
                        OMX_VIDEO_CodingImageHEIC) {
                        portDefn->format.video.nFrameWidth =
                            m_sInPortDef.format.video.nFrameWidth;
                        portDefn->format.video.nFrameHeight =
                            m_sInPortDef.format.video.nFrameHeight;
                    }

                    if (secure_session || allocate_native_handle) {
                        portDefn->nBufferSize =
                                sizeof(native_handle_t) + (sizeof(int) * (1/*numFds*/ + 3/*numInts*/));
                    }
                } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_EXTRADATA_OUT) {
                    portDefn->nBufferSize = m_client_out_extradata_info.getSize();
                    portDefn->nBufferCountMin= m_sOutPortDef.nBufferCountMin;
                    portDefn->nBufferCountActual = m_client_out_extradata_info.getBufferCount();
                    portDefn->eDir =  OMX_DirOutput;
                    DEBUG_PRINT_LOW("extradata port: size = %u, min cnt = %u, actual cnt = %u",
                            (unsigned int)portDefn->nBufferSize, (unsigned int)portDefn->nBufferCountMin,
                            (unsigned int)portDefn->nBufferCountActual);
                } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_EXTRADATA_IN) {
                    portDefn->nBufferSize = m_client_in_extradata_info.getSize();
                    portDefn->nBufferCountMin= m_sInPortDef.nBufferCountMin;
                    portDefn->nBufferCountActual = m_client_in_extradata_info.getBufferCount();
                    portDefn->eDir =  OMX_DirInput;
                    DEBUG_PRINT_LOW("extradata port: size = %u, min cnt = %u, actual cnt = %u",
                            (unsigned int)portDefn->nBufferSize, (unsigned int)portDefn->nBufferCountMin,
                            (unsigned int)portDefn->nBufferCountActual);
                } else {
                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
                    eRet = OMX_ErrorBadPortIndex;
                }

                DEBUG_PRINT_HIGH("get_parameter: OMX_IndexParamPortDefinition: port %d, wxh %dx%d, min %d, actual %d, size %d, colorformat %#x, compression format %#x",
                    portDefn->nPortIndex, portDefn->format.video.nFrameWidth,
                    portDefn->format.video.nFrameHeight, portDefn->nBufferCountMin,
                    portDefn->nBufferCountActual, portDefn->nBufferSize,
                    portDefn->format.video.eColorFormat, portDefn->format.video.eCompressionFormat);

                break;
            }
        case OMX_IndexParamVideoInit:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
                OMX_PORT_PARAM_TYPE *portParamType =
                    (OMX_PORT_PARAM_TYPE *) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");

                memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam));
                break;
            }
        case OMX_IndexParamVideoPortFormat:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
                OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
                    (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");

                if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
                    unsigned index = portFmt->nIndex;
                    OMX_U32 colorFormat = OMX_COLOR_FormatUnused;
                    if(dev_get_supported_color_format(index, &colorFormat)) {
                        memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat));
                        portFmt->nIndex = index; //restore index set from client
                        portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
                    } else {
                        eRet = OMX_ErrorNoMore;
                    }
                } else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
                    memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat));
                } else {
                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
                    eRet = OMX_ErrorBadPortIndex;
                }
                break;
            }
        case OMX_IndexParamVideoBitrate:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_BITRATETYPE);
                OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate");

                if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
                    memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate));
                } else {
                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
                    eRet = OMX_ErrorBadPortIndex;
                }

                break;
            }
        case OMX_IndexParamVideoMpeg4:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_MPEG4TYPE);
                OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4");
                memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4));
                break;
            }
        case OMX_IndexParamVideoH263:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_H263TYPE);
                OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263");
                memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263));
                break;
            }
        case OMX_IndexParamVideoAvc:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_AVCTYPE);
                OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc");
                memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC));
                break;
            }
        case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_VP8TYPE);
                OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoVp8");
                memcpy(pParam, &m_sParamVP8, sizeof(m_sParamVP8));
                break;
            }
        case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_HEVCTYPE);
                OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoHevc");
                memcpy(pParam, &m_sParamHEVC, sizeof(m_sParamHEVC));
                break;
            }
        case OMX_IndexParamVideoAndroidImageGrid:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE);
                OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE* pParam =
                    (OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAndroidImageGrid");
                m_sParamAndroidImageGrid.bEnabled = OMX_TRUE;
                m_sParamAndroidImageGrid.nTileWidth = DEFAULT_TILE_DIMENSION;
                m_sParamAndroidImageGrid.nTileHeight = DEFAULT_TILE_DIMENSION;
                m_sParamAndroidImageGrid.nGridRows =
                    m_sInPortDef.format.video.nFrameHeight > 0 ?
                    ((m_sInPortDef.format.video.nFrameHeight - 1) / DEFAULT_TILE_DIMENSION + 1) :
                    DEFAULT_TILE_ROWS;
                m_sParamAndroidImageGrid.nGridCols =
                    m_sInPortDef.format.video.nFrameWidth > 0 ?
                    ((m_sInPortDef.format.video.nFrameWidth - 1) / DEFAULT_TILE_DIMENSION + 1) :
                    DEFAULT_TILE_COLS;
                memcpy(pParam, &m_sParamAndroidImageGrid, sizeof(m_sParamAndroidImageGrid));
                break;
            }
        case OMX_IndexParamVideoProfileLevelQuerySupported:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
                OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported");
                eRet = dev_get_supported_profile_level(pParam);
                if (eRet && eRet != OMX_ErrorNoMore)
                    DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %u, %u",
                            (unsigned int)pParam->eProfile, (unsigned int)pParam->eLevel);
                break;
            }
        case OMX_IndexParamVideoProfileLevelCurrent:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
                OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent");
                memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel));
                break;
            }
            /*Component should support this port definition*/
        case OMX_IndexParamAudioInit:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
                OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
                memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio));
                break;
            }
            /*Component should support this port definition*/
        case OMX_IndexParamImageInit:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
                OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
                memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img));
                break;

            }
            /*Component should support this port definition*/
        case OMX_IndexParamOtherInit:
            {
                DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x", paramIndex);
                eRet =OMX_ErrorUnsupportedIndex;
                break;
            }
        case OMX_IndexParamStandardComponentRole:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
                OMX_PARAM_COMPONENTROLETYPE *comp_role;
                comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
                comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
                comp_role->nSize = sizeof(*comp_role);

                DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",paramIndex);
                strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE);
                break;
            }
            /* Added for parameter test */
        case OMX_IndexParamPriorityMgmt:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
                OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
                memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt));
                break;
            }
            /* Added for parameter test */
        case OMX_IndexParamCompBufferSupplier:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
                OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
                if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) {
                    memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier));
                } else if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT) {
                    memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier));
                } else {
                    DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
                    eRet = OMX_ErrorBadPortIndex;
                }
                break;
            }

        case OMX_IndexParamVideoQuantization:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
                OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization");
                memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization));
                break;
            }

        case QOMX_IndexParamVideoInitialQp:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP);
                QOMX_EXTNINDEX_VIDEO_INITIALQP *initial_qp = (QOMX_EXTNINDEX_VIDEO_INITIALQP*) paramData;
                DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoInitialQp");
                initial_qp->nQpI = m_sSessionQuantization.nQpI;
                initial_qp->nQpP = m_sSessionQuantization.nQpP;
                initial_qp->nQpB = m_sSessionQuantization.nQpB;
                initial_qp->bEnableInitQp = m_QPSet;
                break;
            }

        case OMX_QcomIndexParamVideoIPBQPRange:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE);
                OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE*) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoIPBQPRange");
                memcpy(qp_range, &m_sSessionQPRange, sizeof(m_sSessionQPRange));
                break;
            }

        case OMX_IndexParamVideoErrorCorrection:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE);
                OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData;
                DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection");
                errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC;
                errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync;
                errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing;
                break;
            }
        case OMX_IndexParamVideoIntraRefresh:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_INTRAREFRESHTYPE);
                OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData;
                DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh");
                DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET");
                intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode;
                intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs;
                break;
            }
        case OMX_QcomIndexPortDefn:
            //TODO
            break;
        case OMX_COMPONENT_CAPABILITY_TYPE_INDEX:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMXComponentCapabilityFlagsType);
                OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData);
                DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX");
                pParam->iIsOMXComponentMultiThreaded = OMX_TRUE;
                pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE;
                pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
                pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
                pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE;
                pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE;
                pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE;
                pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE;
                m_use_input_pmem = OMX_TRUE;
                DEBUG_PRINT_LOW("Supporting capability index in encoder node");
                break;
            }
        case OMX_QcomIndexParamIndexExtraDataType:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType");
                QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData;
                if (pParam->nIndex == (OMX_INDEXTYPE)OMX_QTI_ExtraDataCategory_Advanced) {
                    if (pParam->nPortIndex == PORT_INDEX_OUT) {
                        pParam->bEnabled = (OMX_BOOL)(m_sExtraData & EXTRADATA_ADVANCED);
                        DEBUG_PRINT_HIGH("Advanced extradata %d", pParam->bEnabled);
                    } else {
                        DEBUG_PRINT_ERROR("get_parameter: Advanced extradata is "
                                "valid for output port only");
                        eRet = OMX_ErrorUnsupportedIndex;
                    }
                } else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_QTI_ExtraDataCategory_Enc_ROI) {
                    if (pParam->nPortIndex == PORT_INDEX_IN) {
                        pParam->bEnabled = (OMX_BOOL)(m_sExtraData & EXTRADATA_ENC_INPUT_ROI);
                        DEBUG_PRINT_HIGH("ROI %d", pParam->bEnabled);
                    } else {
                        DEBUG_PRINT_ERROR("get_parameter: ROI is valid for input port only");
                        eRet = OMX_ErrorUnsupportedIndex;
                    }
                } else {
                    DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
                            pParam->nPortIndex);
                    eRet = OMX_ErrorUnsupportedIndex;
                }
                break;
            }
        case OMX_QTIIndexParamVideoClientExtradata:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
                DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
                QOMX_EXTRADATA_ENABLE *pParam =
                    (QOMX_EXTRADATA_ENABLE *)paramData;
                if (pParam->nPortIndex == PORT_INDEX_EXTRADATA_OUT) {
                    OMX_U32 output_extradata_mask = EXTRADATA_ADVANCED;
                    pParam->bEnable = (m_sExtraData & output_extradata_mask) ? OMX_TRUE : OMX_FALSE;
                    eRet = OMX_ErrorNone;
                } else if (pParam->nPortIndex == PORT_INDEX_EXTRADATA_IN) {
                    OMX_U32 input_extradata_mask = EXTRADATA_ENC_INPUT_ROI;
                    pParam->bEnable = (m_sExtraData & input_extradata_mask) ? OMX_TRUE : OMX_FALSE;
                    eRet = OMX_ErrorNone;
                } else {
                    DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
                            pParam->nPortIndex);
                    eRet = OMX_ErrorUnsupportedIndex;
                }
                break;
            }
        case OMX_QcomIndexParamVideoLTRCount:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE);
                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoLTRCount");
                OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE *pParam =
                        reinterpret_cast<OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*>(paramData);
                memcpy(pParam, &m_sParamLTRCount, sizeof(m_sParamLTRCount));
                break;
            }
        case QOMX_IndexParamVideoSyntaxHdr:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE);
                DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr");
                QOMX_EXTNINDEX_PARAMTYPE* pParam =
                    reinterpret_cast<QOMX_EXTNINDEX_PARAMTYPE*>(paramData);
                if (pParam->pData == NULL) {
                    DEBUG_PRINT_ERROR("Error: Data buffer is NULL");
                    eRet = OMX_ErrorBadParameter;
                    break;
                }
                if (get_syntaxhdr_enable == false) {
                    DEBUG_PRINT_ERROR("ERROR: get_parameter: Get syntax header disabled");
                    eRet = OMX_ErrorUnsupportedIndex;
                    break;
                }
                BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_START_PENDING);
                if (dev_loaded_start()) {
                    DEBUG_PRINT_LOW("device start successful");
                } else {
                    DEBUG_PRINT_ERROR("device start failed");
                    BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_START_PENDING);
                    return OMX_ErrorHardware;
                }
                if (dev_get_seq_hdr(pParam->pData,
                            (unsigned)(pParam->nSize - sizeof(QOMX_EXTNINDEX_PARAMTYPE)),
                            (unsigned *)(void *)&pParam->nDataSize)) {
                    DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %u)",
                            (unsigned int)pParam->nDataSize);
                    for (unsigned i = 0; i < pParam->nDataSize; i++) {
                        DEBUG_PRINT_LOW("Header[%d] = %x", i, *((char *)pParam->pData + i));
                    }
                } else {
                    DEBUG_PRINT_ERROR("Error returned from GetSyntaxHeader()");
                    eRet = OMX_ErrorHardware;
                }
                BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING);
                if (dev_loaded_stop()) {
                    DEBUG_PRINT_LOW("device stop successful");
                } else {
                    DEBUG_PRINT_ERROR("device stop failed");
                    BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING);
                    eRet = OMX_ErrorHardware;
                }
                break;
            }
        case OMX_QcomIndexHierarchicalStructure:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_HIERARCHICALLAYERS);
                QOMX_VIDEO_HIERARCHICALLAYERS* hierp = (QOMX_VIDEO_HIERARCHICALLAYERS*) paramData;
                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexHierarchicalStructure");
                memcpy(hierp, &m_sHierLayers, sizeof(m_sHierLayers));
                break;
            }
        case OMX_QcomIndexParamH264VUITimingInfo:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO);
                OMX_U32 enabled;
                OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam =
                    reinterpret_cast<OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO*>(paramData);
                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamH264VUITimingInfo");
                if (!dev_get_vui_timing_info(&enabled)) {
                    DEBUG_PRINT_ERROR("Invalid entry returned from get_vui_Timing_info %d",
                        pParam->bEnable);
                } else {
                    pParam->bEnable = (OMX_BOOL)enabled;
                }
                break;
            }
        case OMX_QcomIndexParamBatchSize:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_U32TYPE);
                OMX_PARAM_U32TYPE* batch =
                    reinterpret_cast<OMX_PARAM_U32TYPE *>(paramData);

                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamBatchSize");
                if (!dev_get_batch_size(&batch->nU32)) {
                    DEBUG_PRINT_ERROR("Invalid entry returned from dev_get_batch_size %u",
                        (unsigned int)batch->nSize);
                    eRet = OMX_ErrorUnsupportedIndex;
                    break;
                }

                batch->nPortIndex = PORT_INDEX_IN;
                break;
            }
        case OMX_QcomIndexParamSequenceHeaderWithIDR:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, PrependSPSPPSToIDRFramesParams);
                PrependSPSPPSToIDRFramesParams * pParam =
                    reinterpret_cast<PrependSPSPPSToIDRFramesParams *>(paramData);
                DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamSequenceHeaderWithIDR");
                memcpy(pParam, &m_sPrependSPSPPS, sizeof(m_sPrependSPSPPS));
                break;
            }
        case OMX_QcomIndexParamVencAspectRatio:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_VENC_SAR);
               QOMX_EXTNINDEX_VIDEO_VENC_SAR * pParam =
                   reinterpret_cast<QOMX_EXTNINDEX_VIDEO_VENC_SAR *>(paramData);
                memcpy(pParam, &m_sSar, sizeof(m_sSar));
                break;
            }
        case OMX_IndexParamAndroidVideoTemporalLayering:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE);
                OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pLayerInfo =
                        reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE*>(paramData);
                if (!dev_get_temporal_layer_caps(&m_sParamTemporalLayers.nLayerCountMax,
                        &m_sParamTemporalLayers.nBLayerCountMax, &m_sParamTemporalLayers.eSupportedPatterns)) {
                    DEBUG_PRINT_ERROR("Failed to get temporal layer capabilities");
                    eRet = OMX_ErrorHardware;
                }
                memcpy(pLayerInfo, &m_sParamTemporalLayers, sizeof(m_sParamTemporalLayers));
                break;
            }
        case OMX_QcomIndexParamVideoDownScalar:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
                QOMX_INDEXDOWNSCALAR *pDownScalarParam =
                    reinterpret_cast<QOMX_INDEXDOWNSCALAR *>(paramData);
                memcpy(pDownScalarParam, &m_sParamDownScalar, sizeof(m_sParamDownScalar));
                break;
            }
        case OMX_IndexParamVideoAndroidVp8Encoder:
            {
                VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE);
                OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pVp8Params =
                        reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE*>(paramData);
                memcpy(pVp8Params,&m_sParamVP8Encoder,sizeof(m_sParamVP8Encoder));
                break;
            }
        case OMX_IndexParamConsumerUsageBits:
            {
               /*                            Consumer usage bits
                *  --------------------------------------------------------------------
                *  GRALLOC_USAGE_PRIVATE_    | GRALLOC_USAGE_PRIVATE_  |  Color       |
                *  ALLOC_UBWC                | ALLOC_10BITS            |  Format      |
                *   (bit 28)                 |  (bit30)                |              |
                *  --------------------------------------------------------------------
                *    0                       |     0                   |   NV12       |
                *    0                       |     1                   |   P010       |
                *    1                       |     0                   |   UBWC_NV12  |
                *    1                       |     1                   |   BPP10_UBWC |
                *  --------------------------------------------------------------------
                */

                if (paramData == NULL) { return OMX_ErrorBadParameter; }

                OMX_U32 *consumerUsage = (OMX_U32 *)paramData;
                m_sParamConsumerUsage = 0;
                dev_get_consumer_usage(&m_sParamConsumerUsage);
                memcpy(consumerUsage, &m_sParamConsumerUsage, sizeof(m_sParamConsumerUsage));
                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamConsumerUsageBits %x",
                    m_sParamConsumerUsage);
                break;
            }
        case OMX_IndexParamVideoSliceFMO:
        default:
            {
                DEBUG_PRINT_LOW("ERROR: get_parameter: unknown param %08x", paramIndex);
                eRet =OMX_ErrorUnsupportedIndex;
                break;
            }

    }

    return eRet;

}
/* ======================================================================
   FUNCTION
   omx_video::GetConfig

   DESCRIPTION
   OMX Get Config Method implementation.

   PARAMETERS
   <TBD>.

   RETURN VALUE
   OMX Error None if successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::get_config(OMX_IN OMX_HANDLETYPE      hComp,
        OMX_IN OMX_INDEXTYPE configIndex,
        OMX_INOUT OMX_PTR     configData)
{
    (void)hComp;
    ////////////////////////////////////////////////////////////////
    // Supported Config Index           Type
    // =============================================================
    // OMX_IndexConfigVideoBitrate      OMX_VIDEO_CONFIG_BITRATETYPE
    // OMX_IndexConfigVideoFramerate    OMX_CONFIG_FRAMERATETYPE
    // OMX_IndexConfigCommonRotate      OMX_CONFIG_ROTATIONTYPE
    ////////////////////////////////////////////////////////////////

    if (configData == NULL) {
        DEBUG_PRINT_ERROR("ERROR: param is null");
        return OMX_ErrorBadParameter;
    }

    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: can't be in invalid state");
        return OMX_ErrorIncorrectStateOperation;
    }

    //@todo need to validate params
    switch ((int)configIndex) {
        case OMX_IndexConfigVideoBitrate:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_BITRATETYPE);
                OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData);
                memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate));
                break;
            }
        case OMX_IndexConfigVideoFramerate:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_FRAMERATETYPE);
                OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData);
                memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate));
                break;
            }
        case OMX_IndexConfigCommonRotate:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ROTATIONTYPE);
                OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
                memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation));
                break;
            }
        case OMX_IndexConfigCommonMirror:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_MIRRORTYPE);
                OMX_CONFIG_MIRRORTYPE* pParam = reinterpret_cast<OMX_CONFIG_MIRRORTYPE*>(configData);
                memcpy(pParam, &m_sConfigFrameMirror, sizeof(m_sConfigFrameMirror));
                break;
            }
        case QOMX_IndexConfigVideoIntraperiod:
            {
                DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod nPframes : %d nBframes : %d",
                              m_sIntraperiod.nPFrames, m_sIntraperiod.nBFrames);
                VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_INTRAPERIODTYPE);
                QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData);
                memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod));
                break;
            }
        case OMX_IndexConfigVideoAVCIntraPeriod:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_AVCINTRAPERIOD);
                OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pParam =
                    reinterpret_cast<OMX_VIDEO_CONFIG_AVCINTRAPERIOD*>(configData);
                DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoAVCIntraPeriod");
                memcpy(pParam, &m_sConfigAVCIDRPeriod, sizeof(m_sConfigAVCIDRPeriod));
                break;
            }
       case OMX_IndexConfigVideoVp8ReferenceFrame:
           {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_VP8REFERENCEFRAMETYPE);
               OMX_VIDEO_VP8REFERENCEFRAMETYPE* pParam =
                   reinterpret_cast<OMX_VIDEO_VP8REFERENCEFRAMETYPE*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoVp8ReferenceFrame");
               memcpy(pParam, &m_sConfigVp8ReferenceFrame, sizeof(m_sConfigVp8ReferenceFrame));
               break;
           }
       case OMX_QcomIndexConfigNumHierPLayers:
           {
                VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS);
               QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS* pParam =
                   reinterpret_cast<QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigNumHierPLayers");
               memcpy(pParam, &m_sHPlayers, sizeof(m_sHPlayers));
               break;
           }
       case OMX_QcomIndexConfigQp:
           {
               VALIDATE_OMX_PARAM_DATA(configData, OMX_SKYPE_VIDEO_CONFIG_QP);
               OMX_SKYPE_VIDEO_CONFIG_QP* pParam =
                   reinterpret_cast<OMX_SKYPE_VIDEO_CONFIG_QP*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigQp");
               memcpy(pParam, &m_sConfigQP, sizeof(m_sConfigQP));
               break;
           }
       case OMX_QcomIndexConfigBaseLayerId:
           {
               VALIDATE_OMX_PARAM_DATA(configData, OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID);
               OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID* pParam =
                   reinterpret_cast<OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigBaseLayerId");
               memcpy(pParam, &m_sBaseLayerID, sizeof(m_sBaseLayerID));
               break;
           }
       case OMX_IndexConfigAndroidIntraRefresh:
           {
               VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE);
               OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE* pParam =
                   reinterpret_cast<OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidIntraRefresh");
               memcpy(pParam, &m_sConfigIntraRefresh, sizeof(m_sConfigIntraRefresh));
               break;
           }
        case OMX_IndexConfigOperatingRate:
           {
               VALIDATE_OMX_PARAM_DATA(configData, OMX_PARAM_U32TYPE);
               OMX_PARAM_U32TYPE* pParam =
                   reinterpret_cast<OMX_PARAM_U32TYPE*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_IndexConfigOperatingRate");
               pParam->nU32 = m_nOperatingRate;
               break;
           }
       case OMX_QTIIndexConfigVideoBlurResolution:
           {
               VALIDATE_OMX_PARAM_DATA(configData, OMX_QTI_VIDEO_CONFIG_BLURINFO);
               OMX_QTI_VIDEO_CONFIG_BLURINFO* pParam =
                   reinterpret_cast<OMX_QTI_VIDEO_CONFIG_BLURINFO*>(configData);
               DEBUG_PRINT_LOW("get_config: OMX_QTIIndexConfigVideoBlurResolution");
               memcpy(pParam, &m_blurInfo, sizeof(OMX_QTI_VIDEO_CONFIG_BLURINFO));
               break;
           }
       case OMX_QTIIndexConfigDescribeColorAspects:
            {
                VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
                DescribeColorAspectsParams* pParam =
                    reinterpret_cast<DescribeColorAspectsParams*>(configData);
                DEBUG_PRINT_LOW("get_config: OMX_QTIIndexConfigDescribeColorAspects");
                if (pParam->bRequestingDataSpace) {
                    DEBUG_PRINT_LOW("Does not handle dataspace request. Please ignore this Unsupported Setting (0x80001019).");
                    return OMX_ErrorUnsupportedSetting;
                }
                if (pParam->bDataSpaceChanged == OMX_TRUE) {

                    print_debug_color_aspects(&(pParam->sAspects), "get_config (dataspace changed) Client says");
                    // If the dataspace says RGB, recommend 601-limited;
                    // since that is the destination colorspace that C2D or Venus will convert to.
                    if (pParam->nPixelFormat == HAL_PIXEL_FORMAT_RGBA_8888) {
                        DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: Recommend 601 for RGBA8888");
                        pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625;
                        // keep client-default setting for range
                        // pParam->sAspects.mRange = ColorAspects::RangeLimited;
                        pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
                        pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
                    } else {
                         DEBUG_PRINT_INFO("get_config (dataspace changed): dataspace=0x%x", pParam->nDataSpace);
                         if (pParam->nDataSpace == HAL_DATASPACE_JFIF || pParam->nDataSpace == HAL_DATASPACE_V0_JFIF) {
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_JFIF");
                             pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625;
                             pParam->sAspects.mRange = ColorAspects::RangeFull;
                             pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
                             pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
                         } else if (pParam->nDataSpace == HAL_DATASPACE_BT601_525 || pParam->nDataSpace == HAL_DATASPACE_V0_BT601_525) {
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT601_525");
                             pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525;
                             pParam->sAspects.mRange = ColorAspects::RangeLimited;
                             pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
                             pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
                         } else if (pParam->nDataSpace == HAL_DATASPACE_BT601_625 || pParam->nDataSpace == HAL_DATASPACE_V0_BT601_625) {
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT601_625");
                             pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625;
                             pParam->sAspects.mRange = ColorAspects::RangeLimited;
                             pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
                             pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
                         } else if (pParam->nDataSpace == HAL_DATASPACE_BT709 || pParam->nDataSpace == HAL_DATASPACE_V0_BT709) {
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT709");
                             pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT709_5;
                             pParam->sAspects.mRange = ColorAspects::RangeLimited;
                             pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
                             pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5;
                         } else if (pParam->nDataSpace == HAL_DATASPACE_BT2020) {
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT2020");
                             pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT2020;
                             pParam->sAspects.mRange = ColorAspects::RangeFull;
                             pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
                             pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020;
                         } else if (pParam->nDataSpace == (HAL_DATASPACE_STANDARD_BT2020|HAL_DATASPACE_TRANSFER_HLG|HAL_DATASPACE_RANGE_LIMITED)) {
                             //For SONY HDR
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_STANDARD_BT2020|HAL_DATASPACE_TRANSFER_HLG|HAL_DATASPACE_RANGE_LIMITED");
                             pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT2020;
                             pParam->sAspects.mRange = ColorAspects::RangeLimited;
                             pParam->sAspects.mTransfer = ColorAspects::TransferHLG;
                             pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020;
                         } else {
                             // Stick to client's defaults.
                             DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: use client-default for format=%x",
                             pParam->nPixelFormat);
                         }
                    }
                    print_debug_color_aspects(&(pParam->sAspects), "get_config (dataspace changed) recommended");
                } else {
                    memcpy(pParam, &m_sConfigColorAspects, sizeof(m_sConfigColorAspects));
                    print_debug_color_aspects(&(pParam->sAspects), "get_config");
                }
                break;
            }
        case OMX_IndexConfigAndroidVideoTemporalLayering:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE);
                OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *layerConfig =
                        (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)configData;
                DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidVideoTemporalLayering");
                memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers));
                break;
            }
        case OMX_IndexConfigAndroidVendorExtension:
            {
                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);

                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
                    reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
                VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
                return get_vendor_extension_config(ext);
            }

        default:
            DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
            return OMX_ErrorUnsupportedIndex;
    }
    return OMX_ErrorNone;

}

#define extn_equals(param, extn) (!strcmp(param, extn))

/* ======================================================================
   FUNCTION
   omx_video::GetExtensionIndex

   DESCRIPTION
   OMX GetExtensionIndex method implementaion.  <TBD>

   PARAMETERS
   <TBD>.

   RETURN VALUE
   OMX Error None if everything successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
        OMX_IN OMX_STRING      paramName,
        OMX_OUT OMX_INDEXTYPE* indexType)
{
    (void)hComp;
    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State");
        return OMX_ErrorInvalidState;
    }

#ifdef _ANDROID_ICS_
    if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
        return OMX_ErrorNone;
    }
#endif
    if (extn_equals(paramName, "OMX.google.android.index.prependSPSPPSToIDRFrames")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamSequenceHeaderWithIDR;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.param.video.HierStructure")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexHierarchicalStructure;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.param.video.LTRCount")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoLTRCount;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.param.video.LTRPeriod")) {
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.config.video.LTRUse")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoLTRUse;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.config.video.LTRMark")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoLTRMark;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.config.video.hierplayers")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.param.video.baselayerid")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigBaseLayerId;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.config.video.qp")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigQp;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.param.video.sar")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVencAspectRatio;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.QCOM.index.param.video.InputBatch")) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamBatchSize;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_SETTIMEDATA)) {
        *indexType = (OMX_INDEXTYPE)OMX_IndexConfigTimePosition;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_ENABLE_ROIINFO)) {
        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_ROIINFO)) {
        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoRoiInfo;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_BLURINFO)) {
        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoBlurResolution;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
        return OMX_ErrorNone;
    }

    if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_NATIVE_RECORDER)) {
        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamNativeRecorder;
        return OMX_ErrorNone;
    }

    return OMX_ErrorNotImplemented;
}

/* ======================================================================
   FUNCTION
   omx_video::GetState

   DESCRIPTION
   Returns the state information back to the caller.<TBD>

   PARAMETERS
   <TBD>.

   RETURN VALUE
   Error None if everything is successful.
   ========================================================================== */
OMX_ERRORTYPE  omx_video::get_state(OMX_IN OMX_HANDLETYPE  hComp,
        OMX_OUT OMX_STATETYPE* state)
{
    (void)hComp;
    *state = m_state;
    DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
    return OMX_ErrorNone;
}

/* ======================================================================
   FUNCTION
   omx_video::ComponentTunnelRequest

   DESCRIPTION
   OMX Component Tunnel Request method implementation. <TBD>

   PARAMETERS
   None.

   RETURN VALUE
   OMX Error None if everything successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
        OMX_IN OMX_U32                        port,
        OMX_IN OMX_HANDLETYPE        peerComponent,
        OMX_IN OMX_U32                    peerPort,
        OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
{
    (void) hComp, (void) port, (void) peerComponent, (void) peerPort, (void) tunnelSetup;
    DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented");
    return OMX_ErrorNotImplemented;
}

/* ======================================================================
   FUNCTION
   omx_video::UseInputBuffer

   DESCRIPTION
   Helper function for Use buffer in the input pin

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::use_input_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes,
        OMX_IN OMX_U8*                   buffer)
{
    (void) hComp;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;

    unsigned   i = 0;
    unsigned char *buf_addr = NULL;

    DEBUG_PRINT_HIGH("use_input_buffer: port = %u appData = %p bytes = %u buffer = %p",(unsigned int)port,appData,(unsigned int)bytes,buffer);
    if (bytes < m_sInPortDef.nBufferSize) {
        DEBUG_PRINT_ERROR("ERROR: use_input_buffer: Size Mismatch!! "
                "bytes[%u] < Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sInPortDef.nBufferSize);
        return OMX_ErrorBadParameter;
    }

    if (!m_inp_mem_ptr) {
        input_use_buffer = true;
        m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
                        calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
        if (m_inp_mem_ptr == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_inp_mem_ptr");
            return OMX_ErrorInsufficientResources;
        }
        DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr);


        m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
        if (m_pInput_pmem == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_pmem");
            return OMX_ErrorInsufficientResources;
        }
#ifdef USE_ION
        m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual);
        if (m_pInput_ion == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_ion");
            return OMX_ErrorInsufficientResources;
        }
#endif

        for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
            m_pInput_pmem[i].fd = -1;
#ifdef USE_ION
            m_pInput_ion[i].data_fd =-1;
            m_pInput_ion[i].dev_fd =-1;
#endif
        }

    }

    for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
        if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
            break;
        }
    }

    if (i < m_sInPortDef.nBufferCountActual) {

        *bufferHdr = (m_inp_mem_ptr + i);
        BITMASK_SET(&m_inp_bm_count,i);
        BITMASK_SET(&m_client_in_bm_count,i);

        (*bufferHdr)->pBuffer           = (OMX_U8 *)buffer;
        (*bufferHdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
        (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
        (*bufferHdr)->nAllocLen         = m_sInPortDef.nBufferSize;
        (*bufferHdr)->pAppPrivate       = appData;
        (*bufferHdr)->nInputPortIndex   = PORT_INDEX_IN;

        if (!m_use_input_pmem) {
#ifdef USE_ION
            bool status = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
                    &m_pInput_ion[i],
                    secure_session ? SECURE_FLAGS_INPUT_BUFFER : 0);
            if (status == false) {
                DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
                return OMX_ErrorInsufficientResources;
            }
            m_pInput_pmem[i].fd = m_pInput_ion[i].data_fd;
#endif
            m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
            m_pInput_pmem[i].offset = 0;

            m_pInput_pmem[i].buffer = NULL;
            if(!secure_session) {
                m_pInput_pmem[i].buffer = (unsigned char *)ion_map(m_pInput_pmem[i].fd,
                                                                   m_pInput_pmem[i].size);

                if (m_pInput_pmem[i].buffer == MAP_FAILED) {
                    DEBUG_PRINT_ERROR("ERROR: mmap() Failed");
                    m_pInput_pmem[i].buffer = NULL;
#ifdef USE_ION
                    free_ion_memory(&m_pInput_ion[i]);
#endif
                    return OMX_ErrorInsufficientResources;
                }
            }

        } else {
            OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>((*bufferHdr)->pAppPrivate);
            DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (unsigned)pParam->offset);

            if (pParam) {
                m_pInput_pmem[i].fd = pParam->pmem_fd;
                m_pInput_pmem[i].offset = pParam->offset;
                m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
                m_pInput_pmem[i].buffer = (unsigned char *)buffer;
                DEBUG_PRINT_LOW("DBG:: pParam->pmem_fd = %u, pParam->offset = %u",
                        (unsigned int)pParam->pmem_fd, (unsigned int)pParam->offset);
            } else {
                DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case");
                return OMX_ErrorBadParameter;
            }
        }

        DEBUG_PRINT_LOW("use_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p",
                (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer);
        if (dev_use_buf(PORT_INDEX_IN) != true) {
            DEBUG_PRINT_ERROR("ERROR: dev_use_buf() Failed for i/p buf");
            return OMX_ErrorInsufficientResources;
        }
    } else {
        DEBUG_PRINT_ERROR("ERROR: All buffers are already used, invalid use_buf call for "
                "index = %u", i);
        eRet = OMX_ErrorInsufficientResources;
    }

    return eRet;
}



/* ======================================================================
   FUNCTION
   omx_video::UseOutputBuffer

   DESCRIPTION
   Helper function for Use buffer in the input pin

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::use_output_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes,
        OMX_IN OMX_U8*                   buffer)
{
    (void)hComp, (void)port;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
    unsigned                         i= 0; // Temporary counter
    unsigned char *buf_addr = NULL;
    int align_size;

    DEBUG_PRINT_HIGH("Inside use_output_buffer()");
    if (bytes < m_sOutPortDef.nBufferSize) {
        DEBUG_PRINT_ERROR("ERROR: use_output_buffer: Size Mismatch!! "
                "bytes[%u] < Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sOutPortDef.nBufferSize);
        return OMX_ErrorBadParameter;
    }

    if (!m_out_mem_ptr) {
        output_use_buffer = true;
        int nBufHdrSize        = 0;

        DEBUG_PRINT_LOW("Allocating First Output Buffer(%u)",(unsigned int)m_sOutPortDef.nBufferCountActual);
        nBufHdrSize        = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);
        /*
         * Memory for output side involves the following:
         * 1. Array of Buffer Headers
         * 2. Bitmask array to hold the buffer allocation details
         * In order to minimize the memory management entire allocation
         * is done in one step.
         */
        //OMX Buffer header
        m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
        if (m_out_mem_ptr == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_out_mem_ptr");
            return OMX_ErrorInsufficientResources;
        }

        m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual);
        if (m_pOutput_pmem == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_pmem");
            return OMX_ErrorInsufficientResources;
        }
#ifdef USE_ION
        m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual);
        if (m_pOutput_ion == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_ion");
            return OMX_ErrorInsufficientResources;
        }
#endif
        if (m_out_mem_ptr) {
            bufHdr          =  m_out_mem_ptr;
            DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
            // Settting the entire storage nicely
            for (i=0; i < m_sOutPortDef.nBufferCountActual ; i++) {
                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
                bufHdr->nAllocLen          = bytes;
                bufHdr->nFilledLen         = 0;
                bufHdr->pAppPrivate        = appData;
                bufHdr->nOutputPortIndex   = PORT_INDEX_OUT;
                bufHdr->pBuffer            = NULL;
                bufHdr++;
                m_pOutput_pmem[i].fd = -1;
#ifdef USE_ION
                m_pOutput_ion[i].data_fd =-1;
                m_pOutput_ion[i].dev_fd =-1;
#endif
            }
        } else {
            DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%p]",m_out_mem_ptr);
            eRet =  OMX_ErrorInsufficientResources;
        }
    }

    for (i=0; i< m_sOutPortDef.nBufferCountActual; i++) {
        if (BITMASK_ABSENT(&m_out_bm_count,i)) {
            break;
        }
    }

    if (eRet == OMX_ErrorNone) {
        if (i < m_sOutPortDef.nBufferCountActual) {
            *bufferHdr = (m_out_mem_ptr + i );
            (*bufferHdr)->pBuffer = (OMX_U8 *)buffer;
            (*bufferHdr)->pAppPrivate = appData;

            if (!m_use_output_pmem) {
#ifdef USE_ION
                align_size = (m_sOutPortDef.nBufferSize + (SZ_4K - 1)) & ~(SZ_4K - 1);
                bool status = alloc_map_ion_memory(align_size,
                        &m_pOutput_ion[i],
                        secure_session ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
                if (status == false) {
                    DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
                    return OMX_ErrorInsufficientResources;
                }
                m_pOutput_pmem[i].fd = m_pOutput_ion[i].data_fd;
#endif
                m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
                m_pOutput_pmem[i].offset = 0;

                m_pOutput_pmem[i].buffer = NULL;
                if(!secure_session) {
                    m_pOutput_pmem[i].buffer = (unsigned char *)ion_map(m_pOutput_pmem[i].fd,
                                                                        align_size);
                    if (m_pOutput_pmem[i].buffer == MAP_FAILED) {
                        DEBUG_PRINT_ERROR("ERROR: mmap() Failed");
                        m_pOutput_pmem[i].buffer = NULL;
#ifdef USE_ION
                        free_ion_memory(&m_pOutput_ion[i]);
#endif
                        return OMX_ErrorInsufficientResources;
                    }
                }
            } else {
                OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*>((*bufferHdr)->pAppPrivate);
                DEBUG_PRINT_LOW("Inside qcom_ext pParam: %p", pParam);

                if (pParam) {
                    DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (int)pParam->offset);
                    m_pOutput_pmem[i].fd = pParam->pmem_fd;
                    m_pOutput_pmem[i].offset = pParam->offset;
                    m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
                    m_pOutput_pmem[i].buffer = (unsigned char *)buffer;
                } else {
                    DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case");
                    return OMX_ErrorBadParameter;
                }
                buf_addr = (unsigned char *)buffer;
            }

            DEBUG_PRINT_LOW("use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p",
                    (*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer);
            if (dev_use_buf(PORT_INDEX_OUT) != true) {
                DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf");
                return OMX_ErrorInsufficientResources;
            }

            BITMASK_SET(&m_out_bm_count,i);
            BITMASK_SET(&m_client_out_bm_count,i);
        } else {
            DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for "
                    "index = %u", i);
            eRet = OMX_ErrorInsufficientResources;
        }
    }
    return eRet;
}


/* ======================================================================
   FUNCTION
   omx_video::UseBuffer

   DESCRIPTION
   OMX Use Buffer method implementation.

   PARAMETERS
   <TBD>.

   RETURN VALUE
   OMX Error None , if everything successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::use_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes,
        OMX_IN OMX_U8*                   buffer)
{
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State");
        return OMX_ErrorInvalidState;
    }

    auto_lock l(m_buf_lock);
    if (port == PORT_INDEX_IN) {
        eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
    } else if (port == PORT_INDEX_OUT) {
        eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
    } else if (port == PORT_INDEX_EXTRADATA_OUT) {
        eRet = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
    } else if (port == PORT_INDEX_EXTRADATA_IN) {
        eRet = use_client_input_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
    } else {
        DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d",(int)port);
        eRet = OMX_ErrorBadPortIndex;
    }
    if (eRet == OMX_ErrorNone) {
        if (allocate_done()) {
            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
                // Send the callback now
                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
                post_event(OMX_CommandStateSet,OMX_StateIdle,
                        OMX_COMPONENT_GENERATE_EVENT);
            }
        }
        if (port == PORT_INDEX_IN && m_sInPortDef.bPopulated) {
            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
                post_event(OMX_CommandPortEnable,
                        PORT_INDEX_IN,
                        OMX_COMPONENT_GENERATE_EVENT);
            }

        } else if (port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) {
            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
                post_event(OMX_CommandPortEnable,
                        PORT_INDEX_OUT,
                        OMX_COMPONENT_GENERATE_EVENT);
                m_event_port_settings_sent = false;
            }
        }
    }
    return eRet;
}

OMX_ERRORTYPE omx_video::allocate_client_output_extradata_headers() {
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
    int i = 0;

    if (!m_client_output_extradata_mem_ptr) {
        int nBufferCount       = 0;

        nBufferCount = m_client_out_extradata_info.getBufferCount();
        DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);

        m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));

        if (m_client_output_extradata_mem_ptr) {
            bufHdr          =  m_client_output_extradata_mem_ptr;
            for (i=0; i < nBufferCount; i++) {
                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
                // Set the values when we determine the right HxW param
                bufHdr->nAllocLen          = 0;
                bufHdr->nFilledLen         = 0;
                bufHdr->pAppPrivate        = NULL;
                bufHdr->nOutputPortIndex   = PORT_INDEX_EXTRADATA_OUT;
                bufHdr->pBuffer            = NULL;
                bufHdr->pOutputPortPrivate = NULL;
                bufHdr++;
            }
        } else {
             DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
                    m_client_output_extradata_mem_ptr);
              eRet =  OMX_ErrorInsufficientResources;
        }
    }
    return eRet;
}

OMX_ERRORTYPE omx_video::allocate_client_input_extradata_headers() {
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
    int i = 0;

    if (!m_client_input_extradata_mem_ptr) {
        int nBufferCount       = 0;

        nBufferCount = m_client_in_extradata_info.getBufferCount();
        DEBUG_PRINT_HIGH("allocate_client_input_extradata_headers buffer_count - %d", nBufferCount);

        m_client_input_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));

        if (m_client_input_extradata_mem_ptr) {
            bufHdr          =  m_client_input_extradata_mem_ptr;
            for (i=0; i < nBufferCount; i++) {
                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
                // Set the values when we determine the right HxW param
                bufHdr->nAllocLen          = 0;
                bufHdr->nFilledLen         = 0;
                bufHdr->pAppPrivate        = NULL;
                bufHdr->nInputPortIndex    = PORT_INDEX_EXTRADATA_IN;
                bufHdr->pBuffer            = NULL;
                bufHdr->pOutputPortPrivate = NULL;
                bufHdr++;
            }
        } else {
             DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
                    m_client_input_extradata_mem_ptr);
              eRet =  OMX_ErrorInsufficientResources;
        }
    }
    return eRet;
}

OMX_ERRORTYPE  omx_video::use_client_output_extradata_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes,
        OMX_IN OMX_U8*                   buffer)
{
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    unsigned i = 0; // Temporary counter
    unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
    OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
    (void) hComp;

    if (port != PORT_INDEX_EXTRADATA_OUT ||
            !m_sExtraData || bytes != buffer_size|| bufferHdr == NULL) {
        DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
            "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
            PORT_INDEX_EXTRADATA_OUT, m_sExtraData, bytes, buffer_size, bufferHdr);
        eRet = OMX_ErrorBadParameter;
        return eRet;
    }

    if (!m_client_output_extradata_mem_ptr) {
        eRet = allocate_client_output_extradata_headers();
    }

    if (eRet == OMX_ErrorNone) {
        for (i = 0; i < buffer_count; i++) {
            if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
                break;
            }
        }
    }

    if (i >= buffer_count) {
        DEBUG_PRINT_ERROR("invalid buffer index");
        eRet = OMX_ErrorInsufficientResources;
    }

    if (eRet == OMX_ErrorNone) {
        BITMASK_SET(&m_out_extradata_bm_count,i);
        *bufferHdr = (m_client_output_extradata_mem_ptr + i );
        (*bufferHdr)->pAppPrivate = appData;
        (*bufferHdr)->pBuffer = buffer;
        (*bufferHdr)->nAllocLen = bytes;
    }

    return eRet;
}

OMX_ERRORTYPE  omx_video::use_client_input_extradata_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes,
        OMX_IN OMX_U8*                   buffer)
{
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    unsigned i = 0; // Temporary counter
    unsigned buffer_count = m_client_in_extradata_info.getBufferCount();
    OMX_U32 buffer_size = m_client_in_extradata_info.getSize();
    (void) hComp;

    if (port != PORT_INDEX_EXTRADATA_IN ||
            !m_sExtraData || bytes != buffer_size|| bufferHdr == NULL) {
        DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
            "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
            PORT_INDEX_EXTRADATA_IN, m_sExtraData, bytes, buffer_size, bufferHdr);
        eRet = OMX_ErrorBadParameter;
        return eRet;
    }

    if (!m_client_input_extradata_mem_ptr) {
        eRet = allocate_client_input_extradata_headers();
    }

    if (eRet == OMX_ErrorNone) {
        for (i = 0; i < buffer_count; i++) {
            if (BITMASK_ABSENT(&m_in_extradata_bm_count,i)) {
                break;
            }
        }
    }

    if (i >= buffer_count) {
        DEBUG_PRINT_ERROR("invalid buffer index");
        eRet = OMX_ErrorInsufficientResources;
    }

    if (eRet == OMX_ErrorNone) {
        BITMASK_SET(&m_in_extradata_bm_count,i);
        *bufferHdr = (m_client_input_extradata_mem_ptr + i );
        (*bufferHdr)->pAppPrivate = appData;
        (*bufferHdr)->pBuffer = buffer;
        (*bufferHdr)->nAllocLen = bytes;
    }

    return eRet;
}

OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
{
    unsigned int index = 0;
    OMX_U8 *temp_buff ;

    if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
        DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]",
                bufferHdr, m_inp_mem_ptr);
        return OMX_ErrorBadParameter;
    }

    print_omx_buffer("free_input_buffer", bufferHdr);

    index = bufferHdr - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);
#ifdef _ANDROID_ICS_
    if (meta_mode_enable) {
        if (index < m_sInPortDef.nBufferCountActual) {
            memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index]));
            memset(&meta_buffers[index], 0, sizeof(meta_buffers[index]));
        }
        if (!mUseProxyColorFormat)
            return OMX_ErrorNone;
        else {
            opaque_buffer_hdr[index] = NULL;
        }
    }
#endif
    if (index < m_sInPortDef.nBufferCountActual && !mUseProxyColorFormat &&
            dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) {
        DEBUG_PRINT_LOW("ERROR: dev_free_buf() Failed for i/p buf");
    }

    if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) {

        if (mUseProxyColorFormat) {
            if (m_opq_pmem_q.m_size) {
                unsigned long addr, p1, id;
                m_opq_pmem_q.pop_entry(&addr, &p1, &id);
                DEBUG_PRINT_LOW("Removed entry in m_opq_pmem_q: address %lu", addr);
            }
        }

        if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) {
            DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case");
            if(!secure_session) {
                ion_unmap(m_pInput_ion[index].data_fd,
                          m_pInput_pmem[index].buffer,
                          m_pInput_pmem[index].size);
            } else {
                free(m_pInput_pmem[index].buffer);
            }
            m_pInput_pmem[index].buffer = NULL;
#ifdef USE_ION
            free_ion_memory(&m_pInput_ion[index]);
#endif
            m_pInput_pmem[index].fd = -1;
        } else if (m_pInput_pmem[index].fd > 0 && (input_use_buffer == true &&
                    m_use_input_pmem == OMX_FALSE)) {
            DEBUG_PRINT_LOW("FreeBuffer:: i/p Heap UseBuffer case");
            if (dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) {
                DEBUG_PRINT_ERROR("ERROR: dev_free_buf() Failed for i/p buf");
            }
            if(!secure_session) {
                ion_unmap(m_pInput_ion[index].data_fd,
                          m_pInput_pmem[index].buffer,
                          m_pInput_pmem[index].size);
                m_pInput_pmem[index].buffer = NULL;
            }
#ifdef USE_ION
            free_ion_memory(&m_pInput_ion[index]);
#endif
            m_pInput_pmem[index].fd = -1;
        } else {
            DEBUG_PRINT_ERROR("FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case");
        }
    }
    return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
{
    unsigned int index = 0;
    OMX_U8 *temp_buff ;

    if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
        DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]",
                bufferHdr, m_out_mem_ptr);
        return OMX_ErrorBadParameter;
    }
    index = bufferHdr - m_out_mem_ptr;

    print_omx_buffer("free_output_buffer", bufferHdr);

    if (index < m_sOutPortDef.nBufferCountActual &&
            dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) {
        DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
    }

    if (index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem) {
        if (m_pOutput_pmem[index].fd > 0 && output_use_buffer == false ) {
            DEBUG_PRINT_LOW("FreeBuffer:: o/p AllocateBuffer case");
            if(!secure_session) {
                ion_unmap(m_pOutput_pmem[index].fd,
                          m_pOutput_pmem[index].buffer,
                          m_pOutput_pmem[index].size);
            } else if (m_pOutput_pmem[index].buffer) {
                native_handle_t *handle;
                if (allocate_native_handle) {
                    handle = (native_handle_t *)m_pOutput_pmem[index].buffer;
                } else {
                    handle = ((output_metabuffer *)m_pOutput_pmem[index].buffer)->nh;
                    free(m_pOutput_pmem[index].buffer);
                }
                native_handle_close(handle);
                native_handle_delete(handle);
            }
#ifdef USE_ION
            free_ion_memory(&m_pOutput_ion[index]);
#endif

            m_pOutput_pmem[index].buffer = NULL;
            m_pOutput_pmem[index].fd = -1;
        } else if ( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true
                    && m_use_output_pmem == OMX_FALSE)) {
            DEBUG_PRINT_LOW("FreeBuffer:: o/p Heap UseBuffer case");
            if (dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) {
                DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
            }
            if(!secure_session) {
                ion_unmap(m_pOutput_pmem[index].fd,
                          m_pOutput_pmem[index].buffer,
                          m_pOutput_pmem[index].size);
            }
#ifdef USE_ION
            free_ion_memory(&m_pOutput_ion[index]);
#endif
            m_pOutput_pmem[index].fd = -1;
        } else {
            DEBUG_PRINT_LOW("FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case");
        }
    }
    return OMX_ErrorNone;
}
#ifdef _ANDROID_ICS_
OMX_ERRORTYPE omx_video::allocate_input_meta_buffer(
        OMX_HANDLETYPE       hComp,
        OMX_BUFFERHEADERTYPE **bufferHdr,
        OMX_PTR              appData,
        OMX_U32              bytes)
{
    unsigned index = 0;
    // In meta-mode alloc-length is not known conclusively
    // Allow allocation for atleast gralloc metadata handles
    //  and check for size in ETB
    if (!bufferHdr || bytes < sizeof(VideoGrallocMetadata)) {
        DEBUG_PRINT_ERROR("wrong params allocate_input_meta_buffer Hdr %p len %u",
                bufferHdr, (unsigned int)bytes);
        return OMX_ErrorBadParameter;
    }

    if (!m_inp_mem_ptr && !mUseProxyColorFormat) {
        m_inp_mem_ptr = meta_buffer_hdr;
        DEBUG_PRINT_LOW("use meta_buffer_hdr (%p) as m_inp_mem_ptr = %p",
                meta_buffer_hdr, m_inp_mem_ptr);
    }
    for (index = 0; ((index < m_sInPortDef.nBufferCountActual) &&
                meta_buffer_hdr[index].pBuffer &&
                BITMASK_PRESENT(&m_inp_bm_count, index)); index++);

    if (index == m_sInPortDef.nBufferCountActual) {
        DEBUG_PRINT_ERROR("All buffers are allocated input_meta_buffer");
        return OMX_ErrorBadParameter;
    }
    if (mUseProxyColorFormat) {
        if (opaque_buffer_hdr[index]) {
            DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr");
            return OMX_ErrorBadParameter;
        }
        if (allocate_input_buffer(hComp,&opaque_buffer_hdr[index],
                    PORT_INDEX_IN,appData,m_sInPortDef.nBufferSize) != OMX_ErrorNone) {
            DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr");
            return OMX_ErrorBadParameter;
        }
    }
    BITMASK_SET(&m_inp_bm_count,index);
    *bufferHdr = &meta_buffer_hdr[index];
    memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index]));
    meta_buffer_hdr[index].nSize = sizeof(meta_buffer_hdr[index]);
    meta_buffer_hdr[index].nAllocLen = bytes;
    meta_buffer_hdr[index].nVersion.nVersion = OMX_SPEC_VERSION;
    meta_buffer_hdr[index].nInputPortIndex = PORT_INDEX_IN;
    meta_buffer_hdr[index].pBuffer = (OMX_U8*)&meta_buffers[index];
    meta_buffer_hdr[index].pAppPrivate = appData;
    if (mUseProxyColorFormat) {
        m_opq_pmem_q.insert_entry((unsigned long)opaque_buffer_hdr[index],0,0);
        DEBUG_PRINT_HIGH("opaque_buffer_hdr insert %p", opaque_buffer_hdr[index]);
    }
    return OMX_ErrorNone;
}
#endif
/* ======================================================================
   FUNCTION
   omx_venc::AllocateInputBuffer

   DESCRIPTION
   Helper function for allocate buffer in the input pin

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::allocate_input_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes)
{
    (void)hComp, (void)port;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    unsigned   i = 0;

    DEBUG_PRINT_HIGH("allocate_input_buffer()::");
    if (bytes < m_sInPortDef.nBufferSize) {
        DEBUG_PRINT_ERROR("ERROR: Buffer size mismatch error: bytes[%u] < nBufferSize[%u]",
                (unsigned int)bytes, (unsigned int)m_sInPortDef.nBufferSize);
        return OMX_ErrorBadParameter;
    }

    if (!m_inp_mem_ptr) {
        DEBUG_PRINT_HIGH("%s: size = %u, actual cnt %u", __FUNCTION__,
                (unsigned int)m_sInPortDef.nBufferSize, (unsigned int)m_sInPortDef.nBufferCountActual);
        m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
                        calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
        if (m_inp_mem_ptr == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_inp_mem_ptr");
            return OMX_ErrorInsufficientResources;
        }

        DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr);
        m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);

        if (m_pInput_pmem == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_pmem");
            return OMX_ErrorInsufficientResources;
        }
#ifdef USE_ION
        m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual);
        if (m_pInput_ion == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_ion");
            return OMX_ErrorInsufficientResources;
        }
#endif
        for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
            m_pInput_pmem[i].fd = -1;
#ifdef USE_ION
            m_pInput_ion[i].data_fd = -1;
            m_pInput_ion[i].dev_fd = -1;
#endif
        }
    }

    for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
        if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
            break;
        }
    }
    if (i < m_sInPortDef.nBufferCountActual) {

        *bufferHdr = (m_inp_mem_ptr + i);
        (*bufferHdr)->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
        (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
        (*bufferHdr)->nAllocLen         = m_sInPortDef.nBufferSize;
        (*bufferHdr)->pAppPrivate       = appData;
        (*bufferHdr)->nInputPortIndex   = PORT_INDEX_IN;
        // make fd available to app layer, help with testing
        (*bufferHdr)->pInputPortPrivate = (OMX_PTR)&m_pInput_pmem[i];

#ifdef USE_ION
        // No use case where caching encoder makes sense
        bool status = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
                &m_pInput_ion[i],
                secure_session ? SECURE_FLAGS_INPUT_BUFFER : 0);
        if (status == false) {
            DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
            return OMX_ErrorInsufficientResources;
        }
        m_pInput_pmem[i].fd = m_pInput_ion[i].data_fd;
#endif
        m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
        m_pInput_pmem[i].offset = 0;

        m_pInput_pmem[i].buffer = NULL;
        if(!secure_session) {
            m_pInput_pmem[i].buffer = (unsigned char *)ion_map(m_pInput_pmem[i].fd,
                                                               m_pInput_pmem[i].size);
            if (m_pInput_pmem[i].buffer == MAP_FAILED) {
                DEBUG_PRINT_ERROR("ERROR: mmap FAILED= %d", errno);
                m_pInput_pmem[i].buffer = NULL;
#ifdef USE_ION
                free_ion_memory(&m_pInput_ion[i]);
#endif
                return OMX_ErrorInsufficientResources;
            }
        } else {
            //This should only be used for passing reference to source type and
            //secure handle fd struct native_handle_t*
            m_pInput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*));
            if (m_pInput_pmem[i].buffer == NULL) {
                DEBUG_PRINT_ERROR("%s: failed to allocate native-handle", __func__);
                return OMX_ErrorInsufficientResources;
            }
            (*bufferHdr)->nAllocLen = sizeof(OMX_U32) + sizeof(native_handle_t*);
        }

        (*bufferHdr)->pBuffer           = (OMX_U8 *)m_pInput_pmem[i].buffer;
        DEBUG_PRINT_LOW("Virtual address in allocate buffer is %p", m_pInput_pmem[i].buffer);
        BITMASK_SET(&m_inp_bm_count,i);
        //here change the I/P param here from buf_adr to pmem
        if (!mUseProxyColorFormat && (dev_use_buf(PORT_INDEX_IN) != true)) {
            DEBUG_PRINT_ERROR("ERROR: dev_use_buf FAILED for i/p buf");
            return OMX_ErrorInsufficientResources;
        }
    } else {
        DEBUG_PRINT_ERROR("ERROR: All i/p buffers are allocated, invalid allocate buf call"
                "for index [%d]", i);
        eRet = OMX_ErrorInsufficientResources;
    }

    return eRet;
}


/* ======================================================================
   FUNCTION
   omx_venc::AllocateOutputBuffer

   DESCRIPTION
   Helper fn for AllocateBuffer in the output pin

   PARAMETERS
   <TBD>.

   RETURN VALUE
   OMX Error None if everything went well.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::allocate_output_buffer(
        OMX_IN OMX_HANDLETYPE            hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                   port,
        OMX_IN OMX_PTR                   appData,
        OMX_IN OMX_U32                   bytes)
{
    (void)hComp, (void)port;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
    unsigned                         i= 0; // Temporary counter
    int align_size;

    DEBUG_PRINT_HIGH("allocate_output_buffer()for %u bytes", (unsigned int)bytes);
    if (!m_out_mem_ptr) {
        int nBufHdrSize        = 0;
        DEBUG_PRINT_HIGH("%s: size = %u, actual cnt %u", __FUNCTION__,
                (unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)m_sOutPortDef.nBufferCountActual);
        nBufHdrSize        = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);

        /*
         * Memory for output side involves the following:
         * 1. Array of Buffer Headers
         * 2. Bitmask array to hold the buffer allocation details
         * In order to minimize the memory management entire allocation
         * is done in one step.
         */
        m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);

#ifdef USE_ION
        m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual);
        if (m_pOutput_ion == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_ion");
            return OMX_ErrorInsufficientResources;
        }
#endif
        m_pOutput_pmem = (struct pmem *) calloc(sizeof(struct pmem), m_sOutPortDef.nBufferCountActual);
        if (m_pOutput_pmem == NULL) {
            DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_pmem");
            return OMX_ErrorInsufficientResources;
        }
        if (m_out_mem_ptr && m_pOutput_pmem) {
            bufHdr          =  m_out_mem_ptr;

            for (i=0; i < m_sOutPortDef.nBufferCountActual ; i++) {
                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
                // Set the values when we determine the right HxW param
                bufHdr->nAllocLen          = bytes;
                bufHdr->nFilledLen         = 0;
                bufHdr->pAppPrivate        = appData;
                bufHdr->nOutputPortIndex   = PORT_INDEX_OUT;
                // make fd available to app layer, help with testing
                bufHdr->pOutputPortPrivate = (OMX_PTR)&m_pOutput_pmem[i];
                bufHdr->pBuffer            = NULL;
                bufHdr++;
                m_pOutput_pmem[i].fd = -1;
#ifdef USE_ION
                m_pOutput_ion[i].data_fd = -1;
                m_pOutput_ion[i].dev_fd = -1;
#endif
            }
        } else {
            DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem");
            eRet = OMX_ErrorInsufficientResources;
        }
    }

    DEBUG_PRINT_HIGH("actual cnt = %u", (unsigned int)m_sOutPortDef.nBufferCountActual);
    for (i=0; i< m_sOutPortDef.nBufferCountActual; i++) {
        if (BITMASK_ABSENT(&m_out_bm_count,i)) {
            DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
            break;
        }
    }
    if (eRet == OMX_ErrorNone) {
        if (i < m_sOutPortDef.nBufferCountActual) {
#ifdef USE_ION
            align_size = ALIGN(m_sOutPortDef.nBufferSize, 4096);
            // Output buffers are cached so that muxer writing is faster
            bool status = alloc_map_ion_memory(align_size,
                    &m_pOutput_ion[i],
                    secure_session ? SECURE_FLAGS_OUTPUT_BUFFER : ION_FLAG_CACHED);
            if (status == false) {
                DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
                return OMX_ErrorInsufficientResources;
            }

            m_pOutput_pmem[i].fd = m_pOutput_ion[i].data_fd;
#endif
            m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
            m_pOutput_pmem[i].offset = 0;

            m_pOutput_pmem[i].buffer = NULL;
            *bufferHdr = (m_out_mem_ptr + i );

            if(!secure_session) {
                m_pOutput_pmem[i].buffer = (unsigned char *)ion_map(m_pOutput_pmem[i].fd,
                                                                    align_size);
                if (m_pOutput_pmem[i].buffer == MAP_FAILED) {
                    DEBUG_PRINT_ERROR("ERROR: MMAP_FAILED in o/p alloc buffer");
                    m_pOutput_pmem[i].buffer = NULL;
#ifdef USE_ION
                    free_ion_memory(&m_pOutput_ion[i]);
#endif
                    return OMX_ErrorInsufficientResources;
                }
            }
            else {
                //This should only be used for passing reference to source type and
                //secure handle fd struct native_handle_t*
                if (allocate_native_handle) {
                    native_handle_t *nh = native_handle_create(1 /*numFds*/, 3 /*numInts*/);
                    if (!nh) {
                        DEBUG_PRINT_ERROR("Native handle create failed");
                        return OMX_ErrorInsufficientResources;
                    }
                    nh->data[0] = m_pOutput_pmem[i].fd;
                    nh->data[1] = 0;
                    nh->data[2] = 0;
                    nh->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096);
                    m_pOutput_pmem[i].buffer = (OMX_U8 *)nh;
                } else {
                    native_handle_t *handle = native_handle_create(1, 3); //fd, offset, size, alloc length
                    if (!handle) {
                        DEBUG_PRINT_ERROR("ERROR: native handle creation failed");
                        return OMX_ErrorInsufficientResources;
                    }
                    m_pOutput_pmem[i].buffer = malloc(sizeof(output_metabuffer));
                    if (m_pOutput_pmem[i].buffer == NULL) {
                        DEBUG_PRINT_ERROR("%s: Failed to allocate meta buffer", __func__);
                        return OMX_ErrorInsufficientResources;
                    }
                    (*bufferHdr)->nAllocLen = sizeof(output_metabuffer);
                    handle->data[0] = m_pOutput_pmem[i].fd;
                    handle->data[1] = 0;
                    handle->data[2] = 0;
                    handle->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096);
                    output_metabuffer *buffer = (output_metabuffer*) m_pOutput_pmem[i].buffer;
                    buffer->type = 1;
                    buffer->nh = handle;
                }
            }

            (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer;
            (*bufferHdr)->pAppPrivate = appData;

            BITMASK_SET(&m_out_bm_count,i);

            if (dev_use_buf(PORT_INDEX_OUT) != true) {
                DEBUG_PRINT_ERROR("ERROR: dev_use_buf FAILED for o/p buf");
                return OMX_ErrorInsufficientResources;
            }
        } else {
            DEBUG_PRINT_ERROR("ERROR: All o/p buffers are allocated, invalid allocate buf call"
                    "for index [%d] actual: %u", i, (unsigned int)m_sOutPortDef.nBufferCountActual);
        }
    }

    return eRet;
}


// AllocateBuffer  -- API Call
/* ======================================================================
   FUNCTION
   omx_video::AllocateBuffer

   DESCRIPTION
   Returns zero if all the buffers released..

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                        port,
        OMX_IN OMX_PTR                     appData,
        OMX_IN OMX_U32                       bytes)
{

    OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type

    DEBUG_PRINT_LOW("Allocate buffer of size = %u on port %d", (unsigned int)bytes, (int)port);
    if (m_state == OMX_StateInvalid) {
        DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State");
        return OMX_ErrorInvalidState;
    }
     auto_lock l(m_buf_lock);
    // What if the client calls again.
    if (port == PORT_INDEX_IN) {
#ifdef _ANDROID_ICS_
        if (meta_mode_enable)
            eRet = allocate_input_meta_buffer(hComp,bufferHdr,appData,bytes);
        else
#endif
            eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
    } else if (port == PORT_INDEX_OUT) {
        eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
    } else {
        DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d",(int)port);
        eRet = OMX_ErrorBadPortIndex;
    }
    DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
    if (eRet == OMX_ErrorNone) {
        if (allocate_done()) {
            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
                // Send the callback now
                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
                post_event(OMX_CommandStateSet,OMX_StateIdle,
                        OMX_COMPONENT_GENERATE_EVENT);
            }
        }
        if (port == PORT_INDEX_IN && m_sInPortDef.bPopulated) {
            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
                post_event(OMX_CommandPortEnable,
                        PORT_INDEX_IN,
                        OMX_COMPONENT_GENERATE_EVENT);
            }
        }
        if (port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) {
            if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
                BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
                post_event(OMX_CommandPortEnable,
                        PORT_INDEX_OUT,
                        OMX_COMPONENT_GENERATE_EVENT);
                m_event_port_settings_sent = false;
            }
        }
    }
    DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
    return eRet;
}


// Free Buffer - API call
/* ======================================================================
   FUNCTION
   omx_video::FreeBuffer

   DESCRIPTION

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
        OMX_IN OMX_U32                 port,
        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
    (void)hComp;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    unsigned int nPortIndex;

    DEBUG_PRINT_LOW("In for encoder free_buffer");
    auto_lock l(m_buf_lock);
    if (port == PORT_INDEX_OUT) { //client called freebuffer, clearing client buffer bitmask right away to avoid use after free
        nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
        if(BITMASK_PRESENT(&m_client_out_bm_count, nPortIndex))
            BITMASK_CLEAR(&m_client_out_bm_count,nPortIndex);
    } else if (port == PORT_INDEX_IN) {
        nPortIndex = buffer - (meta_mode_enable?meta_buffer_hdr:m_inp_mem_ptr);
        if(BITMASK_PRESENT(&m_client_in_bm_count, nPortIndex))
            BITMASK_CLEAR(&m_client_in_bm_count,nPortIndex);
    }
    if (m_state == OMX_StateIdle &&
            (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
        DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
    } else if ((m_sInPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_IN)||
            (m_sOutPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_OUT)) {
        DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
    } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
        DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,ports need to be disabled");
        m_buffer_freed = true;
        post_event(OMX_EventError,
                OMX_ErrorPortUnpopulated,
                OMX_COMPONENT_GENERATE_EVENT);
        return eRet;
    } else {
        DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,port lost Buffers");
        m_buffer_freed = true;
        post_event(OMX_EventError,
                OMX_ErrorPortUnpopulated,
                OMX_COMPONENT_GENERATE_EVENT);
    }

    if (port == PORT_INDEX_IN) {
        // check if the buffer is valid
        nPortIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);

        DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %u, actual cnt %u",
                nPortIndex, (unsigned int)m_sInPortDef.nBufferCountActual);
        if (nPortIndex < m_sInPortDef.nBufferCountActual &&
                BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
            // Clear the bit associated with it.
            BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
            free_input_buffer (buffer);
            m_sInPortDef.bPopulated = OMX_FALSE;

            /*Free the Buffer Header*/
            if (release_input_done()) {
                input_use_buffer = false;
                // "m_inp_mem_ptr" may point to "meta_buffer_hdr" in some modes,
                // in which case, it was not explicitly allocated
                if (m_inp_mem_ptr && m_inp_mem_ptr != meta_buffer_hdr) {
                    DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr");
                    free (m_inp_mem_ptr);
                }
                m_inp_mem_ptr = NULL;
                if (m_pInput_pmem) {
                    DEBUG_PRINT_LOW("Freeing m_pInput_pmem");
                    free(m_pInput_pmem);
                    m_pInput_pmem = NULL;
                }
#ifdef USE_ION
                if (m_pInput_ion) {
                    DEBUG_PRINT_LOW("Freeing m_pInput_ion");
                    free(m_pInput_ion);
                    m_pInput_ion = NULL;
                }
#endif
            }
        } else {
            DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid");
            eRet = OMX_ErrorBadPortIndex;
        }

        if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
                && release_input_done()) {
            DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
            post_event(OMX_CommandPortDisable,
                    PORT_INDEX_IN,
                    OMX_COMPONENT_GENERATE_EVENT);
        }
    } else if (port == PORT_INDEX_OUT) {
        // check if the buffer is valid
        nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;

        DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %u, actual cnt %u",
                nPortIndex, (unsigned int)m_sOutPortDef.nBufferCountActual);
        if (nPortIndex < m_sOutPortDef.nBufferCountActual &&
                BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
            // Clear the bit associated with it.
            BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
            m_sOutPortDef.bPopulated = OMX_FALSE;
            free_output_buffer (buffer);

            if (release_output_done()) {
                output_use_buffer = false;
                if (m_out_mem_ptr) {
                    DEBUG_PRINT_LOW("Freeing m_out_mem_ptr");
                    free (m_out_mem_ptr);
                    m_out_mem_ptr = NULL;
                }
                if (m_pOutput_pmem) {
                    DEBUG_PRINT_LOW("Freeing m_pOutput_pmem");
                    free(m_pOutput_pmem);
                    m_pOutput_pmem = NULL;
                }
#ifdef USE_ION
                if (m_pOutput_ion) {
                    DEBUG_PRINT_LOW("Freeing m_pOutput_ion");
                    free(m_pOutput_ion);
                    m_pOutput_ion = NULL;
                }
#endif
            }
        } else {
            DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid");
            eRet = OMX_ErrorBadPortIndex;
        }
        if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
                && release_output_done() ) {
            DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");

            DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
            post_event(OMX_CommandPortDisable,
                    PORT_INDEX_OUT,
                    OMX_COMPONENT_GENERATE_EVENT);

        }
    } else if (port == PORT_INDEX_EXTRADATA_OUT) {
        nPortIndex = buffer - m_client_output_extradata_mem_ptr;
        DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);

        BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);

        if (release_output_extradata_done()) {
            free_output_extradata_buffer_header();
        }
    } else if (port == PORT_INDEX_EXTRADATA_IN) {
        nPortIndex = buffer - m_client_input_extradata_mem_ptr;
        DEBUG_PRINT_LOW("free_buffer on extradata input port - Port idx %d", nPortIndex);

        BITMASK_CLEAR(&m_in_extradata_bm_count,nPortIndex);

        if (release_input_extradata_done()) {
            free_input_extradata_buffer_header();
        }
    } else {
        eRet = OMX_ErrorBadPortIndex;
    }
    if ((eRet == OMX_ErrorNone) &&
            (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
        if (release_done()) {
            if (dev_stop() != 0) {
                DEBUG_PRINT_ERROR("ERROR: dev_stop() FAILED");
                eRet = OMX_ErrorHardware;
            }
            // Send the callback now
            BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
            post_event(OMX_CommandStateSet, OMX_StateLoaded,
                    OMX_COMPONENT_GENERATE_EVENT);
        } else {
            DEBUG_PRINT_HIGH("in free buffer, release not done, need to free more buffers output %" PRIx64" input %" PRIx64,
                    m_out_bm_count, m_inp_bm_count);
        }
    }
    if (eRet != OMX_ErrorNone) {
        m_buffer_freed = true;
    }

    return eRet;
}

void omx_video::free_output_extradata_buffer_header() {
    m_sExtraData = false;
    if (m_client_output_extradata_mem_ptr) {
        DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
        free(m_client_output_extradata_mem_ptr);
        m_client_output_extradata_mem_ptr = NULL;
    }
}

void omx_video::free_input_extradata_buffer_header() {
    m_sExtraData = false;
    if (m_client_input_extradata_mem_ptr) {
        DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
        free(m_client_input_extradata_mem_ptr);
        m_client_input_extradata_mem_ptr = NULL;
    }
}

/* ======================================================================
   FUNCTION
   omx_video::EmptyThisBuffer

   DESCRIPTION
   This routine is used to push the encoded video frames to
   the video decoder.

   PARAMETERS
   None.

   RETURN VALUE
   OMX Error None if everything went successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
    if(buffer != NULL && buffer->nInputPortIndex == PORT_INDEX_EXTRADATA_IN) {
        if(!dev_handle_client_input_extradata(buffer)) {
            DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> handling client extradata failed");
            return OMX_ErrorMax;
        }
        return OMX_ErrorNone;
    }
    OMX_ERRORTYPE ret1 = OMX_ErrorNone;
    unsigned int nBufferIndex ;

    if (m_state != OMX_StateExecuting &&
            m_state != OMX_StatePause &&
            m_state != OMX_StateIdle) {
        DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State");
        return OMX_ErrorInvalidState;
    }

    if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) {
        DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> buffer is null or buffer size is invalid");
        return OMX_ErrorBadParameter;
    }

    if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) {
        DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> OMX Version Invalid");
        return OMX_ErrorVersionMismatch;
    }

    print_omx_buffer("EmptyThisBuffer", buffer);
    if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN) {
        DEBUG_PRINT_ERROR("ERROR: Bad port index to call empty_this_buffer");
        return OMX_ErrorBadPortIndex;
    }
    if (!m_sInPortDef.bEnabled) {
        DEBUG_PRINT_ERROR("ERROR: Cannot call empty_this_buffer while I/P port is disabled");
        return OMX_ErrorIncorrectStateOperation;
    }

    nBufferIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);

    if (nBufferIndex > m_sInPortDef.nBufferCountActual ) {
        DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]", nBufferIndex);
        return OMX_ErrorBadParameter;
    }

    m_etb_count++;
    m_etb_timestamp = buffer->nTimeStamp;
    post_event ((unsigned long)hComp,(unsigned long)buffer,m_input_msg_id);
    return OMX_ErrorNone;
}

bool omx_video::profile_etb() {
    if (profile_mode) {
        struct timeval act_time = {0, 0};
        gettimeofday(&act_time, NULL);
        if (profile_start_time == 0) {
            profile_start_time = (act_time.tv_usec + act_time.tv_sec * 1e6);
        } else {
            profile_last_time = (act_time.tv_usec + act_time.tv_sec * 1e6);
        }
        profile_frame_count++;
        return true;
    }
    return false;
}

/* ======================================================================
   FUNCTION
   omx_video::empty_this_buffer_proxy

   DESCRIPTION
   This routine is used to push the encoded video frames to
   the video decoder.

   PARAMETERS
   None.

   RETURN VALUE
   OMX Error None if everything went successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
    VIDC_TRACE_NAME_HIGH("ETB");
    (void)hComp;
    OMX_U8 *pmem_data_buf = NULL;
    int push_cnt = 0;
    unsigned nBufIndex = 0;
    OMX_ERRORTYPE ret = OMX_ErrorNone;
    LEGACY_CAM_METADATA_TYPE *media_buffer = NULL;

    int fd = 0;

    DEBUG_PRINT_LOW("ETBProxy: buffer->pBuffer[%p]", buffer->pBuffer);
    if (buffer == NULL) {
        DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid buffer[%p]", buffer);
        return OMX_ErrorBadParameter;
    }

    if (profile_etb()) {
        m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
        return OMX_ErrorNone;
    }

    // Buffer sanity checks
    if (meta_mode_enable && !mUsesColorConversion) {
        //For color-conversion case, we have an internal buffer and not a meta buffer
        bool met_error = false;
        nBufIndex = buffer - meta_buffer_hdr;
        if (nBufIndex >= m_sInPortDef.nBufferCountActual) {
            DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid meta-bufIndex = %u", nBufIndex);
            return OMX_ErrorBadParameter;
        }
        media_buffer = (LEGACY_CAM_METADATA_TYPE *)meta_buffer_hdr[nBufIndex].pBuffer;
        if (!media_buffer) {
            DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__);
            return OMX_ErrorBadParameter;
        }
        if ((media_buffer->buffer_type == LEGACY_CAM_SOURCE)
                && buffer->nAllocLen != sizeof(LEGACY_CAM_METADATA_TYPE)) {
            DEBUG_PRINT_ERROR("Invalid metadata size expected(%u) v/s recieved(%zu)",
                    buffer->nAllocLen, sizeof(LEGACY_CAM_METADATA_TYPE));
            met_error = true;
        } else if (media_buffer) {
            if (media_buffer->buffer_type != LEGACY_CAM_SOURCE &&
                    media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) {
                DEBUG_PRINT_ERROR("Buffer type is neither LEGACY_CAM_SOURCE nor gralloc source");
                met_error = true;
            } else {
                if (media_buffer->buffer_type == LEGACY_CAM_SOURCE) {
                    if (media_buffer->meta_handle == NULL) {
                        DEBUG_PRINT_ERROR("Buffer type is LEGACY_CAM_SOURCE but handle is null");
                        met_error = true;
                    }
                    else {
                        // TBD: revisit this check !
                        int nFds = media_buffer->meta_handle->numFds,
                            nInt = media_buffer->meta_handle->numInts;
                        met_error = ((nFds == 1 && nInt >= 2) /*normal*/ ||
                                (nFds < 16 && nInt >= nFds*3) /*batch*/) ? false : true;
                        if (met_error) {
                            DEBUG_PRINT_ERROR("Unbalanced fds in handle: fds=%d ints=%d",
                                    nFds, nInt);
                        }
                    }
                }
            }
        } else {
            met_error = true;
            DEBUG_PRINT_ERROR("Unrecognized camera source type");
        }
        if (met_error) {
            DEBUG_PRINT_ERROR("ERROR: Unkown source/metahandle in ETB call");
            post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
            return OMX_ErrorBadParameter;
        }
    } else {
        nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
        if (nBufIndex >= m_sInPortDef.nBufferCountActual) {
            DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid bufIndex = %u", nBufIndex);
            return OMX_ErrorBadParameter;
        }
    }

    if (buffer->nFilledLen == 0 && (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
        DEBUG_PRINT_LOW("Zero length EOS buffer");
        handle_empty_eos_buffer();
        post_event ((unsigned long)buffer,0,
                OMX_COMPONENT_GENERATE_EBD);
        return OMX_ErrorNone;
    }

    pending_input_buffers++;
    VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
    if (input_flush_progress == true) {
        post_event ((unsigned long)buffer,0,
                OMX_COMPONENT_GENERATE_EBD);
        DEBUG_PRINT_ERROR("ERROR: ETBProxy: Input flush in progress");
        return OMX_ErrorNone;
    }

    if (is_stop_in_progress == true) {
        post_event ((unsigned long)buffer,0,
                OMX_COMPONENT_GENERATE_EBD);
        DEBUG_PRINT_ERROR("ERROR: ETBProxy: stop in progress");
        return OMX_ErrorNone;
    }

    if (!meta_mode_enable) {
        fd = m_pInput_pmem[nBufIndex].fd;
    }
#ifdef _ANDROID_ICS_
    if (meta_mode_enable && !mUsesColorConversion) {
        // Camera or Gralloc-source meta-buffers queued with encodeable color-format
        struct pmem Input_pmem_info;
        if (!media_buffer) {
            DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__);
            return OMX_ErrorBadParameter;
        }
        if (media_buffer->buffer_type == LEGACY_CAM_SOURCE) {
            Input_pmem_info.buffer = media_buffer;
            Input_pmem_info.fd = MetaBufferUtil::getFdAt(media_buffer->meta_handle, 0);
            fd = Input_pmem_info.fd;

            int offset = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_OFFSET);
            int size = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_SIZE);
            if (offset < 0 || size < 0) {
                DEBUG_PRINT_ERROR("meta-buffer is invalid!");
                return OMX_ErrorBadParameter;
            }
            Input_pmem_info.offset = offset;
            Input_pmem_info.size = size;
            DEBUG_PRINT_HIGH("ETB (meta-Camera) fd = %d, offset = %d, size = %d",
                    Input_pmem_info.fd, Input_pmem_info.offset,
                    Input_pmem_info.size);
        } else {
            VideoGrallocMetadata *media_buffer = (VideoGrallocMetadata *)meta_buffer_hdr[nBufIndex].pBuffer;
            private_handle_t *handle = (private_handle_t *)media_buffer->pHandle;
            Input_pmem_info.buffer = media_buffer;
            Input_pmem_info.fd = handle->fd;
            fd = Input_pmem_info.fd;
            Input_pmem_info.offset = 0;
            Input_pmem_info.size = handle->size;
            DEBUG_PRINT_LOW("ETB (meta-gralloc) fd = %d, offset = %d, size = %d",
                    Input_pmem_info.fd, Input_pmem_info.offset,
                    Input_pmem_info.size);
            // if input buffer dimensions is different from what is configured,
            // reject the buffer
            if (ALIGN((int)m_sInPortDef.format.video.nFrameWidth,32) != ALIGN(handle->unaligned_width,32) ||
                    ALIGN((int)m_sInPortDef.format.video.nFrameHeight,32) != ALIGN(handle->unaligned_height,32)) {
                ALOGE("Graphic buf size(%dx%d) does not match configured size(%ux%u)",
                        handle->unaligned_width, handle->unaligned_height,
                        m_sInPortDef.format.video.nFrameWidth, m_sInPortDef.format.video.nFrameHeight);
                post_event ((unsigned long)buffer, 0, OMX_COMPONENT_GENERATE_EBD);
                return OMX_ErrorNone;
            }
        }
        if (dev_use_buf(PORT_INDEX_IN) != true) {
            DEBUG_PRINT_ERROR("ERROR: in dev_use_buf");
            post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
            return OMX_ErrorBadParameter;
        }
    } else if (input_use_buffer && !m_use_input_pmem && m_pInput_pmem[nBufIndex].buffer)
#else
    if (input_use_buffer && !m_use_input_pmem && m_pInput_pmem[nBufIndex].buffer)
#endif
    {
        DEBUG_PRINT_LOW("Heap UseBuffer case, so memcpy the data");

        auto_lock l(m_buf_lock);
        pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer;
        if (pmem_data_buf && BITMASK_PRESENT(&m_client_in_bm_count, nBufIndex)) {
            memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset),
                    buffer->nFilledLen);
        }
        DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf");
    } else if (mUseProxyColorFormat) {
        // Gralloc-source buffers with color-conversion
        fd = m_pInput_pmem[nBufIndex].fd;
        DEBUG_PRINT_LOW("ETB (color-converted) fd = %d, size = %u",
                fd, (unsigned int)buffer->nFilledLen);
    } else if (m_sInPortDef.format.video.eColorFormat ==
                    OMX_COLOR_FormatYUV420SemiPlanar) {
            //For the case where YUV420SP buffers are qeueued to component
            //by sources other than camera (Apps via MediaCodec), conversion
            //to vendor flavoured NV12 color format is required.
            if (!dev_color_align(buffer, m_sInPortDef.format.video.nFrameWidth,
                                    m_sInPortDef.format.video.nFrameHeight)) {
                    DEBUG_PRINT_ERROR("Failed to adjust buffer color");
                    post_event((unsigned long)buffer, 0, OMX_COMPONENT_GENERATE_EBD);
                    return OMX_ErrorUndefined;
            }
    }
    if (dev_empty_buf(buffer, pmem_data_buf,nBufIndex,fd) != true)
    {
        DEBUG_PRINT_ERROR("ERROR: ETBProxy: dev_empty_buf failed");
#ifdef _ANDROID_ICS_
        omx_release_meta_buffer(buffer);
#endif
        post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
        /*Generate an async error and move to invalid state*/
        pending_input_buffers--;
        VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
        if (hw_overload) {
            return OMX_ErrorInsufficientResources;
        }
        return OMX_ErrorBadParameter;
    }
    return ret;
}

/* ======================================================================
   FUNCTION
   omx_video::FillThisBuffer

   DESCRIPTION
   IL client uses this method to release the frame buffer
   after displaying them.

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
   if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) {
      DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size");
      return OMX_ErrorBadParameter;
    }

    print_omx_buffer("FillThisBuffer", buffer);

    if (m_state != OMX_StateExecuting &&
            m_state != OMX_StatePause &&
            m_state != OMX_StateIdle) {
        DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State");
        return OMX_ErrorInvalidState;
    }

    if (buffer->nOutputPortIndex == PORT_INDEX_EXTRADATA_OUT) {
        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->invalid port in header");
        return OMX_ErrorBadParameter;
    }

    if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) {
        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid");
        return OMX_ErrorVersionMismatch;
    }

    if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT) {
        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index");
        return OMX_ErrorBadPortIndex;
    }

    if (!m_sOutPortDef.bEnabled) {
        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled");
        return OMX_ErrorIncorrectStateOperation;
    }

    post_event((unsigned long) hComp, (unsigned long)buffer,OMX_COMPONENT_GENERATE_FTB);
    return OMX_ErrorNone;
}

/* ======================================================================
   FUNCTION
   omx_video::fill_this_buffer_proxy

   DESCRIPTION
   IL client uses this method to release the frame buffer
   after displaying them.

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
OMX_ERRORTYPE  omx_video::fill_this_buffer_proxy(
        OMX_IN OMX_HANDLETYPE        hComp,
        OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
{
    VIDC_TRACE_NAME_HIGH("FTB");
    (void)hComp;
    OMX_U8 *pmem_data_buf = NULL;
    OMX_ERRORTYPE nRet = OMX_ErrorNone;
    auto_lock l(m_buf_lock);
    if (m_buffer_freed == true) {
        DEBUG_PRINT_ERROR("ERROR: FTBProxy: Invalid call. Called after freebuffer");
        return OMX_ErrorBadParameter;
    }

    if (bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= (int)m_sOutPortDef.nBufferCountActual) ) {
        DEBUG_PRINT_ERROR("ERROR: FTBProxy: Invalid i/p params");
        return OMX_ErrorBadParameter;
    }

    pending_output_buffers++;
    VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
    /*Return back the output buffer to client*/
    if ( m_sOutPortDef.bEnabled != OMX_TRUE || output_flush_progress == true) {
        DEBUG_PRINT_LOW("o/p port is Disabled or Flush in Progress");
        post_event ((unsigned long)bufferAdd,0,
                OMX_COMPONENT_GENERATE_FBD);
        return OMX_ErrorNone;
    }

    if (output_use_buffer && !m_use_output_pmem) {
        DEBUG_PRINT_LOW("Heap UseBuffer case");
        pmem_data_buf = (OMX_U8 *)m_pOutput_pmem[bufferAdd - m_out_mem_ptr].buffer;
    }

    if (dev_fill_buf(bufferAdd, pmem_data_buf,(bufferAdd - m_out_mem_ptr),m_pOutput_pmem[bufferAdd - m_out_mem_ptr].fd) != true) {
        DEBUG_PRINT_ERROR("ERROR: dev_fill_buf() Failed");
        post_event ((unsigned long)bufferAdd,0,OMX_COMPONENT_GENERATE_FBD);
        pending_output_buffers--;
        VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
        return OMX_ErrorBadParameter;
    }

    return OMX_ErrorNone;
}

/* ======================================================================
   FUNCTION
   omx_video::SetCallbacks

   DESCRIPTION
   Set the callbacks.

   PARAMETERS
   None.

   RETURN VALUE
   OMX Error None if everything successful.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
        OMX_IN OMX_CALLBACKTYPE* callbacks,
        OMX_IN OMX_PTR             appData)
{
    (void)hComp;

    if (!callbacks)
       return OMX_ErrorBadParameter;

    m_pCallbacks       = *callbacks;
    DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_pCallbacks.EmptyBufferDone,\
            m_pCallbacks.EventHandler,m_pCallbacks.FillBufferDone);
    m_app_data =    appData;
    return OMX_ErrorNone;
}


/* ======================================================================
   FUNCTION
   omx_venc::UseEGLImage

   DESCRIPTION
   OMX Use EGL Image method implementation <TBD>.

   PARAMETERS
   <TBD>.

   RETURN VALUE
   Not Implemented error.

   ========================================================================== */
OMX_ERRORTYPE  omx_video::use_EGL_image(OMX_IN OMX_HANDLETYPE   hComp,
        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
        OMX_IN OMX_U32                        port,
        OMX_IN OMX_PTR                     appData,
        OMX_IN void*                      eglImage)
{
    (void)hComp, (void)bufferHdr, (void)port, (void)appData, (void)eglImage;
    DEBUG_PRINT_ERROR("ERROR: use_EGL_image:  Not Implemented");
    return OMX_ErrorNotImplemented;
}

/* ======================================================================
   FUNCTION
   omx_venc::ComponentRoleEnum

   DESCRIPTION
   OMX Component Role Enum method implementation.

   PARAMETERS
   <TBD>.

   RETURN VALUE
   OMX Error None if everything is successful.
   ========================================================================== */
OMX_ERRORTYPE  omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
        OMX_OUT OMX_U8*        role,
        OMX_IN OMX_U32        index)
{
    (void)hComp;
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    if (!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
        if ((0 == index) && role) {
            strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
        } else {
            DEBUG_PRINT_ERROR("ERROR: No more roles");
            eRet = OMX_ErrorNoMore;
        }
    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE) ||
                !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc.secure",OMX_MAX_STRINGNAME_SIZE)) {
        if ((0 == index) && role) {
            strlcpy((char *)role, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE);
            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
        } else {
            DEBUG_PRINT_ERROR("ERROR: No more roles");
            eRet = OMX_ErrorNoMore;
        }
    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
        if ((0 == index) && role) {
            strlcpy((char *)role, "video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE);
            DEBUG_PRINT_LOW("component_role_enum: role %s",role);
        } else {
            DEBUG_PRINT_ERROR("ERROR: No more roles");
            eRet = OMX_ErrorNoMore;
        }
    } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE) ||
                !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc.cq", OMX_MAX_STRINGNAME_SIZE) ||
                !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc.secure", OMX_MAX_STRINGNAME_SIZE) ||
                !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.heic", OMX_MAX_STRINGNAME_SIZE)) {
        if ((0 == index) && role) {
            strlcpy((char *)role, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE);
            DEBUG_PRINT_LOW("component_role_enum: role %s", role);
        } else {
            DEBUG_PRINT_ERROR("ERROR: No more roles");
            eRet = OMX_ErrorNoMore;
        }
    } else {
        DEBUG_PRINT_ERROR("ERROR: Querying Role on Unknown Component");
        eRet = OMX_ErrorInvalidComponentName;
    }
    return eRet;
}




/* ======================================================================
   FUNCTION
   omx_venc::AllocateDone

   DESCRIPTION
   Checks if entire buffer pool is allocated by IL Client or not.
   Need this to move to IDLE state.

   PARAMETERS
   None.

   RETURN VALUE
   true/false.

   ========================================================================== */
bool omx_video::allocate_done(void)
{
    bool bRet = false;
    bool bRet_In = false;
    bool bRet_Out = false;
    bool bRet_Out_Extra = false;
    bool bRet_In_Extra = false;

    bRet_In = allocate_input_done();
    bRet_Out = allocate_output_done();
    bRet_In_Extra =  allocate_input_extradata_done();
    bRet_Out_Extra = allocate_output_extradata_done();

    if (bRet_In && bRet_Out && bRet_Out_Extra && bRet_In_Extra) {
        bRet = true;
    }

    return bRet;
}
/* ======================================================================
   FUNCTION
   omx_venc::AllocateInputDone

   DESCRIPTION
   Checks if I/P buffer pool is allocated by IL Client or not.

   PARAMETERS
   None.

   RETURN VALUE
   true/false.

   ========================================================================== */
bool omx_video::allocate_input_done(void)
{
    bool bRet = false;
    unsigned i=0;

    if (m_inp_mem_ptr == NULL) {
        return bRet;
    }
    if (m_inp_mem_ptr ) {
        for (; i<m_sInPortDef.nBufferCountActual; i++) {
            if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
                break;
            }
        }
    }
    if (i==m_sInPortDef.nBufferCountActual) {
        bRet = true;
    }
    if (i==m_sInPortDef.nBufferCountActual && m_sInPortDef.bEnabled) {
        m_sInPortDef.bPopulated = OMX_TRUE;
    }
    return bRet;
}
/* ======================================================================
   FUNCTION
   omx_venc::AllocateOutputDone

   DESCRIPTION
   Checks if entire O/P buffer pool is allocated by IL Client or not.

   PARAMETERS
   None.

   RETURN VALUE
   true/false.

   ========================================================================== */
bool omx_video::allocate_output_done(void)
{
    bool bRet = false;
    unsigned j=0;

    if (m_out_mem_ptr == NULL) {
        return bRet;
    }

    if (m_out_mem_ptr ) {
        for (; j<m_sOutPortDef.nBufferCountActual; j++) {
            if (BITMASK_ABSENT(&m_out_bm_count,j)) {
                break;
            }
        }
    }

    if (j==m_sOutPortDef.nBufferCountActual) {
        bRet = true;
    }

    if (j==m_sOutPortDef.nBufferCountActual && m_sOutPortDef.bEnabled) {
        m_sOutPortDef.bPopulated = OMX_TRUE;
    }
    return bRet;
}

bool omx_video::allocate_output_extradata_done(void) {
    bool bRet = false;
    unsigned j=0;
    unsigned nBufferCount = 0;

    nBufferCount = m_client_out_extradata_info.getBufferCount();

    if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
        return true;
    }

    if (m_client_output_extradata_mem_ptr) {
        for (; j < nBufferCount; j++) {
            if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
                break;
            }
        }

        if (j == nBufferCount) {
            bRet = true;
            DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
        }
    }

    return bRet;
}

bool omx_video::allocate_input_extradata_done(void) {
    bool bRet = false;
    unsigned j=0;
    unsigned nBufferCount = 0;

    nBufferCount = m_client_in_extradata_info.getBufferCount();

    if (!m_client_in_extradata_info.is_client_extradata_enabled()) {
        return true;
    }

    if (m_client_input_extradata_mem_ptr) {
        for (; j < nBufferCount; j++) {
            if (BITMASK_ABSENT(&m_in_extradata_bm_count,j)) {
                break;
            }
        }

        if (j == nBufferCount) {
            bRet = true;
            DEBUG_PRINT_HIGH("Allocate done for all extradata i/p buffers");
        }
    }

    return bRet;
}

/* ======================================================================
   FUNCTION
   omx_venc::ReleaseDone

   DESCRIPTION
   Checks if IL client has released all the buffers.

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
bool omx_video::release_done(void)
{
    bool bRet = false;
    DEBUG_PRINT_LOW("Inside release_done()");
    if (release_input_done()) {
        if (release_output_done()) {
            if (release_output_extradata_done()) {
                bRet = true;
            }
        }
    }
    return bRet;
}


/* ======================================================================
   FUNCTION
   omx_venc::ReleaseOutputDone

   DESCRIPTION
   Checks if IL client has released all the buffers.

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
bool omx_video::release_output_done(void)
{
    bool bRet = false;
    unsigned i=0,j=0;

    DEBUG_PRINT_LOW("Inside release_output_done()");
    if (m_out_mem_ptr) {
        for (; j<m_sOutPortDef.nBufferCountActual; j++) {
            if (BITMASK_PRESENT(&m_out_bm_count,j)) {
                break;
            }
        }
        if (j==m_sOutPortDef.nBufferCountActual) {
            bRet = true;
        }
    } else {
        bRet = true;
    }
    return bRet;
}
/* ======================================================================
   FUNCTION
   omx_venc::ReleaseInputDone

   DESCRIPTION
   Checks if IL client has released all the buffers.

   PARAMETERS
   None.

   RETURN VALUE
   true/false

   ========================================================================== */
bool omx_video::release_input_done(void)
{
    bool bRet = false;
    unsigned i=0,j=0;

    DEBUG_PRINT_LOW("Inside release_input_done()");
    if (m_inp_mem_ptr) {
        for (; j<m_sInPortDef.nBufferCountActual; j++) {
            if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
                break;
            }
        }
        if (j==m_sInPortDef.nBufferCountActual) {
            bRet = true;
        }
    } else {
        bRet = true;
    }
    return bRet;
}

bool omx_video::release_output_extradata_done(void) {
    bool bRet = false;
    unsigned i=0,j=0, buffer_count=0;

    buffer_count = m_client_out_extradata_info.getBufferCount();
    DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
            m_client_output_extradata_mem_ptr, buffer_count);

    if (m_client_output_extradata_mem_ptr) {
        for (; j<buffer_count; j++) {
            if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
                break;
            }
        }
        if (j == buffer_count) {
            bRet = true;
        }
    } else {
        bRet = true;
    }
    return bRet;
}

bool omx_video::release_input_extradata_done(void) {
    bool bRet = false;
    unsigned i=0,j=0, buffer_count=0;

    buffer_count = m_client_in_extradata_info.getBufferCount();
    DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
            m_client_input_extradata_mem_ptr, buffer_count);

    if (m_client_input_extradata_mem_ptr) {
        for (; j<buffer_count; j++) {
            if ( BITMASK_PRESENT(&m_in_extradata_bm_count,j)) {
                break;
            }
        }
        if (j == buffer_count) {
            bRet = true;
        }
    } else {
        bRet = true;
    }
    return bRet;
}

OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp,
        OMX_BUFFERHEADERTYPE * buffer)
{
    VIDC_TRACE_NAME_HIGH("FBD");
    int index = buffer - m_out_mem_ptr;

    if (buffer == NULL || ((buffer - m_out_mem_ptr) > (int)m_sOutPortDef.nBufferCountActual)) {
        return OMX_ErrorBadParameter;
    }

    pending_output_buffers--;
    VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
    VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
    VIDC_TRACE_INT_LOW("FBD-size", buffer->nFilledLen);

    print_omx_buffer("FillBufferDone", buffer);
    if (secure_session && m_pCallbacks.FillBufferDone) {
        if (buffer->nFilledLen > 0)
            m_fbd_count++;
        m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer);
        return OMX_ErrorNone;
    }

    /* For use buffer we need to copy the data */
    if (m_pCallbacks.FillBufferDone) {
        if (buffer->nFilledLen > 0) {
            m_fbd_count++;

            if (dev_get_output_log_flag()) {
                sync_start_read(m_pOutput_ion[index].data_fd);
                dev_output_log_buffers((const char*)buffer->pBuffer + buffer->nOffset, buffer->nFilledLen,
                                        buffer->nTimeStamp);
                sync_end_read(m_pOutput_ion[index].data_fd);

            }
        }
        if (buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) {
            if (!dev_handle_output_extradata((void *)buffer, index))
                DEBUG_PRINT_ERROR("Failed to parse output extradata");
        }
        m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer);
    } else {
        return OMX_ErrorBadParameter;
    }
    return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE         hComp,
        OMX_BUFFERHEADERTYPE* buffer)
{
    VIDC_TRACE_NAME_HIGH("EBD");
    int buffer_index  = -1;

    buffer_index = buffer - ((mUseProxyColorFormat && !mUsesColorConversion) ? meta_buffer_hdr : m_inp_mem_ptr);
    if (buffer == NULL ||
            ((buffer_index > (int)m_sInPortDef.nBufferCountActual))) {
        DEBUG_PRINT_ERROR("ERROR in empty_buffer_done due to index buffer");
        return OMX_ErrorBadParameter;
    }

    print_omx_buffer("EmptyBufferDone", buffer);
    pending_input_buffers--;
    VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);

    if (mUseProxyColorFormat &&
        (buffer_index >= 0 && (buffer_index < (int)m_sInPortDef.nBufferCountActual))) {
        if (!pdest_frame  && !input_flush_progress && mUsesColorConversion) {
            pdest_frame = buffer;
            DEBUG_PRINT_LOW("empty_buffer_done pdest_frame address is %p",pdest_frame);
            return push_input_buffer(hComp);
        }
        if (mUsesColorConversion) {
            // return color-conversion buffer back to the pool
            DEBUG_PRINT_LOW("empty_buffer_done insert address is %p",buffer);
            if (!m_opq_pmem_q.insert_entry((unsigned long)buffer, 0, 0)) {
                DEBUG_PRINT_ERROR("empty_buffer_done: pmem queue is full");
                return OMX_ErrorBadParameter;
            }
        } else {
            // We are not dealing with color-conversion, Buffer being returned
            // here is client's buffer, return it back to client
            if (m_pCallbacks.EmptyBufferDone && buffer) {
                m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
                DEBUG_PRINT_LOW("empty_buffer_done: Returning client buf %p", buffer);
            }
        }
    } else if (m_pCallbacks.EmptyBufferDone) {
        m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, buffer);
    }
    return OMX_ErrorNone;
}

void omx_video::complete_pending_buffer_done_cbs()
{
    unsigned long p1;
    unsigned long p2;
    unsigned long ident;
    omx_cmd_queue tmp_q, pending_bd_q;
    pthread_mutex_lock(&m_lock);
    // pop all pending GENERATE FDB from ftb queue
    while (m_ftb_q.m_size) {
        m_ftb_q.pop_entry(&p1,&p2,&ident);
        if (ident == OMX_COMPONENT_GENERATE_FBD) {
            pending_bd_q.insert_entry(p1,p2,ident);
        } else {
            tmp_q.insert_entry(p1,p2,ident);
        }
    }
    //return all non GENERATE FDB to ftb queue
    while (tmp_q.m_size) {
        tmp_q.pop_entry(&p1,&p2,&ident);
        m_ftb_q.insert_entry(p1,p2,ident);
    }
    // pop all pending GENERATE EDB from etb queue
    while (m_etb_q.m_size) {
        m_etb_q.pop_entry(&p1,&p2,&ident);
        if (ident == OMX_COMPONENT_GENERATE_EBD) {
            pending_bd_q.insert_entry(p1,p2,ident);
        } else {
            tmp_q.insert_entry(p1,p2,ident);
        }
    }
    //return all non GENERATE FDB to etb queue
    while (tmp_q.m_size) {
        tmp_q.pop_entry(&p1,&p2,&ident);
        m_etb_q.insert_entry(p1,p2,ident);
    }
    pthread_mutex_unlock(&m_lock);
    // process all pending buffer dones
    while (pending_bd_q.m_size) {
        pending_bd_q.pop_entry(&p1,&p2,&ident);
        switch (ident) {
            case OMX_COMPONENT_GENERATE_EBD:
                if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
                    DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
                    omx_report_error ();
                }
                break;

            case OMX_COMPONENT_GENERATE_FBD:
                if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
                    DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
                    omx_report_error ();
                }
                break;
        }
    }
}

char *omx_video::ion_map(int fd, int len)
{
    char *bufaddr = (char*)mmap(NULL, len, PROT_READ|PROT_WRITE,
                                MAP_SHARED, fd, 0);
    if (bufaddr != MAP_FAILED)
        cache_clean_invalidate(fd);
    return bufaddr;
}

OMX_ERRORTYPE omx_video::ion_unmap(int fd, void *bufaddr, int len)
{
    cache_clean_invalidate(fd);
    if (-1 == munmap(bufaddr, len)) {
        DEBUG_PRINT_ERROR("munmap failed.");
        return OMX_ErrorInsufficientResources;
    }
    return OMX_ErrorNone;
}

#ifdef USE_ION
bool omx_video::alloc_map_ion_memory(int size, venc_ion *ion_info, int flag)
{
    struct venc_ion buf_ion_info;
    int rc=0;

    if (size <=0 || !ion_info) {
        DEBUG_PRINT_ERROR("Invalid input to alloc_map_ion_memory");
        return false;
    }

    if (is_stop_in_progress) {
        DEBUG_PRINT_ERROR("Stop in progress: do not allocate any memory");
        return false;
    }

    ion_info->data_fd = -1;
    ion_info->dev_fd = ion_open();
    if (ion_info->dev_fd <= 0) {
        DEBUG_PRINT_ERROR("ERROR: ION Device open() Failed");
        return false;
    }

    if(secure_session) {
        ion_info->alloc_data.len = (size + (SECURE_ALIGN - 1)) & ~(SECURE_ALIGN - 1);
        ion_info->alloc_data.flags = flag;
        ion_info->alloc_data.heap_id_mask = ION_HEAP(MEM_HEAP_ID);
        if (ion_info->alloc_data.flags & ION_FLAG_CP_BITSTREAM) {
            ion_info->alloc_data.heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
        }
        DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %u flags %x",
                (unsigned int)ion_info->alloc_data.len,
                ion_info->alloc_data.flags);
    } else {
        ion_info->alloc_data.len = (size + (SZ_4K - 1)) & ~(SZ_4K - 1);
        ion_info->alloc_data.flags = (flag & ION_FLAG_CACHED);

        /* If color format is Vanilla NV12, we will need to use caching for optimal
           color alignment performance.
         */

        if (m_sInPortDef.format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)
        {
            DEBUG_PRINT_HIGH("Enabling cacheing for this buffer");
            ion_info->alloc_data.flags = ION_FLAG_CACHED;
        }
        ion_info->alloc_data.heap_id_mask = (ION_HEAP(MEM_HEAP_ID) |
                                    ION_HEAP(ION_SYSTEM_HEAP_ID));
        DEBUG_PRINT_HIGH("ION ALLOC unsec buf: size %u flags %x",
                (unsigned int)ion_info->alloc_data.len,
                ion_info->alloc_data.flags);
    }

    rc = ion_alloc_fd(ion_info->dev_fd, ion_info->alloc_data.len, 0,
                      ion_info->alloc_data.heap_id_mask,
                      ion_info->alloc_data.flags, &ion_info->data_fd);
    if (rc || ion_info->data_fd < 0) {
        DEBUG_PRINT_ERROR("ION ALLOC memory failed 0x%x", rc);
        ion_close(ion_info->dev_fd);
        ion_info->data_fd = -1;
        ion_info->dev_fd = -1;
        return false;
    }

    DEBUG_PRINT_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
        ion_info->dev_fd, ion_info->data_fd, (unsigned int)ion_info->alloc_data.len,
        (unsigned int)ion_info->alloc_data.flags,
        (unsigned int)ion_info->alloc_data.heap_id_mask);

    return true;
}

void omx_video::free_ion_memory(struct venc_ion *buf_ion_info)
{
    if (!buf_ion_info) {
        DEBUG_PRINT_ERROR("Invalid input to free_ion_memory");
        return;
    }
    DEBUG_PRINT_HIGH("Free ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
        buf_ion_info->dev_fd, buf_ion_info->data_fd,
        (unsigned int)buf_ion_info->alloc_data.len,
        (unsigned int)buf_ion_info->alloc_data.flags,
        (unsigned int)buf_ion_info->alloc_data.heap_id_mask);
    if (buf_ion_info->data_fd >= 0) {
        close(buf_ion_info->data_fd);
        buf_ion_info->data_fd = -1;
    }
    if (buf_ion_info->dev_fd >= 0) {
        ion_close(buf_ion_info->dev_fd);
        buf_ion_info->dev_fd = -1;
    }
}
#endif

#ifdef _ANDROID_ICS_
void omx_video::omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer)
{
    if (buffer && meta_mode_enable) {
        LEGACY_CAM_METADATA_TYPE *media_ptr;
        struct pmem Input_pmem;
        unsigned int index_pmem = 0;

        index_pmem = (buffer - m_inp_mem_ptr);
        if (mUsesColorConversion &&
                (index_pmem < m_sInPortDef.nBufferCountActual)) {
            if (!dev_free_buf((&m_pInput_pmem[index_pmem]),PORT_INDEX_IN)) {
                DEBUG_PRINT_ERROR("omx_release_meta_buffer dev free failed");
            }
        } else {
            media_ptr = (LEGACY_CAM_METADATA_TYPE *) buffer->pBuffer;
            if (media_ptr && media_ptr->meta_handle) {
                if (media_ptr->buffer_type == LEGACY_CAM_SOURCE) {
                    Input_pmem.buffer = media_ptr;
                    Input_pmem.fd = MetaBufferUtil::getFdAt(media_ptr->meta_handle, 0);
                    int size = MetaBufferUtil::getIntAt(media_ptr->meta_handle, 0, MetaBufferUtil::INT_SIZE);
                    int offset = MetaBufferUtil::getIntAt(media_ptr->meta_handle, 0, MetaBufferUtil::INT_OFFSET);
                    if (Input_pmem.fd < 0 || size < 0 || offset < 0)
                        DEBUG_PRINT_ERROR("Invalid meta buffer");

                    Input_pmem.size = size;
                    Input_pmem.offset = offset;
                    DEBUG_PRINT_LOW("EBD fd = %d, offset = %d, size = %d",Input_pmem.fd,
                            Input_pmem.offset,
                            Input_pmem.size);
                } else if (media_ptr->buffer_type == kMetadataBufferTypeGrallocSource) {
                    VideoGrallocMetadata *media_ptr = (VideoGrallocMetadata *)buffer->pBuffer;
                    private_handle_t *handle = (private_handle_t *)media_ptr->pHandle;
                    Input_pmem.buffer = media_ptr;
                    Input_pmem.fd = handle->fd;
                    Input_pmem.offset = 0;
                    Input_pmem.size = handle->size;
                }
            }
        }
    }
}
#endif

bool is_ubwc_interlaced(private_handle_t *handle) {
    int interlace_flag = 0;

    if (getMetaData(const_cast<private_handle_t *>(handle),
                  GET_PP_PARAM_INTERLACED, &interlace_flag)) {
        interlace_flag = 0;
    }
    return (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC) &&
                !!interlace_flag;
}

bool omx_video::is_rotation_enabled()
{
    bool bRet = false;

    if (m_sConfigFrameRotation.nRotation == 90 ||
        m_sConfigFrameRotation.nRotation == 180 ||
        m_sConfigFrameRotation.nRotation == 270) {
        bRet = true;
    }

    return bRet;
}

void omx_video::initFastCV() {
    fcvSetOperationMode(FASTCV_OP_CPU_PERFORMANCE);
    fcvMemInit();
    m_fastCV_init_done = true;
}

bool omx_video::is_flip_conv_needed(private_handle_t *handle) {
    OMX_MIRRORTYPE mirror;
    mirror = m_sConfigFrameMirror.eMirror;
    OMX_U32 captureRate = m_nOperatingRate >> 16;
    bool is_flip_needed = false;

    if (m_no_vpss && m_fastCV_init_done && captureRate <= 30 &&
        (mirror == OMX_MirrorVertical || mirror == OMX_MirrorHorizontal ||
         mirror == OMX_MirrorBoth)) {
        is_flip_needed = true;
    }

    if (handle && !(handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE ||
            handle->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS)) {
        is_flip_needed = false;
    }

    return is_flip_needed;
}

OMX_ERRORTYPE omx_video::do_flip_conversion(struct pmem *buffer) {
    OMX_U32 width = m_sInPortDef.format.video.nFrameWidth;
    OMX_U32 height = m_sInPortDef.format.video.nFrameHeight;
    OMX_U32 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
    OMX_U32 scanLines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
    fcvFlipDir direction;
    OMX_ERRORTYPE ret = OMX_ErrorNone;

    switch(m_sConfigFrameMirror.eMirror) {
        case OMX_MirrorVertical:
            direction = FASTCV_FLIP_VERT;
            break;
        case OMX_MirrorHorizontal:
            direction = FASTCV_FLIP_HORIZ;
            break;
        case OMX_MirrorBoth:
            direction = FASTCV_FLIP_BOTH;
            break;
        default:
            return OMX_ErrorBadParameter;
    }

    unsigned char *uva = (unsigned char *)ion_map(buffer->fd, buffer->size);
    if (uva == MAP_FAILED) {
        ret = OMX_ErrorBadParameter;
        return ret;
    }
    unsigned char *src = uva;
    DEBUG_PRINT_LOW("start flip conversion");
    fcvFlipu8( src, width, height, stride, src, stride, direction);
    src = src + (stride * scanLines);
    fcvFlipu16((OMX_U16 *)src,width/2,height/2,stride,(OMX_U16 *)src,stride,direction);

    ion_unmap(buffer->fd, uva, buffer->size);
    return ret;
}

bool omx_video::is_conv_needed(private_handle_t *handle)
{
    bool bRet = false;
    bool interlaced = is_ubwc_interlaced(handle);

    if (!strncmp(m_platform, "msm8996", 7)) {
        bRet = handle->format == HAL_PIXEL_FORMAT_RGBA_8888 &&
            !(handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
              handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI);
    } else {
        bRet = handle->format == HAL_PIXEL_FORMAT_RGBA_8888;
    }

#ifdef _HW_RGBA
    bRet = false;
#endif
    bRet |= interlaced;
    if (m_no_vpss && is_rotation_enabled()) {
        bRet = true;
    }
    DEBUG_PRINT_LOW("RGBA conversion %s. Format %d Flag %d interlace_flag = %d",
                                bRet ? "Needed":"Not-Needed", handle->format,
                                handle->flags, interlaced);
    return bRet;
}

void omx_video::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) {
    DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d",
            prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
}

OMX_ERRORTYPE  omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp,
        OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
    VIDC_TRACE_NAME_LOW("ETB-Opaque");
    unsigned nBufIndex = 0;
    OMX_ERRORTYPE ret = OMX_ErrorNone;
    VideoGrallocMetadata *media_buffer; // This method primarily assumes gralloc-metadata
    private_handle_t *handle = NULL;
    DEBUG_PRINT_LOW("ETBProxyOpaque: buffer[%p]", buffer);

    if (buffer == NULL) {
        DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid buffer[%p]",buffer);
        return OMX_ErrorBadParameter;
    }

    if (profile_etb()) {
        m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
        return OMX_ErrorNone;
    }

    if (!dev_buffer_ready_to_queue(buffer)) {
        DEBUG_PRINT_HIGH("Info: ETBProxyA: buffer[%p] is deffered", buffer);
        return OMX_ErrorNone;
    }

    nBufIndex = buffer - meta_buffer_hdr;
    if (nBufIndex >= m_sInPortDef.nBufferCountActual) {
        DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid bufindex = %u",
                nBufIndex);
        return OMX_ErrorBadParameter;
    }

    media_buffer = (VideoGrallocMetadata *)buffer->pBuffer;
    if (!media_buffer) {
        DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__);
        return OMX_ErrorBadParameter;
    }
    if ((media_buffer->eType == LEGACY_CAM_SOURCE)
            && buffer->nAllocLen != sizeof(LEGACY_CAM_METADATA_TYPE)) {
        DEBUG_PRINT_ERROR("Invalid metadata size expected(%u) v/s recieved(%zu)",
                buffer->nAllocLen, sizeof(LEGACY_CAM_METADATA_TYPE));
        return OMX_ErrorBadParameter;
    }

    if (media_buffer && media_buffer->eType == LEGACY_CAM_SOURCE) {
        return empty_this_buffer_proxy(hComp, buffer);
    }

    if ((!media_buffer || !media_buffer->pHandle || media_buffer->eType != kMetadataBufferTypeGrallocSource) &&
            !(buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
        DEBUG_PRINT_ERROR("Incorrect Buffer queued media buffer = %p",
            media_buffer);
        m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
        return OMX_ErrorBadParameter;
    } else if (media_buffer) {
        handle = (private_handle_t *)media_buffer->pHandle;
    }

    /*Enable following code once private handle color format is
      updated correctly*/

    if (buffer->nFilledLen > 0 && handle && !is_streamon_done((OMX_U32) PORT_INDEX_OUT)) {

        ColorConvertFormat c2dSrcFmt = RGBA8888;
        ColorConvertFormat c2dDestFmt = m_ubwc_supported ? NV12_UBWC : NV12_128m;

        ColorMapping::const_iterator found =
             mMapPixelFormat2Converter.find(handle->format);

        if (found != mMapPixelFormat2Converter.end() && is_conv_needed(handle)) {
            c2dSrcFmt = (ColorConvertFormat)found->second;
            c2dcc.setConversionNeeded(true);
        } else {
            DEBUG_PRINT_HIGH("Couldn't find color mapping for (%x).", handle->format);
            c2dcc.setConversionNeeded(false);
        }

        mUsesColorConversion = is_conv_needed(handle);
        bool interlaced = is_ubwc_interlaced(handle);
        int  full_range_flag = m_sConfigColorAspects.sAspects.mRange == ColorAspects::RangeFull ?
                               private_handle_t::PRIV_FLAGS_ITU_R_601_FR : 0;

        if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingImageHEIC)
            c2dDestFmt = NV12_512;

        if (c2dcc.getConversionNeeded() &&
            c2dcc.isPropChanged(m_sInPortDef.format.video.nFrameWidth,
                                interlaced ? ((m_sInPortDef.format.video.nFrameHeight + 1) / 2) :
                                m_sInPortDef.format.video.nFrameHeight,
                                m_sInPortDef.format.video.nFrameWidth,
                                m_sInPortDef.format.video.nFrameHeight,
                                c2dSrcFmt, c2dDestFmt,
                                handle->flags, handle->width)) {
            DEBUG_PRINT_HIGH("C2D setRotation - %u", m_sConfigFrameRotation.nRotation);
            if (m_no_vpss && is_rotation_enabled()) {
                c2dcc.setRotation(m_sConfigFrameRotation.nRotation);
            }
            DEBUG_PRINT_HIGH("C2D setResolution (0x%X -> 0x%x) HxW (%dx%d) Stride (%d)",
                             c2dSrcFmt, c2dDestFmt,
                             m_sInPortDef.format.video.nFrameHeight,
                             m_sInPortDef.format.video.nFrameWidth,
                             handle->width);
            if (!c2dcc.setResolution(m_sInPortDef.format.video.nFrameWidth,
                                     interlaced ? ((m_sInPortDef.format.video.nFrameHeight + 1) / 2) :
                                     m_sInPortDef.format.video.nFrameHeight,
                                     m_sInPortDef.format.video.nFrameWidth,
                                     m_sInPortDef.format.video.nFrameHeight,
                                     c2dSrcFmt, c2dDestFmt,
                                     handle->flags | full_range_flag, handle->width)) {
                m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
                DEBUG_PRINT_ERROR("SetResolution failed");
                return OMX_ErrorBadParameter;
            }

            mC2dSrcFmt = c2dSrcFmt;
            mC2DFrameHeight = m_sInPortDef.format.video.nFrameHeight;
            mC2DFrameWidth = m_sInPortDef.format.video.nFrameWidth;

            if (mC2dDestFmt != c2dDestFmt && !dev_set_format(c2dDestFmt)) {
                DEBUG_PRINT_ERROR("cannot set color format");
                return OMX_ErrorBadParameter;
            }
            mC2dDestFmt = c2dDestFmt;
        }

        dev_get_buf_req (&m_sInPortDef.nBufferCountMin,
                         &m_sInPortDef.nBufferCountActual,
                         &m_sInPortDef.nBufferSize,
                         m_sInPortDef.nPortIndex);
    }

    if (input_flush_progress == true) {
        m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
        DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Input flush in progress");
        return OMX_ErrorNone;
    }

    if (dev_is_meta_mode()) {
        LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;

        meta_buf = (LEGACY_CAM_METADATA_TYPE *)buffer->pBuffer;

        if (meta_buf && m_no_vpss && is_rotation_enabled() &&
            meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
            VideoGrallocMetadata *meta_buf = (VideoGrallocMetadata *)buffer->pBuffer;
#ifdef USE_GBM
            struct gbm_bo *handle = (struct gbm_bo *)meta_buf->pHandle;
#else
            private_handle_t *handle = (private_handle_t *)meta_buf->pHandle;
#endif
            if (!handle) {
                DEBUG_PRINT_ERROR("%s : handle is null!", __FUNCTION__);
                return OMX_ErrorUndefined;
            }

            // if input buffer dimensions is different from what is configured,
            // reject the buffer
#ifdef USE_GBM
            if (ALIGN((int)m_sInPortDef.format.video.nFrameWidth,32) != ALIGN(handle->width,32) ||
                    ALIGN((int)m_sInPortDef.format.video.nFrameHeight,32) != ALIGN(handle->height,32)) {
                ALOGE("%s: Graphic buf size(%dx%d) does not match configured size(%ux%u)",
                        __func__, handle->width, handle->height,
#else
            if (ALIGN((int)m_sInPortDef.format.video.nFrameWidth,32) != ALIGN(handle->unaligned_width,32) ||
                    ALIGN((int)m_sInPortDef.format.video.nFrameHeight,32) != ALIGN(handle->unaligned_height,32)) {
                ALOGE("%s: Graphic buf size(%dx%d) does not match configured size(%ux%u)",
                        __func__, handle->unaligned_width, handle->unaligned_height,
#endif
                        m_sInPortDef.format.video.nFrameWidth, m_sInPortDef.format.video.nFrameHeight);
                m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
                return OMX_ErrorNone;
            }
        }
    }

    if (!psource_frame) {
        psource_frame = buffer;
        ret = push_input_buffer(hComp);
    } else {
        if (!m_opq_meta_q.insert_entry((unsigned long)buffer,0,0)) {
            DEBUG_PRINT_ERROR("ERROR: ETBProxy: Queue is full");
            m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
            ret = OMX_ErrorBadParameter;
        }
    }
    return ret;
}

OMX_ERRORTYPE omx_video::queue_meta_buffer(OMX_HANDLETYPE hComp)
{

    OMX_ERRORTYPE ret = OMX_ErrorNone;
    unsigned long address = 0,p2,id;

    DEBUG_PRINT_LOW("In queue Meta Buffer");
    if (!psource_frame || !pdest_frame) {
        DEBUG_PRINT_ERROR("convert_queue_buffer invalid params");
        return OMX_ErrorBadParameter;
    }

    if (psource_frame->nFilledLen > 0) {
        if (dev_use_buf(PORT_INDEX_IN) != true) {
            DEBUG_PRINT_ERROR("ERROR: in dev_use_buf");
            post_event ((unsigned long)psource_frame,0,OMX_COMPONENT_GENERATE_EBD);
            ret = OMX_ErrorBadParameter;
        }
    }

    if (ret == OMX_ErrorNone)
        ret = empty_this_buffer_proxy(hComp,psource_frame);

    if (ret == OMX_ErrorNone) {
        psource_frame = NULL;
        if (!psource_frame && m_opq_meta_q.m_size) {
            m_opq_meta_q.pop_entry(&address,&p2,&id);
            psource_frame = (OMX_BUFFERHEADERTYPE* ) address;
        }
    } else {
        // there has been an error and source frame has been scheduled for an EBD
        psource_frame = NULL;
    }
    return ret;
}

OMX_ERRORTYPE omx_video::convert_queue_buffer(OMX_HANDLETYPE hComp,
        struct pmem &Input_pmem_info,unsigned long &index)
{

    unsigned char *uva;
    OMX_ERRORTYPE ret = OMX_ErrorNone;
    unsigned long address = 0,p2,id;
    LEGACY_CAM_METADATA_TYPE * meta_buf = NULL;

    DEBUG_PRINT_LOW("In Convert and queue Meta Buffer");
    if (!psource_frame || !pdest_frame) {
        DEBUG_PRINT_ERROR("convert_queue_buffer invalid params");
        return OMX_ErrorBadParameter;
    }
    if (secure_session) {
        DEBUG_PRINT_ERROR("cannot convert buffer during secure session");
        return OMX_ErrorInvalidState;
    }

    if (!psource_frame->nFilledLen) {
        if(psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
            pdest_frame->nFilledLen = psource_frame->nFilledLen;
            pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
            pdest_frame->nFlags = psource_frame->nFlags;
            DEBUG_PRINT_HIGH("Skipping color conversion for empty EOS Buffer "
                    "header=%p filled-len=%u", pdest_frame, (unsigned int)pdest_frame->nFilledLen);
        } else {
            pdest_frame->nOffset = 0;
            pdest_frame->nFilledLen = 0;
            pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
            pdest_frame->nFlags = psource_frame->nFlags;
            DEBUG_PRINT_LOW("Buffer header %p Filled len size %u",
                    pdest_frame, (unsigned int)pdest_frame->nFilledLen);
        }
    } else if (c2dcc.getConversionNeeded()) {
        uva = (unsigned char *)ion_map(Input_pmem_info.fd,Input_pmem_info.size);
        if (uva == MAP_FAILED) {
            ret = OMX_ErrorBadParameter;
        } else {
            DEBUG_PRINT_HIGH("Start Color Conversion...");
            if (!c2dcc.convertC2D(Input_pmem_info.fd, uva,
                                  uva, m_pInput_pmem[index].fd,
                                  pdest_frame->pBuffer,
                                  pdest_frame->pBuffer)) {
                DEBUG_PRINT_ERROR("Color Conversion failed");
                ret = OMX_ErrorBadParameter;
            } else {
                if (dev_is_avtimer_needed() && dev_is_meta_mode()) {
                    meta_buf = (LEGACY_CAM_METADATA_TYPE *)psource_frame->pBuffer;

                    if (meta_buf && m_no_vpss && is_rotation_enabled() &&
                        meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
                        VideoGrallocMetadata *meta_buf = (VideoGrallocMetadata *)psource_frame->pBuffer;
                        private_handle_t *handle = (private_handle_t *)meta_buf->pHandle;

                        if (!handle) {
                            DEBUG_PRINT_ERROR("%s : handle is null!", __FUNCTION__);
                            ret = OMX_ErrorUndefined;
                            return ret;
                        }

                        uint64_t avTimerTimestampNs = psource_frame->nTimeStamp * 1000;
                        if (getMetaData(handle, GET_VT_TIMESTAMP, &avTimerTimestampNs) == 0
                                && avTimerTimestampNs > 0) {
                            psource_frame->nTimeStamp = avTimerTimestampNs / 1000;
                            DEBUG_PRINT_LOW("C2d AVTimer TS : %llu us", (unsigned long long)psource_frame->nTimeStamp);
                        }
                    }
                }
                unsigned int buf_size = 0;
                buf_size = c2dcc.getBuffSize(C2D_OUTPUT);
                pdest_frame->nOffset = 0;
                pdest_frame->nFilledLen = buf_size;
                pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
                pdest_frame->nFlags = psource_frame->nFlags;
                DEBUG_PRINT_LOW("Buffer header %p Filled len size %u",
                                pdest_frame,
                                (unsigned int)pdest_frame->nFilledLen);
            }
            ion_unmap(Input_pmem_info.fd, uva,Input_pmem_info.size);
        }
    }
    if (dev_use_buf(PORT_INDEX_IN) != true) {
        DEBUG_PRINT_ERROR("ERROR: in dev_use_buf");
        post_event ((unsigned long)pdest_frame,0,OMX_COMPONENT_GENERATE_EBD);
        ret = OMX_ErrorBadParameter;
    }
    if (ret == OMX_ErrorNone)
        ret = empty_this_buffer_proxy(hComp,pdest_frame);
    if (ret == OMX_ErrorNone) {
        m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, psource_frame);
        psource_frame = NULL;
        pdest_frame = NULL;
        if (!psource_frame && m_opq_meta_q.m_size) {
            m_opq_meta_q.pop_entry(&address,&p2,&id);
            psource_frame = (OMX_BUFFERHEADERTYPE* ) address;
        }
        if (!pdest_frame && m_opq_pmem_q.m_size) {
            m_opq_pmem_q.pop_entry(&address,&p2,&id);
            pdest_frame = (OMX_BUFFERHEADERTYPE* ) address;
            DEBUG_PRINT_LOW("pdest_frame pop address is %p",pdest_frame);
        }
    } else {
        // there has been an error and source frame has been scheduled for an EBD
        psource_frame = NULL;
    }
    return ret;
}

OMX_ERRORTYPE omx_video::push_input_buffer(OMX_HANDLETYPE hComp)
{
    unsigned long address = 0,p2,id, index = 0;
    OMX_ERRORTYPE ret = OMX_ErrorNone;

    DEBUG_PRINT_LOW("In push input buffer");
    if (!psource_frame && m_opq_meta_q.m_size) {
        m_opq_meta_q.pop_entry(&address,&p2,&id);
        psource_frame = (OMX_BUFFERHEADERTYPE* ) address;
    }
    if (!pdest_frame && m_opq_pmem_q.m_size) {
        m_opq_pmem_q.pop_entry(&address,&p2,&id);
        pdest_frame = (OMX_BUFFERHEADERTYPE* ) address;
    }
    while (psource_frame != NULL && pdest_frame != NULL &&
            ret == OMX_ErrorNone) {
        struct pmem Input_pmem_info;
        LEGACY_CAM_METADATA_TYPE *media_buffer;
        index = pdest_frame - m_inp_mem_ptr;
        if (index >= m_sInPortDef.nBufferCountActual) {
            DEBUG_PRINT_ERROR("Output buffer index is wrong %u act count %u",
                    (unsigned int)index, (unsigned int)m_sInPortDef.nBufferCountActual);
            return OMX_ErrorBadParameter;
        }

        if (psource_frame->nFilledLen == 0 && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
            return handle_empty_eos_buffer();
        }
        media_buffer = (LEGACY_CAM_METADATA_TYPE *)psource_frame->pBuffer;
        /*Will enable to verify camcorder in current TIPS can be removed*/
        if (media_buffer->buffer_type == LEGACY_CAM_SOURCE) {
            Input_pmem_info.buffer = media_buffer;
            Input_pmem_info.fd = MetaBufferUtil::getFdAt(media_buffer->meta_handle, 0);
            Input_pmem_info.offset = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_OFFSET);
            Input_pmem_info.size = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_SIZE);
            m_graphicbuffer_size = Input_pmem_info.size;
            DEBUG_PRINT_LOW("ETB fd = %d, offset = %d, size = %d",Input_pmem_info.fd,
                    Input_pmem_info.offset,
                    Input_pmem_info.size);
            ret = queue_meta_buffer(hComp);
        } else {
            VideoGrallocMetadata *media_buffer = (VideoGrallocMetadata *)psource_frame->pBuffer;
            private_handle_t *handle = (private_handle_t *)media_buffer->pHandle;

            Input_pmem_info.buffer = media_buffer;
            Input_pmem_info.fd = handle->fd;
            Input_pmem_info.offset = 0;
            Input_pmem_info.size = handle->size;

            if (is_flip_conv_needed(handle)) {
                ret = do_flip_conversion(&Input_pmem_info);
                if (ret != OMX_ErrorNone) {
                    return ret;
                }
            }

            m_graphicbuffer_size = Input_pmem_info.size;
            if (is_conv_needed(handle))
                ret = convert_queue_buffer(hComp,Input_pmem_info,index);
            else
                ret = queue_meta_buffer(hComp);
        }
    }
    return ret;
}

OMX_ERRORTYPE omx_video::handle_empty_eos_buffer(void)
{
    if(!dev_handle_empty_eos_buffer())
        return OMX_ErrorHardware;
    else
        return OMX_ErrorNone;
}

// no code beyond this !

// inline import of vendor extensions implementation
#include "omx_video_extensions.hpp"
