/*--------------------------------------------------------------------------
Copyright (c) 2010-2012, Code Aurora Forum. 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 Code Aurora 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
//////////////////////////////////////////////////////////////////////////////

#include <string.h>
#include "omx_video_base.h"
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/prctl.h>
#ifdef _ANDROID_ICS_
#include <media/hardware/HardwareAPI.h>
#include <gralloc_priv.h>
#endif
#ifndef _ANDROID_
#include <glib.h>
#define strlcpy g_strlcpy
#endif
#define H264_SUPPORTED_WIDTH (480)
#define H264_SUPPORTED_HEIGHT (368)

#define MPEG4_SUPPORTED_WIDTH (480)
#define MPEG4_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 IS_NOT_ALIGNED( num, to) (num & (to-1))
#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
#define SZ_2K (2048)

typedef struct OMXComponentCapabilityFlagsType
{
    ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS
    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
#ifdef OUTPUT_BUFFER_LOG
extern FILE *outputBufferFile1;
#endif

void* message_thread(void *input)
{
  omx_video* omx = reinterpret_cast<omx_video*>(input);
  unsigned char id;
  int n;

  DEBUG_PRINT_LOW("omx_venc: message thread start\n");
  prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0);
  while(1)
  {
    n = read(omx->m_pipe_in, &id, 1);
    if(0 == n)
    {
      break;
    }

    if(1 == n)
    {
      omx->process_event_cb(omx, id);
    }
#ifdef QLE_BUILD
    if(n < 0) break;
#else
    if((n < 0) && (errno != EINTR)) break;
#endif
  }
  DEBUG_PRINT_LOW("omx_venc: message thread stop\n");
  return 0;
}

void post_message(omx_video *omx, unsigned char id)
{
  DEBUG_PRINT_LOW("omx_venc: post_message %d\n", id);
  write(omx->m_pipe_out, &id, 1);
}

// 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 p1, unsigned p2, unsigned 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\n");
  }
  return ret;
}

// omx cmd queue pop
bool omx_video::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *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;
}



#ifdef _ANDROID_
VideoHeap::VideoHeap(int fd, size_t size, void* base)
{
  // dup file descriptor, map once, use pmem
  init(dup(fd), base, size, 0 , MEM_DEVICE);
}
#endif // _ANDROID_

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

DESCRIPTION
  Constructor

PARAMETERS
  None

RETURN VALUE
  None.
========================================================================== */
omx_video::omx_video(): m_state(OMX_StateInvalid),
                        m_app_data(NULL),
                        m_inp_mem_ptr(NULL),
                        m_out_mem_ptr(NULL),
                        m_pInput_pmem(NULL),
                        m_pOutput_pmem(NULL),
#ifdef USE_ION
                        m_pInput_ion(NULL),
                        m_pOutput_ion(NULL),
#endif
                        pending_input_buffers(0),
                        pending_output_buffers(0),
                        m_out_bm_count(0),
                        m_inp_bm_count(0),
                        m_flags(0),
                        m_event_port_settings_sent(false),
                        output_flush_progress (false),
                        input_flush_progress (false),
                        input_use_buffer (false),
                        output_use_buffer (false),
                        m_use_input_pmem(OMX_FALSE),
                        m_use_output_pmem(OMX_FALSE),
                        m_etb_count(0),
                        m_fbd_count(0),
                        m_error_propogated(false),
                        m_input_msg_id(OMX_COMPONENT_GENERATE_ETB),
                        psource_frame(NULL),
                        pdest_frame(NULL),
                        c2d_opened(false),
                        secure_session(false)
{
  DEBUG_PRINT_HIGH("\n omx_video(): Inside Constructor()");
  memset(&m_cmp,0,sizeof(m_cmp));
  memset(&m_pCallbacks,0,sizeof(m_pCallbacks));
  secure_color_format = (int) OMX_COLOR_FormatYUV420SemiPlanar;
  pthread_mutex_init(&m_lock, NULL);
  sem_init(&m_cmd_lock,0,0);
}


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

DESCRIPTION
  Destructor

PARAMETERS
  None

RETURN VALUE
  None.
========================================================================== */
omx_video::~omx_video()
{
  DEBUG_PRINT_HIGH("\n ~omx_video(): Inside Destructor()");
  if(m_pipe_in) close(m_pipe_in);
  if(m_pipe_out) close(m_pipe_out);
  DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit\n");
  pthread_join(msg_thread_id,NULL);
  DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit\n");
  pthread_join(async_thread_id,NULL);
  pthread_mutex_destroy(&m_lock);
  sem_destroy(&m_cmd_lock);
  DEBUG_PRINT_HIGH("\n m_etb_count = %u, m_fbd_count = %u\n", m_etb_count,
      m_fbd_count);
  DEBUG_PRINT_HIGH("omx_video: Destructor exit\n");
  DEBUG_PRINT_HIGH("Exiting 7x30 OMX Video Encoder ...\n");
}

/* ======================================================================
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 char id)
{
  unsigned p1; // Parameter - 1
  unsigned p2; // Parameter - 2
  unsigned ident;
  unsigned qsize=0; // qsize
  omx_video *pThis = (omx_video *) ctxt;

  if(!pThis)
  {
    DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out\n");
    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)
    {
      id = ident;
      switch(id)
      {
      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 \n", pThis->m_state);
            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                             OMX_EventCmdComplete, p1, p2, NULL);
            break;

          case OMX_EventError:
            DEBUG_PRINT_ERROR("\nERROR: OMX_EventError: p2 = %d\n", p2);
            if(p2 == 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, NULL, NULL );

            }
            break;

          case OMX_CommandPortDisable:
            DEBUG_PRINT_LOW("Process -> Port %d set to PORT_STATE_DISABLED" \
                        "state \n", 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 %d set PORT_STATE_ENABLED state\n" \
                        , p2);
            pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
                                             OMX_EventCmdComplete, p1, p2, NULL );
            break;

          default:
            DEBUG_PRINT_LOW("\n process_event_cb forwarding EventCmdComplete %d \n", 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\n");
        }
        break;
      case OMX_COMPONENT_GENERATE_ETB_OPQ:
        DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB_OPQ\n");
        if(pThis->empty_this_buffer_opaque((OMX_HANDLETYPE)p1,\
                                          (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
        {
          DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n");
          pThis->omx_report_error ();
        }
        break;
      case OMX_COMPONENT_GENERATE_ETB:
        DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB\n");
        if(pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
                                          (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
        {
          DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n");
          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("\nERROR: FTBProxy() failed!\n");
          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("\nERROR: empty_buffer_done() failed!\n");
          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("\nERROR: fill_buffer_done() failed!\n");
          pThis->omx_report_error ();
        }
        break;

      case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:

        pThis->input_flush_progress = false;
        DEBUG_PRINT_HIGH("\nm_etb_count at i/p flush = %u", 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("\n dev_stop called after input flush complete\n");
              if(dev_stop() != 0)
              {
                DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in i/p flush!\n");
                pThis->omx_report_error ();
              }
            }
          }
        }

        break;

      case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:

        pThis->output_flush_progress = false;
        DEBUG_PRINT_HIGH("\nm_fbd_count at o/p flush = %u", 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("\n dev_stop called after Output flush complete\n");
            if(!pThis->input_flush_progress)
            {
              if(dev_stop() != 0)
              {
                DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in o/p flush!\n");
                pThis->omx_report_error ();
              }
            }
          }
        }
        break;

      case OMX_COMPONENT_GENERATE_START_DONE:
        DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE msg");

        if(pThis->m_pCallbacks.EventHandler)
        {
          DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success");
          if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
          {
            DEBUG_PRINT_LOW("\n 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("\nERROR: dev_pause() failed in Start Done!\n");
              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_ERROR("\nERROR: unknown flags=%x\n",pThis->m_flags);
          }
        }
        else
        {
          DEBUG_PRINT_LOW("\n Event Handler callback is NULL");
        }
        break;

      case OMX_COMPONENT_GENERATE_PAUSE_DONE:
        DEBUG_PRINT_LOW("\n 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\n");
            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("\n 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("\n 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_ERROR("\nERROR: unknown flags=%x\n",pThis->m_flags);
          }
        }

        break;

      case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
        DEBUG_PRINT_ERROR("\nERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!\n");
        pThis->omx_report_error ();
        break;

      default:
        DEBUG_PRINT_LOW("\n process_event_cb unknown msg id 0x%02x", id);
        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("\n exited the while loop\n");

}




/* ======================================================================
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
)
{
  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State\n");
    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
                                      )
{
  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n");
    return OMX_ErrorInvalidState;
  }

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

  post_event((unsigned)cmd,(unsigned)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
                                            )
{
  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\n");
        }
        else
        {
          DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending\n");
          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\n");
        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\n");
      }
      /* Requesting transition from Loaded to Executing */
      else if(eState == OMX_StateExecuting)
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing\n");
        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\n");
        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\n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled\n",\
                          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\n");
          if(dev_stop() != 0)
          {
            DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed at Idle --> Loaded");
            eRet = OMX_ErrorHardware;
          }
        }
        else
        {
          DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending\n");
          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("\nERROR: dev_start() failed in SCP on Idle --> Exe\n");
          omx_report_error ();
          eRet = OMX_ErrorHardware;
        }
        else
        {
          BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
          DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n");
          bFlag = 0;
        }

	dev_start_done();
      }
      /* Requesting transition from Idle to Idle */
      else if(eState == OMX_StateIdle)
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle\n");
        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\n");
        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("\nERROR: dev_start() failed in SCP on Idle --> Pause\n");
          omx_report_error ();
          eRet = OMX_ErrorHardware;
        }
        else
        {
          BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
          DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause\n");
          bFlag = 0;
        }
      }
      /* Requesting transition from Idle to Invalid */
      else if(eState == OMX_StateInvalid)
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid\n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled\n",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("\n OMXCORE-SM: Executing --> Idle \n");
        //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;
	dev_stop_done();
      }
      /* Requesting transition from Executing to Paused */
      else if(eState == OMX_StatePause)
      {

        if(dev_pause())
        {
          DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in SCP on Exe --> Pause\n");
          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\n");
          bFlag = 0;
        }
      }
      /* Requesting transition from Executing to Loaded */
      else if(eState == OMX_StateLoaded)
      {
        DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Loaded \n");
        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("\nERROR: OMXCORE-SM: Executing --> WaitForResources \n");
        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("\nERROR: OMXCORE-SM: Executing --> Executing \n");
        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("\nERROR: OMXCORE-SM: Executing --> Invalid \n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled\n",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("\n Pause --> Executing \n");
        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\n");
          post_event (NULL, NULL, 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("\n Pause --> Idle \n");
        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("\nERROR: Pause --> loaded \n");
        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("\nERROR: Pause --> WaitForResources \n");
        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("\nERROR: Pause --> Pause \n");
        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("\nERROR: Pause --> Invalid \n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled\n",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\n");
      }
      /* Requesting transition from WaitForResources to WaitForResources */
      else if(eState == OMX_StateWaitForResources)
      {
        DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources\n");
        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\n");
        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\n");
        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\n");
        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)\n",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 || OMX_StateWaitForResources
                  || OMX_StateIdle || OMX_StateExecuting
                  || OMX_StatePause || OMX_StateInvalid))
    {
      DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded\n");
      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\n");
        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\n");
        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)\n",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("\n execute_omx_flush -  %d\n", flushType);
  if(flushType == 0 || flushType == OMX_ALL)
  {
    input_flush_progress = true;
    //flush input only
    bRet = execute_input_flush();
  }
  if(flushType == 1 || flushType == OMX_ALL)
  {
    //flush output only
    output_flush_progress = true;
    bRet = execute_output_flush();
  }
  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      p1 = 0; // Parameter - 1
  unsigned      p2 = 0; // Parameter - 2
  unsigned      ident = 0;
  bool bRet = true;

  /*Generate FBD for all Buffers in the FTBq*/
  DEBUG_PRINT_LOW("\n execute_output_flush\n");
  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++;
      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("\nERROR: 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      p1 = 0; // Parameter - 1
  unsigned      p2 = 0; // Parameter - 2
  unsigned      ident = 0;
  bool bRet = true;

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

  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++;
      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);
    }
  }
  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 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 int)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("\nERROR: i/p 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 int p1,
                           unsigned int p2,
                           unsigned int id)
{
  bool bRet      =                      false;


  pthread_mutex_lock(&m_lock);

  if( id == OMX_COMPONENT_GENERATE_FTB || \
      (id == OMX_COMPONENT_GENERATE_FRAME_DONE))
  {
    m_ftb_q.insert_entry(p1,p2,id);
  }
  else if((id == m_input_msg_id) \
          || (id == OMX_COMPONENT_GENERATE_EBD))
  {
    m_etb_q.insert_entry(p1,p2,id);
  }
  else
  {
    m_cmd_q.insert_entry(p1,p2,id);
  }

  bRet = true;
  DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this);
  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)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  unsigned int height=0,width = 0;

  DEBUG_PRINT_LOW("get_parameter: \n");
  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State\n");
    return OMX_ErrorInvalidState;
  }
  if(paramData == NULL)
  {
    DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n");
    return OMX_ErrorBadParameter;
  }
  switch(paramIndex)
  {
  case OMX_IndexParamPortDefinition:
    {
      OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
      portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;

      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n");
      if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN)
      {
        DEBUG_PRINT_LOW("m_sInPortDef: size = %d, min cnt = %d, actual cnt = %d",
            m_sInPortDef.nBufferSize, m_sInPortDef.nBufferCountMin,
            m_sInPortDef.nBufferCountActual);
        memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef));
#ifdef _ANDROID_ICS_
        if(meta_mode_enable)
        {
          portDefn->nBufferSize = sizeof(encoder_media_buffer_type);
        }
        if(secure_session) {
          portDefn->format.video.eColorFormat =
            (OMX_COLOR_FORMATTYPE)secure_color_format;
        }
        else if (mUseProxyColorFormat) {
            portDefn->format.video.eColorFormat =
              (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque;
        }
#endif
      }
      else if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
      {
        dev_get_buf_req (&m_sOutPortDef.nBufferCountMin,
                         &m_sOutPortDef.nBufferCountActual,
                         &m_sOutPortDef.nBufferSize,
                         m_sOutPortDef.nPortIndex);
        DEBUG_PRINT_LOW("m_sOutPortDef: size = %d, min cnt = %d, actual cnt = %d",
            m_sOutPortDef.nBufferSize, m_sOutPortDef.nBufferCountMin,
            m_sOutPortDef.nBufferCountActual);
        memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef));
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
        eRet = OMX_ErrorBadPortIndex;
      }
      break;
    }
  case OMX_IndexParamVideoInit:
    {
      OMX_PORT_PARAM_TYPE *portParamType =
      (OMX_PORT_PARAM_TYPE *) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n");

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

      if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN)
      {
          int index = portFmt->nIndex;

          if (index > 1) {
              eRet = OMX_ErrorNoMore;
          } else {
              memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat));
#ifdef _ANDROID_ICS_
              if (index == 1) {
                  //we support two formats
                  //index 0 - YUV420SP
                  //index 1 - opaque which internally maps to YUV420SP.
                  //this can be extended in the future
                  portFmt->nIndex = index; //restore index set from client
                  portFmt->eColorFormat =
                    (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque;
              }
          }
#endif
      }
      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:
    {
      OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate\n");

      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:
    {
      OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4\n");
      memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4));
      break;
    }
  case OMX_IndexParamVideoH263:
    {
      OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263\n");
      memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263));
      break;
    }
  case OMX_IndexParamVideoAvc:
    {
      OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc\n");
      memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC));
      break;
    }
  case OMX_IndexParamVideoProfileLevelQuerySupported:
    {
      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported\n");
      eRet = get_supported_profile_level(pParam);
      if(eRet)
        DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %d, %d",
                          pParam->eProfile, pParam->eLevel);
      break;
     }
  case OMX_IndexParamVideoProfileLevelCurrent:
    {
      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent\n");
      memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel));
      break;
    }
    /*Component should support this port definition*/
  case OMX_IndexParamAudioInit:
    {
      OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n");
      memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio));
      break;
    }
    /*Component should support this port definition*/
  case OMX_IndexParamImageInit:
    {
      OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n");
      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\n", paramIndex);
      eRet =OMX_ErrorUnsupportedIndex;
      break;
    }
  case OMX_IndexParamStandardComponentRole:
    {
      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\n",paramIndex);
      if(NULL != comp_role->cRole)
      {
        strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE);
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",paramIndex);
        eRet =OMX_ErrorBadParameter;
      }
      break;
    }
    /* Added for parameter test */
  case OMX_IndexParamPriorityMgmt:
    {

      OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n");
      memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt));
      break;
    }
    /* Added for parameter test */
  case OMX_IndexParamCompBufferSupplier:
    {
      OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n");
      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:
    {
      OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization\n");
      memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization));
      break;
    }

    case OMX_IndexParamVideoErrorCorrection:
    {
      OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData;
      DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection\n");
      errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC;
      errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync;
      errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing;
      break;
    }
  case OMX_IndexParamVideoIntraRefresh:
    {
      OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData;
      DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh\n");
      DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET\n");
      intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode;
      intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs;
      break;
    }
  case OMX_QcomIndexPortDefn:
    //TODO
    break;
  case OMX_COMPONENT_CAPABILITY_TYPE_INDEX:
   {
        OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData);
        DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX\n");
        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;
   }
#ifndef MAX_RES_720P
  case OMX_QcomIndexParamIndexExtraDataType:
    {
      DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType");
      QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData;
      if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo)
      {
        if (pParam->nPortIndex == PORT_INDEX_OUT)
        {
          pParam->bEnabled =
             (OMX_BOOL)((m_sExtraData & VEN_EXTRADATA_SLICEINFO) ? 1 : 0);
          DEBUG_PRINT_HIGH("Slice Info extradata %d", pParam->bEnabled);
        }
        else
        {
          DEBUG_PRINT_ERROR("get_parameter: slice information is "
              "valid for output port only");
          eRet =OMX_ErrorUnsupportedIndex;
        }
      }
      else
      {
        DEBUG_PRINT_ERROR("get_parameter: unsupported index (%x), "
            "only slice information extradata is supported", pParam->nIndex);
        eRet =OMX_ErrorUnsupportedIndex;
      }
      break;
    }
#endif
  case QOMX_IndexParamVideoSyntaxHdr:
    {
       DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr");
       QOMX_EXTNINDEX_PARAMTYPE* pParam =
          reinterpret_cast<QOMX_EXTNINDEX_PARAMTYPE*>(paramData);
       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 *)&pParam->nDataSize))
       {
         DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %d)",
            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_IndexParamVideoSliceFMO:
  default:
    {
      DEBUG_PRINT_ERROR("ERROR: get_parameter: unknown param %08x\n", 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)
{
  ////////////////////////////////////////////////////////////////
  // 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(configIndex)
  {
  case OMX_IndexConfigVideoBitrate:
    {
      OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData);
      memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate));
      break;
    }
  case OMX_IndexConfigVideoFramerate:
    {
      OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData);
      memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate));
      break;
    }
  case OMX_IndexConfigCommonRotate:
    {
      OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
      memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation));
      break;
    }
  case QOMX_IndexConfigVideoIntraperiod:
    {
      DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod\n");
      QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData);
      memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod));
      break;
    }
  default:
    DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
    return OMX_ErrorUnsupportedIndex;
  }
  return OMX_ErrorNone;

}

/* ======================================================================
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)
{
  char *extns[] = {
    "OMX.QCOM.index.param.SliceDeliveryMode",
    "OMX.google.android.index.storeMetaDataInBuffers",
    "OMX.google.android.index.prependSPSPPSToIDRFrames",
    "OMX.google.android.index.setVUIStreamRestrictFlag"
  };

  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State\n");
    return OMX_ErrorInvalidState;
  }
#ifdef MAX_RES_1080P
  if (!strncmp(paramName, extns[0], strlen(extns[0]))) {
    *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode;
    return OMX_ErrorNone;
  }
#endif
#ifdef _ANDROID_ICS_
  if (!strncmp(paramName, extns[1], strlen(extns[1]))) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoEncodeMetaBufferMode;
        return OMX_ErrorNone;
  } else if (!strncmp(paramName, extns[2], strlen(extns[2]))) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamSequenceHeaderWithIDR;
        return OMX_ErrorNone;
  } else if (!strncmp(paramName, extns[3], strlen(extns[3]))) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamEnableVUIStreamRestrictFlag;
        return OMX_ErrorNone;
  }
#endif
  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)
{
  *state = m_state;
  DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*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)
{
  DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented\n");
  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)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;

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

  DEBUG_PRINT_HIGH("use_input_buffer: port = %d appData = %p bytes = %d buffer = %p",port,appData,bytes,buffer);
  if(bytes != m_sInPortDef.nBufferSize || secure_session)
  {
    DEBUG_PRINT_ERROR("\nERROR: use_input_buffer: Size Mismatch!! "
                      "bytes[%d] != Port.nBufferSize[%d]", bytes, 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("\nERROR: calloc() Failed for m_inp_mem_ptr");
      return OMX_ErrorInsufficientResources;
    }


    m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
    if(m_pInput_pmem == NULL)
    {
      DEBUG_PRINT_ERROR("\nERROR: 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("\nERROR: 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].ion_device_fd =-1;
      m_pInput_ion[i].fd_ion_data.fd =-1;
      m_pInput_ion[i].ion_alloc_data.handle=NULL;
#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);

    (*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
      m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
                                      &m_pInput_ion[i].ion_alloc_data,
                                      &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED);
      if(m_pInput_ion[i].ion_device_fd < 0) {
        DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed");
        return OMX_ErrorInsufficientResources;
      }
      m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd;
#else
      m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
      if(m_pInput_pmem[i].fd == 0)
      {
        m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
      }

      if(m_pInput_pmem[i] .fd < 0)
      {
        DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed");
        return OMX_ErrorInsufficientResources;
      }
#endif
      m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
      m_pInput_pmem[i].offset = 0;
      m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
                                                      MAP_SHARED,m_pInput_pmem[i].fd,0);

      if(m_pInput_pmem[i].buffer == MAP_FAILED)
      {
        DEBUG_PRINT_ERROR("\nERROR: mmap() Failed");
        close(m_pInput_pmem[i].fd);
#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:%d,offset:0x%x)", pParam->pmem_fd, 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("\n DBG:: pParam->pmem_fd = %u, pParam->offset = %u",
            pParam->pmem_fd, pParam->offset);
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case");
        return OMX_ErrorBadParameter;
      }
    }

    DEBUG_PRINT_LOW("\nuse_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p",
                (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer);
    if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true)
    {
      DEBUG_PRINT_ERROR("\nERROR: dev_use_buf() Failed for i/p buf");
      return OMX_ErrorInsufficientResources;
    }
  }
  else
  {
    DEBUG_PRINT_ERROR("\nERROR: 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)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
  unsigned                         i= 0; // Temporary counter
  unsigned char *buf_addr = NULL;

  DEBUG_PRINT_HIGH("\n Inside use_output_buffer()");
  if(bytes != m_sOutPortDef.nBufferSize || secure_session)
  {
    DEBUG_PRINT_ERROR("\nERROR: use_output_buffer: Size Mismatch!! "
                      "bytes[%d] != Port.nBufferSize[%d]", bytes, 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(%d)\n",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("\nERROR: 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("\nERROR: 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("\nERROR: 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\n",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].ion_device_fd =-1;
        m_pOutput_ion[i].fd_ion_data.fd=-1;
        m_pOutput_ion[i].ion_alloc_data.handle =NULL;
#endif
      }
    }
    else
    {
      DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%x]\n",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;
      BITMASK_SET(&m_out_bm_count,i);

      if(!m_use_output_pmem)
      {
#ifdef USE_ION
        m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(
                                         m_sOutPortDef.nBufferSize,
                                         &m_pOutput_ion[i].ion_alloc_data,
                                         &m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED);
      if(m_pOutput_ion[i].ion_device_fd < 0) {
        DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed");
        return OMX_ErrorInsufficientResources;
      }
      m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd;
#else
        m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);

        if(m_pOutput_pmem[i].fd == 0)
        {
          m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
        }

        if(m_pOutput_pmem[i].fd < 0)
        {
          DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed");
          return OMX_ErrorInsufficientResources;
        }
#endif
        m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
        m_pOutput_pmem[i].offset = 0;
        m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
                                                         MAP_SHARED,m_pOutput_pmem[i].fd,0);
        if(m_pOutput_pmem[i].buffer == MAP_FAILED)
        {
          DEBUG_PRINT_ERROR("\nERROR: mmap() Failed");
          close(m_pOutput_pmem[i].fd);
#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:0x%x )", pParam);

        if(pParam)
        {
          DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, 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("\n use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p",
                (*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer);
      if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != 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 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\n");
    return OMX_ErrorInvalidState;
  }
  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
  {
    DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(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::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;
  }

  index = bufferHdr - ((!mUseProxyColorFormat)?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 {
      c2d_conv.close();
      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("\nERROR: dev_free_buf() Failed for i/p buf");
  }

  if(index < m_sInPortDef.nBufferCountActual && m_pInput_pmem)
  {
    if(m_pInput_pmem[index].fd > 0 && input_use_buffer == false)
    {
      DEBUG_PRINT_LOW("\n FreeBuffer:: i/p AllocateBuffer case");
      munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
      close (m_pInput_pmem[index].fd);
#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("\n FreeBuffer:: i/p Heap UseBuffer case");
      if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true)
      {
        DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf");
      }
      munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
      close (m_pInput_pmem[index].fd);
#ifdef USE_ION
      free_ion_memory(&m_pInput_ion[index]);
#endif
      m_pInput_pmem[index].fd = -1;
    }
    else
    {
      DEBUG_PRINT_ERROR("\n 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;

  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("\n FreeBuffer:: o/p AllocateBuffer case");
      if(!secure_session)
        munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size);
      close (m_pOutput_pmem[index].fd);
#ifdef USE_ION
      free_ion_memory(&m_pOutput_ion[index]);
#endif
      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("\n 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");
      }
      munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size);
      close (m_pOutput_pmem[index].fd);
#ifdef USE_ION
      free_ion_memory(&m_pOutput_ion[index]);
#endif
      m_pOutput_pmem[index].fd = -1;
    }
    else
    {
      DEBUG_PRINT_LOW("\n 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;
  if(!bufferHdr || bytes != sizeof(encoder_media_buffer_type))
  {
    DEBUG_PRINT_ERROR("wrong params allocate_input_meta_buffer Hdr %p len %d",
                     bufferHdr,bytes);
    return OMX_ErrorBadParameter;
  }
  if(!m_inp_mem_ptr && !mUseProxyColorFormat)
    m_inp_mem_ptr = meta_buffer_hdr;
  for(index = 0;((index < m_sInPortDef.nBufferCountActual) &&
      meta_buffer_hdr[index].pBuffer); 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 int)opaque_buffer_hdr[index],0,0);
    DEBUG_PRINT_HIGH("\n 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)
{

  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  unsigned   i = 0;

  DEBUG_PRINT_HIGH("\n allocate_input_buffer()::");
  if(bytes != m_sInPortDef.nBufferSize || secure_session)
  {
    DEBUG_PRINT_ERROR("\nERROR: Buffer size mismatch error: bytes[%u] != nBufferSize[%u]\n",
      bytes, m_sInPortDef.nBufferSize);
    return OMX_ErrorBadParameter;
  }

  if(!m_inp_mem_ptr)
  {
    DEBUG_PRINT_HIGH("%s: size = %d, actual cnt %d", __FUNCTION__,
        m_sInPortDef.nBufferSize, 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("\nERROR: calloc() Failed for m_inp_mem_ptr");
      return OMX_ErrorInsufficientResources;
    }

    m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);

    if(m_pInput_pmem == NULL)
    {
      DEBUG_PRINT_ERROR("\nERROR: 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("\nERROR: 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].ion_device_fd =-1;
      m_pInput_ion[i].fd_ion_data.fd =-1;
      m_pInput_ion[i].ion_alloc_data.handle=NULL;
#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;

#ifdef USE_ION
    m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
                                    &m_pInput_ion[i].ion_alloc_data,
                                    &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED);
    if(m_pInput_ion[i].ion_device_fd < 0) {
      DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed");
      return OMX_ErrorInsufficientResources;
    }

    m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd;
#else
    m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);

    if(m_pInput_pmem[i].fd == 0)
    {
      m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
    }

    if(m_pInput_pmem[i].fd < 0)
    {
      DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed\n");
      return OMX_ErrorInsufficientResources;
    }
#endif
    m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
    m_pInput_pmem[i].offset = 0;

    m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
                                                    MAP_SHARED,m_pInput_pmem[i].fd,0);
    if(m_pInput_pmem[i].buffer == MAP_FAILED)
    {
      DEBUG_PRINT_ERROR("\nERROR: mmap FAILED= %d\n", errno);
      close(m_pInput_pmem[i].fd);
#ifdef USE_ION
      free_ion_memory(&m_pInput_ion[i]);
#endif
      return OMX_ErrorInsufficientResources;
    }

    (*bufferHdr)->pBuffer           = (OMX_U8 *)m_pInput_pmem[i].buffer;
    DEBUG_PRINT_LOW("\n 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(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true))
    {
      DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for i/p buf\n");
      return OMX_ErrorInsufficientResources;
    }
  }
  else
  {
    DEBUG_PRINT_ERROR("\nERROR: All i/p buffers are allocated, invalid allocate buf call"
                      "for index [%d]\n", 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)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
  unsigned                         i= 0; // Temporary counter

  DEBUG_PRINT_HIGH("\n allocate_output_buffer()::");
  if(!m_out_mem_ptr)
  {
    int nBufHdrSize        = 0;
    DEBUG_PRINT_HIGH("%s: size = %d, actual cnt %d", __FUNCTION__,
        m_sOutPortDef.nBufferSize, 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("\nERROR: 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("\nERROR: 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;
        bufHdr->pBuffer            = NULL;
        bufHdr++;
        m_pOutput_pmem[i].fd = -1;
#ifdef USE_ION
        m_pOutput_ion[i].ion_device_fd =-1;
        m_pOutput_ion[i].fd_ion_data.fd=-1;
        m_pOutput_ion[i].ion_alloc_data.handle =NULL;
#endif
      }
    }
    else
    {
      DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem");
      eRet = OMX_ErrorInsufficientResources;
    }
  }

  DEBUG_PRINT_HIGH("\n actual cnt = %u", m_sOutPortDef.nBufferCountActual);
  for(i=0; i< m_sOutPortDef.nBufferCountActual; i++)
  {
    if(BITMASK_ABSENT(&m_out_bm_count,i))
    {
      DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i);
      break;
    }
  }
  if(eRet == OMX_ErrorNone)
  {
    if(i < m_sOutPortDef.nBufferCountActual)
    {
#ifdef USE_ION
      m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sOutPortDef.nBufferSize,
                                       &m_pOutput_ion[i].ion_alloc_data,
                                       &m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED);
      if(m_pOutput_ion[i].ion_device_fd < 0) {
        DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed");
        return OMX_ErrorInsufficientResources;
      }
      m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd;
#else
      m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
      if(m_pOutput_pmem[i].fd == 0)
      {
        m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
      }

      if(m_pOutput_pmem[i].fd < 0)
      {
        DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() failed");
        return OMX_ErrorInsufficientResources;
      }
#endif
      m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
      m_pOutput_pmem[i].offset = 0;
      if(!secure_session) {
          m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
                  MAP_SHARED,m_pOutput_pmem[i].fd,0);
          if(m_pOutput_pmem[i].buffer == MAP_FAILED)
          {
              DEBUG_PRINT_ERROR("\nERROR: MMAP_FAILED in o/p alloc buffer");
              close (m_pOutput_pmem[i].fd);
#ifdef USE_ION
              free_ion_memory(&m_pOutput_ion[i]);
#endif
              return OMX_ErrorInsufficientResources;
          }
      }

      *bufferHdr = (m_out_mem_ptr + i );
      if(!secure_session)
        (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer;
      else {
        m_pOutput_pmem[i].buffer = (OMX_U8 *)(i + 12345);
        (*bufferHdr)->pBuffer = (OMX_U8 *)(i + 12345);
      }
      (*bufferHdr)->pAppPrivate = appData;

      BITMASK_SET(&m_out_bm_count,i);

      if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true)
      {
        DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for o/p buf");
        return OMX_ErrorInsufficientResources;
      }
    }
    else
    {
      DEBUG_PRINT_ERROR("\nERROR: All o/p buffers are allocated, invalid allocate buf call"
                        "for index [%d]\n", i);
    }
  }

  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("\n Allocate buffer of size = %d on port %d \n", bytes, (int)port);
  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State\n");
    return OMX_ErrorInvalidState;
  }

  // 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\n",(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\n",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)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  unsigned int nPortIndex;

  DEBUG_PRINT_LOW("In for decoder free_buffer \n");

  if(m_state == OMX_StateIdle &&
     (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
  {
    DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n");
  }
  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 %d disabled\n", 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\n");
    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\n");
    post_event(OMX_EventError,
               OMX_ErrorPortUnpopulated,
               OMX_COMPONENT_GENERATE_EVENT);
  }

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

    DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d, actual cnt %d \n",
                    nPortIndex, m_sInPortDef.nBufferCountActual);
    if(nPortIndex < m_sInPortDef.nBufferCountActual)
    {
      // 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()
#ifdef _ANDROID_ICS_
         && !meta_mode_enable
#endif
         )
      {
        input_use_buffer = false;
        if(m_inp_mem_ptr)
        {
          DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr\n");
          free (m_inp_mem_ptr);
          m_inp_mem_ptr = NULL;
        }
        if(m_pInput_pmem)
        {
          DEBUG_PRINT_LOW("Freeing m_pInput_pmem\n");
          free(m_pInput_pmem);
          m_pInput_pmem = NULL;
        }
#ifdef USE_ION
        if(m_pInput_ion)
        {
          DEBUG_PRINT_LOW("Freeing m_pInput_ion\n");
          free(m_pInput_ion);
          m_pInput_ion = NULL;
        }
#endif
      }
    }
    else
    {
      DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid\n");
      eRet = OMX_ErrorBadPortIndex;
    }

    if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
       && release_input_done())
    {
      DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
      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 %d, actual cnt %d \n",
                    nPortIndex, m_sOutPortDef.nBufferCountActual);
    if(nPortIndex < m_sOutPortDef.nBufferCountActual)
    {
      // 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\n");
          free (m_out_mem_ptr);
          m_out_mem_ptr = NULL;
        }
        if(m_pOutput_pmem)
        {
          DEBUG_PRINT_LOW("Freeing m_pOutput_pmem\n");
          free(m_pOutput_pmem);
          m_pOutput_pmem = NULL;
        }
#ifdef USE_ION
        if(m_pOutput_ion)
        {
          DEBUG_PRINT_LOW("Freeing m_pOutput_ion\n");
          free(m_pOutput_ion);
          m_pOutput_ion = NULL;
        }
#endif
      }
    }
    else
    {
      DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid\n");
      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\n");

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

    }
  }
  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\n");
        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);
    }
  }

  return eRet;
}


/* ======================================================================
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)
{
  OMX_ERRORTYPE ret1 = OMX_ErrorNone;
  unsigned int nBufferIndex ;

  DEBUG_PRINT_LOW("\n ETB: buffer = %p, buffer->pBuffer[%p]\n", buffer, buffer->pBuffer);
  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State\n");
    return OMX_ErrorInvalidState;
  }

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

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

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

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

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

  m_etb_count++;
  DEBUG_PRINT_LOW("\n DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp);
  post_event ((unsigned)hComp,(unsigned)buffer,m_input_msg_id);
  return OMX_ErrorNone;
}
/* ======================================================================
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)
{
  OMX_U8 *pmem_data_buf = NULL;
  int push_cnt = 0;
  unsigned nBufIndex = 0,nBufIndex_meta = 0;
  OMX_ERRORTYPE ret = OMX_ErrorNone;

  DEBUG_PRINT_LOW("\n ETBProxy: buffer[%p]\n", buffer);

  if(buffer == NULL)
  {
    DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid buffer[%p]\n", buffer);
    return OMX_ErrorBadParameter;
  }

  nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
  nBufIndex_meta = buffer - meta_buffer_hdr;
  if(nBufIndex >= m_sInPortDef.nBufferCountActual &&
     nBufIndex_meta >= m_sInPortDef.nBufferCountActual)
  {
    DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid bufindex = %u\n", nBufIndex);
    return OMX_ErrorBadParameter;
  }

  pending_input_buffers++;
  if(input_flush_progress == true)
  {
    post_event ((unsigned int)buffer,0,
                OMX_COMPONENT_GENERATE_EBD);
    DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Input flush in progress");
    return OMX_ErrorNone;
  }
#ifdef _ANDROID_ICS_
  if(meta_mode_enable && !mUseProxyColorFormat)
  {
    encoder_media_buffer_type *media_buffer;
    bool met_error = false;
    media_buffer = (encoder_media_buffer_type *)meta_buffer_hdr[nBufIndex].pBuffer;
    if(media_buffer)
    {
      if (media_buffer->buffer_type != kMetadataBufferTypeCameraSource &&
          media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) {
          met_error = true;
      } else {
        if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource)
        {
          if(media_buffer->meta_handle == NULL) {
            met_error = true;
          }
          else if((media_buffer->meta_handle->numFds != 1 &&
                   media_buffer->meta_handle->numInts != 2))
          {
            met_error = true;
          }
        }
      }
    } else {
      met_error = true;
    }
    if(met_error)
    {
      DEBUG_PRINT_ERROR("\nERROR: Unkown source/metahandle in ETB call");
      post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD);
      return OMX_ErrorBadParameter;
    }

    struct pmem Input_pmem_info;
    if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource)
    {
      Input_pmem_info.buffer = media_buffer;
      Input_pmem_info.fd = media_buffer->meta_handle->data[0];
      Input_pmem_info.offset = media_buffer->meta_handle->data[1];
      Input_pmem_info.size = media_buffer->meta_handle->data[2];
      DEBUG_PRINT_LOW("ETB fd = %d, offset = %d, size = %d",Input_pmem_info.fd,
                        Input_pmem_info.offset,
                        Input_pmem_info.size);

    } else {
      private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle;
      if(handle->format != HAL_PIXEL_FORMAT_NV12_ENCODEABLE) {
        DEBUG_PRINT_ERROR("\n Incorrect pixel format");
        post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD);
        return OMX_ErrorBadParameter;
      }
      Input_pmem_info.buffer = media_buffer;
      Input_pmem_info.fd = handle->fd;
      Input_pmem_info.offset = 0;
      Input_pmem_info.size = handle->size;
    }
    if(dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) {
      DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf");
      post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD);
      return OMX_ErrorBadParameter;
    }
  }
  else if(input_use_buffer && !m_use_input_pmem)
#else
  if(input_use_buffer && !m_use_input_pmem)
#endif
  {
    DEBUG_PRINT_LOW("\n Heap UseBuffer case, so memcpy the data");
    pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer;

    memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset),
            buffer->nFilledLen);
    DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf");
  } else if (m_sInPortDef.format.video.eColorFormat ==
      OMX_COLOR_FormatYUV420SemiPlanar && !mUseProxyColorFormat) {
      //For the case where YUV420SP buffers are qeueued to component
      //by sources other than camera (Apps via MediaCodec), alignment
      //of chroma-plane to 2K is necessary.
      //For RGB buffers, color-conversion takes care of such alignment
      OMX_U32 width = m_sInPortDef.format.video.nFrameWidth;
      OMX_U32 height = m_sInPortDef.format.video.nFrameHeight;
      OMX_U32 chromaOffset = width * height;
      if (IS_NOT_ALIGNED(chromaOffset, SZ_2K)) {
          OMX_U32 chromaSize = (width * height)/2;
          chromaOffset = ALIGN(chromaOffset,SZ_2K);
          if (buffer->nAllocLen >= chromaOffset + chromaSize) {
              OMX_U8* buf = buffer->pBuffer;
              memmove(buf + chromaOffset, buf + (width*height), chromaSize);
          } else {
             DEBUG_PRINT_ERROR("Failed to align Chroma. from %u to %u : \
                 Insufficient bufferLen=%u v/s Required=%u",
                 (width*height), chromaOffset, buffer->nAllocLen,
                 chromaOffset+chromaSize);
          }
      }
  }
#ifdef _COPPER_
  if(dev_empty_buf(buffer, pmem_data_buf,nBufIndex,m_pInput_pmem[nBufIndex].fd) != true)
#else
  if(dev_empty_buf(buffer, pmem_data_buf,0,0) != true)
#endif
  {
    DEBUG_PRINT_ERROR("\nERROR: ETBProxy: dev_empty_buf failed");
#ifdef _ANDROID_ICS_
    omx_release_meta_buffer(buffer);
#endif
    post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD);
    /*Generate an async error and move to invalid state*/
    pending_input_buffers--;
    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)
{
  DEBUG_PRINT_LOW("\n FTB: buffer->pBuffer[%p]\n", buffer->pBuffer);
  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State\n");
    return OMX_ErrorInvalidState;
  }

  if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)))
  {
    DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size\n");
    return OMX_ErrorBadParameter;
  }

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

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

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

  post_event((unsigned) hComp, (unsigned)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)
{
  OMX_U8 *pmem_data_buf = NULL;
  OMX_ERRORTYPE nRet = OMX_ErrorNone;

  DEBUG_PRINT_LOW("\n FTBProxy: bufferAdd->pBuffer[%p]\n", bufferAdd->pBuffer);

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

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

  if(output_use_buffer && !m_use_output_pmem)
  {
    DEBUG_PRINT_LOW("\n 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("\nERROR: dev_fill_buf() Failed");
    post_event ((unsigned int)bufferAdd,0,OMX_COMPONENT_GENERATE_FBD);
    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)
{

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


/* ======================================================================
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)
{
  DEBUG_PRINT_ERROR("ERROR: use_EGL_image:  Not Implemented \n");
  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)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      eRet = OMX_ErrorNoMore;
    }
  }
  else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  else 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\n",role);
    }
    else
    {
      DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      eRet = OMX_ErrorNoMore;
    }
  }
  else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE))
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",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\n",role);
    }
    else
    {
      DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  else
  {
    DEBUG_PRINT_ERROR("\nERROR: Querying Role on Unknown Component\n");
    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;

  bRet_In = allocate_input_done();
  bRet_Out = allocate_output_done();

  if(bRet_In && bRet_Out)
  {
    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;
}

/* ======================================================================
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()\n");
  if(release_input_done())
  {
    if(release_output_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()\n");
  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()\n");
  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;
}

OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp,
                                          OMX_BUFFERHEADERTYPE * buffer)
{
  DEBUG_PRINT_LOW("fill_buffer_done: buffer->pBuffer[%p], flags=0x%x size = %d",
     buffer->pBuffer, buffer->nFlags,buffer->nFilledLen);
  if(buffer == NULL || ((buffer - m_out_mem_ptr) > m_sOutPortDef.nBufferCountActual))
  {
    return OMX_ErrorBadParameter;
  }

  pending_output_buffers--;
  if(!secure_session)
  {
    extra_data_handle.create_extra_data(buffer);
  }

  if (!secure_session && m_sDebugSliceinfo) {
    if(buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) {
       DEBUG_PRINT_HIGH("parsing extradata");
       extra_data_handle.parse_extra_data(buffer);
    }
  }
  /* For use buffer we need to copy the data */
  if(m_pCallbacks.FillBufferDone)
  {
    if(buffer->nFilledLen > 0)
    {
      m_fbd_count++;

#ifdef OUTPUT_BUFFER_LOG
      if(outputBufferFile1)
      {
        fwrite((const char *)buffer->pBuffer, buffer->nFilledLen, 1, outputBufferFile1);
      }
#endif
    }
    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)
{
  int buffer_index  = -1;
  int buffer_index_meta = -1;

  buffer_index = (buffer - m_inp_mem_ptr);
  buffer_index_meta = (buffer - meta_buffer_hdr);
  DEBUG_PRINT_LOW("\n empty_buffer_done: buffer[%p]", buffer);
  if(buffer == NULL ||
     ((buffer_index > m_sInPortDef.nBufferCountActual) &&
      (buffer_index_meta > m_sInPortDef.nBufferCountActual)))
  {
    DEBUG_PRINT_ERROR("\n ERROR in empty_buffer_done due to index buffer");
    return OMX_ErrorBadParameter;
  }

  pending_input_buffers--;

  if(mUseProxyColorFormat && (buffer_index < m_sInPortDef.nBufferCountActual)) {
    if(!pdest_frame) {
      pdest_frame = buffer;
      DEBUG_PRINT_LOW("\n empty_buffer_done pdest_frame address is %p",pdest_frame);
      return push_input_buffer(hComp);

    } else {
      DEBUG_PRINT_LOW("\n empty_buffer_done insert address is %p",buffer);
      if (!m_opq_pmem_q.insert_entry((unsigned int)buffer, 0, 0)) {
        DEBUG_PRINT_ERROR("\n empty_buffer_done: pmem queue is full");
        return OMX_ErrorBadParameter;
      }
    }
  } 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 p1;
  unsigned p2;
  unsigned 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("\nERROR: empty_buffer_done() failed!\n");
          omx_report_error ();
        }
        break;

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

#ifdef MAX_RES_720P
OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if(!profileLevelType)
    return OMX_ErrorBadParameter;

  if(profileLevelType->nPortIndex == 1) {
    if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
        profileLevelType->eLevel   = OMX_VIDEO_AVCLevel31;
      }
      else if (profileLevelType->nProfileIndex == 1)
      {
        profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
        profileLevelType->eLevel   = OMX_VIDEO_AVCLevel31;
      }
      else if(profileLevelType->nProfileIndex == 2)
      {
        profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
        profileLevelType->eLevel   = OMX_VIDEO_AVCLevel31;
      }
      else
      {
        DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
            profileLevelType->nProfileIndex);
        eRet = OMX_ErrorNoMore;
      }
    }
    else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263)
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
        profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
      }
      else
      {
        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
        eRet = OMX_ErrorNoMore;
      }
    }
    else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
        profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
      }
      else if(profileLevelType->nProfileIndex == 1)
      {
        profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
        profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
      }
      else
      {
        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
        eRet = OMX_ErrorNoMore;
      }
    }
  }
  else
  {
    DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex);
    eRet = OMX_ErrorBadPortIndex;
  }
  DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d\n",
                    profileLevelType->eProfile,profileLevelType->eLevel);
  return eRet;
}
#endif

#ifdef MAX_RES_1080P
OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if(!profileLevelType)
    return OMX_ErrorBadParameter;

  if(profileLevelType->nPortIndex == 1) {
    if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
        profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;

      }
      else if (profileLevelType->nProfileIndex == 1)
      {
        profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
        profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
      }
      else if(profileLevelType->nProfileIndex == 2)
      {
        profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
        profileLevelType->eLevel   = OMX_VIDEO_AVCLevel4;
      }
      else
      {
        DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
            profileLevelType->nProfileIndex);
        eRet = OMX_ErrorNoMore;
      }
    }
    else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263)
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
        profileLevelType->eLevel   = OMX_VIDEO_H263Level70;
      }
      else
      {
        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
        eRet = OMX_ErrorNoMore;
      }
    }
    else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
        profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
      }
      else if(profileLevelType->nProfileIndex == 1)
      {
        profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
        profileLevelType->eLevel   = OMX_VIDEO_MPEG4Level5;
      }
      else
      {
        DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex);
        eRet = OMX_ErrorNoMore;
      }
    }
  }
  else
  {
    DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex);
    eRet = OMX_ErrorBadPortIndex;
  }
  DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d\n",
                    profileLevelType->eProfile,profileLevelType->eLevel);
  return eRet;
}

#ifdef USE_ION
int omx_video::alloc_map_ion_memory(int size,struct ion_allocation_data *alloc_data,
                                    struct ion_fd_data *fd_data,int flag)
{
  struct venc_ion buf_ion_info;
  int ion_device_fd =-1,rc=0,ion_dev_flags = 0;
  if (size <=0 || !alloc_data || !fd_data) {
    DEBUG_PRINT_ERROR("\nInvalid input to alloc_map_ion_memory");
    return -EINVAL;
	}
    ion_dev_flags = O_RDONLY;
        ion_device_fd = open (MEM_DEVICE,ion_dev_flags);
        if(ion_device_fd < 0)
        {
           DEBUG_PRINT_ERROR("\nERROR: ION Device open() Failed");
           return ion_device_fd;
        }
        alloc_data->len = size;
        alloc_data->align = 4096;
        alloc_data->flags = 0;
        if(!secure_session && (flag & ION_FLAG_CACHED))
        {
          alloc_data->flags = ION_FLAG_CACHED;
        }

        if (secure_session)
           alloc_data->heap_mask = (ION_HEAP(MEM_HEAP_ID) | ION_SECURE);
        else
           alloc_data->heap_mask = (ION_HEAP(MEM_HEAP_ID) |
                ION_HEAP(ION_IOMMU_HEAP_ID));

        rc = ioctl(ion_device_fd,ION_IOC_ALLOC,alloc_data);
        if(rc || !alloc_data->handle) {
           DEBUG_PRINT_ERROR("\n ION ALLOC memory failed ");
           alloc_data->handle =NULL;
           close(ion_device_fd);
           ion_device_fd = -1;
           return ion_device_fd;
        }
        fd_data->handle = alloc_data->handle;
        rc = ioctl(ion_device_fd,ION_IOC_MAP,fd_data);
        if(rc) {
            DEBUG_PRINT_ERROR("\n ION MAP failed ");
            buf_ion_info.ion_alloc_data = *alloc_data;
            buf_ion_info.ion_device_fd = ion_device_fd;
            buf_ion_info.fd_ion_data = *fd_data;
            free_ion_memory(&buf_ion_info);
            fd_data->fd =-1;
            ion_device_fd =-1;
        }
        return ion_device_fd;
}

void omx_video::free_ion_memory(struct venc_ion *buf_ion_info)
{
     if (!buf_ion_info) {
        DEBUG_PRINT_ERROR("\n Invalid input to free_ion_memory");
        return;
     }
     if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
              &buf_ion_info->ion_alloc_data.handle)) {
         DEBUG_PRINT_ERROR("\n ION free failed ");
         return;
     }
     close(buf_ion_info->ion_device_fd);
     buf_ion_info->ion_alloc_data.handle = NULL;
     buf_ion_info->ion_device_fd = -1;
     buf_ion_info->fd_ion_data.fd = -1;
}
#endif
#endif
#ifdef _ANDROID_ICS_
void omx_video::omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer)
{
  if(buffer && meta_mode_enable)
  {
    encoder_media_buffer_type *media_ptr;
    struct pmem Input_pmem;
    unsigned int index_pmem = 0;
    bool meta_error = false;

    index_pmem = (buffer - m_inp_mem_ptr);
    if(mUseProxyColorFormat &&
       (index_pmem < m_sInPortDef.nBufferCountActual)) {
        if(!dev_free_buf((&m_pInput_pmem[index_pmem]),PORT_INDEX_IN)){
          DEBUG_PRINT_ERROR("\n omx_release_meta_buffer dev free failed");
        }
    } else {
      media_ptr = (encoder_media_buffer_type *) buffer->pBuffer;
      if(media_ptr && media_ptr->meta_handle)
      {
        if(media_ptr->buffer_type == kMetadataBufferTypeCameraSource &&
           media_ptr->meta_handle->numFds == 1 &&
           media_ptr->meta_handle->numInts == 2) {
          Input_pmem.fd = media_ptr->meta_handle->data[0];
          Input_pmem.buffer = media_ptr;
          Input_pmem.size = media_ptr->meta_handle->data[2];
          Input_pmem.offset = media_ptr->meta_handle->data[1];
          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) {
          private_handle_t *handle = (private_handle_t *)media_ptr->meta_handle;
          Input_pmem.buffer = media_ptr;
          Input_pmem.fd = handle->fd;
          Input_pmem.offset = 0;
          Input_pmem.size = handle->size;
        } else {
          meta_error = true;
          DEBUG_PRINT_ERROR(" Meta Error set in EBD");
        }
        if(!meta_error)
           meta_error = !dev_free_buf(&Input_pmem,PORT_INDEX_IN);
          if(meta_error)
          {
           DEBUG_PRINT_ERROR(" Warning dev_free_buf failed flush value is %d",
               input_flush_progress);
          }
        }
     }
  }
}
#endif
omx_video::omx_c2d_conv::omx_c2d_conv()
{
  c2dcc = NULL;
  mLibHandle = NULL;
  mConvertOpen = NULL;
  mConvertClose = NULL;
  src_format = NV12_2K;
}

bool omx_video::omx_c2d_conv::init() {
  bool status = true;
  if(mLibHandle || mConvertOpen || mConvertClose) {
    DEBUG_PRINT_ERROR("\n omx_c2d_conv::init called twice");
    status = false;
  }
  if(status) {
    mLibHandle = dlopen("libc2dcolorconvert.so", RTLD_LAZY);
    if(mLibHandle){
       mConvertOpen = (createC2DColorConverter_t *)
       dlsym(mLibHandle,"createC2DColorConverter");
       mConvertClose = (destroyC2DColorConverter_t *)
       dlsym(mLibHandle,"destroyC2DColorConverter");
       if(!mConvertOpen || !mConvertClose)
         status = false;
    } else
      status = false;
  }
  if(!status && mLibHandle){
    dlclose(mLibHandle);
    mLibHandle = NULL;
    mConvertOpen = NULL;
    mConvertClose = NULL;
  }
  return status;
}

bool omx_video::omx_c2d_conv::convert(int src_fd, void *src_viraddr,
     int dest_fd,void *dest_viraddr)
{
  int result;
  if(!src_viraddr || !dest_viraddr || !c2dcc){
    DEBUG_PRINT_ERROR("\n Invalid arguments omx_c2d_conv::convert");
    return false;
  }
  result =  c2dcc->convertC2D(src_fd,src_viraddr,
                              dest_fd,dest_viraddr);
  DEBUG_PRINT_LOW("\n Color convert status %d",result);
  return ((result < 0)?false:true);
}

bool omx_video::omx_c2d_conv::open(unsigned int height,unsigned int width,
     ColorConvertFormat src, ColorConvertFormat dest)
{
  bool status = false;
  if(!c2dcc) {
     c2dcc = mConvertOpen(width, height, width, height,
             src,dest,0);
     if(c2dcc) {
       src_format = src;
       status = true;
     } else
       DEBUG_PRINT_ERROR("\n mConvertOpen failed");
  }
   return status;
}
void omx_video::omx_c2d_conv::close()
{
  if(mLibHandle) {
    if(mConvertClose && c2dcc)
     mConvertClose(c2dcc);
    c2dcc = NULL;
  }
}
omx_video::omx_c2d_conv::~omx_c2d_conv()
{
  DEBUG_PRINT_ERROR("\n Destroy C2D instance");
  if(mLibHandle) {
    if(mConvertClose && c2dcc)
      mConvertClose(c2dcc);
    dlclose(mLibHandle);
  }
  c2dcc = NULL;
  mLibHandle = NULL;
  mConvertOpen = NULL;
  mConvertClose = NULL;
}
int omx_video::omx_c2d_conv::get_src_format()
{
  int format = -1;
  if(src_format == NV12_2K) {
    format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE;
  } else if(src_format == RGBA8888) {
    format = HAL_PIXEL_FORMAT_RGBA_8888;
  }
  return format;
}
bool omx_video::omx_c2d_conv::get_buffer_size(int port,unsigned int &buf_size)
{
  int cret = 0;
  bool ret = false;
  C2DBuffReq bufferreq;
  if(c2dcc){
    bufferreq.size = 0;
    cret = c2dcc->getBuffReq(port,&bufferreq);
    DEBUG_PRINT_LOW("\n Status of getbuffer is %d", cret);
    ret = (cret)?false:true;
    buf_size = bufferreq.size;
  }
  return ret;
}
OMX_ERRORTYPE  omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp,
                                                  OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
  unsigned nBufIndex = 0;
  OMX_ERRORTYPE ret = OMX_ErrorNone;
  encoder_media_buffer_type *media_buffer;
  DEBUG_PRINT_LOW("\n ETBProxyOpaque: buffer[%p]\n", buffer);

  if(buffer == NULL) {
    DEBUG_PRINT_ERROR("\nERROR: ETBProxyA: Invalid buffer[%p]\n",buffer);
    return OMX_ErrorBadParameter;
  }
  nBufIndex = buffer - meta_buffer_hdr;
  if(nBufIndex >= m_sInPortDef.nBufferCountActual) {
    DEBUG_PRINT_ERROR("\nERROR: ETBProxyA: Invalid bufindex = %u\n",
                      nBufIndex);
    return OMX_ErrorBadParameter;
  }
  media_buffer = (encoder_media_buffer_type *)buffer->pBuffer;
  private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle;
  /*Enable following code once private handle color format is
    updated correctly*/

  if(buffer->nFilledLen > 0) {
    if(c2d_opened && handle->format != c2d_conv.get_src_format()) {
      c2d_conv.close();
      c2d_opened = false;
    }
    if (!c2d_opened) {
        if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) {
          DEBUG_PRINT_ERROR("\n open Color conv for RGBA888");
          if(!c2d_conv.open(m_sInPortDef.format.video.nFrameHeight,
               m_sInPortDef.format.video.nFrameWidth,RGBA8888,NV12_2K)){
             m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
             DEBUG_PRINT_ERROR("\n Color conv open failed");
             return OMX_ErrorBadParameter;
          }
          c2d_opened = true;
        } else if(handle->format != HAL_PIXEL_FORMAT_NV12_ENCODEABLE) {
          DEBUG_PRINT_ERROR("\n Incorrect color format");
          m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
          return OMX_ErrorBadParameter;
        }
    }
  }

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

  if(!psource_frame) {
    psource_frame = buffer;
    ret = push_input_buffer(hComp);
  } else {
    if (!m_opq_meta_q.insert_entry((unsigned)buffer,0,0)) {
      DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Queue is full");
      ret = OMX_ErrorBadParameter;
    }
  }
  if(ret != OMX_ErrorNone) {
    m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer);
    DEBUG_PRINT_LOW("\nERROR: ETBOpaque failed:");
  }
  return ret;
}
OMX_ERRORTYPE omx_video::queue_meta_buffer(OMX_HANDLETYPE hComp,
     struct pmem &Input_pmem_info) {

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

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

  if(psource_frame->nFilledLen > 0) {
   if(dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) {
     DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf");
     post_event ((unsigned int)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;
    }
  }
  return ret;
}

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

  unsigned char *uva;
  OMX_ERRORTYPE ret = OMX_ErrorNone;
  unsigned address = 0,p2,id;

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

  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("\n Skipping color conversion for empty EOS \
          Buffer header=%p filled-len=%d", pdest_frame,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("\n Buffer header %p Filled len size %d",
           pdest_frame,pdest_frame->nFilledLen);
    }
  } else {
     uva = (unsigned char *)mmap(NULL, Input_pmem_info.size,
                           PROT_READ|PROT_WRITE,
                           MAP_SHARED,Input_pmem_info.fd,0);
     if(uva == MAP_FAILED) {
       ret = OMX_ErrorBadParameter;
     } else {
       if(!c2d_conv.convert(Input_pmem_info.fd,uva,
          m_pInput_pmem[index].fd,pdest_frame->pBuffer)) {
          DEBUG_PRINT_ERROR("\n Color Conversion failed");
          ret = OMX_ErrorBadParameter;
       } else {
          unsigned int buf_size = 0;
          if (!c2d_conv.get_buffer_size(C2D_OUTPUT,buf_size))
            ret = OMX_ErrorBadParameter;
          else {
            pdest_frame->nOffset = 0;
            if(!buf_size || buf_size > pdest_frame->nAllocLen) {
              DEBUG_PRINT_ERROR("\n convert_queue_buffer buffer"
               "size mismatch buf size %d alloc size %d",
                      buf_size, pdest_frame->nAllocLen);
              ret = OMX_ErrorBadParameter;
              buf_size = 0;
            }
            pdest_frame->nFilledLen = buf_size;
            pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
            pdest_frame->nFlags = psource_frame->nFlags;
            DEBUG_PRINT_LOW("\n Buffer header %p Filled len size %d",
               pdest_frame,pdest_frame->nFilledLen);
           }
         }
         munmap(uva,Input_pmem_info.size);
      }
    }
    if((ret == OMX_ErrorNone) &&
       dev_use_buf(&m_pInput_pmem[index],PORT_INDEX_IN,0) != true) {
      DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf");
      post_event ((unsigned int)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("\n pdest_frame pop address is %p",pdest_frame);
      }
    }
    return ret;
}

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

  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;
    encoder_media_buffer_type *media_buffer;
    index = pdest_frame - m_inp_mem_ptr;
    if(index >= m_sInPortDef.nBufferCountActual){
       DEBUG_PRINT_ERROR("\n Output buffer index is wrong %d act count %d",
                         index,m_sInPortDef.nBufferCountActual);
       return OMX_ErrorBadParameter;
    }
    media_buffer = (encoder_media_buffer_type *)psource_frame->pBuffer;
    /*Will enable to verify camcorder in current TIPS can be removed*/
    if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource) {
      Input_pmem_info.buffer = media_buffer;
      Input_pmem_info.fd = media_buffer->meta_handle->data[0];
      Input_pmem_info.offset = media_buffer->meta_handle->data[1];
      Input_pmem_info.size = media_buffer->meta_handle->data[2];
      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,Input_pmem_info);
    } else if(psource_frame->nFlags & OMX_BUFFERFLAG_EOS & mUseProxyColorFormat) {
       ret = convert_queue_buffer(hComp,Input_pmem_info,index);
    } else {
      private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle;
      Input_pmem_info.buffer = media_buffer;
      Input_pmem_info.fd = handle->fd;
      Input_pmem_info.offset = 0;
      Input_pmem_info.size = handle->size;
      if(handle->format == HAL_PIXEL_FORMAT_RGBA_8888)
        ret = convert_queue_buffer(hComp,Input_pmem_info,index);
      else if(handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE)
        ret = queue_meta_buffer(hComp,Input_pmem_info);
      else
        ret = OMX_ErrorBadParameter;
    }
   }
  return ret;
}