/*--------------------------------------------------------------------------
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_vdec.cpp
  This module contains the implementation of the OpenMAX core & component.

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

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

#include <string.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "omx_vdec.h"
#include <fcntl.h>
#include <limits.h>

#ifndef _ANDROID_
#include <sys/ioctl.h>
#include <sys/mman.h>
#endif //_ANDROID_

#ifdef _ANDROID_
#include <cutils/properties.h>
#undef USE_EGL_IMAGE_GPU
#endif

#if  defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
#include <gralloc_priv.h>
#endif

#ifdef _ANDROID_
#include "DivXDrmDecrypt.h"
#endif //_ANDROID_

#ifdef USE_EGL_IMAGE_GPU
#include <EGL/egl.h>
#include <EGL/eglQCOM.h>
#define EGL_BUFFER_HANDLE_QCOM 0x4F00
#define EGL_BUFFER_OFFSET_QCOM 0x4F01
#endif

#ifdef INPUT_BUFFER_LOG
#define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0"
#define INPUT_BUFFER_FILE_NAME_LEN 30
FILE *inputBufferFile1;
char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0";
#endif
#ifdef OUTPUT_BUFFER_LOG
FILE *outputBufferFile1;
char outputfilename [] = "/data/output.yuv";
#endif
#ifdef OUTPUT_EXTRADATA_LOG
FILE *outputExtradataFile;
char ouputextradatafilename [] = "/data/extradata";
#endif

#define DEFAULT_FPS 30
#define MAX_NUM_SPS 32
#define MAX_NUM_PPS 256
#define MAX_INPUT_ERROR (MAX_NUM_SPS + MAX_NUM_PPS)
#define MAX_SUPPORTED_FPS 120

#define VC1_SP_MP_START_CODE        0xC5000000
#define VC1_SP_MP_START_CODE_MASK   0xFF000000
#define VC1_AP_SEQ_START_CODE       0x0F010000
#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

#ifdef USE_ION
    #define MEM_DEVICE "/dev/ion"
    #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
#elif MAX_RES_720P
#define MEM_DEVICE "/dev/pmem_adsp"
#elif MAX_RES_1080P_EBI
#define MEM_DEVICE "/dev/pmem_adsp"
#elif MAX_RES_1080P
#define MEM_DEVICE "/dev/pmem_smipool"
#endif

/*
#ifdef _ANDROID_
    extern "C"{
        #include<utils/Log.h>
    }
#endif//_ANDROID_
*/

#undef DEBUG_PRINT_LOW
#undef DEBUG_PRINT_HIGH
#undef DEBUG_PRINT_ERROR

#define DEBUG_PRINT_LOW ALOGV
#define DEBUG_PRINT_HIGH ALOGV
#define DEBUG_PRINT_ERROR ALOGE

#ifndef _ANDROID_
#include <glib.h>
#define strlcpy g_strlcpy
#endif

#define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }

bool omx_vdec::m_secure_display = false;

void* async_message_thread (void *input)
{
  struct vdec_ioctl_msg ioctl_msg;
  struct vdec_msginfo vdec_msg;
  omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
  int error_code = 0;
  DEBUG_PRINT_HIGH("omx_vdec: Async thread start\n");
  prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
  while (1)
  {
    ioctl_msg.in = NULL;
    ioctl_msg.out = (void*)&vdec_msg;
    /*Wait for a message from the video decoder driver*/
    error_code = ioctl ( omx->drv_ctx.video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG,
                         (void*)&ioctl_msg);
    if (error_code == -512) // ERESTARTSYS
    {
      DEBUG_PRINT_ERROR("\n ERESTARTSYS received in ioctl read next msg!");
    }
    else if (error_code < 0)
    {
      DEBUG_PRINT_ERROR("\n Error in ioctl read next msg");
      break;
    }        /*Call Instance specific process function*/
    else if (omx->async_message_process(input,&vdec_msg) < 0)
    {
      DEBUG_PRINT_ERROR("\nERROR:Wrong ioctl message");
    }
  }
  DEBUG_PRINT_HIGH("omx_vdec: Async thread stop\n");
  return NULL;
}

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

  DEBUG_PRINT_HIGH("omx_vdec: message thread start\n");
  prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 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);
    }
    if ((n < 0) && (errno != EINTR))
    {
      DEBUG_PRINT_ERROR("\nERROR: read from pipe failed, ret %d errno %d", n, errno);
      break;
    }
  }
  DEBUG_PRINT_HIGH("omx_vdec: message thread stop\n");
  return 0;
}

void post_message(omx_vdec *omx, unsigned char id)
{
      int ret_value;
      DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d\n", id,omx->m_pipe_out);
      ret_value = write(omx->m_pipe_out, &id, 1);
      DEBUG_PRINT_LOW("post_message to pipe done %d\n",ret_value);
}

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

// omx cmd queue constructor
omx_vdec::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_vdec::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: %s()::Command Queue Full\n", __func__);
  }
  return ret;
}

// omx cmd queue pop
bool omx_vdec::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_vdec::omx_cmd_queue::get_q_msg_type()
{
    return m_q[m_read].id;
}

#ifdef _ANDROID_
omx_vdec::ts_arr_list::ts_arr_list()
{
  //initialize timestamps array
  memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
}
omx_vdec::ts_arr_list::~ts_arr_list()
{
  //free m_ts_arr_list?
}

bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
{
  bool ret = true;
  bool duplicate_ts = false;
  int idx = 0;

  //insert at the first available empty location
  for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
  {
    if (!m_ts_arr_list[idx].valid)
    {
      //found invalid or empty entry, save timestamp
      m_ts_arr_list[idx].valid = true;
      m_ts_arr_list[idx].timestamp = ts;
      DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
                       ts, idx);
      break;
    }
  }

  if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS)
  {
    DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
    ret = false;
  }
  return ret;
}

bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
{
  bool ret = true;
  int min_idx = -1;
  OMX_TICKS min_ts = 0;
  int idx = 0;

  for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
  {

    if (m_ts_arr_list[idx].valid)
    {
      //found valid entry, save index
      if (min_idx < 0)
      {
        //first valid entry
        min_ts = m_ts_arr_list[idx].timestamp;
        min_idx = idx;
      }
      else if (m_ts_arr_list[idx].timestamp < min_ts)
      {
        min_ts = m_ts_arr_list[idx].timestamp;
        min_idx = idx;
      }
    }

  }

  if (min_idx < 0)
  {
    //no valid entries found
    DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
    ts = 0;
    ret = false;
  }
  else
  {
    ts = m_ts_arr_list[min_idx].timestamp;
    m_ts_arr_list[min_idx].valid = false;
    DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
                     ts, min_idx);
  }

  return ret;

}


bool omx_vdec::ts_arr_list::reset_ts_list()
{
  bool ret = true;
  int idx = 0;

  DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
  for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++)
  {
    m_ts_arr_list[idx].valid = false;
  }
  return ret;
}
#endif

// factory function executed by the core to create instances
void *get_omx_component_factory_fn(void)
{
  return (new omx_vdec);
}

#ifdef _ANDROID_
#ifdef USE_ION
VideoHeap::VideoHeap(int devicefd, size_t size, void* base,
                     struct ion_handle *handle, int ionMapfd)
{
    m_ion_device_fd = devicefd;
    m_ion_handle = handle;
    MemoryHeapBase::init(ionMapfd, base, size, 0, MEM_DEVICE);
    //ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd);
}
#else
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
#endif // _ANDROID_
/* ======================================================================
FUNCTION
  omx_vdec::omx_vdec

DESCRIPTION
  Constructor

PARAMETERS
  None

RETURN VALUE
  None.
========================================================================== */
omx_vdec::omx_vdec(): m_state(OMX_StateInvalid),
                      m_app_data(NULL),
                      m_inp_mem_ptr(NULL),
                      m_out_mem_ptr(NULL),
                      m_phdr_pmem_ptr(NULL),
                      pending_input_buffers(0),
                      pending_output_buffers(0),
                      m_out_bm_count(0),
                      m_inp_bm_count(0),
                      m_inp_bPopulated(OMX_FALSE),
                      m_out_bPopulated(OMX_FALSE),
                      m_flags(0),
                      m_inp_bEnabled(OMX_TRUE),
                      m_out_bEnabled(OMX_TRUE),
                      m_platform_list(NULL),
                      m_platform_entry(NULL),
                      m_pmem_info(NULL),
                      output_flush_progress (false),
                      input_flush_progress (false),
                      input_use_buffer (false),
                      output_use_buffer (false),
                      arbitrary_bytes (true),
                      psource_frame (NULL),
                      pdest_frame (NULL),
                      m_inp_heap_ptr (NULL),
                      m_heap_inp_bm_count (0),
                      codec_type_parse ((codec_type)0),
                      first_frame_meta (true),
                      frame_count (0),
                      nal_length(0),
                      nal_count (0),
                      look_ahead_nal (false),
                      first_frame(0),
                      first_buffer(NULL),
                      first_frame_size (0),
                      m_error_propogated(false),
                      m_device_file_ptr(NULL),
                      m_vc1_profile((vc1_profile_type)0),
                      prev_ts(LLONG_MAX),
                      rst_prev_ts(true),
                      frm_int(0),
                      m_in_alloc_cnt(0),
                      m_display_id(NULL),
                      ouput_egl_buffers(false),
                      h264_parser(NULL),
                      client_extradata(0),
                      h264_last_au_ts(LLONG_MAX),
                      h264_last_au_flags(0),
                      m_inp_err_count(0),
#ifdef _ANDROID_
                      m_heap_ptr(NULL),
                      m_heap_count(0),
                      m_enable_android_native_buffers(OMX_FALSE),
                      m_use_android_native_buffers(OMX_FALSE),
#endif
                      in_reconfig(false),
                      m_use_output_pmem(OMX_FALSE),
                      m_out_mem_region_smi(OMX_FALSE),
                      m_out_pvt_entry_pmem(OMX_FALSE),
                      secure_mode(false)
#ifdef _ANDROID_
                    ,iDivXDrmDecrypt(NULL)
#endif
                    ,m_desc_buffer_ptr(NULL)
                    ,m_extradata(NULL)
{
  /* Assumption is that , to begin with , we have all the frames with decoder */
  DEBUG_PRINT_HIGH("In OMX vdec Constructor");
#ifdef _ANDROID_
  char property_value[PROPERTY_VALUE_MAX] = {0};
  property_get("vidc.dec.debug.perf", property_value, "0");
  perf_flag = atoi(property_value);
  if (perf_flag)
  {
    DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag);
    dec_time.start();
    proc_frms = latency = 0;
  }
  property_value[0] = NULL;
  property_get("vidc.dec.debug.ts", property_value, "0");
  m_debug_timestamp = atoi(property_value);
  DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp);
  if (m_debug_timestamp)
  {
    time_stamp_dts.set_timestamp_reorder_mode(true);
    time_stamp_dts.enable_debug_print(true);
  }

  property_value[0] = NULL;
  property_get("vidc.dec.debug.concealedmb", property_value, "0");
  m_debug_concealedmb = atoi(property_value);
  DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb);

#endif
  memset(&m_cmp,0,sizeof(m_cmp));
  memset(&m_cb,0,sizeof(m_cb));
  memset (&drv_ctx,0,sizeof(drv_ctx));
  memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
  memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
  memset(&op_buf_rcnfg, 0 ,sizeof(vdec_allocatorproperty));
  memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
  m_demux_entries = 0;
  drv_ctx.timestamp_adjust = false;
  drv_ctx.video_driver_fd = -1;
  m_vendor_config.pData = NULL;
  pthread_mutex_init(&m_lock, NULL);
  sem_init(&m_cmd_lock,0,0);
#ifdef _ANDROID_
  char extradata_value[PROPERTY_VALUE_MAX] = {0};
  property_get("vidc.dec.debug.extradata", extradata_value, "0");
  m_debug_extradata = atoi(extradata_value);
  DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata);
#endif
  m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
  client_buffers.set_vdec_client(this);
}


/* ======================================================================
FUNCTION
  omx_vdec::~omx_vdec

DESCRIPTION
  Destructor

PARAMETERS
  None

RETURN VALUE
  None.
========================================================================== */
omx_vdec::~omx_vdec()
{
  m_pmem_info = NULL;
  DEBUG_PRINT_HIGH("In OMX vdec Destructor");
  if(m_pipe_in) close(m_pipe_in);
  if(m_pipe_out) close(m_pipe_out);
  m_pipe_in = -1;
  m_pipe_out = -1;
  DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
  pthread_join(msg_thread_id,NULL);
  DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
  pthread_join(async_thread_id,NULL);
  pthread_mutex_destroy(&m_lock);
  sem_destroy(&m_cmd_lock);
#ifdef _ANDROID_
  if (perf_flag)
  {
    DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
    dec_time.end();
  }
#endif /* _ANDROID_ */
  DEBUG_PRINT_HIGH("Exit OMX vdec Destructor");
}

/* ======================================================================
FUNCTION
  omx_vdec::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_vdec::process_event_cb(void *ctxt, unsigned char id)
{
  unsigned p1; // Parameter - 1
  unsigned p2; // Parameter - 2
  unsigned ident;
  unsigned qsize=0; // qsize
  omx_vdec *pThis = (omx_vdec *) ctxt;

  if(!pThis)
  {
    DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out\n",
        __func__);
    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 && pThis->m_state != OMX_StatePause)
    {
      qsize = pThis->m_ftb_q.m_size;
      if (qsize)
      {
        pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
      }
    }

    if (qsize == 0 && pThis->m_state != OMX_StatePause)
    {
      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_cb.EventHandler)
          {
            switch (p1)
            {
              case OMX_CommandStateSet:
                pThis->m_state = (OMX_STATETYPE) p2;
                DEBUG_PRINT_HIGH("\n OMX_CommandStateSet complete, m_state = %d",
                    pThis->m_state);
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                      OMX_EventCmdComplete, p1, p2, NULL);
                break;

              case OMX_EventError:
                if(p2 == OMX_StateInvalid)
                {
                    DEBUG_PRINT_ERROR("\n OMX_EventError: p2 is OMX_StateInvalid");
                    pThis->m_state = (OMX_STATETYPE) p2;
                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                               OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
                }
                else if (p2 == OMX_ErrorHardware)
                {
                   pThis->omx_report_error();
                }
                else
                {
                    pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                      OMX_EventError, p2, NULL, NULL );
                }
                break;

              case OMX_CommandPortDisable:
                DEBUG_PRINT_HIGH("\n OMX_CommandPortDisable complete for port [%d]", p2);
                if (BITMASK_PRESENT(&pThis->m_flags,
                    OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING))
                {
                  BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
                  break;
                }
                if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig)
                {
                  pThis->in_reconfig = false;
                  pThis->drv_ctx.op_buf = pThis->op_buf_rcnfg;
                  OMX_ERRORTYPE eRet = pThis->set_buffer_req(&pThis->drv_ctx.op_buf);
                  if(eRet !=  OMX_ErrorNone)
                  {
                      DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
                      pThis->omx_report_error();
                      break;
                  }
                }
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                      OMX_EventCmdComplete, p1, p2, NULL );
                break;
              case OMX_CommandPortEnable:
                DEBUG_PRINT_HIGH("\n OMX_CommandPortEnable complete for port [%d]", p2);
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
                                      OMX_EventCmdComplete, p1, p2, NULL );
                break;

              default:
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                         OMX_EventCmdComplete, p1, p2, NULL );
                break;

            }
          }
          else
          {
            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL\n", __func__);
          }
          break;
        case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
          if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
              (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
          {
            DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
            pThis->omx_report_error ();
          }
      break;
        case OMX_COMPONENT_GENERATE_ETB:
          if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
              (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
          {
            DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
            pThis->omx_report_error ();
          }
         break;

        case OMX_COMPONENT_GENERATE_FTB:
          if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
               (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
          {
             DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure");
             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 (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR)
          {
            DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EBD failure");
            pThis->omx_report_error ();
          }
          else
          {
            if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1)
            {
              pThis->m_inp_err_count++;
              pThis->time_stamp_dts.remove_time_stamp(
              ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp,
              (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
                ?true:false);
            }
            else
            {
              pThis->m_inp_err_count = 0;
            }
            if ( pThis->empty_buffer_done(&pThis->m_cmp,
                 (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
            {
               DEBUG_PRINT_ERROR("\n empty_buffer_done failure");
               pThis->omx_report_error ();
            }
            if(!pThis->arbitrary_bytes && pThis->m_inp_err_count > MAX_INPUT_ERROR)
            {
               DEBUG_PRINT_ERROR("\n Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR);
               pThis->omx_report_error ();
            }
          }
          break;
        case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED:
          {
            int64_t *timestamp = (int64_t *)p1;
            if (p1)
            {
              pThis->time_stamp_dts.remove_time_stamp(*timestamp,
              (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
              ?true:false);
              free(timestamp);
            }
          }
          break;
        case OMX_COMPONENT_GENERATE_FBD:
          if (p2 != VDEC_S_SUCCESS)
          {
            DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_FBD failure");
            pThis->omx_report_error ();
          }
          else if ( pThis->fill_buffer_done(&pThis->m_cmp,
                  (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
          {
            DEBUG_PRINT_ERROR("\n fill_buffer_done failure");
            pThis->omx_report_error ();
          }
          break;

        case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
          DEBUG_PRINT_HIGH("\n Driver flush i/p Port complete");
          if (!pThis->input_flush_progress)
          {
            DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver");
          }
          else
          {
            pThis->execute_input_flush();
            if (pThis->m_cb.EventHandler)
            {
              if (p2 != VDEC_S_SUCCESS)
              {
                DEBUG_PRINT_ERROR("\nOMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
                pThis->omx_report_error ();
              }
              else
              {
                /*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);
                  DEBUG_PRINT_LOW("\n Input Flush completed - Notify Client");
                  pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                           OMX_EventCmdComplete,OMX_CommandFlush,
                                           OMX_CORE_INPUT_PORT_INDEX,NULL );
                }
                if (BITMASK_PRESENT(&pThis->m_flags,
                                         OMX_COMPONENT_IDLE_PENDING))
                {
                  if (!pThis->output_flush_progress)
                  {
                     DEBUG_PRINT_LOW("\n Output flush done hence issue stop");
                     if (ioctl (pThis->drv_ctx.video_driver_fd,
                                VDEC_IOCTL_CMD_STOP,NULL ) < 0)
                     {
                       DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed");
                       pThis->omx_report_error ();
                     }
                  }
                }
              }
            }
            else
            {
              DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
            }
          }
          break;

        case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
          DEBUG_PRINT_HIGH("\n Driver flush o/p Port complete");
          if (!pThis->output_flush_progress)
          {
            DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver");
          }
          else
          {
            pThis->execute_output_flush();
            if (pThis->m_cb.EventHandler)
            {
              if (p2 != VDEC_S_SUCCESS)
              {
                DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
                pThis->omx_report_error ();
              }
              else
              {
                /*Check if we need generate event for Flush done*/
                if(BITMASK_PRESENT(&pThis->m_flags,
                                   OMX_COMPONENT_OUTPUT_FLUSH_PENDING))
                {
                  DEBUG_PRINT_LOW("\n Notify Output Flush done");
                  BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
                  pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                           OMX_EventCmdComplete,OMX_CommandFlush,
                                           OMX_CORE_OUTPUT_PORT_INDEX,NULL );
                }
                if(BITMASK_PRESENT(&pThis->m_flags,
                       OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING))
                {
                  DEBUG_PRINT_LOW("\n Internal flush complete");
                  BITMASK_CLEAR (&pThis->m_flags,
                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
                  if (BITMASK_PRESENT(&pThis->m_flags,
                          OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED))
                  {
                    pThis->post_event(OMX_CommandPortDisable,
                               OMX_CORE_OUTPUT_PORT_INDEX,
                               OMX_COMPONENT_GENERATE_EVENT);
                    BITMASK_CLEAR (&pThis->m_flags,
                                   OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);

                  }
                }

                if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING))
                {
                  if (!pThis->input_flush_progress)
                  {
                    DEBUG_PRINT_LOW("\n Input flush done hence issue stop");
                    if (ioctl (pThis->drv_ctx.video_driver_fd,
                               VDEC_IOCTL_CMD_STOP,NULL ) < 0)
                    {
                      DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed");
                      pThis->omx_report_error ();
                    }
                  }
                }
              }
            }
            else
            {
              DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
            }
          }
          break;

        case OMX_COMPONENT_GENERATE_START_DONE:
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_START_DONE");

          if (pThis->m_cb.EventHandler)
          {
            if (p2 != VDEC_S_SUCCESS)
            {
              DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_START_DONE Failure");
              pThis->omx_report_error ();
            }
            else
            {
              DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success");
              if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
              {
                DEBUG_PRINT_LOW("\n Move to executing");
                // Send the callback now
                BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
                pThis->m_state = OMX_StateExecuting;
                pThis->m_cb.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 (ioctl (pThis->drv_ctx.video_driver_fd,
                           VDEC_IOCTL_CMD_PAUSE,NULL ) < 0)
                {
                  DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_PAUSE failed");
                  pThis->omx_report_error ();
                }
              }
            }
          }
          else
          {
            DEBUG_PRINT_LOW("\n Event Handler callback is NULL");
          }
          break;

        case OMX_COMPONENT_GENERATE_PAUSE_DONE:
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
          if (pThis->m_cb.EventHandler)
          {
            if (p2 != VDEC_S_SUCCESS)
            {
              DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
              pThis->omx_report_error ();
            }
            else
            {
              pThis->complete_pending_buffer_done_cbs();
              if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING))
              {
                DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
                //Send the callback now
                BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
                pThis->m_state = OMX_StatePause;
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                       OMX_EventCmdComplete,OMX_CommandStateSet,
                                       OMX_StatePause, NULL);
              }
            }
          }
          else
          {
            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
          }

          break;

        case OMX_COMPONENT_GENERATE_RESUME_DONE:
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
          if (pThis->m_cb.EventHandler)
          {
            if (p2 != VDEC_S_SUCCESS)
            {
              DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_RESUME_DONE failed");
              pThis->omx_report_error ();
            }
            else
            {
              if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
              {
                DEBUG_PRINT_LOW("\n Moving the decoder to execute state");
                // Send the callback now
                BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
                pThis->m_state = OMX_StateExecuting;
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                                       OMX_EventCmdComplete,OMX_CommandStateSet,
                                       OMX_StateExecuting,NULL);
              }
            }
          }
          else
          {
            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
          }

          break;

        case OMX_COMPONENT_GENERATE_STOP_DONE:
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
          if (pThis->m_cb.EventHandler)
          {
            if (p2 != VDEC_S_SUCCESS)
            {
              DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
              pThis->omx_report_error ();
            }
            else
            {
              pThis->complete_pending_buffer_done_cbs();
              if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING))
              {
                DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE Success");
                // Send the callback now
                BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
                pThis->m_state = OMX_StateIdle;
                DEBUG_PRINT_LOW("\n Move to Idle State");
                pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
                                         OMX_EventCmdComplete,OMX_CommandStateSet,
                                         OMX_StateIdle,NULL);
              }
            }
          }
          else
          {
            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
          }

          break;

        case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG");
          if (pThis->start_port_reconfig() != OMX_ErrorNone)
              pThis->omx_report_error();
          else
          {
            if (pThis->in_reconfig)
            {
              if (pThis->m_cb.EventHandler) {
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                    OMX_EventPortSettingsChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
              } else {
                DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
              }
            }
            if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
            {
              OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1;
              OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged;
              if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
                  format = OMX_InterlaceInterleaveFrameTopFieldFirst;
              else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
                  format = OMX_InterlaceInterleaveFrameBottomFieldFirst;
              else //unsupported interlace format; raise a error
                  event = OMX_EventError;
              if (pThis->m_cb.EventHandler) {
                pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                    event, format, 0, NULL );
              } else {
                DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
              }
            }
          }
        break;

        case OMX_COMPONENT_GENERATE_EOS_DONE:
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
          if (pThis->m_cb.EventHandler) {
            pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
                            OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
          } else {
            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
          }
          pThis->prev_ts = LLONG_MAX;
          pThis->rst_prev_ts = true;
          break;

        case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
          DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
          pThis->omx_report_error ();
          break;
        case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG:
        {
          DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG");
          if (pThis->m_cb.EventHandler) {
            pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
          } else {
            DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
          }
        }
        default:
          break;
        }
      }
    pthread_mutex_lock(&pThis->m_lock);
    qsize = pThis->m_cmd_q.m_size;
    if (pThis->m_state != OMX_StatePause)
        qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
    pthread_mutex_unlock(&pThis->m_lock);
  }
  while(qsize>0);

}



/* ======================================================================
FUNCTION
  omx_vdec::ComponentInit

DESCRIPTION
  Initialize the component.

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.

========================================================================== */
OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
{

  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
  unsigned int   alignment = 0,buffer_size = 0;
  int fds[2];
  int r;
  OMX_STRING device_name = "/dev/msm_vidc_dec";

  if(!strncmp(role, "OMX.qcom.video.decoder.avc.secure",OMX_MAX_STRINGNAME_SIZE)){
      secure_mode = true;
      arbitrary_bytes = false;
      role = "OMX.qcom.video.decoder.avc";
      device_name =  "/dev/msm_vidc_dec_sec";
  }

  if (secure_mode) {
    if (secureDisplay(qService::IQService::START) < 0) {
      DEBUG_PRINT_HIGH("Sending message to start securing display failed");
    }
  }

  DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Start of New Playback : role  = %s : DEVICE = %s",
        role, device_name);

  drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK);

  DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Open returned fd %d, errno %d",
                   drv_ctx.video_driver_fd, errno);

  if(drv_ctx.video_driver_fd == 0){
    drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK);
  }

  if(drv_ctx.video_driver_fd < 0)
  {
      DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d\n", errno);
      eRet = OMX_ErrorInsufficientResources;
      goto cleanup;
  }
  drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
  drv_ctx.frame_rate.fps_denominator = 1;


#ifdef INPUT_BUFFER_LOG
    strcpy(inputfilename, INPUT_BUFFER_FILE_NAME);
#endif
#ifdef OUTPUT_BUFFER_LOG
  outputBufferFile1 = fopen (outputfilename, "ab");
#endif
#ifdef OUTPUT_EXTRADATA_LOG
  outputExtradataFile = fopen (ouputextradatafilename, "ab");
#endif

  // Copy the role information which provides the decoder kind
  strlcpy(drv_ctx.kind,role,128);
  if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\
      OMX_MAX_STRINGNAME_SIZE))
  {
     strlcpy((char *)m_cRole, "video_decoder.mpeg4",\
     OMX_MAX_STRINGNAME_SIZE);
     drv_ctx.timestamp_adjust = true;
     drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4;
     eCompressionFormat = OMX_VIDEO_CodingMPEG4;
     /*Initialize Start Code for MPEG4*/
     codec_type_parse = CODEC_TYPE_MPEG4;
     m_frame_parser.init_start_codes (codec_type_parse);
#ifdef INPUT_BUFFER_LOG
    strcat(inputfilename, "m4v");
#endif
  }
  else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
        OMX_MAX_STRINGNAME_SIZE))
  {
    strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
        OMX_MAX_STRINGNAME_SIZE);
    drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
    eCompressionFormat = OMX_VIDEO_CodingMPEG2;
    /*Initialize Start Code for MPEG2*/
    codec_type_parse = CODEC_TYPE_MPEG2;
    m_frame_parser.init_start_codes (codec_type_parse);
#ifdef INPUT_BUFFER_LOG
    strcat(inputfilename, "mpg");
#endif
  }
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\
         OMX_MAX_STRINGNAME_SIZE))
  {
     strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
     DEBUG_PRINT_LOW("\n H263 Decoder selected");
     drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
     eCompressionFormat = OMX_VIDEO_CodingH263;
     codec_type_parse = CODEC_TYPE_H263;
     m_frame_parser.init_start_codes (codec_type_parse);
#ifdef INPUT_BUFFER_LOG
    strcat(inputfilename, "263");
#endif
  }
#ifdef MAX_RES_1080P
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\
         OMX_MAX_STRINGNAME_SIZE))
  {
     strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
     DEBUG_PRINT_LOW ("\n DIVX 311 Decoder selected");
     drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
     eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
     codec_type_parse = CODEC_TYPE_DIVX;
     m_frame_parser.init_start_codes (codec_type_parse);
#ifdef _ANDROID_
     OMX_ERRORTYPE err = createDivxDrmContext();
     if( err != OMX_ErrorNone ) {
         DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
         eRet = err;
         goto cleanup;
     }
#endif //_ANDROID_
  }
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
         OMX_MAX_STRINGNAME_SIZE))
  {
     strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
     DEBUG_PRINT_ERROR ("\n DIVX 4 Decoder selected");
     drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
     eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
     codec_type_parse = CODEC_TYPE_DIVX;
     m_frame_parser.init_start_codes (codec_type_parse);
#ifdef _ANDROID_
     OMX_ERRORTYPE err = createDivxDrmContext();
     if( err != OMX_ErrorNone ) {
         DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
         eRet = err;
         goto cleanup;
     }
#endif //_ANDROID_
  }
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\
         OMX_MAX_STRINGNAME_SIZE))
  {
     strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
     DEBUG_PRINT_ERROR ("\n DIVX 5/6 Decoder selected");
     drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
     eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
     codec_type_parse = CODEC_TYPE_DIVX;
     m_frame_parser.init_start_codes (codec_type_parse);
#ifdef _ANDROID_
     OMX_ERRORTYPE err = createDivxDrmContext();
     if( err != OMX_ErrorNone ) {
         DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
         eRet = err;
         goto cleanup;
     }
#endif //_ANDROID_
  }
#else
  else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\
         OMX_MAX_STRINGNAME_SIZE)) || (!strncmp(drv_ctx.kind, \
         "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)))
  {
     strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
     DEBUG_PRINT_ERROR ("\n DIVX Decoder selected");
     drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_5;
     eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
     codec_type_parse = CODEC_TYPE_DIVX;
     m_frame_parser.init_start_codes (codec_type_parse);

#ifdef _ANDROID_
     OMX_ERRORTYPE err = createDivxDrmContext();
     if( err != OMX_ErrorNone ) {
         DEBUG_PRINT_ERROR("createDivxDrmContext Failed");
         eRet = err;
         goto cleanup;
     }
#endif //_ANDROID_
  }
#endif
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
         OMX_MAX_STRINGNAME_SIZE))
  {
    strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
    drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
    eCompressionFormat = OMX_VIDEO_CodingAVC;
    codec_type_parse = CODEC_TYPE_H264;
    m_frame_parser.init_start_codes (codec_type_parse);
    m_frame_parser.init_nal_length(nal_length);
#ifdef INPUT_BUFFER_LOG
    strcat(inputfilename, "264");
#endif
  }
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\
         OMX_MAX_STRINGNAME_SIZE))
  {
    strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
    drv_ctx.decoder_format = VDEC_CODECTYPE_VC1;
    eCompressionFormat = OMX_VIDEO_CodingWMV;
    codec_type_parse = CODEC_TYPE_VC1;
    m_frame_parser.init_start_codes (codec_type_parse);
#ifdef INPUT_BUFFER_LOG
    strcat(inputfilename, "vc1");
#endif
  }
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\
         OMX_MAX_STRINGNAME_SIZE))
  {
    strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
    drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV;
    eCompressionFormat = OMX_VIDEO_CodingWMV;
    codec_type_parse = CODEC_TYPE_VC1;
    m_frame_parser.init_start_codes (codec_type_parse);
#ifdef INPUT_BUFFER_LOG
    strcat(inputfilename, "vc1");
#endif
  }
  else
  {
    DEBUG_PRINT_ERROR("\nERROR:Unknown Component\n");
    eRet = OMX_ErrorInvalidComponentName;
  }
#ifdef INPUT_BUFFER_LOG
  inputBufferFile1 = fopen (inputfilename, "ab");
#endif
  if (eRet == OMX_ErrorNone)
  {
#ifdef MAX_RES_720P
    drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;

#endif
#ifdef MAX_RES_1080P
    drv_ctx.output_format = VDEC_YUV_FORMAT_TILE_4x2;
    OMX_COLOR_FORMATTYPE dest_color_format = (OMX_COLOR_FORMATTYPE)
    QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
    if (!client_buffers.set_color_format(dest_color_format)) {
      DEBUG_PRINT_ERROR("\n Setting color format failed");
      eRet = OMX_ErrorInsufficientResources;
    }
#endif
    /*Initialize Decoder with codec type and resolution*/
    ioctl_msg.in = &drv_ctx.decoder_format;
    ioctl_msg.out = NULL;

    if ( (eRet == OMX_ErrorNone) &&
         ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_CODEC,
                (void*)&ioctl_msg) < 0)

    {
      DEBUG_PRINT_ERROR("\n Set codec type failed");
      eRet = OMX_ErrorInsufficientResources;
    }

    /*Set the output format*/
    ioctl_msg.in = &drv_ctx.output_format;
    ioctl_msg.out = NULL;

    if ( (eRet == OMX_ErrorNone) &&
         ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT,
           (void*)&ioctl_msg) < 0)
    {
      DEBUG_PRINT_ERROR("\n Set output format failed");
      eRet = OMX_ErrorInsufficientResources;
    }

#ifdef MAX_RES_720P
    drv_ctx.video_resolution.frame_height =
        drv_ctx.video_resolution.scan_lines = 720;
    drv_ctx.video_resolution.frame_width =
        drv_ctx.video_resolution.stride = 1280;
#endif
#ifdef MAX_RES_1080P
    drv_ctx.video_resolution.frame_height =
        drv_ctx.video_resolution.scan_lines = 1088;
    drv_ctx.video_resolution.frame_width =
        drv_ctx.video_resolution.stride = 1920;
#endif

    ioctl_msg.in = &drv_ctx.video_resolution;
    ioctl_msg.out = NULL;

    if ( (eRet == OMX_ErrorNone) &&
        ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_PICRES,
           (void*)&ioctl_msg) < 0)
    {
      DEBUG_PRINT_ERROR("\n Set Resolution failed");
      eRet = OMX_ErrorInsufficientResources;
    }

    /*Get the Buffer requirements for input and output ports*/
    drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
    drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
    drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
    drv_ctx.extradata = 0;
    drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
    drv_ctx.idr_only_decoding = 0;

    if (eRet == OMX_ErrorNone)
        eRet = get_buffer_req(&drv_ctx.ip_buf);
    if (eRet == OMX_ErrorNone)
        eRet = get_buffer_req(&drv_ctx.op_buf);
    m_state = OMX_StateLoaded;
#ifdef DEFAULT_EXTRADATA
    if (eRet == OMX_ErrorNone && !secure_mode)
      eRet = enable_extradata(DEFAULT_EXTRADATA);
#endif
    if ( (codec_type_parse == CODEC_TYPE_VC1) ||
        (codec_type_parse == CODEC_TYPE_H264)) //add CP check here
    {
      //Check if dmx can be disabled
      struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
      OMX_ERRORTYPE eRet = OMX_ErrorNone;
      ioctl_msg.out = &drv_ctx.disable_dmx;
      if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT, &ioctl_msg))
      {
        DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT");
        eRet = OMX_ErrorHardware;
      }
      else
      {
        if (drv_ctx.disable_dmx && !secure_mode)
        {
          DEBUG_PRINT_HIGH("DMX disable is supported");

          int rc = ioctl(drv_ctx.video_driver_fd,
                      VDEC_IOCTL_SET_DISABLE_DMX);
          if(rc < 0) {
              DEBUG_PRINT_ERROR("Failed to disable dmx on driver.");
              drv_ctx.disable_dmx = false;
              eRet = OMX_ErrorHardware;
          }
        }
        else {
          drv_ctx.disable_dmx = false;
        }
      }
    }
    if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
    {
      if (m_frame_parser.mutils == NULL)
      {
        m_frame_parser.mutils = new H264_Utils();

        if (m_frame_parser.mutils == NULL)
        {
           DEBUG_PRINT_ERROR("\n parser utils Allocation failed ");
           eRet = OMX_ErrorInsufficientResources;
        }
        else
        {
         h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
         h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
         h264_scratch.nFilledLen = 0;
         h264_scratch.nOffset = 0;

         if (h264_scratch.pBuffer == NULL)
         {
           DEBUG_PRINT_ERROR("\n h264_scratch.pBuffer Allocation failed ");
           return OMX_ErrorInsufficientResources;
         }
         m_frame_parser.mutils->initialize_frame_checking_environment();
         m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
       }
      }

      h264_parser = new h264_stream_parser();
      if (!h264_parser)
      {
        DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
        eRet = OMX_ErrorInsufficientResources;
      }
    }

    if(pipe(fds))
    {
      DEBUG_PRINT_ERROR("pipe creation failed\n");
      eRet = OMX_ErrorInsufficientResources;
    }
    else
    {
      int temp1[2];
      if(fds[0] == 0 || fds[1] == 0)
      {
        if (pipe (temp1))
        {
          DEBUG_PRINT_ERROR("pipe creation failed\n");
          return OMX_ErrorInsufficientResources;
        }
        //close (fds[0]);
        //close (fds[1]);
        fds[0] = temp1 [0];
        fds[1] = temp1 [1];
      }
      m_pipe_in = fds[0];
      m_pipe_out = fds[1];
      r = pthread_create(&msg_thread_id,0,message_thread,this);

      if(r < 0)
      {
        DEBUG_PRINT_ERROR("\n component_init(): message_thread creation failed");
        eRet = OMX_ErrorInsufficientResources;
      }
      else
      {
        r = pthread_create(&async_thread_id,0,async_message_thread,this);
        if(r < 0)
        {
          DEBUG_PRINT_ERROR("\n component_init(): async_message_thread creation failed");
          eRet = OMX_ErrorInsufficientResources;
        }
      }
    }
  }

  if (eRet != OMX_ErrorNone)
  {
    DEBUG_PRINT_ERROR("\n Component Init Failed");
    DEBUG_PRINT_HIGH("\n Calling VDEC_IOCTL_STOP_NEXT_MSG");
    (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
        NULL);
    DEBUG_PRINT_HIGH("\n Calling close() on Video Driver");
    close (drv_ctx.video_driver_fd);
    drv_ctx.video_driver_fd = -1;
  }
  else
  {
    DEBUG_PRINT_HIGH("\n omx_vdec::component_init() success");
  }

  memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));

cleanup:

  if (secure_mode && (eRet == OMX_ErrorNone)) {
    if (secureDisplay(qService::IQService::END) < 0) {
      DEBUG_PRINT_HIGH("sending message to stop securing display failed");
    }
  }

  return eRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::GetComponentVersion

DESCRIPTION
  Returns the component version.

PARAMETERS
  TBD.

RETURN VALUE
  OMX_ErrorNone.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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("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_vdec::SendCommand

DESCRIPTION
  Returns zero if all the buffers released..

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
                                      OMX_IN OMX_COMMANDTYPE cmd,
                                      OMX_IN OMX_U32 param1,
                                      OMX_IN OMX_PTR cmdData
                                      )
{
    DEBUG_PRINT_LOW("\n send_command: Recieved a Command from Client");
    if(m_state == OMX_StateInvalid)
    {
        DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n");
        return OMX_ErrorInvalidState;
    }
    if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
      && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL)
    {
      DEBUG_PRINT_ERROR("\n send_command(): ERROR OMX_CommandFlush "
        "to invalid port: %d", param1);
      return OMX_ErrorBadPortIndex;
    }
    post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
    sem_wait(&m_cmd_lock);
    DEBUG_PRINT_LOW("\n send_command: Command Processed\n");
    return OMX_ErrorNone;
}

/* ======================================================================
FUNCTION
  omx_vdec::SendCommand

DESCRIPTION
  Returns zero if all the buffers released..

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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,sem_posted = 0;

  DEBUG_PRINT_LOW("\n send_command_proxy(): cmd = %d", cmd);
  DEBUG_PRINT_HIGH("\n send_command_proxy(): Current State %d, Expected State %d",
    m_state, eState);

  if(cmd == OMX_CommandStateSet)
  {
    DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandStateSet issued");
    DEBUG_PRINT_HIGH("\n Current State %d, Expected State %d", m_state, eState);
    /***************************/
    /* 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_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE))
        {
          DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle\n");
        }
        else
        {
          DEBUG_PRINT_LOW("send_command_proxy(): 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::send_command_proxy(): 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("send_command_proxy(): Loaded-->WaitForResources\n");
      }
      /* Requesting transition from Loaded to Executing */
      else if(eState == OMX_StateExecuting)
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): 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::send_command_proxy(): 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::send_command_proxy(): Loaded-->Invalid\n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%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("send_command_proxy(): Idle-->Loaded\n");
        }
        else
        {
          DEBUG_PRINT_LOW("send_command_proxy(): 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)
      {
        DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
        BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
        bFlag = 0;
        if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
                    NULL) < 0)
        {
          DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED");
          omx_report_error ();
          eRet = OMX_ErrorHardware;
        }
      }
      /* Requesting transition from Idle to Idle */
      else if(eState == OMX_StateIdle)
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): 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::send_command_proxy(): 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 (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
                    NULL) < 0)
         {
           DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED");
           omx_report_error ();
           eRet = OMX_ErrorHardware;
         }
         else
         {
           BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
           DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause\n");
           bFlag = 0;
         }
      }
      /* Requesting transition from Idle to Invalid */
       else if(eState == OMX_StateInvalid)
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState);
        eRet = OMX_ErrorBadParameter;
      }
    }

    /******************************/
    /* Current State is Executing */
    /******************************/
    else if(m_state == OMX_StateExecuting)
    {
       DEBUG_PRINT_LOW("\n Command Recieved in 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 send_command_proxy(): Executing --> Idle \n");
         BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
         if(!sem_posted)
         {
           sem_posted = 1;
           sem_post (&m_cmd_lock);
           execute_omx_flush(OMX_ALL);
         }
         bFlag = 0;
       }
       /* Requesting transition from Executing to Paused */
       else if(eState == OMX_StatePause)
       {
         DEBUG_PRINT_LOW("\n PAUSE Command Issued");
         if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_PAUSE,
                    NULL) < 0)
         {
           DEBUG_PRINT_ERROR("\n Error In Pause State");
           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("send_command_proxy(): Executing-->Pause\n");
           bFlag = 0;
         }
       }
       /* Requesting transition from Executing to Loaded */
       else if(eState == OMX_StateLoaded)
       {
         DEBUG_PRINT_ERROR("\n send_command_proxy(): 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("\n send_command_proxy(): 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("\n send_command_proxy(): 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("\n send_command_proxy(): Executing --> Invalid \n");
         post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
         eRet = OMX_ErrorInvalidState;
       }
       else
       {
         DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): 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 (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_RESUME,
                   NULL) < 0)
        {
          DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_RESUME failed");
          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("send_command_proxy(): Idle-->Executing\n");
          post_event (NULL,VDEC_S_SUCCESS,\
                      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);
         if(!sem_posted)
         {
           sem_posted = 1;
           sem_post (&m_cmd_lock);
           execute_omx_flush(OMX_ALL);
         }
         bFlag = 0;
      }
      /* Requesting transition from Pause to loaded */
      else if(eState == OMX_StateLoaded)
      {
        DEBUG_PRINT_ERROR("\n 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("\n 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("\n 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("\n Pause --> Invalid \n");
        post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
        eRet = OMX_ErrorInvalidState;
      }
      else
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): 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("send_command_proxy(): WaitForResources-->Loaded\n");
      }
      /* Requesting transition from WaitForResources to WaitForResources */
      else if (eState == OMX_StateWaitForResources)
      {
        DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): 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::send_command_proxy(): 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::send_command_proxy(): 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::send_command_proxy(): 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::send_command_proxy(): %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::send_command_proxy(): Invalid -->Loaded\n");
      post_event(OMX_EventError,OMX_ErrorInvalidState,\
                 OMX_COMPONENT_GENERATE_EVENT);
      eRet = OMX_ErrorInvalidState;
    }
  }
  else if (cmd == OMX_CommandFlush)
  {
    DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued"
        "with param1: %d", param1);
    if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1)
    {
      BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
    }
    if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1)
    {
      BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
    }
    if (!sem_posted){
      sem_posted = 1;
      DEBUG_PRINT_LOW("\n Set the Semaphore");
      sem_post (&m_cmd_lock);
      execute_omx_flush(param1);
    }
    bFlag = 0;
  }
  else if ( cmd == OMX_CommandPortEnable)
  {
    DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortEnable issued"
        "with param1: %d", param1);
    if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
      {
        m_inp_bEnabled = OMX_TRUE;

        if( (m_state == OMX_StateLoaded &&
             !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
            || allocate_input_done())
        {
          post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
                     OMX_COMPONENT_GENERATE_EVENT);
        }
        else
        {
          DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
          BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
          // Skip the event notification
          bFlag = 0;
        }
      }
      if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
      {
          DEBUG_PRINT_LOW("\n Enable output Port command recieved");
          m_out_bEnabled = OMX_TRUE;

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

          }
          else
          {
              DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
              BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
              // Skip the event notification
              bFlag = 0;
          }
      }
  }
  else if (cmd == OMX_CommandPortDisable)
  {
      DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued"
          "with param1: %d", param1);
      if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
      {
          m_inp_bEnabled = OMX_FALSE;
          if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
              && release_input_done())
          {
             post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
                        OMX_COMPONENT_GENERATE_EVENT);
          }
          else
          {
             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
             if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
             {
               if(!sem_posted)
               {
                 sem_posted = 1;
                 sem_post (&m_cmd_lock);
               }
               execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
             }

             // Skip the event notification
             bFlag = 0;
          }
      }
      if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
      {
          m_out_bEnabled = OMX_FALSE;
          DEBUG_PRINT_LOW("\n Disable output Port command recieved");
          if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
              && release_output_done())
          {
             post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
                        OMX_COMPONENT_GENERATE_EVENT);
          }
          else
         {
            BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
            if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
            {
              if (!sem_posted)
              {
                sem_posted = 1;
                sem_post (&m_cmd_lock);
              }
                BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
                execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
            }
            // Skip the event notification
            bFlag = 0;

         }
      }
  }
  else
  {
    DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd);
    eRet = OMX_ErrorNotImplemented;
  }
  if(eRet == OMX_ErrorNone && bFlag)
  {
    post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
  }
  if(!sem_posted)
  {
    sem_post(&m_cmd_lock);
  }

  return eRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::ExecuteOmxFlush

DESCRIPTION
  Executes the OMX flush.

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

RETURN VALUE
  true/false

========================================================================== */
bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
{
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  enum vdec_bufferflush flush_dir;
  bool bRet = false;
  switch (flushType)
  {
    case OMX_CORE_INPUT_PORT_INDEX:
      input_flush_progress = true;
      flush_dir = VDEC_FLUSH_TYPE_INPUT;
    break;
    case OMX_CORE_OUTPUT_PORT_INDEX:
      output_flush_progress = true;
      flush_dir = VDEC_FLUSH_TYPE_OUTPUT;
    break;
    default:
      input_flush_progress = true;
      output_flush_progress = true;
      flush_dir = VDEC_FLUSH_TYPE_ALL;
  }
  ioctl_msg.in = &flush_dir;
  ioctl_msg.out = NULL;
  if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_CMD_FLUSH, &ioctl_msg) < 0)
  {
    DEBUG_PRINT_ERROR("\n Flush Port (%d) Failed ", (int)flush_dir);
    bRet = false;
  }
  return bRet;
}
/*=========================================================================
FUNCTION : execute_output_flush

DESCRIPTION
  Executes the OMX flush at OUTPUT PORT.

PARAMETERS
  None.

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

  /*Generate FBD for all Buffers in the FTBq*/
  pthread_mutex_lock(&m_lock);
  DEBUG_PRINT_LOW("\n Initiate Output Flush");
  while (m_ftb_q.m_size)
  {
    DEBUG_PRINT_LOW("\n Buffer queue size %d pending buf cnt %d",
                       m_ftb_q.m_size,pending_output_buffers);
    m_ftb_q.pop_entry(&p1,&p2,&ident);
    DEBUG_PRINT_LOW("\n ID(%x) P1(%x) P2(%x)", ident, p1, p2);
    if(ident == m_fill_output_msg)
    {
      pending_output_buffers++;
      m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
    }
    else if (ident == OMX_COMPONENT_GENERATE_FBD)
    {
      fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
    }
  }
  pthread_mutex_unlock(&m_lock);
  output_flush_progress = false;

  if (arbitrary_bytes)
  {
    prev_ts = LLONG_MAX;
    rst_prev_ts = true;
  }
  DEBUG_PRINT_HIGH("\n OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
  return bRet;
}
/*=========================================================================
FUNCTION : execute_input_flush

DESCRIPTION
  Executes the OMX flush at INPUT PORT.

PARAMETERS
  None.

RETURN VALUE
  true/false
==========================================================================*/
bool omx_vdec::execute_input_flush()
{
  unsigned       i =0;
  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 Initiate Input Flush \n");

  pthread_mutex_lock(&m_lock);
  DEBUG_PRINT_LOW("\n Check if the Queue is empty \n");
  while (m_etb_q.m_size)
  {
    m_etb_q.pop_entry(&p1,&p2,&ident);

    if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
    {
      DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
      m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
    }
    else if(ident == OMX_COMPONENT_GENERATE_ETB)
    {
      pending_input_buffers++;
      DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
        (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
      empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
    }
    else if (ident == OMX_COMPONENT_GENERATE_EBD)
    {
      DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
        (OMX_BUFFERHEADERTYPE *)p1);
      empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
    }
  }
  time_stamp_dts.flush_timestamp();
  /*Check if Heap Buffers are to be flushed*/
  if (arbitrary_bytes && !(codec_config_flag))
  {
    DEBUG_PRINT_LOW("\n Reset all the variables before flusing");
    h264_scratch.nFilledLen = 0;
    nal_count = 0;
    look_ahead_nal = false;
    frame_count = 0;
    h264_last_au_ts = LLONG_MAX;
    h264_last_au_flags = 0;
    memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
    m_demux_entries = 0;
    DEBUG_PRINT_LOW("\n Initialize parser");
    if (m_frame_parser.mutils)
    {
      m_frame_parser.mutils->initialize_frame_checking_environment();
    }

    while (m_input_pending_q.m_size)
    {
      m_input_pending_q.pop_entry(&p1,&p2,&ident);
      m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
    }

    if (psource_frame)
    {
      m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
      psource_frame = NULL;
    }

    if (pdest_frame)
    {
      pdest_frame->nFilledLen = 0;
      m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
      pdest_frame = NULL;
    }
    m_frame_parser.flush();
  }
  else if (codec_config_flag)
  {
    DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
       "is not sent to the driver yet");
  }
  pthread_mutex_unlock(&m_lock);
  input_flush_progress = false;
  if (!arbitrary_bytes)
  {
    prev_ts = LLONG_MAX;
    rst_prev_ts = true;
  }
#ifdef _ANDROID_
  if (m_debug_timestamp)
  {
    m_timestamp_list.reset_ts_list();
  }
#endif
  DEBUG_PRINT_HIGH("\n OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
  return bRet;
}


/* ======================================================================
FUNCTION
  omx_vdec::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_vdec::post_event(unsigned int p1,
                          unsigned int p2,
                          unsigned int id)
{
  bool bRet      =                      false;


  pthread_mutex_lock(&m_lock);

  if (id == m_fill_output_msg ||
      id == OMX_COMPONENT_GENERATE_FBD)
  {
    m_ftb_q.insert_entry(p1,p2,id);
  }
  else if (id == OMX_COMPONENT_GENERATE_ETB ||
           id == OMX_COMPONENT_GENERATE_EBD ||
           id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
  {
    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 0x%x", p2);
  post_message(this, id);

  pthread_mutex_unlock(&m_lock);

  return bRet;
}
#ifdef MAX_RES_720P
OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_720p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if(!profileLevelType)
    return OMX_ErrorBadParameter;

  if(profileLevelType->nPortIndex == 0) {
    if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
    {
      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((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)))
    {
      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 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
    {
      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;
  }
  return eRet;
}
#endif
#ifdef MAX_RES_1080P
OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if(!profileLevelType)
    return OMX_ErrorBadParameter;

  if(profileLevelType->nPortIndex == 0) {
    if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
    {
      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((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)))
    {
      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 (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
    {
      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 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
    {
      if (profileLevelType->nProfileIndex == 0)
      {
        profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple;
        profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
      }
      else if(profileLevelType->nProfileIndex == 1)
      {
        profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain;
        profileLevelType->eLevel   = OMX_VIDEO_MPEG2LevelHL;
      }
      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;
  }
  return eRet;
}
#endif

/* ======================================================================
FUNCTION
  omx_vdec::GetParameter

DESCRIPTION
  OMX Get Parameter method implementation

PARAMETERS
  <TBD>.

RETURN VALUE
  Error None if successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
                                           OMX_IN OMX_INDEXTYPE paramIndex,
                                           OMX_INOUT OMX_PTR     paramData)
{
    OMX_ERRORTYPE eRet = OMX_ErrorNone;

    DEBUG_PRINT_LOW("get_parameter: \n");
    if(m_state == OMX_StateInvalid)
    {
        DEBUG_PRINT_ERROR("Get Param in Invalid State\n");
        return OMX_ErrorInvalidState;
    }
    if(paramData == NULL)
    {
        DEBUG_PRINT_LOW("Get Param in Invalid paramData \n");
        return OMX_ErrorBadParameter;
    }
  switch(paramIndex)
  {
    case OMX_IndexParamPortDefinition:
    {
      OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
                            (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n");
      eRet = update_portdef(portDefn);
      if (eRet == OMX_ErrorNone)
          m_port_def = *portDefn;
      break;
    }
    case OMX_IndexParamVideoInit:
    {
      OMX_PORT_PARAM_TYPE *portParamType =
                              (OMX_PORT_PARAM_TYPE *) paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n");

      portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
      portParamType->nSize = sizeof(portParamType);
      portParamType->nPorts           = 2;
      portParamType->nStartPortNumber = 0;
      break;
    }
    case OMX_IndexParamVideoPortFormat:
    {
      OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
      DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n");

      portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
      portFmt->nSize             = sizeof(portFmt);

      if (0 == portFmt->nPortIndex)
      {
        if (0 == portFmt->nIndex)
        {
              portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
              portFmt->eCompressionFormat = eCompressionFormat;
        }
        else
        {
          DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
              " NoMore compression formats\n");
          eRet =  OMX_ErrorNoMore;
        }
      }
      else if (1 == portFmt->nPortIndex)
      {
        portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
#ifdef MAX_RES_720P
        if (0 == portFmt->nIndex)
          portFmt->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
        else if(1 == portFmt->nIndex)
          portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)
            QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
#endif
#ifdef MAX_RES_1080P
        if(0 == portFmt->nIndex)
          portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)
            QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
#endif
        else if (1 == portFmt->nIndex) {
          portFmt->eColorFormat = OMX_COLOR_FormatYUV420Planar;
        }
        else
        {
           DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
                  " NoMore Color formats\n");
           eRet =  OMX_ErrorNoMore;
        }
      }
      else
      {
        DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n",
                          (int)portFmt->nPortIndex);
        eRet = OMX_ErrorBadPortIndex;
      }
      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");
        audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
        audioPortParamType->nSize = sizeof(audioPortParamType);
        audioPortParamType->nPorts           = 0;
        audioPortParamType->nStartPortNumber = 0;
        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");
        imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
        imagePortParamType->nSize = sizeof(imagePortParamType);
        imagePortParamType->nPorts           = 0;
        imagePortParamType->nStartPortNumber = 0;
        break;

    }
    /*Component should support this port definition*/
    case OMX_IndexParamOtherInit:
    {
        DEBUG_PRINT_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);
        strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
                    OMX_MAX_STRINGNAME_SIZE);
        break;
    }
    /* Added for parameter test */
    case OMX_IndexParamPriorityMgmt:
        {

            OMX_PRIORITYMGMTTYPE *priorityMgmType =
                                             (OMX_PRIORITYMGMTTYPE *) paramData;
            DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n");
            priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
            priorityMgmType->nSize = sizeof(priorityMgmType);

            break;
        }
    /* Added for parameter test */
    case OMX_IndexParamCompBufferSupplier:
        {
            OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
                                     (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
            DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n");

            bufferSupplierType->nSize = sizeof(bufferSupplierType);
            bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
            if(0 == bufferSupplierType->nPortIndex)
                bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
            else if (1 == bufferSupplierType->nPortIndex)
                bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
            else
                eRet = OMX_ErrorBadPortIndex;


            break;
        }
    case OMX_IndexParamVideoAvc:
        {
            DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x\n",
                        paramIndex);
            break;
        }
    case OMX_IndexParamVideoH263:
        {
            DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x\n",
                        paramIndex);
            break;
        }
    case OMX_IndexParamVideoMpeg4:
        {
            DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x\n",
                        paramIndex);
            break;
        }
    case OMX_IndexParamVideoMpeg2:
        {
          DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x\n",
              paramIndex);
          break;
        }
    case OMX_IndexParamVideoProfileLevelQuerySupported:
        {
          DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x\n", paramIndex);
          OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
            (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
#ifdef MAX_RES_720P
          eRet = get_supported_profile_level_for_720p(profileLevelType);
#endif
#ifdef MAX_RES_1080P
          eRet = get_supported_profile_level_for_1080p(profileLevelType);
#endif
          break;
        }
#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
    case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
        {
            DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage\n");
            GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
            if(nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
#ifdef USE_ION
                if(secure_mode) {
                        nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
                                                      GRALLOC_USAGE_PRIVATE_CP_BUFFER | GRALLOC_USAGE_PRIVATE_UNCACHED);
                } else {
                        nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
                }
#else
#if defined (MAX_RES_720P) ||  defined (MAX_RES_1080P_EBI)
                nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
#elif MAX_RES_1080P
                nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_SMI_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED);
#endif
#endif
            } else {
                DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!\n");
                eRet = OMX_ErrorBadParameter;
            }
        }
        break;
#endif

    default:
    {
      DEBUG_PRINT_ERROR("get_parameter: unknown param %08x\n", paramIndex);
      eRet =OMX_ErrorUnsupportedIndex;
    }

  }

  DEBUG_PRINT_LOW("\n get_parameter returning WxH(%d x %d) SxSH(%d x %d)\n",
      drv_ctx.video_resolution.frame_width,
      drv_ctx.video_resolution.frame_height,
      drv_ctx.video_resolution.stride,
      drv_ctx.video_resolution.scan_lines);

  return eRet;
}

#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
{
    DEBUG_PRINT_LOW("Inside use_android_native_buffer");
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;

    if((params == NULL) ||
      (params->nativeBuffer == NULL) ||
      (params->nativeBuffer->handle == NULL) ||
      !m_enable_android_native_buffers)
        return OMX_ErrorBadParameter;
    m_use_android_native_buffers = OMX_TRUE;
    sp<android_native_buffer_t> nBuf = params->nativeBuffer;
    private_handle_t *handle = (private_handle_t *)nBuf->handle;

    if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
        DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
                          " expected %u, got %lu",
                          drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size);
        return OMX_ErrorBadParameter;
    }

    if(OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) {  //android native buffers can be used only on Output port
        OMX_U8 *buffer = NULL;
        if(!secure_mode) {
                buffer = (OMX_U8*)mmap(0, handle->size,
                    PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
                if(buffer == MAP_FAILED) {
                    DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
                    return OMX_ErrorInsufficientResources;
            }
        }
        eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
    } else {
        eRet = OMX_ErrorBadParameter;
    }
    return eRet;
}
#endif
/* ======================================================================
FUNCTION
  omx_vdec::Setparameter

DESCRIPTION
  OMX Set Parameter method implementation.

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
                                           OMX_IN OMX_INDEXTYPE paramIndex,
                                           OMX_IN OMX_PTR        paramData)
{
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};

    if(m_state == OMX_StateInvalid)
    {
        DEBUG_PRINT_ERROR("Set Param in Invalid State\n");
        return OMX_ErrorInvalidState;
    }
    if(paramData == NULL)
    {
         DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n");
         return OMX_ErrorBadParameter;
    }
    if((m_state != OMX_StateLoaded) &&
          BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
          (m_out_bEnabled == OMX_TRUE) &&
          BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
          (m_inp_bEnabled == OMX_TRUE)) {
        DEBUG_PRINT_ERROR("Set Param in Invalid State \n");
        return OMX_ErrorIncorrectStateOperation;
    }

  switch(paramIndex)
  {
    case OMX_IndexParamPortDefinition:
    {
      OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
      portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
      //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
      //been called.
      DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
             (int)portDefn->format.video.nFrameHeight,
             (int)portDefn->format.video.nFrameWidth);
      if(OMX_DirOutput == portDefn->eDir)
      {
          eRet = update_color_format(portDefn->format.video.eColorFormat);
          if (eRet != OMX_ErrorNone) {
            DEBUG_PRINT_ERROR("\n Setparam: color format failed for %u",
                              portDefn->format.video.eColorFormat);
            break;
          }
          DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
          m_display_id = portDefn->format.video.pNativeWindow;
          unsigned int buffer_size;
          if (!client_buffers.get_buffer_req(buffer_size)) {
            DEBUG_PRINT_ERROR("\n Error in getting buffer requirements");
            eRet = OMX_ErrorBadParameter;
          } else {
            if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount &&
                 portDefn->nBufferSize >=  buffer_size)
              {
                drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual;
                drv_ctx.op_buf.buffer_size = portDefn->nBufferSize;
                eRet = set_buffer_req(&drv_ctx.op_buf);
                if (eRet == OMX_ErrorNone)
                    m_port_def = *portDefn;
            }
            else
            {
                DEBUG_PRINT_HIGH("ERROR: OP Requirements(#%d: %u) Requested(#%d: %u)\n",
                  drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size,
                  portDefn->nBufferCountActual, portDefn->nBufferSize);
                eRet = OMX_ErrorBadParameter;
            }
          }
      }
      else if(OMX_DirInput == portDefn->eDir)
      {
        if((portDefn->format.video.xFramerate >> 16) > 0 &&
           (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS)
        {
            // Frame rate only should be set if this is a "known value" or to
            // activate ts prediction logic (arbitrary mode only) sending input
            // timestamps with max value (LLONG_MAX).
            DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %d",
                             portDefn->format.video.xFramerate >> 16);
            Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
                          drv_ctx.frame_rate.fps_denominator);
            if(!drv_ctx.frame_rate.fps_numerator)
            {
              DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
              drv_ctx.frame_rate.fps_numerator = 30;
            }
            if(drv_ctx.frame_rate.fps_denominator)
              drv_ctx.frame_rate.fps_numerator = (int)
                  drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
              drv_ctx.frame_rate.fps_denominator = 1;
            frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
                      drv_ctx.frame_rate.fps_numerator;
            ioctl_msg.in = &drv_ctx.frame_rate;
            if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE,
                       (void*)&ioctl_msg) < 0)
            {
              DEBUG_PRINT_ERROR("Setting frame rate to driver failed");
            }
            DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
                             frm_int, drv_ctx.frame_rate.fps_numerator /
                             (float)drv_ctx.frame_rate.fps_denominator);
        }
         DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port\n");
         if(drv_ctx.video_resolution.frame_height !=
               portDefn->format.video.nFrameHeight ||
             drv_ctx.video_resolution.frame_width  !=
               portDefn->format.video.nFrameWidth)
         {
             DEBUG_PRINT_LOW("\n SetParam IP: WxH(%d x %d)\n",
                           portDefn->format.video.nFrameWidth,
                           portDefn->format.video.nFrameHeight);
             if (portDefn->format.video.nFrameHeight != 0x0 &&
                 portDefn->format.video.nFrameWidth != 0x0)
             {
               drv_ctx.video_resolution.frame_height =
                 drv_ctx.video_resolution.scan_lines =
                 portDefn->format.video.nFrameHeight;
               drv_ctx.video_resolution.frame_width =
                 drv_ctx.video_resolution.stride =
                 portDefn->format.video.nFrameWidth;
               ioctl_msg.in = &drv_ctx.video_resolution;
               ioctl_msg.out = NULL;
               if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICRES,
                            (void*)&ioctl_msg) < 0)
               {
                   DEBUG_PRINT_ERROR("\n Set Resolution failed");
                   eRet = OMX_ErrorUnsupportedSetting;
               }
               else
                   eRet = get_buffer_req(&drv_ctx.op_buf);
             }
         }
         else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
                  && portDefn->nBufferSize == drv_ctx.ip_buf.buffer_size)
         {
             drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
             drv_ctx.ip_buf.buffer_size = portDefn->nBufferSize;
             eRet = set_buffer_req(&drv_ctx.ip_buf);
         }
         else
         {
             DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%d: %u)\n",
               drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size,
               portDefn->nBufferCountActual, portDefn->nBufferSize);
             eRet = OMX_ErrorBadParameter;
         }
      }
      else if (portDefn->eDir ==  OMX_DirMax)
      {
          DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
                      (int)portDefn->nPortIndex);
          eRet = OMX_ErrorBadPortIndex;
      }
    }
    break;
    case OMX_IndexParamVideoPortFormat:
    {
      OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
      DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
              portFmt->eColorFormat);

      if(1 == portFmt->nPortIndex)
          eRet = update_color_format(portFmt->eColorFormat);

      DEBUG_PRINT_HIGH("Set_parameter: OMX_IndexParamVideoPortFormat: "
          "nPortIndex (%d), nIndex (%d), eCompressionFormat (0x%x), "
          "eColorFormat (0x%x), xFramerate (0x%x)", (int)portFmt->nPortIndex,
          (int)portFmt->nIndex, (int)portFmt->eCompressionFormat,
          (int)portFmt->eColorFormat, (int)portFmt->xFramerate);
    }
    break;

    case OMX_QcomIndexPortDefn:
    {
        OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
            (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
        DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d\n",
            portFmt->nFramePackingFormat);

        /* Input port */
        if (portFmt->nPortIndex == 0)
        {
            if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary)
            {
              if(secure_mode) {
                arbitrary_bytes = false;
                DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session");
                eRet = OMX_ErrorUnsupportedSetting;
              } else {
               arbitrary_bytes = true;
               DEBUG_PRINT_HIGH("setparameter: arbitrary_bytes enabled");
              }
            }
            else if (portFmt->nFramePackingFormat ==
                OMX_QCOM_FramePacking_OnlyOneCompleteFrame)
            {
               arbitrary_bytes = false;
               DEBUG_PRINT_HIGH("setparameter: arbitrary_bytes disabled");
            }
            else
            {
                DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %d\n",
                    portFmt->nFramePackingFormat);
                eRet = OMX_ErrorUnsupportedSetting;
            }
        }
        else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX)
        {
          DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port\n");
          if( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
               portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
              portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone)
          {
            m_out_mem_region_smi = OMX_TRUE;
            if ((m_out_mem_region_smi && m_out_pvt_entry_pmem))
            {
              DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set\n");
              m_use_output_pmem = OMX_TRUE;
            }
          }
        }
    }
    break;

     case OMX_IndexParamStandardComponentRole:
     {
          OMX_PARAM_COMPONENTROLETYPE *comp_role;
          comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
          DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n",
                       comp_role->cRole);

          if((m_state == OMX_StateLoaded)&&
              !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
          {
           DEBUG_PRINT_LOW("Set Parameter called in valid state");
          }
          else
          {
             DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
             return OMX_ErrorIncorrectStateOperation;
          }

          if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
          {
              if(!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE))
              {
                  strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
              }
              else
              {
                  DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
                  eRet =OMX_ErrorUnsupportedSetting;
              }
          }
          else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
          {
              if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
              {
                  strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
              }
              else
              {
                  DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
                  eRet = OMX_ErrorUnsupportedSetting;
              }
          }
          else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
          {
              if(!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE))
              {
                  strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
              }
              else
              {
                  DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
                  eRet =OMX_ErrorUnsupportedSetting;
              }
          }
          else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
          {
            if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
            {
              strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
            }
            else
            {
              DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
              eRet = OMX_ErrorUnsupportedSetting;
            }
          }
#ifdef MAX_RES_1080P
          else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
                  (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))
                  )
#else
          else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE))
#endif
          {
              if(!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE))
              {
                  strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
              }
              else
              {
                  DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
                  eRet =OMX_ErrorUnsupportedSetting;
              }
          }
          else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
                    (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
                    )
          {
              if(!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
              {
                  strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
              }
              else
              {
                  DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
                  eRet =OMX_ErrorUnsupportedSetting;
              }
          }
          else
          {
               DEBUG_PRINT_ERROR("Setparameter: unknown param %s\n", drv_ctx.kind);
               eRet = OMX_ErrorInvalidComponentName;
          }
          break;
     }

    case OMX_IndexParamPriorityMgmt:
        {
            if(m_state != OMX_StateLoaded)
            {
               DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
               return OMX_ErrorIncorrectStateOperation;
            }
            OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
            DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n",
              priorityMgmtype->nGroupID);

            DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n",
             priorityMgmtype->nGroupPriority);

            m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
            m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;

            break;
        }

      case OMX_IndexParamCompBufferSupplier:
      {
          OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
            DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
                bufferSupplierType->eBufferSupplier);
             if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
                m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;

             else

             eRet = OMX_ErrorBadPortIndex;

          break;

      }
      case OMX_IndexParamVideoAvc:
          {
              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d\n",
                    paramIndex);
              break;
          }
      case OMX_IndexParamVideoH263:
          {
              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d\n",
                    paramIndex);
              break;
          }
      case OMX_IndexParamVideoMpeg4:
          {
              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d\n",
                    paramIndex);
              break;
          }
      case OMX_IndexParamVideoMpeg2:
          {
              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d\n",
                    paramIndex);
              break;
          }
       case OMX_QcomIndexParamVideoDecoderPictureOrder:
          {
              QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
                  (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
              enum vdec_output_order pic_order = VDEC_ORDER_DISPLAY;
              DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d\n",
                    pictureOrder->eOutputPictureOrder);
              if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER)
                  pic_order = VDEC_ORDER_DISPLAY;
              else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER){
                  pic_order = VDEC_ORDER_DECODE;
                  time_stamp_dts.set_timestamp_reorder_mode(false);
              }
              else
                  eRet = OMX_ErrorBadParameter;
#ifdef MAX_RES_720P
              if (drv_ctx.idr_only_decoding)
              {
                  if (pictureOrder->eOutputPictureOrder != QOMX_VIDEO_DECODE_ORDER)
                  {
                      DEBUG_PRINT_HIGH("only decode order is supported for thumbnail mode");
                      eRet = OMX_ErrorBadParameter;
                  }
              }
#endif
              if (eRet == OMX_ErrorNone && pic_order != drv_ctx.picture_order)
              {
                  drv_ctx.picture_order = pic_order;
                  ioctl_msg.in = &drv_ctx.picture_order;
                  ioctl_msg.out = NULL;
                  if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICTURE_ORDER,
                      (void*)&ioctl_msg) < 0)
                  {
                      DEBUG_PRINT_ERROR("\n Set picture order failed");
                      eRet = OMX_ErrorUnsupportedSetting;
                  }
              }
              break;
          }
    case OMX_QcomIndexParamConcealMBMapExtraData:
      if(!secure_mode)
          eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP,
                                  ((QOMX_ENABLETYPE *)paramData)->bEnable);
      else {
          DEBUG_PRINT_ERROR("\n secure mode setting not supported");
          eRet = OMX_ErrorUnsupportedSetting;
      }
      break;
    case OMX_QcomIndexParamFrameInfoExtraData:
      {
        if(!secure_mode)
            eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA,
                                ((QOMX_ENABLETYPE *)paramData)->bEnable);
        else {
            DEBUG_PRINT_ERROR("\n secure mode setting not supported");
            eRet = OMX_ErrorUnsupportedSetting;
        }
       break;
      }
    case OMX_QcomIndexParamInterlaceExtraData:
      if(!secure_mode)
          eRet = enable_extradata(OMX_INTERLACE_EXTRADATA,
                              ((QOMX_ENABLETYPE *)paramData)->bEnable);
      else {
          DEBUG_PRINT_ERROR("\n secure mode setting not supported");
          eRet = OMX_ErrorUnsupportedSetting;
      }
      break;
    case OMX_QcomIndexParamH264TimeInfo:
      if(!secure_mode)
          eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA,
                              ((QOMX_ENABLETYPE *)paramData)->bEnable);
      else {
          DEBUG_PRINT_ERROR("\n secure mode setting not supported");
          eRet = OMX_ErrorUnsupportedSetting;
      }
      break;
    case OMX_QcomIndexParamVideoDivx:
      {
#ifdef MAX_RES_720P
        QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
        if((divXType) && (divXType->eFormat == QOMX_VIDEO_DIVXFormat311)) {
            DEBUG_PRINT_HIGH("set_parameter: DivX 3.11 not supported in 7x30 core.");
            eRet = OMX_ErrorUnsupportedSetting;
        }
#endif
      }
      break;
    case OMX_QcomIndexPlatformPvt:
      {
        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port\n");
        OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
        if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM)
        {
          DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
          eRet = OMX_ErrorUnsupportedSetting;
        }
        else
        {
          m_out_pvt_entry_pmem = OMX_TRUE;
          if ((m_out_mem_region_smi && m_out_pvt_entry_pmem))
          {
            DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set\n");
            m_use_output_pmem = OMX_TRUE;
          }
        }

      }
      break;
    case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
      {
          DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
          DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
          drv_ctx.idr_only_decoding = 1;
          int rc = ioctl(drv_ctx.video_driver_fd,
                      VDEC_IOCTL_SET_IDR_ONLY_DECODING);
          if(rc < 0) {
              DEBUG_PRINT_ERROR("Failed to set IDR only decoding on driver.");
              eRet = OMX_ErrorHardware;
          }
#ifdef MAX_RES_720P
          if (eRet == OMX_ErrorNone)
          {
              DEBUG_PRINT_HIGH("set decode order for thumbnail mode");
              drv_ctx.picture_order = VDEC_ORDER_DECODE;
              ioctl_msg.in = &drv_ctx.picture_order;
              ioctl_msg.out = NULL;
              if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICTURE_ORDER,
                  (void*)&ioctl_msg) < 0)
              {
                  DEBUG_PRINT_ERROR("\n Set picture order failed");
                  eRet = OMX_ErrorUnsupportedSetting;
              }
          }
#endif
      }
      break;
#ifdef MAX_RES_1080P
    case OMX_QcomIndexParamIndexExtraDataType:
      {
        if(!secure_mode) {
            QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
            if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
                   (extradataIndexType->bEnabled == OMX_TRUE) &&
                   (extradataIndexType->nPortIndex == 1))
            {
              DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming\n");
              eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, extradataIndexType->bEnabled);
              // Set smooth streaming parameter
              int rc = ioctl(drv_ctx.video_driver_fd,
                            VDEC_IOCTL_SET_CONT_ON_RECONFIG);
              if(rc < 0) {
                  DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
                  eRet = OMX_ErrorHardware;
              }
            }
         }
       }
      break;
#endif
#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
      /* Need to allow following two set_parameters even in Idle
       * state. This is ANDROID architecture which is not in sync
       * with openmax standard. */
    case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
      {
          EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
          if(enableNativeBuffers) {
              m_enable_android_native_buffers = enableNativeBuffers->enable;
          }
      }
      break;
    case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
      {
          eRet = use_android_native_buffer(hComp, paramData);
      }
      break;
#endif
    case OMX_QcomIndexParamEnableTimeStampReorder:
      {
        QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
        if (drv_ctx.picture_order == QOMX_VIDEO_DISPLAY_ORDER) {
          if (reorder->bEnable == OMX_TRUE) {
              frm_int =0;
              time_stamp_dts.set_timestamp_reorder_mode(true);
          }
          else
            time_stamp_dts.set_timestamp_reorder_mode(false);
        } else {
          time_stamp_dts.set_timestamp_reorder_mode(false);
          if (reorder->bEnable == OMX_TRUE)
          {
            eRet = OMX_ErrorUnsupportedSetting;
          }
        }
      }
      break;
    default:
    {
      DEBUG_PRINT_ERROR("Setparameter: unknown param %d\n", paramIndex);
      eRet = OMX_ErrorUnsupportedIndex;
    }
  }
  return eRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::GetConfig

DESCRIPTION
  OMX Get Config Method implementation.

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
                                        OMX_IN OMX_INDEXTYPE configIndex,
                                        OMX_INOUT OMX_PTR     configData)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;

  if (m_state == OMX_StateInvalid)
  {
     DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
     return OMX_ErrorInvalidState;
  }

  switch (configIndex)
  {
    case OMX_QcomIndexConfigInterlaced:
    {
      OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
                                   (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
      if (configFmt->nPortIndex == 1)
      {
        if (configFmt->nIndex == 0)
        {
          configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
        }
        else if (configFmt->nIndex == 1)
        {
          configFmt->eInterlaceType =
                                  OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
        }
        else if (configFmt->nIndex == 2)
        {
          configFmt->eInterlaceType =
          OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
        }
        else
        {
          DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
                            " NoMore Interlaced formats\n");
          eRet = OMX_ErrorNoMore;
        }

      }
      else
      {
        DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port\n",
        (int)configFmt->nPortIndex);
        eRet = OMX_ErrorBadPortIndex;
      }
    break;
    }
    case OMX_QcomIndexQueryNumberOfVideoDecInstance:
    {
        struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
        QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
        ioctl_msg.out = (void*)&decoderinstances->nNumOfInstances;
        (void)(ioctl(drv_ctx.video_driver_fd,
               VDEC_IOCTL_GET_NUMBER_INSTANCES,&ioctl_msg));
    break;
    }
  case OMX_QcomIndexConfigVideoFramePackingArrangement:
    {
      if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
      {
        OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
          (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
        h264_parser->get_frame_pack_data(configFmt);
      }
      else
      {
        DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
      }
      break;
    }
    case OMX_QcomIndexParamFrameInfoExtraData:
    {
      OMX_QCOM_EXTRADATA_FRAMEINFO *extradata =
        (OMX_QCOM_EXTRADATA_FRAMEINFO *) configData;

      if(m_extradata == NULL){
          DEBUG_PRINT_ERROR("get_config: m_extradata not set. "
                            "Aspect Ratio information missing!!");
      }
      else {
        extradata->aspectRatio.aspectRatioX =
           m_extradata->aspectRatio.aspectRatioX;
         extradata->aspectRatio.aspectRatioY =
            m_extradata->aspectRatio.aspectRatioY;
      }
      break;
    }

    default:
    {
      DEBUG_PRINT_ERROR("get_config: unknown param %d\n",configIndex);
      eRet = OMX_ErrorBadParameter;
    }

  }

  return eRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::SetConfig

DESCRIPTION
  OMX Set Config method implementation

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if successful.
========================================================================== */
OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
                                        OMX_IN OMX_INDEXTYPE configIndex,
                                        OMX_IN OMX_PTR        configData)
{
  if(m_state == OMX_StateInvalid)
  {
      DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
      return OMX_ErrorInvalidState;
  }

  OMX_ERRORTYPE ret = OMX_ErrorNone;
  OMX_VIDEO_CONFIG_NALSIZE *pNal;

  DEBUG_PRINT_LOW("\n Set Config Called");

  if (m_state == OMX_StateExecuting)
  {
     DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n");
     return ret;
  }

  if (configIndex == OMX_IndexVendorVideoExtraData)
  {
    OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData;
    DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData called");
    if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc"))
    {
      DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData AVC");
      OMX_U32 extra_size;
      // Parsing done here for the AVC atom is definitely not generic
      // Currently this piece of code is working, but certainly
      // not tested with all .mp4 files.
      // Incase of failure, we might need to revisit this
      // for a generic piece of code.

      // Retrieve size of NAL length field
      // byte #4 contains the size of NAL lenght field
      nal_length = (config->pData[4] & 0x03) + 1;

      extra_size = 0;
      if (nal_length > 2)
      {
        /* Presently we assume that only one SPS and one PPS in AvC1 Atom */
        extra_size = (nal_length - 2) * 2;
      }

      // SPS starts from byte #6
      OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
      OMX_U8 *pDestBuf;
      m_vendor_config.nPortIndex = config->nPortIndex;

      // minus 6 --> SPS starts from byte #6
      // minus 1 --> picture param set byte to be ignored from avcatom
      m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size;
      m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize);
      OMX_U32 len;
      OMX_U8 index = 0;
      // case where SPS+PPS is sent as part of set_config
      pDestBuf = m_vendor_config.pData;

      DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]\n",
           m_vendor_config.nPortIndex,
           m_vendor_config.nDataSize,
           m_vendor_config.pData);
      while (index < 2)
      {
        uint8 *psize;
        len = *pSrcBuf;
        len = len << 8;
        len |= *(pSrcBuf + 1);
        psize = (uint8 *) & len;
        memcpy(pDestBuf + nal_length, pSrcBuf + 2,len);
        for (int i = 0; i < nal_length; i++)
        {
          pDestBuf[i] = psize[nal_length - 1 - i];
        }
        //memcpy(pDestBuf,pSrcBuf,(len+2));
        pDestBuf += len + nal_length;
        pSrcBuf += len + 2;
        index++;
        pSrcBuf++;   // skip picture param set
        len = 0;
      }
    }
    else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") ||
             !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2"))
    {
      m_vendor_config.nPortIndex = config->nPortIndex;
      m_vendor_config.nDataSize = config->nDataSize;
      m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize));
      memcpy(m_vendor_config.pData, config->pData,config->nDataSize);
    }
    else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1"))
    {
        if(m_vendor_config.pData)
        {
            free(m_vendor_config.pData);
            m_vendor_config.pData = NULL;
            m_vendor_config.nDataSize = 0;
        }

        if (((*((OMX_U32 *) config->pData)) &
             VC1_SP_MP_START_CODE_MASK) ==
             VC1_SP_MP_START_CODE)
        {
            DEBUG_PRINT_LOW("set_config - VC1 simple/main profile\n");
            m_vendor_config.nPortIndex = config->nPortIndex;
            m_vendor_config.nDataSize = config->nDataSize;
            m_vendor_config.pData =
                (OMX_U8 *) malloc(config->nDataSize);
            memcpy(m_vendor_config.pData, config->pData,
                   config->nDataSize);
            m_vc1_profile = VC1_SP_MP_RCV;
        }
        else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE)
        {
            DEBUG_PRINT_LOW("set_config - VC1 Advance profile\n");
            m_vendor_config.nPortIndex = config->nPortIndex;
            m_vendor_config.nDataSize = config->nDataSize;
            m_vendor_config.pData =
                (OMX_U8 *) malloc((config->nDataSize));
            memcpy(m_vendor_config.pData, config->pData,
                   config->nDataSize);
            m_vc1_profile = VC1_AP;
        }
        else if ((config->nDataSize == VC1_STRUCT_C_LEN))
        {
            DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only\n");
            m_vendor_config.nPortIndex = config->nPortIndex;
            m_vendor_config.nDataSize  = config->nDataSize;
            m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
            memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
            m_vc1_profile = VC1_SP_MP_RCV;
        }
        else
        {
            DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile\n");
        }
    }
    return ret;
  }
  else if (configIndex == OMX_IndexConfigVideoNalSize)
  {

    pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
    nal_length = pNal->nNaluBytes;
    m_frame_parser.init_nal_length(nal_length);
    DEBUG_PRINT_LOW("\n OMX_IndexConfigVideoNalSize called with Size %d",nal_length);
    return ret;
  }

  return OMX_ErrorNotImplemented;
}

/* ======================================================================
FUNCTION
  omx_vdec::GetExtensionIndex

DESCRIPTION
  OMX GetExtensionIndex method implementaion.  <TBD>

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if everything successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
                                                OMX_IN OMX_STRING      paramName,
                                                OMX_OUT OMX_INDEXTYPE* indexType)
{
    if(m_state == OMX_StateInvalid)
    {
        DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n");
        return OMX_ErrorInvalidState;
    }
    else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
    }
#ifdef MAX_RES_1080P
    else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1))
    {
        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
    }
#endif
#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
    else if(!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) {
        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
    }
    else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) {
        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
    }
    else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) {
        DEBUG_PRINT_ERROR("Extension: %s is supported\n", paramName);
        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
    }
    else if(!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) {
        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
    }
#endif
	else {
        DEBUG_PRINT_ERROR("Extension: %s not implemented\n", paramName);
        return OMX_ErrorNotImplemented;
    }
    return OMX_ErrorNone;
}

/* ======================================================================
FUNCTION
  omx_vdec::GetState

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

PARAMETERS
  <TBD>.

RETURN VALUE
  Error None if everything is successful.
========================================================================== */
OMX_ERRORTYPE  omx_vdec::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_vdec::ComponentTunnelRequest

DESCRIPTION
  OMX Component Tunnel Request method implementation. <TBD>

PARAMETERS
  None.

RETURN VALUE
  OMX Error None if everything successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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_vdec::UseOutputBuffer

DESCRIPTION
  Helper function for Use buffer in the input pin

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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
  struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
  struct vdec_setbuffer_cmd setbuffers;
  OMX_PTR privateAppData = NULL;
#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
  private_handle_t *handle = NULL;
#endif
  OMX_U8 *buff = buffer;

  if (!m_out_mem_ptr) {
    DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
    eRet = allocate_output_headers();
#ifdef MAX_RES_1080P
    if(drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
    {
      //allocate H264_mv_buffer
      eRet = vdec_alloc_h264_mv();
      if (eRet) {
        DEBUG_PRINT_ERROR("ERROR in allocating MV buffers\n");
        return OMX_ErrorInsufficientResources;
      }
    }
#endif

  }

  if (eRet == OMX_ErrorNone) {
    for(i=0; i< drv_ctx.op_buf.actualcount; i++) {
      if(BITMASK_ABSENT(&m_out_bm_count,i))
      {
        break;
      }
    }
  }

  if(i >= drv_ctx.op_buf.actualcount) {
    eRet = OMX_ErrorInsufficientResources;
  }

  if (eRet == OMX_ErrorNone) {
#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
    if(m_enable_android_native_buffers) {
        if (m_use_android_native_buffers) {
            UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
            sp<android_native_buffer_t> nBuf = params->nativeBuffer;
            handle = (private_handle_t *)nBuf->handle;
            privateAppData = params->pAppPrivate;
        } else {
            handle = (private_handle_t *)buff;
            privateAppData = appData;
        }

        if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
            DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
                              " expected %u, got %lu",
                              drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size);
            return OMX_ErrorBadParameter;
        }

        if (!m_use_android_native_buffers) {
            if (!secure_mode) {
                buff =  (OMX_U8*)mmap(0, handle->size,
                                      PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
                if (buff == MAP_FAILED) {
                  DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
                  return OMX_ErrorInsufficientResources;
                }
            }
        }

        if(!handle) {
            DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
            return OMX_ErrorBadParameter;
        }
        drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
        drv_ctx.ptr_outputbuffer[i].offset = 0;
        drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
        drv_ctx.ptr_outputbuffer[i].mmaped_size =
            drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
    } else
#endif

    if (!ouput_egl_buffers && !m_use_output_pmem) {
#ifdef USE_ION
        drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
                drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
                &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
                &drv_ctx.op_buf_ion_info[i].fd_ion_data,ION_FLAG_CACHED);
        if(drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
          return OMX_ErrorInsufficientResources;
        }
        drv_ctx.ptr_outputbuffer[i].pmem_fd = \
          drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
#else
        drv_ctx.ptr_outputbuffer[i].pmem_fd = \
          open (MEM_DEVICE,O_RDWR);

        if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
          return OMX_ErrorInsufficientResources;
        }

        if(drv_ctx.ptr_outputbuffer[i].pmem_fd == 0)
        {
          drv_ctx.ptr_outputbuffer[i].pmem_fd = \
            open (MEM_DEVICE,O_RDWR);
          if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
            return OMX_ErrorInsufficientResources;
          }
        }

        if(!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
          drv_ctx.op_buf.buffer_size,
          drv_ctx.op_buf.alignment))
        {
          DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
          close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
          return OMX_ErrorInsufficientResources;
        }
#endif
        if(!secure_mode) {
            drv_ctx.ptr_outputbuffer[i].bufferaddr =
              (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
              PROT_READ|PROT_WRITE, MAP_SHARED,
              drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
            if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
                close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
#ifdef USE_ION
                free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
#endif
              return OMX_ErrorInsufficientResources;
            }
        }
        drv_ctx.ptr_outputbuffer[i].offset = 0;
        privateAppData = appData;
     }
     else {

       DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);

       if (!appData || !bytes )
       {
         DEBUG_PRINT_ERROR("\n Invalid appData or bytes");
         return OMX_ErrorBadParameter;
       }

       if(!secure_mode && !buffer)
       {
         DEBUG_PRINT_ERROR("\n Bad parameters for use buffer in EGL image case");
         return OMX_ErrorBadParameter;
       }


        OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
        OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
        pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
        if (!pmem_list->entryList || !pmem_list->entryList->entry ||
            !pmem_list->nEntries ||
            pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
          DEBUG_PRINT_ERROR("\n Pmem info not valid in use buffer");
          return OMX_ErrorBadParameter;
        }
        pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
                    pmem_list->entryList->entry;
        DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x",
                          pmem_info->pmem_fd);
        drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
        drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
        drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
        drv_ctx.ptr_outputbuffer[i].mmaped_size =
        drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
        privateAppData = appData;
     }
     m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
     m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;

     *bufferHdr = (m_out_mem_ptr + i );
     if(secure_mode)
          drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
     setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
     memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
             sizeof (vdec_bufferpayload));

     ioctl_msg.in  = &setbuffers;
     ioctl_msg.out = NULL;

     DEBUG_PRINT_HIGH("\n Set the Output Buffer Idx: %d Addr: %x, pmem_fd=%0x%x", i,
                       drv_ctx.ptr_outputbuffer[i],drv_ctx.ptr_outputbuffer[i].pmem_fd );
     if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
          &ioctl_msg) < 0)
     {
       DEBUG_PRINT_ERROR("\n Set output buffer failed");
       return OMX_ErrorInsufficientResources;
     }
     // found an empty buffer at i
     (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
     if (m_enable_android_native_buffers) {
       DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
       (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
     } else {
       (*bufferHdr)->pBuffer = buff;
     }
     (*bufferHdr)->pAppPrivate = privateAppData;
     BITMASK_SET(&m_out_bm_count,i);
  }
  return eRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::use_input_heap_buffers

DESCRIPTION
  OMX Use Buffer Heap allocation method implementation.

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None , if everything successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
                         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)
{
  DEBUG_PRINT_LOW("Inside %s, %p\n", __FUNCTION__, buffer);
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if(!m_inp_heap_ptr)
    m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
               calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
               drv_ctx.ip_buf.actualcount);
  if(!m_phdr_pmem_ptr)
    m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
               calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
               drv_ctx.ip_buf.actualcount);
  if(!m_inp_heap_ptr || !m_phdr_pmem_ptr)
  {
    DEBUG_PRINT_ERROR("Insufficent memory");
    eRet = OMX_ErrorInsufficientResources;
  }
  else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount)
  {
    input_use_buffer = true;
    memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
    m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
    m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
    m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
    m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
    m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
    *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
    eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
    DEBUG_PRINT_HIGH("\n Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
    if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt], NULL, NULL))
    {
      DEBUG_PRINT_ERROR("\nERROR:Free_q is full");
      return OMX_ErrorInsufficientResources;
    }
    m_in_alloc_cnt++;
  }
  else
  {
    DEBUG_PRINT_ERROR("All i/p buffers have been set!");
    eRet = OMX_ErrorInsufficientResources;
  }
  return eRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::UseBuffer

DESCRIPTION
  OMX Use Buffer method implementation.

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None , if everything successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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 error = OMX_ErrorNone;
  struct vdec_setbuffer_cmd setbuffers;
  struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};

  if (bufferHdr == NULL || bytes == 0)
  {
      DEBUG_PRINT_ERROR("bad param 0x%p %ld",bufferHdr, bytes);
      return OMX_ErrorBadParameter;
  }

  if(!secure_mode && buffer == NULL) {
      DEBUG_PRINT_ERROR("bad param 0x%p",buffer);
      return OMX_ErrorBadParameter;
  }

  if(m_state == OMX_StateInvalid)
  {
    DEBUG_PRINT_ERROR("Use Buffer in Invalid State\n");
    return OMX_ErrorInvalidState;
  }
  if(port == OMX_CORE_INPUT_PORT_INDEX)
    error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
  else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
    error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
  else
  {
    DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
    error = OMX_ErrorBadPortIndex;
  }
  DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, error);
  if(error == OMX_ErrorNone)
  {
    if(allocate_done() && 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 == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
       BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
    {
      BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
      post_event(OMX_CommandPortEnable,
          OMX_CORE_INPUT_PORT_INDEX,
          OMX_COMPONENT_GENERATE_EVENT);
    }
    else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
            BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
    {
      BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
      post_event(OMX_CommandPortEnable,
                 OMX_CORE_OUTPUT_PORT_INDEX,
                 OMX_COMPONENT_GENERATE_EVENT);
    }
  }
  return error;
}

OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
                                OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
{
  if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes)
  {
    if(m_inp_heap_ptr[bufferindex].pBuffer)
      free(m_inp_heap_ptr[bufferindex].pBuffer);
    m_inp_heap_ptr[bufferindex].pBuffer = NULL;
  }
  if (pmem_bufferHdr)
    free_input_buffer(pmem_bufferHdr);
  return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
{
  unsigned int index = 0;
  if (bufferHdr == NULL || m_inp_mem_ptr == NULL)
  {
    return OMX_ErrorBadParameter;
  }

  index = bufferHdr - m_inp_mem_ptr;
  DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index);

  if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer)
  {
    DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index);
    if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0)
    {
       struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
       struct vdec_setbuffer_cmd setbuffers;
       setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
       memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
          sizeof (vdec_bufferpayload));
       ioctl_msg.in  = &setbuffers;
       ioctl_msg.out = NULL;
       int ioctl_r = ioctl (drv_ctx.video_driver_fd,
                            VDEC_IOCTL_FREE_BUFFER, &ioctl_msg);
       if (ioctl_r < 0)
       {
          DEBUG_PRINT_ERROR("\nVDEC_IOCTL_FREE_BUFFER returned error %d", ioctl_r);
       }
       if (!secure_mode) {
           DEBUG_PRINT_LOW("\n unmap the input buffer fd=%d",
                        drv_ctx.ptr_inputbuffer[index].pmem_fd);
           DEBUG_PRINT_LOW("\n unmap the input buffer size=%d  address = %d",
                        drv_ctx.ptr_inputbuffer[index].mmaped_size,
                        drv_ctx.ptr_inputbuffer[index].bufferaddr);
           munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
                   drv_ctx.ptr_inputbuffer[index].mmaped_size);
       }
       close (drv_ctx.ptr_inputbuffer[index].pmem_fd);
       drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
       if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr)
       {
         free(m_desc_buffer_ptr[index].buf_addr);
         m_desc_buffer_ptr[index].buf_addr = NULL;
         m_desc_buffer_ptr[index].desc_data_size = 0;
       }
#ifdef USE_ION
       free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
#endif
    }
  }

  return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
{
  unsigned int index = 0;

  if (bufferHdr == NULL || m_out_mem_ptr == NULL)
  {
    DEBUG_PRINT_ERROR("\nfree_output_buffer ERROR");
    return OMX_ErrorBadParameter;
  }

  index = bufferHdr - m_out_mem_ptr;
  DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d",index);

  if (index < drv_ctx.op_buf.actualcount
      && drv_ctx.ptr_outputbuffer)
  {
    DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d addr = %x", index,
                    drv_ctx.ptr_outputbuffer[index].bufferaddr);

    struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
    struct vdec_setbuffer_cmd setbuffers;
    setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
    memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
        sizeof (vdec_bufferpayload));
    ioctl_msg.in  = &setbuffers;
    ioctl_msg.out = NULL;
    DEBUG_PRINT_LOW("\nRelease the Output Buffer");
    if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_FREE_BUFFER,
          &ioctl_msg) < 0)
      DEBUG_PRINT_ERROR("\nRelease output buffer failed in VCD");

#ifdef _ANDROID_
    if(m_enable_android_native_buffers) {
        if(drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
            if(!secure_mode) {
                munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr,
                        drv_ctx.ptr_outputbuffer[index].mmaped_size);
            }
        }
        drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
    } else {
#endif
            if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem)
            {
               if(!secure_mode) {
                    DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d",
                            drv_ctx.ptr_outputbuffer[index].pmem_fd);
                    DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d  address = %d",
                            drv_ctx.ptr_outputbuffer[index].mmaped_size,
                            drv_ctx.ptr_outputbuffer[index].bufferaddr);
                    munmap (drv_ctx.ptr_outputbuffer[index].bufferaddr,
                            drv_ctx.ptr_outputbuffer[index].mmaped_size);
               }
#ifdef USE_ION
                free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
#endif
                close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
                drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
#ifdef _ANDROID_
                m_heap_ptr[index].video_heap_ptr = NULL;
                m_heap_count = m_heap_count - 1;
                if (m_heap_count == 0)
                {
                    free(m_heap_ptr);
                    m_heap_ptr = NULL;
                }
#endif // _ANDROID_
          }
#ifdef _ANDROID_
       }
#endif
  }
#ifdef MAX_RES_1080P
  if(drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
  {
    vdec_dealloc_h264_mv();
  }
#endif

  return OMX_ErrorNone;

}

OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
                                         OMX_BUFFERHEADERTYPE **bufferHdr,
                                         OMX_U32              port,
                                         OMX_PTR              appData,
                                         OMX_U32              bytes)
{
  OMX_BUFFERHEADERTYPE *input = NULL;
  unsigned char *buf_addr = NULL;
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  unsigned   i = 0;

  /* Sanity Check*/
  if (bufferHdr == NULL)
  {
    return OMX_ErrorBadParameter;
  }

  if (m_inp_heap_ptr == NULL)
  {
    m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
                     calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
                     drv_ctx.ip_buf.actualcount);
    m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
                     calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
                     drv_ctx.ip_buf.actualcount);

    if (m_inp_heap_ptr == NULL)
    {
      DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed ");
      return OMX_ErrorInsufficientResources;
    }
  }

  /*Find a Free index*/
  for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
  {
    if(BITMASK_ABSENT(&m_heap_inp_bm_count,i))
    {
      DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i);
      break;
    }
  }

  if (i < drv_ctx.ip_buf.actualcount)
  {
    buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);

    if (buf_addr == NULL)
    {
      return OMX_ErrorInsufficientResources;
    }

    *bufferHdr = (m_inp_heap_ptr + i);
    input = *bufferHdr;
    BITMASK_SET(&m_heap_inp_bm_count,i);

    input->pBuffer           = (OMX_U8 *)buf_addr;
    input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
    input->nVersion.nVersion = OMX_SPEC_VERSION;
    input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
    input->pAppPrivate       = appData;
    input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
    DEBUG_PRINT_LOW("\n Address of Heap Buffer %p",*bufferHdr );
    eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
    DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",m_phdr_pmem_ptr [i] );
    /*Add the Buffers to freeq*/
    if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr [i],NULL,NULL))
    {
      DEBUG_PRINT_ERROR("\nERROR:Free_q is full");
      return OMX_ErrorInsufficientResources;
    }
  }
  else
  {
    return OMX_ErrorBadParameter;
  }

  return eRet;

}


/* ======================================================================
FUNCTION
  omx_vdec::AllocateInputBuffer

DESCRIPTION
  Helper function for allocate buffer in the input pin

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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;
  struct vdec_setbuffer_cmd setbuffers;
  OMX_BUFFERHEADERTYPE *input = NULL;
  struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
  unsigned   i = 0;
  unsigned char *buf_addr = NULL;
  int pmem_fd = -1;

  if(bytes != drv_ctx.ip_buf.buffer_size)
  {
    DEBUG_PRINT_LOW("\n Requested Size is wrong %d epected is %d",
      bytes, drv_ctx.ip_buf.buffer_size);
    //return OMX_ErrorBadParameter;
  }

  if(!m_inp_mem_ptr)
  {
    DEBUG_PRINT_HIGH("\n Allocate i/p buffer Header: Cnt(%d) Sz(%d)",
      drv_ctx.ip_buf.actualcount,
      drv_ctx.ip_buf.buffer_size);

    m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
    calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);

    if (m_inp_mem_ptr == NULL)
    {
      return OMX_ErrorInsufficientResources;
    }

    drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
    calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);

    if (drv_ctx.ptr_inputbuffer == NULL)
    {
      return OMX_ErrorInsufficientResources;
    }
#ifdef USE_ION
    drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
    calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);

    if (drv_ctx.ip_buf_ion_info == NULL)
    {
      return OMX_ErrorInsufficientResources;
    }
#endif

    for (i=0; i < drv_ctx.ip_buf.actualcount; i++)
    {
      drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
#ifdef USE_ION
      drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
#endif
    }
  }

  for(i=0; i< drv_ctx.ip_buf.actualcount; i++)
  {
    if(BITMASK_ABSENT(&m_inp_bm_count,i))
    {
      DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i);
      break;
    }
  }

  if(i < drv_ctx.ip_buf.actualcount)
  {
    DEBUG_PRINT_LOW("\n Allocate input Buffer");

#ifdef USE_ION
 drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
                    drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
                    &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
		    &drv_ctx.ip_buf_ion_info[i].fd_ion_data,ION_FLAG_CACHED);
    if(drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
        return OMX_ErrorInsufficientResources;
     }
    pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
#else
    pmem_fd = open (MEM_DEVICE,O_RDWR);

    if (pmem_fd < 0)
    {
      DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer");
      return OMX_ErrorInsufficientResources;
    }

    if (pmem_fd == 0)
    {
      pmem_fd = open (MEM_DEVICE,O_RDWR);

      if (pmem_fd < 0)
      {
        DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer");
        return OMX_ErrorInsufficientResources;
      }
    }

    if(!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
      drv_ctx.ip_buf.alignment))
    {
      DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
      close(pmem_fd);
      return OMX_ErrorInsufficientResources;
    }
#endif
    if (!secure_mode) {
        buf_addr = (unsigned char *)mmap(NULL,
          drv_ctx.ip_buf.buffer_size,
          PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);

        if (buf_addr == MAP_FAILED)
        {
            close(pmem_fd);
#ifdef USE_ION
            free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
#endif
          DEBUG_PRINT_ERROR("\n Map Failed to allocate input buffer");
          return OMX_ErrorInsufficientResources;
        }
    }
    *bufferHdr = (m_inp_mem_ptr + i);
    if (secure_mode)
        drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
    else
        drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
    drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
    drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
    drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
    drv_ctx.ptr_inputbuffer [i].offset = 0;

    setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
    memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer [i],
            sizeof (vdec_bufferpayload));
    ioctl_msg.in  = &setbuffers;
    ioctl_msg.out = NULL;

    if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
         &ioctl_msg) < 0)
    {
      DEBUG_PRINT_ERROR("\n Set Buffers Failed");
      return OMX_ErrorInsufficientResources;
    }

    input = *bufferHdr;
    BITMASK_SET(&m_inp_bm_count,i);
    DEBUG_PRINT_LOW("\n Buffer address %p of pmem",*bufferHdr);
    if (secure_mode)
         input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd;
    else
         input->pBuffer           = (OMX_U8 *)buf_addr;
    input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
    input->nVersion.nVersion = OMX_SPEC_VERSION;
    input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
    input->pAppPrivate       = appData;
    input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
    input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];

    if (drv_ctx.disable_dmx)
    {
      eRet = allocate_desc_buffer(i);
    }
  }
  else
  {
    DEBUG_PRINT_ERROR("\nERROR:Input Buffer Index not found");
    eRet = OMX_ErrorInsufficientResources;
  }
  return eRet;
}


/* ======================================================================
FUNCTION
  omx_vdec::AllocateOutputBuffer

DESCRIPTION
  Helper fn for AllocateBuffer in the output pin

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if everything went well.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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
  struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
  struct vdec_setbuffer_cmd setbuffers;
#ifdef USE_ION
  int ion_device_fd =-1;
  struct ion_allocation_data ion_alloc_data;
  struct ion_fd_data fd_ion_data;
#endif

  int nBufHdrSize        = 0;
  int nPlatformEntrySize = 0;
  int nPlatformListSize  = 0;
  int nPMEMInfoSize = 0;
  int pmem_fd = -1;
  unsigned char *pmem_baseaddress = NULL;

  OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
  OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
  OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;

  if (!m_out_mem_ptr)
  {
    DEBUG_PRINT_HIGH("\n Allocate o/p buffer Header: Cnt(%d) Sz(%d)",
      drv_ctx.op_buf.actualcount,
      drv_ctx.op_buf.buffer_size);

    DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",
      drv_ctx.op_buf.actualcount);

    nBufHdrSize        = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_BUFFERHEADERTYPE);

    nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
    nPlatformListSize  = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
    nPlatformEntrySize = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);

    DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize,
                         sizeof(OMX_BUFFERHEADERTYPE),
                         nPMEMInfoSize,
                         nPlatformListSize);
    DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d \n",nPlatformEntrySize,
                         drv_ctx.op_buf.actualcount);

    m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
    // Alloc mem for platform specific info
    char *pPtr=NULL;
    pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
                                     nPMEMInfoSize,1);
    drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
      calloc (sizeof(struct vdec_bufferpayload),
      drv_ctx.op_buf.actualcount);
    drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
      calloc (sizeof (struct vdec_output_frameinfo),
      drv_ctx.op_buf.actualcount);
#ifdef USE_ION
    drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
      calloc (sizeof(struct vdec_ion),
      drv_ctx.op_buf.actualcount);
#endif
#ifdef _ANDROID_
    m_heap_ptr = (struct vidc_heap *)\
       calloc (sizeof(struct vidc_heap),
      drv_ctx.op_buf.actualcount);
#endif

    if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
       && drv_ctx.ptr_respbuffer
#ifdef _ANDROID_
	   && m_heap_ptr
#endif
	   )
    {
      drv_ctx.ptr_outputbuffer[0].mmaped_size =
        (drv_ctx.op_buf.buffer_size *
         drv_ctx.op_buf.actualcount);
      bufHdr          =  m_out_mem_ptr;
      m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
      m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
                        (((char *) m_platform_list)  + nPlatformListSize);
      m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
                        (((char *) m_platform_entry) + nPlatformEntrySize);
      pPlatformList   = m_platform_list;
      pPlatformEntry  = m_platform_entry;
      pPMEMInfo       = m_pmem_info;

      DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);

      // Settting the entire storage nicely
      DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr, m_out_mem_ptr,pPlatformEntry);
      DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo);
      for(i=0; i < drv_ctx.op_buf.actualcount ; i++)
      {
        bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
        bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
        // Set the values when we determine the right HxW param
        bufHdr->nAllocLen          = 0;
        bufHdr->nFilledLen         = 0;
        bufHdr->pAppPrivate        = NULL;
        bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
        // Platform specific PMEM Information
        // Initialize the Platform Entry
        //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d\n",i);
        pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
        pPlatformEntry->entry      = pPMEMInfo;
        // Initialize the Platform List
        pPlatformList->nEntries    = 1;
        pPlatformList->entryList   = pPlatformEntry;
        // Keep pBuffer NULL till vdec is opened
        bufHdr->pBuffer            = NULL;

        pPMEMInfo->offset          =  0;
        pPMEMInfo->pmem_fd = 0;
        bufHdr->pPlatformPrivate = pPlatformList;
        drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
#ifdef USE_ION
        drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
#endif
        /*Create a mapping between buffers*/
        bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
        drv_ctx.ptr_respbuffer[i].client_data = (void *)\
                                            &drv_ctx.ptr_outputbuffer[i];
#ifdef _ANDROID_
        m_heap_ptr[i].video_heap_ptr = NULL;
#endif
        // Move the buffer and buffer header pointers
        bufHdr++;
        pPMEMInfo++;
        pPlatformEntry++;
        pPlatformList++;
      }
#ifdef MAX_RES_1080P
      if(eRet == OMX_ErrorNone && drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
      {
        //Allocate the h264_mv_buffer
        eRet = vdec_alloc_h264_mv();
        if(eRet) {
          DEBUG_PRINT_ERROR("ERROR in allocating MV buffers\n");
          return OMX_ErrorInsufficientResources;
        }
      }
#endif
    }
    else
    {
      DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\
                                        m_out_mem_ptr, pPtr);
      if(m_out_mem_ptr)
      {
        free(m_out_mem_ptr);
        m_out_mem_ptr = NULL;
      }
      if(pPtr)
      {
        free(pPtr);
        pPtr = NULL;
      }
      if(drv_ctx.ptr_outputbuffer)
      {
        free(drv_ctx.ptr_outputbuffer);
        drv_ctx.ptr_outputbuffer = NULL;
      }
      if(drv_ctx.ptr_respbuffer)
      {
        free(drv_ctx.ptr_respbuffer);
        drv_ctx.ptr_respbuffer = NULL;
      }
#ifdef USE_ION
    if (drv_ctx.op_buf_ion_info) {
        DEBUG_PRINT_LOW("\n Free o/p ion context");
	free(drv_ctx.op_buf_ion_info);
        drv_ctx.op_buf_ion_info = NULL;
    }
#endif
      eRet =  OMX_ErrorInsufficientResources;
    }
  }

  for (i=0; i< drv_ctx.op_buf.actualcount; i++)
  {
    if(BITMASK_ABSENT(&m_out_bm_count,i))
    {
      DEBUG_PRINT_LOW("\n Found a Free Output Buffer Index %d",i);
      break;
    }
  }

  if (i < drv_ctx.op_buf.actualcount)
  {
    DEBUG_PRINT_LOW("\n Allocate Output Buffer");

#ifdef USE_ION
    drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
                    drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
                    &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
                    &drv_ctx.op_buf_ion_info[i].fd_ion_data, ION_FLAG_CACHED);
    if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
        return OMX_ErrorInsufficientResources;
     }
    pmem_fd = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
#else
    pmem_fd = open (MEM_DEVICE,O_RDWR);

    if (pmem_fd < 0)
    {
      DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d",
        drv_ctx.op_buf.buffer_size);
      return OMX_ErrorInsufficientResources;
    }

    if (pmem_fd == 0)
    {
      pmem_fd = open (MEM_DEVICE,O_RDWR);

      if (pmem_fd < 0)
      {
         DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d",
           drv_ctx.op_buf.buffer_size);
         return OMX_ErrorInsufficientResources;
      }
    }

    if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size,
      drv_ctx.op_buf.alignment))
    {
      DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
      close(pmem_fd);
      return OMX_ErrorInsufficientResources;
    }
#endif
    if (!secure_mode) {
        pmem_baseaddress = (unsigned char *)mmap(NULL,
                           drv_ctx.op_buf.buffer_size,
                           PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);

        if (pmem_baseaddress == MAP_FAILED)
        {
          DEBUG_PRINT_ERROR("\n MMAP failed for Size %d",
          drv_ctx.op_buf.buffer_size);
          close(pmem_fd);
#ifdef USE_ION
          free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
#endif
          return OMX_ErrorInsufficientResources;
        }
    }

    *bufferHdr = (m_out_mem_ptr + i);
    if (secure_mode)
        drv_ctx.ptr_outputbuffer [i].bufferaddr = *bufferHdr;
    else
        drv_ctx.ptr_outputbuffer [i].bufferaddr = pmem_baseaddress;

    drv_ctx.ptr_outputbuffer [i].pmem_fd = pmem_fd;
    drv_ctx.ptr_outputbuffer [i].buffer_len = drv_ctx.op_buf.buffer_size;
    drv_ctx.ptr_outputbuffer [i].mmaped_size = drv_ctx.op_buf.buffer_size;
    drv_ctx.ptr_outputbuffer [i].offset = 0;

#ifdef _ANDROID_
 #ifdef USE_ION
    m_heap_ptr[i].video_heap_ptr = new VideoHeap (drv_ctx.op_buf_ion_info[i].ion_device_fd,
                                drv_ctx.op_buf.buffer_size,
                                pmem_baseaddress,
                                ion_alloc_data.handle,
                                pmem_fd);
    m_heap_count = m_heap_count + 1;
#else
    m_heap_ptr[i].video_heap_ptr = new VideoHeap (pmem_fd,
                                drv_ctx.op_buf.buffer_size,
                                pmem_baseaddress);
#endif
#endif

    m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
#ifdef _ANDROID_
    m_pmem_info[i].pmem_fd = (OMX_U32) m_heap_ptr[i].video_heap_ptr.get ();
#else
    m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd ;
#endif
    setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
    memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer [i],
            sizeof (vdec_bufferpayload));
    ioctl_msg.in  = &setbuffers;
    ioctl_msg.out = NULL;

    DEBUG_PRINT_LOW("\n Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]);
    if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
         &ioctl_msg) < 0)
    {
      DEBUG_PRINT_ERROR("\n Set output buffer failed");
      return OMX_ErrorInsufficientResources;
    }

    // found an empty buffer at i
    (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
    (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
    (*bufferHdr)->pAppPrivate = appData;
    BITMASK_SET(&m_out_bm_count,i);

  }
  else
  {
    DEBUG_PRINT_ERROR("\nERROR:Output Buffer Index not found");
    eRet = OMX_ErrorInsufficientResources;
  }
  return eRet;
}


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

DESCRIPTION
  Returns zero if all the buffers released..

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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)
{
    unsigned i = 0;
    OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type

    DEBUG_PRINT_LOW("\n Allocate buffer on port %d \n", (int)port);
    if(m_state == OMX_StateInvalid)
    {
        DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n");
        return OMX_ErrorInvalidState;
    }

    if(port == OMX_CORE_INPUT_PORT_INDEX)
    {
      if (arbitrary_bytes)
      {
          eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
      }
      else
      {
        eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
      }
    }
    else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
    {
      eRet = client_buffers.allocate_buffers_color_convert(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 == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated)
        {
          if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
          {
             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
             post_event(OMX_CommandPortEnable,
                        OMX_CORE_INPUT_PORT_INDEX,
                        OMX_COMPONENT_GENERATE_EVENT);
          }
        }
        if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated)
            {
          if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
          {
             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
                post_event(OMX_CommandPortEnable,
                           OMX_CORE_OUTPUT_PORT_INDEX,
                           OMX_COMPONENT_GENERATE_EVENT);
            }
        }
    }
    DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet);
    return eRet;
}

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

DESCRIPTION

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
            (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX))
    {
        DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port);
    }
    else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause)
    {
        DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled\n");
        post_event(OMX_EventError,
                   OMX_ErrorPortUnpopulated,
                   OMX_COMPONENT_GENERATE_EVENT);

        return OMX_ErrorIncorrectStateOperation;
    }
    else if (m_state != OMX_StateInvalid)
    {
        DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers\n");
        post_event(OMX_EventError,
                   OMX_ErrorPortUnpopulated,
                   OMX_COMPONENT_GENERATE_EVENT);
    }

    if(port == OMX_CORE_INPUT_PORT_INDEX)
    {
      /*Check if arbitrary bytes*/
      if(!arbitrary_bytes && !input_use_buffer)
        nPortIndex = buffer - m_inp_mem_ptr;
      else
        nPortIndex = buffer - m_inp_heap_ptr;

        DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d \n", nPortIndex);
        if(nPortIndex < drv_ctx.ip_buf.actualcount)
        {
         // Clear the bit associated with it.
         BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
         BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
         if (input_use_buffer == true)
         {

            DEBUG_PRINT_LOW("\n Free pmem Buffer index %d",nPortIndex);
            if(m_phdr_pmem_ptr)
              free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
         }
         else
         {
            if (arbitrary_bytes)
            {
              if(m_phdr_pmem_ptr)
                free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
              else
                free_input_buffer(nPortIndex,NULL);
            }
            else
              free_input_buffer(buffer);
         }
         m_inp_bPopulated = OMX_FALSE;
         /*Free the Buffer Header*/
          if (release_input_done())
          {
            DEBUG_PRINT_HIGH("\n ALL input buffers are freed/released");
            free_input_buffer_header();
          }
        }
        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,
                       OMX_CORE_INPUT_PORT_INDEX,
                       OMX_COMPONENT_GENERATE_EVENT);
        }
    }
    else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
    {
        // check if the buffer is valid
        nPortIndex = buffer - client_buffers.get_il_buf_hdr();
        if(nPortIndex < drv_ctx.op_buf.actualcount)
        {
            DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d \n", nPortIndex);
            // Clear the bit associated with it.
            BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
            m_out_bPopulated = OMX_FALSE;
            client_buffers.free_output_buffer (buffer);

            if (release_output_done())
            {
              free_output_buffer_header();
            }
        }
        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,
                           OMX_CORE_OUTPUT_PORT_INDEX,
                           OMX_COMPONENT_GENERATE_EVENT);
        }
    }
    else
    {
        eRet = OMX_ErrorBadPortIndex;
    }
    if((eRet == OMX_ErrorNone) &&
       (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
    {
        if(release_done())
        {
            // 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_vdec::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_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
                                           OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
  OMX_ERRORTYPE ret1 = OMX_ErrorNone;
  unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;

  if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
  {
    codec_config_flag = true;
    DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
  }
  else
  {
    codec_config_flag = false;
  }

  if(m_state == OMX_StateInvalid)
  {
      DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n");
      return OMX_ErrorInvalidState;
  }

  if (buffer == NULL)
  {
    DEBUG_PRINT_ERROR("\nERROR:ETB Buffer is NULL");
    return OMX_ErrorBadParameter;
  }

  if (!m_inp_bEnabled)
  {
    DEBUG_PRINT_ERROR("\nERROR:ETB incorrect state operation, input port is disabled.");
    return OMX_ErrorIncorrectStateOperation;
  }

  if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX)
  {
    DEBUG_PRINT_ERROR("\nERROR:ETB invalid port in header %d", buffer->nInputPortIndex);
    return OMX_ErrorBadPortIndex;
  }

#ifdef _ANDROID_
  if(iDivXDrmDecrypt)
  {
    OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer);
    if(drmErr != OMX_ErrorNone) {
        // this error can be ignored
        DEBUG_PRINT_LOW("\nERROR:iDivXDrmDecrypt->Decrypt %d", drmErr);
    }
  }
  if (perf_flag)
  {
    if (!latency)
    {
      dec_time.stop();
      latency = dec_time.processing_time_us();
      dec_time.start();
    }
  }
#endif //_ANDROID_

  if (arbitrary_bytes)
  {
    nBufferIndex = buffer - m_inp_heap_ptr;
  }
  else
  {
     if (input_use_buffer == true)
     {
       nBufferIndex = buffer - m_inp_heap_ptr;
       m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
       m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
       m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
       buffer = &m_inp_mem_ptr[nBufferIndex];
       DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %d",
                         &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen);
     }
     else{
       nBufferIndex = buffer - m_inp_mem_ptr;
     }
  }

  if (nBufferIndex > drv_ctx.ip_buf.actualcount )
  {
    DEBUG_PRINT_ERROR("\nERROR:ETB nBufferIndex is invalid");
    return OMX_ErrorBadParameter;
  }

  DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)",
    buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen);
  if (arbitrary_bytes)
  {
    post_event ((unsigned)hComp,(unsigned)buffer,
                OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
  }
  else
  {
    if (!(client_extradata & OMX_TIMEINFO_EXTRADATA))
      set_frame_rate(buffer->nTimeStamp);
    post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
  }
  return OMX_ErrorNone;
}

/* ======================================================================
FUNCTION
  omx_vdec::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_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE         hComp,
                                                 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
  int push_cnt = 0,i=0;
  unsigned nPortIndex = 0;
  OMX_ERRORTYPE ret = OMX_ErrorNone;
  struct vdec_input_frameinfo frameinfo;
  struct vdec_bufferpayload *temp_buffer;
  struct vdec_ioctl_msg ioctl_msg;
  struct vdec_seqheader seq_header;
  bool port_setting_changed = true;
#ifdef MAX_RES_1080P
  bool not_coded_vop = false;
#endif

  /*Should we generate a Aync error event*/
  if (buffer == NULL || buffer->pInputPortPrivate == NULL)
  {
    DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy is invalid");
    return OMX_ErrorBadParameter;
  }

  nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);

  if (nPortIndex > drv_ctx.ip_buf.actualcount)
  {
    DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
        nPortIndex);
    return OMX_ErrorBadParameter;
  }

  pending_input_buffers++;

  /* return zero length and not an EOS buffer */
  if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
     ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))
  {
    DEBUG_PRINT_HIGH("\n return zero legth buffer");
    post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
                     OMX_COMPONENT_GENERATE_EBD);
    return OMX_ErrorNone;
  }

#ifdef MAX_RES_1080P
  if(codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX){
    mp4StreamType psBits;
    psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset);
    psBits.numBytes = buffer->nFilledLen;
    mp4_headerparser.parseHeader(&psBits);
    not_coded_vop = mp4_headerparser.is_notcodec_vop(
            (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
    if(not_coded_vop) {
        DEBUG_PRINT_HIGH("\n Found Not coded vop len %d frame number %d",
             buffer->nFilledLen,frame_count);
        if(buffer->nFlags & OMX_BUFFERFLAG_EOS){
          DEBUG_PRINT_HIGH("\n Eos and Not coded Vop set len to zero");
          not_coded_vop = false;
          buffer->nFilledLen = 0;
        }
    }
  }
#endif
  if(input_flush_progress == true
#ifdef MAX_RES_1080P
     || not_coded_vop
#endif
     )
  {
    DEBUG_PRINT_LOW("\n Flush in progress return buffer ");
    post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
                     OMX_COMPONENT_GENERATE_EBD);
    return OMX_ErrorNone;
  }

  temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;

  if ((temp_buffer -  drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount)
  {
    return OMX_ErrorBadParameter;
  }

  DEBUG_PRINT_LOW("\n ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
  /*for use buffer we need to memcpy the data*/
  temp_buffer->buffer_len = buffer->nFilledLen;

  if (input_use_buffer)
  {
    if (buffer->nFilledLen <= temp_buffer->buffer_len)
    {
      if(arbitrary_bytes)
      {
        memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
      }
      else
      {
        memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
                buffer->nFilledLen);
      }
    }
    else
    {
      return OMX_ErrorBadParameter;
    }

  }

  frameinfo.bufferaddr = temp_buffer->bufferaddr;
  frameinfo.client_data = (void *) buffer;
  frameinfo.datalen = temp_buffer->buffer_len;
  frameinfo.flags = 0;
  frameinfo.offset = buffer->nOffset;
  frameinfo.pmem_fd = temp_buffer->pmem_fd;
  frameinfo.pmem_offset = temp_buffer->offset;
  frameinfo.timestamp = buffer->nTimeStamp;
  if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr)
  {
    DEBUG_PRINT_LOW("ETB: dmx enabled");
    if (m_demux_entries == 0)
    {
      extract_demux_addr_offsets(buffer);
    }

    DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d",m_demux_entries);
    handle_demux_data(buffer);
    frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
    frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
  }
  else
  {
    frameinfo.desc_addr = NULL;
    frameinfo.desc_size = 0;
  }
  if(!arbitrary_bytes)
  {
      frameinfo.flags |= buffer->nFlags;
  }


#ifdef _ANDROID_
  if (m_debug_timestamp)
  {
    if(arbitrary_bytes)
    {
      DEBUG_PRINT_LOW("\n Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
      m_timestamp_list.insert_ts(buffer->nTimeStamp);
    }
    else if(!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG))
    {
      DEBUG_PRINT_LOW("\n Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
      m_timestamp_list.insert_ts(buffer->nTimeStamp);
    }
  }
#endif

#ifdef INPUT_BUFFER_LOG
  if (inputBufferFile1)
  {
    fwrite((const char *)temp_buffer->bufferaddr,
      temp_buffer->buffer_len,1,inputBufferFile1);
  }
#endif

  if(buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ)
  {
    frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
    buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
  }

  if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS))
  {
    DEBUG_PRINT_HIGH("\n Rxd i/p EOS, Notify Driver that EOS has been reached");
    frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
    h264_scratch.nFilledLen = 0;
    nal_count = 0;
    look_ahead_nal = false;
    frame_count = 0;
    if (m_frame_parser.mutils)
      m_frame_parser.mutils->initialize_frame_checking_environment();
    m_frame_parser.flush();
    h264_last_au_ts = LLONG_MAX;
    h264_last_au_flags = 0;
    memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
    m_demux_entries = 0;
  }
  DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)",
    frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen);
  ioctl_msg.in = &frameinfo;
  ioctl_msg.out = NULL;
  if (ioctl(drv_ctx.video_driver_fd,VDEC_IOCTL_DECODE_FRAME,
            &ioctl_msg) < 0)
  {
    /*Generate an async error and move to invalid state*/
    DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy VDEC_IOCTL_DECODE_FRAME failed");
    if (!arbitrary_bytes)
    {
      DEBUG_PRINT_LOW("\n Return failed buffer");
      post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
                       OMX_COMPONENT_GENERATE_EBD);
    }
    return OMX_ErrorBadParameter;
  } else
      time_stamp_dts.insert_timestamp(buffer);

  return ret;
}

/* ======================================================================
FUNCTION
  omx_vdec::FillThisBuffer

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

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
                                          OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{

  if(m_state == OMX_StateInvalid)
  {
      DEBUG_PRINT_ERROR("FTB in Invalid State\n");
      return OMX_ErrorInvalidState;
  }

  if (!m_out_bEnabled)
  {
    DEBUG_PRINT_ERROR("\nERROR:FTB incorrect state operation, output port is disabled.");
    return OMX_ErrorIncorrectStateOperation;
  }

  if (buffer == NULL ||
     ((buffer - client_buffers.get_il_buf_hdr()) >= drv_ctx.op_buf.actualcount))
  {
    return OMX_ErrorBadParameter;
  }

  if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX)
  {
    DEBUG_PRINT_ERROR("\nERROR:FTB invalid port in header %d", buffer->nOutputPortIndex);
    return OMX_ErrorBadPortIndex;
  }

  DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
  post_event((unsigned) hComp, (unsigned)buffer,m_fill_output_msg);
  return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
  omx_vdec::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_vdec::fill_this_buffer_proxy(
                         OMX_IN OMX_HANDLETYPE        hComp,
                         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
{
  OMX_ERRORTYPE nRet = OMX_ErrorNone;
  struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
  OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
  struct vdec_fillbuffer_cmd fillbuffer;
  struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
  struct vdec_output_frameinfo  *ptr_respbuffer = NULL;


  if (bufferAdd == NULL || ((buffer - client_buffers.get_il_buf_hdr()) >
      drv_ctx.op_buf.actualcount) )
    return OMX_ErrorBadParameter;

  DEBUG_PRINT_LOW("\n FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
      bufferAdd, bufferAdd->pBuffer);
  /*Return back the output buffer to client*/
  if(m_out_bEnabled != OMX_TRUE || output_flush_progress == true)
  {
    DEBUG_PRINT_LOW("\n Output Buffers return flush/disable condition");
    buffer->nFilledLen = 0;
    m_cb.FillBufferDone (hComp,m_app_data,buffer);
    return OMX_ErrorNone;
  }
  pending_output_buffers++;
  buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
  ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
  if (ptr_respbuffer)
  {
    ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
  }

  if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL)
  {
      DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
      buffer->nFilledLen = 0;
      m_cb.FillBufferDone (hComp,m_app_data,buffer);
      pending_output_buffers--;
      return OMX_ErrorBadParameter;
  }

  memcpy (&fillbuffer.buffer,ptr_outputbuffer,\
          sizeof(struct vdec_bufferpayload));
  fillbuffer.client_data = buffer;

  ioctl_msg.in = &fillbuffer;
  ioctl_msg.out = NULL;
  if (ioctl (drv_ctx.video_driver_fd,
         VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
  {
    DEBUG_PRINT_ERROR("\n Decoder frame failed");
    m_cb.FillBufferDone (hComp,m_app_data,buffer);
    pending_output_buffers--;
    return OMX_ErrorBadParameter;
  }

  return OMX_ErrorNone;
}

/* ======================================================================
FUNCTION
  omx_vdec::SetCallbacks

DESCRIPTION
  Set the callbacks.

PARAMETERS
  None.

RETURN VALUE
  OMX Error None if everything successful.

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

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

/* ======================================================================
FUNCTION
  omx_vdec::ComponentDeInit

DESCRIPTION
  Destroys the component and release memory allocated to the heap.

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if everything successful.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
{
#ifdef _ANDROID_
    if(iDivXDrmDecrypt)
    {
        delete iDivXDrmDecrypt;
        iDivXDrmDecrypt=NULL;
    }
#endif //_ANDROID_
    int i = 0;
    if (OMX_StateLoaded != m_state)
    {
        DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\
                          m_state);
        DEBUG_PRINT_ERROR("\nPlayback Ended - FAILED");
    }
    else
    {
      DEBUG_PRINT_HIGH("\n Playback Ended - PASSED");
    }

    if (secure_mode) {
      if (unsecureDisplay(qService::IQService::START) < 0) {
        DEBUG_PRINT_HIGH("Failed to send message to unsecure display START");
      }
    }

    /*Check if the output buffers have to be cleaned up*/
    if(m_out_mem_ptr)
    {
        DEBUG_PRINT_LOW("Freeing the Output Memory\n");
        for (i=0; i < drv_ctx.op_buf.actualcount; i++ )
        {
          free_output_buffer (&m_out_mem_ptr[i]);
        }
    }

    /*Check if the input buffers have to be cleaned up*/
    if(m_inp_mem_ptr || m_inp_heap_ptr)
    {
        DEBUG_PRINT_LOW("Freeing the Input Memory\n");
        for (i=0; i<drv_ctx.ip_buf.actualcount; i++ )
        {
          if (m_inp_mem_ptr)
            free_input_buffer (i,&m_inp_mem_ptr[i]);
          else
            free_input_buffer (i,NULL);
        }
    }
    free_input_buffer_header();
    free_output_buffer_header();
    if(h264_scratch.pBuffer)
    {
        free(h264_scratch.pBuffer);
        h264_scratch.pBuffer = NULL;
    }

    if (h264_parser)
    {
        delete h264_parser;
	h264_parser = NULL;
    }

    if (m_frame_parser.mutils)
    {
        DEBUG_PRINT_LOW("\n Free utils parser");
        delete (m_frame_parser.mutils);
        m_frame_parser.mutils = NULL;
    }

    if(m_platform_list)
    {
        free(m_platform_list);
        m_platform_list = NULL;
    }
    if(m_vendor_config.pData)
    {
        free(m_vendor_config.pData);
        m_vendor_config.pData = NULL;
    }

    // Reset counters in mesg queues
    m_ftb_q.m_size=0;
    m_cmd_q.m_size=0;
    m_etb_q.m_size=0;
    m_ftb_q.m_read = m_ftb_q.m_write =0;
    m_cmd_q.m_read = m_cmd_q.m_write =0;
    m_etb_q.m_read = m_etb_q.m_write =0;
#ifdef _ANDROID_
    if (m_debug_timestamp)
    {
      m_timestamp_list.reset_ts_list();
    }
#endif

    DEBUG_PRINT_LOW("\n Calling VDEC_IOCTL_STOP_NEXT_MSG");
    (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
        NULL);
    DEBUG_PRINT_HIGH("\n Close the driver instance");
#ifdef _ANDROID_
   /* get strong count gets the refernce count of the pmem, the count will
    * be incremented by our kernal driver and surface flinger, by the time
    * we close the pmem, this cound needs to be zero, but there is no way
    * for us to know when surface flinger reduces its cound, so we wait
    * here in a infinite loop till the count is zero
    */
     if (m_heap_ptr)
     {
         for (int indx = 0; indx < drv_ctx.op_buf.actualcount; indx++)
              m_heap_ptr[indx].video_heap_ptr = NULL;
         free(m_heap_ptr);
         m_heap_ptr = NULL;
         m_heap_count = 0;
     }
#endif // _ANDROID_
    close(drv_ctx.video_driver_fd);
#ifdef INPUT_BUFFER_LOG
    fclose (inputBufferFile1);
#endif
#ifdef OUTPUT_BUFFER_LOG
    fclose (outputBufferFile1);
#endif
#ifdef OUTPUT_EXTRADATA_LOG
    fclose (outputExtradataFile);
#endif

    if (secure_mode) {
      if (unsecureDisplay(qService::IQService::END) < 0) {
        DEBUG_PRINT_HIGH("Failed to send message to unsecure display STOP");
      }
    }

  DEBUG_PRINT_HIGH("\n omx_vdec::component_deinit() complete");
  return OMX_ErrorNone;
}

/* ======================================================================
FUNCTION
  omx_vdec::UseEGLImage

DESCRIPTION
  OMX Use EGL Image method implementation <TBD>.

PARAMETERS
  <TBD>.

RETURN VALUE
  Not Implemented error.

========================================================================== */
OMX_ERRORTYPE  omx_vdec::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)
{
  OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
  OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
  OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;

#ifdef USE_EGL_IMAGE_GPU
   PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
   EGLint fd = -1, offset = 0,pmemPtr = 0;
#else
   int fd = -1, offset = 0;
#endif
   DEBUG_PRINT_HIGH("\nuse EGL image support for decoder");
   if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
     DEBUG_PRINT_ERROR("\n ");
   }
#ifdef USE_EGL_IMAGE_GPU
   if(m_display_id == NULL) {
        DEBUG_PRINT_ERROR("Display ID is not set by IL client \n");
        return OMX_ErrorInsufficientResources;
   }
   egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
                    eglGetProcAddress("eglQueryImageKHR");
   egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd);
   egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset);
   egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr);
#else //with OMX test app
    struct temp_egl {
        int pmem_fd;
        int offset;
    };
    struct temp_egl *temp_egl_id = NULL;
    void * pmemPtr = (void *) eglImage;
    temp_egl_id = (struct temp_egl *)eglImage;
    if (temp_egl_id != NULL)
    {
        fd = temp_egl_id->pmem_fd;
        offset = temp_egl_id->offset;
    }
#endif
    if (fd < 0) {
        DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d  \n",fd);
        return OMX_ErrorInsufficientResources;
   }
   pmem_info.pmem_fd = (OMX_U32) fd;
   pmem_info.offset = (OMX_U32) offset;
   pmem_entry.entry = (void *) &pmem_info;
   pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
   pmem_list.entryList = &pmem_entry;
   pmem_list.nEntries = 1;
   ouput_egl_buffers = true;
   if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
       (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
        (OMX_U8 *)pmemPtr)) {
     DEBUG_PRINT_ERROR("use buffer call failed for egl image\n");
     return OMX_ErrorInsufficientResources;
   }
   return OMX_ErrorNone;
}

/* ======================================================================
FUNCTION
  omx_vdec::ComponentRoleEnum

DESCRIPTION
  OMX Component Role Enum method implementation.

PARAMETERS
  <TBD>.

RETURN VALUE
  OMX Error None if everything is successful.
========================================================================== */
OMX_ERRORTYPE  omx_vdec::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(drv_ctx.kind, "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;
    }
  }
  if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE))
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      eRet = OMX_ErrorNoMore;
    }
  }
  else if(!strncmp(drv_ctx.kind, "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_LOW("\n No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
#ifdef MAX_RES_1080P
  else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
          (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))
          )
#else
  else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE))
#endif
  {
    if((0 == index) && role)
    {
      strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
      DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
    }
    else
    {
      DEBUG_PRINT_LOW("\n No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  else if(!strncmp(drv_ctx.kind, "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_LOW("\n No more roles \n");
      eRet = OMX_ErrorNoMore;
    }
  }
  else if( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
           (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",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_LOW("\n 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_vdec::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_vdec::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_vdec::AllocateInputDone

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

PARAMETERS
  None.

RETURN VALUE
  true/false.

========================================================================== */
bool omx_vdec::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<drv_ctx.ip_buf.actualcount;i++)
    {
      if(BITMASK_ABSENT(&m_inp_bm_count,i))
      {
        break;
      }
    }
  }
  if(i == drv_ctx.ip_buf.actualcount)
  {
    bRet = true;
    DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
  }
  if(i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled)
  {
     m_inp_bPopulated = OMX_TRUE;
  }
  return bRet;
}
/* ======================================================================
FUNCTION
  omx_vdec::AllocateOutputDone

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

PARAMETERS
  None.

RETURN VALUE
  true/false.

========================================================================== */
bool omx_vdec::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 < drv_ctx.op_buf.actualcount;j++)
    {
      if(BITMASK_ABSENT(&m_out_bm_count,j))
      {
        break;
      }
    }
  }

  if(j == drv_ctx.op_buf.actualcount)
  {
    bRet = true;
    DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
    if(m_out_bEnabled)
       m_out_bPopulated = OMX_TRUE;
  }

  return bRet;
}

/* ======================================================================
FUNCTION
  omx_vdec::ReleaseDone

DESCRIPTION
  Checks if IL client has released all the buffers.

PARAMETERS
  None.

RETURN VALUE
  true/false

========================================================================== */
bool omx_vdec::release_done(void)
{
  bool bRet = false;

  if(release_input_done())
  {
    if(release_output_done())
    {
        bRet = true;
    }
  }
  return bRet;
}


/* ======================================================================
FUNCTION
  omx_vdec::ReleaseOutputDone

DESCRIPTION
  Checks if IL client has released all the buffers.

PARAMETERS
  None.

RETURN VALUE
  true/false

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

  DEBUG_PRINT_LOW("\n Value of m_out_mem_ptr %p",m_inp_mem_ptr);
  if(m_out_mem_ptr)
  {
      for(;j < drv_ctx.op_buf.actualcount ; j++)
      {
        if(BITMASK_PRESENT(&m_out_bm_count,j))
        {
          break;
        }
      }
    if(j == drv_ctx.op_buf.actualcount)
    {
      m_out_bm_count = 0;
      bRet = true;
    }
  }
  else
  {
    m_out_bm_count = 0;
    bRet = true;
  }
  return bRet;
}
/* ======================================================================
FUNCTION
  omx_vdec::ReleaseInputDone

DESCRIPTION
  Checks if IL client has released all the buffers.

PARAMETERS
  None.

RETURN VALUE
  true/false

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

  DEBUG_PRINT_LOW("\n Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
  if(m_inp_mem_ptr)
  {
      for(;j<drv_ctx.ip_buf.actualcount;j++)
      {
        if( BITMASK_PRESENT(&m_inp_bm_count,j))
        {
          break;
        }
      }
    if(j==drv_ctx.ip_buf.actualcount)
    {
      bRet = true;
    }
  }
  else
  {
    bRet = true;
  }
  return bRet;
}

OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
                               OMX_BUFFERHEADERTYPE * buffer)
{
  OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;

  if (!buffer || (buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount)
  {
    DEBUG_PRINT_ERROR("\n [FBD] ERROR in ptr(%p)", buffer);
    return OMX_ErrorBadParameter;
  }
  else if (output_flush_progress)
  {
    DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
    buffer->nFilledLen = 0;
    buffer->nTimeStamp = 0;
    buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
    buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
    buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
  }

#ifdef _ANDROID_
  char value[PROPERTY_VALUE_MAX];
  property_get("vidc.dec.debug.panframedata", value, NULL);

  if (atoi(value))
  {
    if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ)
    {
      DEBUG_PRINT_HIGH("\n");
      DEBUG_PRINT_HIGH("***************************************************\n");
      DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received\n");
      DEBUG_PRINT_HIGH("***************************************************\n");
    }

    if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT)
    {
      DEBUG_PRINT_HIGH("\n");
      DEBUG_PRINT_HIGH("***************************************************\n");
      DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received\n");
      DEBUG_PRINT_HIGH("***************************************************\n");
    }
  }
#endif

  DEBUG_PRINT_LOW("\n fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
      buffer, buffer->pBuffer);
  pending_output_buffers --;

  if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
  {
    DEBUG_PRINT_HIGH("\n Output EOS has been reached");
    if (!output_flush_progress)
      post_event(NULL,NULL,OMX_COMPONENT_GENERATE_EOS_DONE);

    if (psource_frame)
    {
      m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
      psource_frame = NULL;
    }
    if (pdest_frame)
    {
      pdest_frame->nFilledLen = 0;
      m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
      pdest_frame = NULL;
    }
  }

  DEBUG_PRINT_LOW("\n In fill Buffer done call address %p ",buffer);
#ifdef OUTPUT_BUFFER_LOG
  if (outputBufferFile1)
  {
    OMX_U32 index = buffer - m_out_mem_ptr;
    OMX_U8* pBuffer = (OMX_U8 *)drv_ctx.ptr_outputbuffer[index].bufferaddr;

    fwrite (pBuffer,1,buffer->nFilledLen,
                  outputBufferFile1);
  }
#endif

  /* For use buffer we need to copy the data */
  if (!output_flush_progress)
  {
    time_stamp_dts.get_next_timestamp(buffer,
    (drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
     ?true:false);
  }
  if (m_cb.FillBufferDone)
  {
    if (buffer->nFilledLen > 0)
    {
      if (client_extradata)
        handle_extradata(buffer);
      if (client_extradata & OMX_TIMEINFO_EXTRADATA)
        // Keep min timestamp interval to handle corrupted bit stream scenario
        set_frame_rate(buffer->nTimeStamp);
      else if (arbitrary_bytes)
        adjust_timestamp(buffer->nTimeStamp);
#ifdef _ANDROID_
      if (perf_flag)
      {
        if (!proc_frms)
        {
          dec_time.stop();
          latency = dec_time.processing_time_us() - latency;
          DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
          dec_time.start();
          fps_metrics.start();
        }
        proc_frms++;
        if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
        {
          OMX_U64 proc_time = 0;
          fps_metrics.stop();
          proc_time = fps_metrics.processing_time_us();
          DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)",
                            proc_frms, (float)proc_time / 1e6,
                            (float)(1e6 * proc_frms) / proc_time);
          proc_frms = 0;
        }
      }
#endif //_ANDROID_

#ifdef OUTPUT_EXTRADATA_LOG
  if (outputExtradataFile)
  {

    OMX_U32 index = buffer - m_out_mem_ptr;
    OMX_U8* pBuffer = (OMX_U8 *)drv_ctx.ptr_outputbuffer[index].bufferaddr;

    OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
    p_extra = (OMX_OTHER_EXTRADATATYPE *)
           ((unsigned)(pBuffer + buffer->nOffset +
            buffer->nFilledLen + 3)&(~3));
    while(p_extra &&
          (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) )
    {
      DEBUG_PRINT_LOW("\nWRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType);
      fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
      if (p_extra->eType == OMX_ExtraDataNone)
      {
        break;
      }
      p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
    }
  }
#endif
    }
    if (buffer->nFlags & OMX_BUFFERFLAG_EOS){
      prev_ts = LLONG_MAX;
      rst_prev_ts = true;
      }

    pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
                ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
                buffer->pPlatformPrivate)->entryList->entry;
    DEBUG_PRINT_LOW("\n Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd);
    OMX_BUFFERHEADERTYPE *il_buffer;
    il_buffer = client_buffers.get_il_buf_hdr(buffer);
    if (il_buffer)
      m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
    else {
      DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
      return OMX_ErrorBadParameter;
    }

    DEBUG_PRINT_LOW("\n After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd);
  }
  else
  {
    return OMX_ErrorBadParameter;
  }

  return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
                                          OMX_BUFFERHEADERTYPE* buffer)
{

    if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount))
    {
        DEBUG_PRINT_ERROR("\n empty_buffer_done: ERROR bufhdr = %p", buffer);
       return OMX_ErrorBadParameter;
    }

    DEBUG_PRINT_LOW("\n empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
        buffer, buffer->pBuffer);
    pending_input_buffers--;

    if (arbitrary_bytes)
    {
      if (pdest_frame == NULL && input_flush_progress == false)
      {
        DEBUG_PRINT_LOW("\n Push input from buffer done address of Buffer %p",buffer);
        pdest_frame = buffer;
        buffer->nFilledLen = 0;
        buffer->nTimeStamp = LLONG_MAX;
        push_input_buffer (hComp);
      }
      else
      {
        DEBUG_PRINT_LOW("\n Push buffer into freeq address of Buffer %p",buffer);
        buffer->nFilledLen = 0;
        if (!m_input_free_q.insert_entry((unsigned)buffer,NULL,NULL))
        {
          DEBUG_PRINT_ERROR("\nERROR:i/p free Queue is FULL Error");
        }
      }
    }
    else if(m_cb.EmptyBufferDone)
    {
        buffer->nFilledLen = 0;
        if (input_use_buffer == true){
            buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
        }
        m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
    }
    return OMX_ErrorNone;
}


int omx_vdec::async_message_process (void *context, void* message)
{
  omx_vdec* omx = NULL;
  struct vdec_msginfo *vdec_msg = NULL;
  OMX_BUFFERHEADERTYPE* omxhdr = NULL;
  struct vdec_output_frameinfo *output_respbuf = NULL;

  if (context == NULL || message == NULL)
  {
    DEBUG_PRINT_ERROR("\n FATAL ERROR in omx_vdec::async_message_process NULL Check");
    return -1;
  }
  vdec_msg = (struct vdec_msginfo *)message;

  omx = reinterpret_cast<omx_vdec*>(context);

#ifdef _ANDROID_
  if (omx->m_debug_timestamp)
  {
    if ( (vdec_msg->msgcode == VDEC_MSG_RESP_OUTPUT_BUFFER_DONE) &&
         !(omx->output_flush_progress) )
    {
      OMX_TICKS expected_ts = 0;
      omx->m_timestamp_list.pop_min_ts(expected_ts);
      DEBUG_PRINT_LOW("\n Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
                       vdec_msg->msgdata.output_frame.time_stamp, expected_ts);

      if (vdec_msg->msgdata.output_frame.time_stamp != expected_ts)
      {
        DEBUG_PRINT_ERROR("\n ERROR in omx_vdec::async_message_process timestamp Check");
      }
    }
  }
#endif

  switch (vdec_msg->msgcode)
  {

  case VDEC_MSG_EVT_HW_ERROR:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
  break;

  case VDEC_MSG_RESP_START_DONE:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_START_DONE);
  break;

  case VDEC_MSG_RESP_STOP_DONE:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_STOP_DONE);
  break;

  case VDEC_MSG_RESP_RESUME_DONE:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_RESUME_DONE);
  break;

  case VDEC_MSG_RESP_PAUSE_DONE:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
  break;

  case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
    break;
  case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
    omx->post_event (NULL,vdec_msg->status_code,\
                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
    break;
  case VDEC_MSG_RESP_INPUT_FLUSHED:
  case VDEC_MSG_RESP_INPUT_BUFFER_DONE:

    omxhdr = (OMX_BUFFERHEADERTYPE* )\
              vdec_msg->msgdata.input_frame_clientdata;


    if (omxhdr == NULL ||
       ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) )
    {
       omxhdr = NULL;
       vdec_msg->status_code = VDEC_S_EFATAL;
    }

    omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
                     OMX_COMPONENT_GENERATE_EBD);
    break;
    case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
      int64_t *timestamp;
      timestamp = (int64_t *) malloc(sizeof(int64_t));
      if (timestamp) {
        *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
        omx->post_event ((unsigned int)timestamp, vdec_msg->status_code,
                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
        DEBUG_PRINT_HIGH("\nField dropped time stamp is %lld",
             vdec_msg->msgdata.output_frame.time_stamp);
      }
      break;
  case VDEC_MSG_RESP_OUTPUT_FLUSHED:
    case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
    omxhdr = (OMX_BUFFERHEADERTYPE*)vdec_msg->msgdata.output_frame.client_data;
    DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)",
      omxhdr, vdec_msg->msgdata.output_frame.time_stamp,
      vdec_msg->msgdata.output_frame.pic_type);

    /* update SYNCFRAME flag */
    if (omx->eCompressionFormat == OMX_VIDEO_CodingAVC)
    {
      /* set SYNCFRAME flag if picture type is IDR for h264 */
      if (vdec_msg->msgdata.output_frame.pic_type == PICTURE_TYPE_IDR)
        vdec_msg->msgdata.output_frame.flags |= OMX_BUFFERFLAG_SYNCFRAME;
      else
        vdec_msg->msgdata.output_frame.flags &= ~OMX_BUFFERFLAG_SYNCFRAME;
    }
    else
    {
      /* set SYNCFRAME flag if picture type is I_TYPE */
      if (vdec_msg->msgdata.output_frame.pic_type == PICTURE_TYPE_I)
        vdec_msg->msgdata.output_frame.flags |= OMX_BUFFERFLAG_SYNCFRAME;
      else
        vdec_msg->msgdata.output_frame.flags &= ~OMX_BUFFERFLAG_SYNCFRAME;
    }

    if (omxhdr && omxhdr->pOutputPortPrivate &&
        ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) &&
         (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
            - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount))
    {
      if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen)
      {
        omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
        omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
        omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
        omxhdr->nFlags = (vdec_msg->msgdata.output_frame.flags);

        output_respbuf = (struct vdec_output_frameinfo *)\
                          omxhdr->pOutputPortPrivate;
        output_respbuf->framesize.bottom =
          vdec_msg->msgdata.output_frame.framesize.bottom;
        output_respbuf->framesize.left =
          vdec_msg->msgdata.output_frame.framesize.left;
        output_respbuf->framesize.right =
          vdec_msg->msgdata.output_frame.framesize.right;
        output_respbuf->framesize.top =
          vdec_msg->msgdata.output_frame.framesize.top;
        output_respbuf->len = vdec_msg->msgdata.output_frame.len;
        output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
        output_respbuf->time_stamp = vdec_msg->msgdata.output_frame.time_stamp;
        output_respbuf->flags = vdec_msg->msgdata.output_frame.flags;
        output_respbuf->pic_type = vdec_msg->msgdata.output_frame.pic_type;
        output_respbuf->interlaced_format = vdec_msg->msgdata.output_frame.interlaced_format;
        output_respbuf->aspect_ratio_info =
           vdec_msg->msgdata.output_frame.aspect_ratio_info;


        if (omx->output_use_buffer)
          memcpy ( omxhdr->pBuffer,
                   (vdec_msg->msgdata.output_frame.bufferaddr +
                    vdec_msg->msgdata.output_frame.offset),
                    vdec_msg->msgdata.output_frame.len );
      }
      else
        omxhdr->nFilledLen = 0;
      omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code,
                       OMX_COMPONENT_GENERATE_FBD);
    }
    else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS)
      omx->post_event (NULL, vdec_msg->status_code,
                       OMX_COMPONENT_GENERATE_EOS_DONE);
    else
      omx->post_event (NULL, vdec_msg->status_code,
                       OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
    break;
  case VDEC_MSG_EVT_CONFIG_CHANGED:
    DEBUG_PRINT_HIGH("\n Port settings changed");
    omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
    break;
  case VDEC_MSG_EVT_INFO_CONFIG_CHANGED:
  {
    DEBUG_PRINT_HIGH("\n Port settings changed info");
    // get_buffer_req and populate port defn structure
    OMX_ERRORTYPE eRet = OMX_ErrorNone;
    omx->m_port_def.nPortIndex = 1;
    eRet = omx->update_portdef(&(omx->m_port_def));
    omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
                     OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG);
    break;
  }
  default:
    break;
  }
  return 1;
}

OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
                                                   OMX_HANDLETYPE hComp,
                                                   OMX_BUFFERHEADERTYPE *buffer
                                                           )
{
  unsigned address,p2,id;
  DEBUG_PRINT_LOW("\n Empty this arbitrary");

  if (buffer == NULL)
  {
    return OMX_ErrorBadParameter;
  }
  DEBUG_PRINT_LOW("\n ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
  DEBUG_PRINT_LOW("\n ETBProxyArb: nFilledLen %u, flags %d, timestamp %u",
        buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp);

  /* return zero length and not an EOS buffer */
  /* return buffer if input flush in progress */
  if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
     ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)))
  {
    DEBUG_PRINT_HIGH("\n return zero legth buffer or flush in progress");
    m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
    return OMX_ErrorNone;
  }

  if (psource_frame == NULL)
  {
    DEBUG_PRINT_LOW("\n Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp);
    psource_frame = buffer;
    DEBUG_PRINT_LOW("\n Try to Push One Input Buffer ");
    push_input_buffer (hComp);
  }
  else
  {
    DEBUG_PRINT_LOW("\n Push the source buffer into pendingq %p",buffer);
    if (!m_input_pending_q.insert_entry((unsigned)buffer,NULL,NULL))
    {
      return OMX_ErrorBadParameter;
    }
  }


  return OMX_ErrorNone;
}

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

  if (pdest_frame == NULL || psource_frame == NULL)
  {
    /*Check if we have a destination buffer*/
    if (pdest_frame == NULL)
    {
      DEBUG_PRINT_LOW("\n Get a Destination buffer from the queue");
      if (m_input_free_q.m_size)
      {
        m_input_free_q.pop_entry(&address,&p2,&id);
        pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
        pdest_frame->nFilledLen = 0;
        pdest_frame->nTimeStamp = LLONG_MAX;
        DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",pdest_frame);
      }
    }

    /*Check if we have a destination buffer*/
    if (psource_frame == NULL)
    {
      DEBUG_PRINT_LOW("\n Get a source buffer from the queue");
      if (m_input_pending_q.m_size)
      {
        m_input_pending_q.pop_entry(&address,&p2,&id);
        psource_frame = (OMX_BUFFERHEADERTYPE *)address;
        DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame,
                psource_frame->nTimeStamp);
        DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d",
        psource_frame->nFlags,psource_frame->nFilledLen);

      }
    }

  }

  while ((pdest_frame != NULL) && (psource_frame != NULL))
  {
    switch (codec_type_parse)
    {
      case CODEC_TYPE_MPEG4:
      case CODEC_TYPE_H263:
      case CODEC_TYPE_MPEG2:
        ret =  push_input_sc_codec(hComp);
      break;
      case CODEC_TYPE_H264:
        ret = push_input_h264(hComp);
      break;
      case CODEC_TYPE_VC1:
        ret = push_input_vc1(hComp);
      break;
    }
    if (ret != OMX_ErrorNone)
    {
      DEBUG_PRINT_ERROR("\n Pushing input Buffer Failed");
      omx_report_error ();
      break;
    }
  }

  return ret;
}

OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
{
  OMX_U32 partial_frame = 1;
  OMX_BOOL generate_ebd = OMX_TRUE;
  unsigned address,p2,id;

  DEBUG_PRINT_LOW("\n Start Parsing the bit stream address %p TimeStamp %d",
        psource_frame,psource_frame->nTimeStamp);
  if (m_frame_parser.parse_sc_frame(psource_frame,
                                       pdest_frame,&partial_frame) == -1)
  {
    DEBUG_PRINT_ERROR("\n Error In Parsing Return Error");
    return OMX_ErrorBadParameter;
  }

  if (partial_frame == 0)
  {
    DEBUG_PRINT_LOW("\n Frame size %d source %p frame count %d",
          pdest_frame->nFilledLen,psource_frame,frame_count);


    DEBUG_PRINT_LOW("\n TimeStamp updated %d",pdest_frame->nTimeStamp);
    /*First Parsed buffer will have only header Hence skip*/
    if (frame_count == 0)
    {
      DEBUG_PRINT_LOW("\n H263/MPEG4 Codec First Frame ");
#ifdef MAX_RES_1080P
      if(codec_type_parse == CODEC_TYPE_MPEG4 ||
         codec_type_parse == CODEC_TYPE_DIVX) {
        mp4StreamType psBits;
        psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
        psBits.numBytes = pdest_frame->nFilledLen;
        mp4_headerparser.parseHeader(&psBits);
      }
#endif
      frame_count++;
    }
    else
    {
      pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
      if(pdest_frame->nFilledLen)
      {
        /*Push the frame to the Decoder*/
        if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
        {
          return OMX_ErrorBadParameter;
        }
        frame_count++;
        pdest_frame = NULL;

        if (m_input_free_q.m_size)
        {
          m_input_free_q.pop_entry(&address,&p2,&id);
          pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
          pdest_frame->nFilledLen = 0;
        }
      }
      else if(!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS))
      {
        DEBUG_PRINT_ERROR("\nZero len buffer return back to POOL");
        m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
        pdest_frame = NULL;
      }
    }
  }
  else
  {
    DEBUG_PRINT_LOW("\n Not a Complete Frame %d",pdest_frame->nFilledLen);
    /*Check if Destination Buffer is full*/
    if (pdest_frame->nAllocLen ==
        pdest_frame->nFilledLen + pdest_frame->nOffset)
    {
      DEBUG_PRINT_ERROR("\nERROR:Frame Not found though Destination Filled");
      return OMX_ErrorStreamCorrupt;
    }
  }

  if (psource_frame->nFilledLen == 0)
  {
    if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)
    {
      if (pdest_frame)
      {
        pdest_frame->nFlags |= psource_frame->nFlags;
        DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
                     pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
        DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
                     pdest_frame->nFilledLen,frame_count++);
        /*Push the frame to the Decoder*/
        if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
        {
          return OMX_ErrorBadParameter;
        }
        frame_count++;
        pdest_frame = NULL;
      }
      else
      {
        DEBUG_PRINT_LOW("\n Last frame in else dest addr") ;
        generate_ebd = OMX_FALSE;
      }
   }
    if(generate_ebd)
    {
      DEBUG_PRINT_LOW("\n Buffer Consumed return back to client %p",psource_frame);
      m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
      psource_frame = NULL;

      if (m_input_pending_q.m_size)
      {
        DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame);
        m_input_pending_q.pop_entry(&address,&p2,&id);
        psource_frame = (OMX_BUFFERHEADERTYPE *) address;
        DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame,
                psource_frame->nTimeStamp);
        DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d",
        psource_frame->nFlags,psource_frame->nFilledLen);
      }
    }
   }
  return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
{
  OMX_U32 partial_frame = 1;
  unsigned address,p2,id;
  OMX_BOOL isNewFrame = OMX_FALSE;
  OMX_BOOL generate_ebd = OMX_TRUE;

  if (h264_scratch.pBuffer == NULL)
  {
    DEBUG_PRINT_ERROR("\nERROR:H.264 Scratch Buffer not allocated");
    return OMX_ErrorBadParameter;
  }
  DEBUG_PRINT_LOW("\n Pending h264_scratch.nFilledLen %d "
      "look_ahead_nal %d", h264_scratch.nFilledLen, look_ahead_nal);
  DEBUG_PRINT_LOW("\n Pending pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
  if (h264_scratch.nFilledLen && look_ahead_nal)
  {
    look_ahead_nal = false;
    if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
         h264_scratch.nFilledLen)
    {
      memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
              h264_scratch.pBuffer,h264_scratch.nFilledLen);
      pdest_frame->nFilledLen += h264_scratch.nFilledLen;
      DEBUG_PRINT_LOW("\n Copy the previous NAL (h264 scratch) into Dest frame");
      h264_scratch.nFilledLen = 0;
    }
    else
    {
      DEBUG_PRINT_ERROR("\n Error:1: Destination buffer overflow for H264");
      return OMX_ErrorBadParameter;
    }
  }
  if (nal_length == 0)
  {
    DEBUG_PRINT_LOW("\n Zero NAL, hence parse using start code");
    if (m_frame_parser.parse_sc_frame(psource_frame,
        &h264_scratch,&partial_frame) == -1)
    {
      DEBUG_PRINT_ERROR("\n Error In Parsing Return Error");
      return OMX_ErrorBadParameter;
    }
  }
  else
  {
    DEBUG_PRINT_LOW("\n Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
    if (m_frame_parser.parse_h264_nallength(psource_frame,
        &h264_scratch,&partial_frame) == -1)
    {
      DEBUG_PRINT_ERROR("\n Error In Parsing NAL size, Return Error");
      return OMX_ErrorBadParameter;
    }
  }

  if (partial_frame == 0)
  {
    if (nal_count == 0 && h264_scratch.nFilledLen == 0)
    {
      DEBUG_PRINT_LOW("\n First NAL with Zero Length, hence Skip");
      nal_count++;
      h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
      h264_scratch.nFlags = psource_frame->nFlags;
    }
    else
    {
      DEBUG_PRINT_LOW("\n Parsed New NAL Length = %d",h264_scratch.nFilledLen);
      if(h264_scratch.nFilledLen)
      {
          h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
                                 NALU_TYPE_SPS);
#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
        if (client_extradata & OMX_TIMEINFO_EXTRADATA)
          h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
                                  h264_scratch.nFilledLen, NALU_TYPE_SEI);
        else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
          // If timeinfo is present frame info from SEI is already processed
          h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
                                  h264_scratch.nFilledLen, NALU_TYPE_SEI);
#endif
        m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
        nal_count++;
        if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
          pdest_frame->nTimeStamp = h264_last_au_ts;
          pdest_frame->nFlags = h264_last_au_flags;
#ifdef PANSCAN_HDLR
          if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
            h264_parser->update_panscan_data(h264_last_au_ts);
#endif
        }
        if(m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
           m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
          h264_last_au_ts = h264_scratch.nTimeStamp;
          h264_last_au_flags = h264_scratch.nFlags;
#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
          if (client_extradata & OMX_TIMEINFO_EXTRADATA)
          {
            OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
            if (!VALID_TS(h264_last_au_ts))
              h264_last_au_ts = ts_in_sei;
          }
#endif
        } else
          h264_last_au_ts = LLONG_MAX;
      }

      if (!isNewFrame)
      {
        if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
            h264_scratch.nFilledLen)
        {
          DEBUG_PRINT_LOW("\n Not a NewFrame Copy into Dest len %d",
              h264_scratch.nFilledLen);
          memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
              h264_scratch.pBuffer,h264_scratch.nFilledLen);
          pdest_frame->nFilledLen += h264_scratch.nFilledLen;
          if(m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
            pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
          h264_scratch.nFilledLen = 0;
        }
        else
        {
          DEBUG_PRINT_LOW("\n Error:2: Destination buffer overflow for H264");
          return OMX_ErrorBadParameter;
        }
      }
      else if(h264_scratch.nFilledLen)
      {
        look_ahead_nal = true;
        DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
                     pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
        DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
                     pdest_frame->nFilledLen,frame_count++);

        if (pdest_frame->nFilledLen == 0)
        {
          DEBUG_PRINT_LOW("\n Copy the Current Frame since and push it");
          look_ahead_nal = false;
          if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
               h264_scratch.nFilledLen)
          {
            memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
                    h264_scratch.pBuffer,h264_scratch.nFilledLen);
            pdest_frame->nFilledLen += h264_scratch.nFilledLen;
            h264_scratch.nFilledLen = 0;
          }
          else
          {
            DEBUG_PRINT_ERROR("\n Error:3: Destination buffer overflow for H264");
            return OMX_ErrorBadParameter;
          }
        }
        else
        {
          if(psource_frame->nFilledLen || h264_scratch.nFilledLen)
          {
            DEBUG_PRINT_LOW("\n Reset the EOS Flag");
            pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
          }
          /*Push the frame to the Decoder*/
          if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
          {
            return OMX_ErrorBadParameter;
          }
          //frame_count++;
          pdest_frame = NULL;
          if (m_input_free_q.m_size)
          {
            m_input_free_q.pop_entry(&address,&p2,&id);
            pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
            DEBUG_PRINT_LOW("\n Pop the next pdest_buffer %p",pdest_frame);
            pdest_frame->nFilledLen = 0;
            pdest_frame->nFlags = 0;
            pdest_frame->nTimeStamp = LLONG_MAX;
          }
        }
      }
    }
  }
  else
  {
    DEBUG_PRINT_LOW("\n Not a Complete Frame, pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
    /*Check if Destination Buffer is full*/
    if (h264_scratch.nAllocLen ==
        h264_scratch.nFilledLen + h264_scratch.nOffset)
    {
      DEBUG_PRINT_ERROR("\nERROR: Frame Not found though Destination Filled");
      return OMX_ErrorStreamCorrupt;
    }
  }

  if (!psource_frame->nFilledLen)
  {
    DEBUG_PRINT_LOW("\n Buffer Consumed return source %p back to client",psource_frame);

    if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)
    {
      if (pdest_frame)
      {
        DEBUG_PRINT_LOW("\n EOS Reached Pass Last Buffer");
        if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
             h264_scratch.nFilledLen)
        {
            if (pdest_frame->nFilledLen == 0)
            {
                /* No residual frame from before, send whatever
                 * we have left */
                memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
                h264_scratch.pBuffer, h264_scratch.nFilledLen);
                pdest_frame->nFilledLen += h264_scratch.nFilledLen;
                h264_scratch.nFilledLen = 0;
                pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
            }
            else
            {
                m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
                if (!isNewFrame)
                {
                    /* Have a residual frame, but we know that the
                     * AU in this frame is belonging to whatever
                     * frame we had left over.  So append it */
                    memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
                    h264_scratch.pBuffer, h264_scratch.nFilledLen);
                    pdest_frame->nFilledLen += h264_scratch.nFilledLen;
                    h264_scratch.nFilledLen = 0;
                    pdest_frame->nTimeStamp = h264_last_au_ts;
                }
                else
                {
                    /* Completely new frame, let's just push what
                     * we have now.  The resulting EBD would trigger
                     * another push */
                    generate_ebd = OMX_FALSE;
                    pdest_frame->nTimeStamp = h264_last_au_ts;
                    h264_last_au_ts = h264_scratch.nTimeStamp;
                }
            }
        }
        else
        {
          DEBUG_PRINT_ERROR("\nERROR:4: Destination buffer overflow for H264");
          return OMX_ErrorBadParameter;
        }

        /* Iff we coalesced two buffers, inherit the flags of both bufs */
        if (generate_ebd == OMX_TRUE)
        {
            pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
        }
#ifdef MAX_RES_720P
        if (frame_count == 0)
        {
           DEBUG_PRINT_HIGH("No frames sent to driver yet, "
              "So send zero length EOS buffer");
           pdest_frame->nFilledLen = 0;
        }
#endif
        DEBUG_PRINT_LOW("pdest_frame->nFilledLen = %d, nFlags = 0x%x, TimeStamp = %x",
                     pdest_frame->nFilledLen, pdest_frame->nFlags, pdest_frame->nTimeStamp);
        DEBUG_PRINT_LOW("\n Push AU frame number %d to driver", frame_count++);
#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
        if (client_extradata & OMX_TIMEINFO_EXTRADATA)
        {
          OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
          if (!VALID_TS(pdest_frame->nTimeStamp))
            pdest_frame->nTimeStamp = ts_in_sei;
        }
#endif
        /*Push the frame to the Decoder*/
        if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
        {
          return OMX_ErrorBadParameter;
        }
        frame_count++;
        pdest_frame = NULL;
      }
      else
      {
        DEBUG_PRINT_LOW("\n Last frame in else dest addr %p size %d",
                     pdest_frame,h264_scratch.nFilledLen);
        generate_ebd = OMX_FALSE;
      }
    }
  }
  if(generate_ebd && !psource_frame->nFilledLen)
  {
    m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
    psource_frame = NULL;
    if (m_input_pending_q.m_size)
    {
      DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame);
      m_input_pending_q.pop_entry(&address,&p2,&id);
      psource_frame = (OMX_BUFFERHEADERTYPE *) address;
      DEBUG_PRINT_LOW("\nNext source Buffer flag %d src length %d",
      psource_frame->nFlags,psource_frame->nFilledLen);
    }
  }
  return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp)
{
    OMX_U8 *buf, *pdest;
    OMX_U32 partial_frame = 1;
    OMX_U32 buf_len, dest_len;

    if(first_frame == 0)
    {
        first_frame = 1;
        DEBUG_PRINT_LOW("\nFirst i/p buffer for VC1 arbitrary bytes\n");
        if(!m_vendor_config.pData)
        {
            DEBUG_PRINT_LOW("\nCheck profile type in 1st source buffer\n");
            buf = psource_frame->pBuffer;
            buf_len = psource_frame->nFilledLen;

            if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
                VC1_SP_MP_START_CODE)
            {
                m_vc1_profile = VC1_SP_MP_RCV;
            }
            else if(*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE)
            {
                m_vc1_profile = VC1_AP;
            }
            else
            {
                DEBUG_PRINT_ERROR("\nInvalid sequence layer in first buffer\n");
                return OMX_ErrorStreamCorrupt;
            }
        }
        else
        {
            pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
                pdest_frame->nOffset;
            dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
                pdest_frame->nOffset);

            if(dest_len < m_vendor_config.nDataSize)
            {
                DEBUG_PRINT_ERROR("\nDestination buffer full\n");
                return OMX_ErrorBadParameter;
            }
            else
            {
                memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
                pdest_frame->nFilledLen += m_vendor_config.nDataSize;
            }
        }
    }

    switch(m_vc1_profile)
    {
        case VC1_AP:
            DEBUG_PRINT_LOW("\n VC1 AP, hence parse using frame start code");
            if (push_input_sc_codec(hComp) != OMX_ErrorNone)
            {
                DEBUG_PRINT_ERROR("\n Error In Parsing VC1 AP start code");
                return OMX_ErrorBadParameter;
            }
        break;

        case VC1_SP_MP_RCV:
        default:
            DEBUG_PRINT_ERROR("\n Unsupported VC1 profile in ArbitraryBytes Mode\n");
            return OMX_ErrorBadParameter;
    }
    return OMX_ErrorNone;
}

#ifndef USE_ION
bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
                                  OMX_U32 alignment)
{
  struct pmem_allocation allocation;
  allocation.size = buffer_size;
  allocation.align = clip2(alignment);
  if (allocation.align < 4096)
  {
    allocation.align = 4096;
  }
  if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0)
  {
    DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)",
      allocation.align, allocation.size);
    return false;
  }
  return true;
}
#endif

#ifdef USE_ION
int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
              OMX_U32 alignment, struct ion_allocation_data *alloc_data,
	      struct ion_fd_data *fd_data,int flag)
{
  int fd = -EINVAL;
  int rc = -EINVAL;
  int ion_dev_flag;
  struct vdec_ion ion_buf_info;
  if (!alloc_data || buffer_size <= 0 || !fd_data) {
     DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory\n");
     return -EINVAL;
  }
  ion_dev_flag = O_RDONLY;
  fd = open (MEM_DEVICE, ion_dev_flag);
  if (fd < 0) {
     DEBUG_PRINT_ERROR("opening ion device failed with fd = %d\n", fd);
     return fd;
  }
  alloc_data->flags = 0;
  if (!secure_mode && (flag & ION_FLAG_CACHED))
  {
    alloc_data->flags |= ION_FLAG_CACHED;
  }
  alloc_data->len = buffer_size;
  alloc_data->align = clip2(alignment);
  if (alloc_data->align < 4096)
  {
    alloc_data->align = 4096;
  }

  if(secure_mode) {
    alloc_data->heap_mask = ION_HEAP(MEM_HEAP_ID);
    alloc_data->flags |= ION_SECURE;
  } else {
    alloc_data->heap_mask = (ION_HEAP(ION_IOMMU_HEAP_ID));
  }
  rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
  if (rc || !alloc_data->handle) {
    DEBUG_PRINT_ERROR("\n ION ALLOC memory failed ");
    alloc_data->handle = NULL;
    close(fd);
    fd = -ENOMEM;
    return fd;
  }
  fd_data->handle = alloc_data->handle;
  rc = ioctl(fd,ION_IOC_MAP,fd_data);
  if (rc) {
    DEBUG_PRINT_ERROR("\n ION MAP failed ");
    ion_buf_info.ion_alloc_data = *alloc_data;
    ion_buf_info.ion_device_fd = fd;
    ion_buf_info.fd_ion_data = *fd_data;
    free_ion_memory(&ion_buf_info);
    fd_data->fd =-1;
    close(fd);
    fd = -ENOMEM;
  }

  return fd;
}

void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) {

     if(!buf_ion_info) {
       DEBUG_PRINT_ERROR("\n ION: free called with invalid fd/allocdata");
       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" );
     }
     close(buf_ion_info->ion_device_fd);
     buf_ion_info->ion_device_fd = -1;
     buf_ion_info->ion_alloc_data.handle = NULL;
     buf_ion_info->fd_ion_data.fd = -1;
}
#endif
void omx_vdec::free_output_buffer_header()
{
  DEBUG_PRINT_HIGH("\n ALL output buffers are freed/released");
  output_use_buffer = false;
  ouput_egl_buffers = false;

  if (m_out_mem_ptr)
  {
    free (m_out_mem_ptr);
    m_out_mem_ptr = NULL;
  }

  if(m_platform_list)
  {
    free(m_platform_list);
    m_platform_list = NULL;
  }

  if (drv_ctx.ptr_respbuffer)
  {
    free (drv_ctx.ptr_respbuffer);
    drv_ctx.ptr_respbuffer = NULL;
  }
  if (drv_ctx.ptr_outputbuffer)
  {
    free (drv_ctx.ptr_outputbuffer);
    drv_ctx.ptr_outputbuffer = NULL;
  }
#ifdef USE_ION
    if (drv_ctx.op_buf_ion_info) {
        DEBUG_PRINT_LOW("\n Free o/p ion context");
	free(drv_ctx.op_buf_ion_info);
        drv_ctx.op_buf_ion_info = NULL;
    }
#endif
}

void omx_vdec::free_input_buffer_header()
{
    input_use_buffer = false;
    if (arbitrary_bytes)
    {
      if (m_inp_heap_ptr)
      {
        DEBUG_PRINT_LOW("\n Free input Heap Pointer");
        free (m_inp_heap_ptr);
        m_inp_heap_ptr = NULL;
      }

      if (m_phdr_pmem_ptr)
      {
        DEBUG_PRINT_LOW("\n Free input pmem header Pointer");
        free (m_phdr_pmem_ptr);
        m_phdr_pmem_ptr = NULL;
      }
    }
    if (m_inp_mem_ptr)
    {
      DEBUG_PRINT_LOW("\n Free input pmem Pointer area");
      free (m_inp_mem_ptr);
      m_inp_mem_ptr = NULL;
    }

    /* We just freed all the buffer headers, every thing in m_input_free_q
     * is now invalid */
    while (m_input_free_q.m_size)
    {
      unsigned address,p2,id;
      m_input_free_q.pop_entry(&address,&p2,&id);
    }

    if (drv_ctx.ptr_inputbuffer)
    {
      DEBUG_PRINT_LOW("\n Free Driver Context pointer");
      free (drv_ctx.ptr_inputbuffer);
      drv_ctx.ptr_inputbuffer = NULL;
    }
#ifdef USE_ION
    if (drv_ctx.ip_buf_ion_info) {
        DEBUG_PRINT_LOW("\n Free ion context");
	free(drv_ctx.ip_buf_ion_info);
        drv_ctx.ip_buf_ion_info = NULL;
    }
#endif
}

OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
{
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  unsigned int buf_size = 0, extra_data_size = 0;
  DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)",
    buffer_prop->actualcount, buffer_prop->buffer_size);
  ioctl_msg.in = NULL;
  ioctl_msg.out = buffer_prop;
  if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_GET_BUFFER_REQ,
      (void*)&ioctl_msg) < 0)
  {
    DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
    eRet = OMX_ErrorInsufficientResources;
  }
  else
  {
    buf_size = buffer_prop->buffer_size;
    if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
    {
      DEBUG_PRINT_HIGH("Frame info extra data enabled!");
      extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
    }
    if (client_extradata & OMX_INTERLACE_EXTRADATA)
    {
      DEBUG_PRINT_HIGH("Interlace extra data enabled!");
      extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE;
    }
    if (client_extradata & OMX_PORTDEF_EXTRADATA)
    {
       extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE;
       DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d\n",
         extra_data_size);
    }
    if (extra_data_size)
    {
      extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
      buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit
    }
    buf_size += extra_data_size;
    buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
    DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)",
      buffer_prop->actualcount, buffer_prop->buffer_size, buf_size);
    if (in_reconfig) // BufReq will be set to driver when port is disabled
      buffer_prop->buffer_size = buf_size;
    else if (buf_size != buffer_prop->buffer_size)
    {
      buffer_prop->buffer_size = buf_size;
      eRet = set_buffer_req(buffer_prop);
    }
  }
  DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d)",
    buffer_prop->actualcount, buffer_prop->buffer_size);
  return eRet;
}

OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
{
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  unsigned buf_size = 0;
  DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)",
    buffer_prop->actualcount, buffer_prop->buffer_size);
  buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
  if (buf_size != buffer_prop->buffer_size)
  {
    DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)",
      buffer_prop->buffer_size, buf_size);
    eRet = OMX_ErrorBadParameter;
  }
  else
  {
    ioctl_msg.in = buffer_prop;
    ioctl_msg.out = NULL;
    if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_BUFFER_REQ,
           (void*)&ioctl_msg) < 0)
    {
      DEBUG_PRINT_ERROR("Setting buffer requirements failed");
      eRet = OMX_ErrorInsufficientResources;
    } else {
      if (!client_buffers.update_buffer_req()) {
        DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
        eRet = OMX_ErrorInsufficientResources;
      }
    }
  }
  return eRet;
}

OMX_ERRORTYPE omx_vdec::start_port_reconfig()
{
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  eRet = update_picture_resolution();
  if (eRet == OMX_ErrorNone)
  {
    ioctl_msg.out = &drv_ctx.interlace;
    if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_INTERLACE_FORMAT, &ioctl_msg))
    {
      DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_INTERLACE_FORMAT");
      eRet = OMX_ErrorHardware;
    }
    else
    {
      if (drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
      {
        DEBUG_PRINT_HIGH("Interlace format detected (%x)!", drv_ctx.interlace);
        if(!secure_mode)
            client_extradata |= OMX_INTERLACE_EXTRADATA;
	else {
            DEBUG_PRINT_ERROR("secure mode interlaced format not supported");
            eRet = OMX_ErrorUnsupportedSetting;
        }
      }
      in_reconfig = true;
      op_buf_rcnfg.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
      eRet = get_buffer_req(&op_buf_rcnfg);
    }
  }
  return eRet;
}

OMX_ERRORTYPE omx_vdec::update_picture_resolution()
{
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  ioctl_msg.in = NULL;
  ioctl_msg.out = &drv_ctx.video_resolution;
  if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_PICRES, &ioctl_msg))
  {
    DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_PICRES");
    eRet = OMX_ErrorHardware;
  }
  return eRet;
}

OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if (!portDefn)
  {
    return OMX_ErrorBadParameter;
  }
  DEBUG_PRINT_LOW("omx_vdec::update_portdef\n");
  portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
  portDefn->nSize = sizeof(portDefn);
  portDefn->eDomain    = OMX_PortDomainVideo;
  if (drv_ctx.frame_rate.fps_denominator > 0)
    portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator /
                                        drv_ctx.frame_rate.fps_denominator;
  else {
    DEBUG_PRINT_ERROR("Error: Divide by zero \n");
    return OMX_ErrorBadParameter;
  }
  if (0 == portDefn->nPortIndex)
  {
    portDefn->eDir =  OMX_DirInput;
    portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
    portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
    portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
    portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
    portDefn->format.video.eCompressionFormat = eCompressionFormat;
    portDefn->bEnabled   = m_inp_bEnabled;
    portDefn->bPopulated = m_inp_bPopulated;
  }
  else if (1 == portDefn->nPortIndex)
  {
    portDefn->eDir =  OMX_DirOutput;
    if (update_picture_resolution() != OMX_ErrorNone)
    {
      ALOGE(" update_picture_resolution failed \n");
      return OMX_ErrorHardware;
    }
    if (!client_buffers.update_buffer_req()) {
      DEBUG_PRINT_ERROR("\n client_buffers.update_buffer_req Failed");
      return OMX_ErrorHardware;
    }
    if (in_reconfig)
    {
      portDefn->nBufferCountActual = op_buf_rcnfg.actualcount;
      portDefn->nBufferCountMin    = op_buf_rcnfg.mincount;
      portDefn->nBufferSize        = op_buf_rcnfg.buffer_size;
    }
    else
    {
      portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
      portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
      portDefn->nBufferSize        = drv_ctx.op_buf.buffer_size;
    }
    unsigned int buf_size = 0;
    if (!client_buffers.get_buffer_req(buf_size)) {
      DEBUG_PRINT_ERROR("\n update buffer requirements");
      return OMX_ErrorHardware;
    }
    portDefn->nBufferSize = buf_size;
    portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
    portDefn->bEnabled   = m_out_bEnabled;
    portDefn->bPopulated = m_out_bPopulated;
    if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
      DEBUG_PRINT_ERROR("\n Error in getting color format");
      return OMX_ErrorHardware;
    }
  }
  else
  {
    portDefn->eDir = OMX_DirMax;
    DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
             (int)portDefn->nPortIndex);
    eRet = OMX_ErrorBadPortIndex;
  }
  portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
  portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
  portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
  portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
  DEBUG_PRINT_LOW("update_portdef Width = %d Height = %d Stride = %u"
    "SliceHeight = %u \n", portDefn->format.video.nFrameHeight,
    portDefn->format.video.nFrameWidth,
    portDefn->format.video.nStride,
    portDefn->format.video.nSliceHeight);
  return eRet;

}

OMX_ERRORTYPE omx_vdec::allocate_output_headers()
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  OMX_BUFFERHEADERTYPE *bufHdr = NULL;
  unsigned i= 0;

  if(!m_out_mem_ptr) {
    DEBUG_PRINT_HIGH("\n Use o/p buffer case - Header List allocation");
    int nBufHdrSize        = 0;
    int nPlatformEntrySize = 0;
    int nPlatformListSize  = 0;
    int nPMEMInfoSize = 0;
    OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
    OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
    OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;

    DEBUG_PRINT_LOW("Setting First Output Buffer(%d)\n",
      drv_ctx.op_buf.actualcount);
    nBufHdrSize        = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_BUFFERHEADERTYPE);

    nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
    nPlatformListSize  = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
    nPlatformEntrySize = drv_ctx.op_buf.actualcount *
                         sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);

    DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize,
                         sizeof(OMX_BUFFERHEADERTYPE),
                         nPMEMInfoSize,
                         nPlatformListSize);
    DEBUG_PRINT_LOW("PE %d bmSize %d \n",nPlatformEntrySize,
                         m_out_bm_count);
    m_out_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
    // Alloc mem for platform specific info
    char *pPtr=NULL;
    pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
                                     nPMEMInfoSize,1);
    drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
      calloc (sizeof(struct vdec_bufferpayload),
      drv_ctx.op_buf.actualcount);
    drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo  *)\
      calloc (sizeof (struct vdec_output_frameinfo),
      drv_ctx.op_buf.actualcount);
#ifdef USE_ION
    drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
      calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
#endif

    if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
       && drv_ctx.ptr_respbuffer)
    {
      bufHdr          =  m_out_mem_ptr;
      m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
      m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
                        (((char *) m_platform_list)  + nPlatformListSize);
      m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
                        (((char *) m_platform_entry) + nPlatformEntrySize);
      pPlatformList   = m_platform_list;
      pPlatformEntry  = m_platform_entry;
      pPMEMInfo       = m_pmem_info;

      DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);

      // Settting the entire storage nicely
      DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr,
                      m_out_mem_ptr,pPlatformEntry);
      DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo);
      for(i=0; i < drv_ctx.op_buf.actualcount ; i++)
      {
        bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
        bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
        // Set the values when we determine the right HxW param
        bufHdr->nAllocLen          = 0;
        bufHdr->nFilledLen         = 0;
        bufHdr->pAppPrivate        = NULL;
        bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
        pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
        pPlatformEntry->entry      = pPMEMInfo;
        // Initialize the Platform List
        pPlatformList->nEntries    = 1;
        pPlatformList->entryList   = pPlatformEntry;
        // Keep pBuffer NULL till vdec is opened
        bufHdr->pBuffer            = NULL;
        pPMEMInfo->offset          =  0;
        pPMEMInfo->pmem_fd = 0;
        bufHdr->pPlatformPrivate = pPlatformList;
        drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
#ifdef USE_ION
        drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
#endif
        /*Create a mapping between buffers*/
        bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
        drv_ctx.ptr_respbuffer[i].client_data = (void *) \
                                            &drv_ctx.ptr_outputbuffer[i];
        // Move the buffer and buffer header pointers
        bufHdr++;
        pPMEMInfo++;
        pPlatformEntry++;
        pPlatformList++;
      }
    }
    else
    {
      DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\
                                        m_out_mem_ptr, pPtr);
      if(m_out_mem_ptr)
      {
        free(m_out_mem_ptr);
        m_out_mem_ptr = NULL;
      }
      if(pPtr)
      {
        free(pPtr);
        pPtr = NULL;
      }
      if(drv_ctx.ptr_outputbuffer)
      {
        free(drv_ctx.ptr_outputbuffer);
        drv_ctx.ptr_outputbuffer = NULL;
      }
      if(drv_ctx.ptr_respbuffer)
      {
        free(drv_ctx.ptr_respbuffer);
        drv_ctx.ptr_respbuffer = NULL;
      }
#ifdef USE_ION
    if (drv_ctx.op_buf_ion_info) {
        DEBUG_PRINT_LOW("\n Free o/p ion context");
	free(drv_ctx.op_buf_ion_info);
        drv_ctx.op_buf_ion_info = NULL;
    }
#endif
      eRet =  OMX_ErrorInsufficientResources;
    }
  } else {
    eRet =  OMX_ErrorInsufficientResources;
  }
  return eRet;
}

void omx_vdec::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;
    }
  }
}

void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
{
  OMX_U32 new_frame_interval = 0;
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
     && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000))
  {
    new_frame_interval = (act_timestamp > prev_ts)?
                          act_timestamp - prev_ts :
                          prev_ts - act_timestamp;
    if (new_frame_interval < frm_int || frm_int == 0)
    {
      frm_int = new_frame_interval;
      if(frm_int)
      {
        drv_ctx.frame_rate.fps_numerator = 1e6;
        drv_ctx.frame_rate.fps_denominator = frm_int;
        DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
                         frm_int, drv_ctx.frame_rate.fps_numerator /
                         (float)drv_ctx.frame_rate.fps_denominator);
        ioctl_msg.in = &drv_ctx.frame_rate;
        if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE,
                  (void*)&ioctl_msg) < 0)
        {
          DEBUG_PRINT_ERROR("Setting frame rate failed");
        }
      }
    }
  }
  prev_ts = act_timestamp;
}

void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
{
  if (rst_prev_ts && VALID_TS(act_timestamp))
  {
    prev_ts = act_timestamp;
    rst_prev_ts = false;
  }
  else if (VALID_TS(prev_ts))
  {
    bool codec_cond = (drv_ctx.timestamp_adjust)?
                      (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)?
                      (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)):
                      (!VALID_TS(act_timestamp) || act_timestamp == prev_ts);
    if(frm_int > 0 && codec_cond)
    {
      DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
      act_timestamp = prev_ts + frm_int;
      DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
      prev_ts = act_timestamp;
    }
    else
      set_frame_rate(act_timestamp);
  }
  else if (frm_int > 0)           // In this case the frame rate was set along
  {                               // with the port definition, start ts with 0
    act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
    rst_prev_ts = true;
  }
}

void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
{
  OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
  OMX_U32 num_conceal_MB = 0;
  OMX_S64 ts_in_sei = 0;
  OMX_U32 frame_rate = 0;

  OMX_U32 index = p_buf_hdr - m_out_mem_ptr;
  OMX_U8* pBuffer = (OMX_U8 *)drv_ctx.ptr_outputbuffer[index].bufferaddr;

  p_extra = (OMX_OTHER_EXTRADATATYPE *)
           ((unsigned)(pBuffer + p_buf_hdr->nOffset +
            p_buf_hdr->nFilledLen + 3)&(~3));
  if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))
    p_extra = NULL;
  if (drv_ctx.extradata && (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA))
  {
    // Process driver extradata
    while(p_extra && p_extra->eType != VDEC_EXTRADATA_NONE)
    {
      DEBUG_PRINT_LOW("handle_extradata : pBuf(%p) BufTS(%lld) Type(%x) DataSz(%u)",
           p_buf_hdr, p_buf_hdr->nTimeStamp, p_extra->eType, p_extra->nDataSize);
      if (p_extra->nSize < p_extra->nDataSize)
      {
        DEBUG_PRINT_ERROR(" \n Corrupt metadata Buffer size %d payload size %d",
                          p_extra->nSize, p_extra->nDataSize);
        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
        if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen) ||
            p_extra->nDataSize == 0 || p_extra->nSize == 0)
          p_extra = NULL;
          continue;
      }
      if (p_extra->eType == VDEC_EXTRADATA_MB_ERROR_MAP)
      {
        if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
          num_conceal_MB = count_MB_in_extradata(p_extra);
        if (client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP)
          // Map driver extradata to corresponding OMX type
          p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataConcealMB;
        else
          p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client
#ifdef _ANDROID_
        if (m_debug_concealedmb) {
            DEBUG_PRINT_HIGH("Concealed MB percentage is %u", num_conceal_MB);
        }
#endif /* _ANDROID_ */
      }
      else if (p_extra->eType == VDEC_EXTRADATA_SEI)
      {
        p_sei = p_extra;
#ifdef MAX_RES_1080P
        h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI);
#endif
        p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client
      }
      else if (p_extra->eType == VDEC_EXTRADATA_VUI)
      {
        p_vui = p_extra;
#ifdef MAX_RES_1080P
        h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false);
#endif
        p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client
      }
      print_debug_extradata(p_extra);
      p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
      if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen) ||
          p_extra->nDataSize == 0 || p_extra->nSize == 0)
        p_extra = NULL;
    }
    if (!(client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP))
    {
      // Driver extradata is only exposed if MB map is requested by client,
      // otherwise can be overwritten by omx extradata.
      p_extra = (OMX_OTHER_EXTRADATATYPE *)
               ((unsigned)(pBuffer + p_buf_hdr->nOffset +
                p_buf_hdr->nFilledLen + 3)&(~3));
      p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
    }
  }

#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT
  if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
  {
    if (client_extradata & OMX_TIMEINFO_EXTRADATA)
    {
      if (p_vui)
        h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false);
      if (p_sei)
        h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI);
      ts_in_sei = h264_parser->process_ts_with_sei_vui(p_buf_hdr->nTimeStamp);
      if (!VALID_TS(p_buf_hdr->nTimeStamp))
        p_buf_hdr->nTimeStamp = ts_in_sei;
    }
    else if ((client_extradata & OMX_FRAMEINFO_EXTRADATA) && p_sei)
      // If timeinfo is present frame info from SEI is already processed
      h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI);
  }
#endif
   if ((client_extradata & OMX_INTERLACE_EXTRADATA) && p_extra &&
      ((OMX_U8*)p_extra + OMX_INTERLACE_EXTRADATA_SIZE) <
       (pBuffer + p_buf_hdr->nAllocLen))
  {
    p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
    append_interlace_extradata(p_extra,
         ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->interlaced_format);
    p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
  }
  if (client_extradata & OMX_FRAMEINFO_EXTRADATA && p_extra &&
      ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) <
       (pBuffer + p_buf_hdr->nAllocLen))
  {
    p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
    /* vui extra data (frame_rate) information */
    if (h264_parser)
        h264_parser->get_frame_rate(&frame_rate);
    append_frame_info_extradata(p_extra, num_conceal_MB,
        ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type,
        p_buf_hdr->nTimeStamp, frame_rate,
        &((struct vdec_output_frameinfo *)
          p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
    p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
  }
  if ((client_extradata & OMX_PORTDEF_EXTRADATA) &&
       p_extra != NULL &&
      ((OMX_U8*)p_extra + OMX_PORTDEF_EXTRADATA_SIZE) <
       (pBuffer + p_buf_hdr->nAllocLen))
  {
    p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
    append_portdef_extradata(p_extra);
    p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
  }
  if (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA)
    if (p_extra &&
      ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) <
        (pBuffer + p_buf_hdr->nAllocLen))
      append_terminator_extradata(p_extra);
    else
    {
      DEBUG_PRINT_ERROR("ERROR: Terminator extradata cannot be added");
      p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
    }
}

OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, bool enable)
{
  OMX_ERRORTYPE ret = OMX_ErrorNone;
  OMX_U32 driver_extradata = 0, extradata_size = 0;
  struct vdec_ioctl_msg ioctl_msg = {NULL, NULL};
  if(m_state != OMX_StateLoaded)
  {
     DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
     return OMX_ErrorIncorrectStateOperation;
  }
  if (requested_extradata & OMX_FRAMEINFO_EXTRADATA)
    extradata_size += OMX_FRAMEINFO_EXTRADATA_SIZE;
  if (requested_extradata & OMX_INTERLACE_EXTRADATA)
    extradata_size += OMX_INTERLACE_EXTRADATA_SIZE;
  if (requested_extradata & OMX_PORTDEF_EXTRADATA)
  {
    extradata_size += OMX_PORTDEF_EXTRADATA_SIZE;
  }
  DEBUG_PRINT_ERROR("enable_extradata: actual[%x] requested[%x] enable[%d]",
    client_extradata, requested_extradata, enable);

  if (enable)
    requested_extradata |= client_extradata;
  else
  {
    requested_extradata = client_extradata & ~requested_extradata;
    extradata_size *= -1;
  }

  driver_extradata = requested_extradata & DRIVER_EXTRADATA_MASK;
  if (requested_extradata & OMX_FRAMEINFO_EXTRADATA)
    driver_extradata |= VDEC_EXTRADATA_MB_ERROR_MAP; // Required for conceal MB frame info
#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT
  if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
  {
    driver_extradata |= ((requested_extradata & OMX_FRAMEINFO_EXTRADATA)?
                          VDEC_EXTRADATA_SEI : 0); // Required for pan scan frame info
    driver_extradata |= ((requested_extradata & OMX_TIMEINFO_EXTRADATA)?
                          VDEC_EXTRADATA_VUI | VDEC_EXTRADATA_SEI : 0); //Required for time info
  }

#endif
  if (driver_extradata != drv_ctx.extradata)
  {
    client_extradata = requested_extradata;
    drv_ctx.extradata = driver_extradata;
    ioctl_msg.in = &drv_ctx.extradata;
    ioctl_msg.out = NULL;
    if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_EXTRADATA,
        (void*)&ioctl_msg) < 0)
    {
        DEBUG_PRINT_ERROR("\nSet extradata failed");
        ret = OMX_ErrorUnsupportedSetting;
    }
    else
      ret = get_buffer_req(&drv_ctx.op_buf);
  }
  else if ((client_extradata & ~DRIVER_EXTRADATA_MASK) != (requested_extradata & ~DRIVER_EXTRADATA_MASK))
  {
    client_extradata = requested_extradata;
    drv_ctx.op_buf.buffer_size += extradata_size;
    // align the buffer size
    drv_ctx.op_buf.buffer_size = (drv_ctx.op_buf.buffer_size + drv_ctx.op_buf.alignment - 1)&(~(drv_ctx.op_buf.alignment - 1));
    DEBUG_PRINT_LOW("Aligned buffer size with exreadata = %d\n", drv_ctx.op_buf.buffer_size);
    if (!(client_extradata & ~DRIVER_EXTRADATA_MASK)) // If no omx extradata is required remove space for terminator
      drv_ctx.op_buf.buffer_size -= sizeof(OMX_OTHER_EXTRADATATYPE);
    ret = set_buffer_req(&drv_ctx.op_buf);
  }
  return ret;
}

OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
{
  OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
  OMX_U8 *data_ptr = extra->data, data = 0;
  while (byte_count < extra->nDataSize)
  {
    data = *data_ptr;
    while (data)
    {
      num_MB += (data&0x01);
      data >>= 1;
    }
    data_ptr++;
    byte_count++;
  }
  num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
                     (drv_ctx.video_resolution.frame_height + 15)) >> 8;
  return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
}

void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
{
#ifdef _ANDROID_
  if (!m_debug_extradata)
     return;

  DEBUG_PRINT_HIGH(
    "============== Extra Data ==============\n"
    "           Size: %u \n"
    "        Version: %u \n"
    "      PortIndex: %u \n"
    "           Type: %x \n"
    "       DataSize: %u \n",
    extra->nSize, extra->nVersion.nVersion,
    extra->nPortIndex, extra->eType, extra->nDataSize);

  if (extra->eType == OMX_ExtraDataInterlaceFormat)
  {
    OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data;
    DEBUG_PRINT_HIGH(
      "------ Interlace Format ------\n"
      "                Size: %u \n"
      "             Version: %u \n"
      "           PortIndex: %u \n"
      " Is Interlace Format: %u \n"
      "   Interlace Formats: %u \n"
      "=========== End of Interlace ===========\n",
      intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex,
      intfmt->bInterlaceFormat, intfmt->nInterlaceFormats);
  }
  else if (extra->eType == OMX_ExtraDataFrameInfo)
  {
    OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;

    DEBUG_PRINT_HIGH(
      "-------- Frame Format --------\n"
      "             Picture Type: %u \n"
      "           Interlace Type: %u \n"
      " Pan Scan Total Frame Num: %u \n"
      "   Concealed Macro Blocks: %u \n"
      "               frame rate: %u \n"
      "           Aspect Ratio X: %u \n"
      "           Aspect Ratio Y: %u \n",
      fminfo->ePicType,
      fminfo->interlaceType,
      fminfo->panScan.numWindows,
      fminfo->nConcealedMacroblocks,
      fminfo->nFrameRate,
      fminfo->aspectRatio.aspectRatioX,
      fminfo->aspectRatio.aspectRatioY);

    for (int i = 0; i < fminfo->panScan.numWindows; i++)
    {
      DEBUG_PRINT_HIGH(
        "------------------------------\n"
        "     Pan Scan Frame Num: %d \n"
        "            Rectangle x: %d \n"
        "            Rectangle y: %d \n"
        "           Rectangle dx: %d \n"
        "           Rectangle dy: %d \n",
        i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y,
        fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy);
    }

    DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
  }
  else if (extra->eType == OMX_ExtraDataNone)
  {
    DEBUG_PRINT_HIGH("========== End of Terminator ===========");
  }
  else
  {
    DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
  }
#endif /* _ANDROID_ */
}

void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
                                          OMX_U32 interlaced_format_type)
{
  OMX_STREAMINTERLACEFORMAT *interlace_format;
  OMX_U32 mbaff = 0;
  extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
  extra->nVersion.nVersion = OMX_SPEC_VERSION;
  extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
  extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
  extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
  interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data;
  interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
  interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
  interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
  mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
  if ((interlaced_format_type == VDEC_InterlaceFrameProgressive)  && !mbaff)
  {
    interlace_format->bInterlaceFormat = OMX_FALSE;
    interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
    drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
  }
  else
  {
    interlace_format->bInterlaceFormat = OMX_TRUE;
    interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
    drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
  }
  print_debug_extradata(extra);
}

void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
    OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_S64 timestamp,
    OMX_U32 frame_rate, struct vdec_aspectratioinfo *aspect_ratio_info)
{
  OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
  extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
  extra->nVersion.nVersion = OMX_SPEC_VERSION;
  extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
  extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
  extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
  frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data;

  switch (picture_type)
  {
    case PICTURE_TYPE_I:
      frame_info->ePicType = OMX_VIDEO_PictureTypeI;
    break;
    case PICTURE_TYPE_P:
      frame_info->ePicType = OMX_VIDEO_PictureTypeP;
    break;
    case PICTURE_TYPE_B:
      frame_info->ePicType = OMX_VIDEO_PictureTypeB;
    break;
    default:
       frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
  }
  if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
    frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
  else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
    frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
  else
    frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
  memset(&frame_info->panScan,0,sizeof(frame_info->panScan));
  memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
  if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
  {
    h264_parser->fill_pan_scan_data(&frame_info->panScan, timestamp);
  }

  fill_aspect_ratio_info(aspect_ratio_info, frame_info);
  frame_info->nConcealedMacroblocks = num_conceal_mb;
  frame_info->nFrameRate = frame_rate;
  print_debug_extradata(extra);
}

void omx_vdec::fill_aspect_ratio_info(
                       struct vdec_aspectratioinfo *aspect_ratio_info,
                       OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
{
  m_extradata = frame_info;

  m_extradata->aspectRatio.aspectRatioX = 0;
  m_extradata->aspectRatio.aspectRatioY = 0;

  if(drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
  {
     h264_parser->fill_aspect_ratio_info(&m_extradata->aspectRatio);
  }
#ifdef MAX_RES_1080P
  else if(drv_ctx.decoder_format == VDEC_CODECTYPE_MPEG4 ||
          drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_3 ||
          drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4 ||
          drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5 ||
          drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_6)
  {
      mp4_fill_aspect_ratio_info(aspect_ratio_info,m_extradata);
  }
#endif
  if(m_extradata->aspectRatio.aspectRatioX == 0 ||
     m_extradata->aspectRatio.aspectRatioY == 0) {
       m_extradata->aspectRatio.aspectRatioX = 1;
       m_extradata->aspectRatio.aspectRatioY = 1;
  }
}

void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
{
  OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
  extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
  extra->nVersion.nVersion = OMX_SPEC_VERSION;
  extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
  extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
  extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
  portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data;
  *portDefn = m_port_def;
  DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u stride = %u"
     "sliceheight = %u \n",portDefn->format.video.nFrameHeight,
     portDefn->format.video.nFrameWidth,
     portDefn->format.video.nStride,
     portDefn->format.video.nSliceHeight);
}

void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
{
  extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
  extra->nVersion.nVersion = OMX_SPEC_VERSION;
  extra->eType = OMX_ExtraDataNone;
  extra->nDataSize = 0;
  extra->data[0] = 0;

  print_debug_extradata(extra);
}

OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if (index >= drv_ctx.ip_buf.actualcount)
  {
    DEBUG_PRINT_ERROR("\nERROR:Desc Buffer Index not found");
    return OMX_ErrorInsufficientResources;
  }
  if (m_desc_buffer_ptr == NULL)
  {
    m_desc_buffer_ptr = (desc_buffer_hdr*) \
                     calloc( (sizeof(desc_buffer_hdr)),
                     drv_ctx.ip_buf.actualcount);
    if (m_desc_buffer_ptr == NULL)
    {
      DEBUG_PRINT_ERROR("\n m_desc_buffer_ptr Allocation failed ");
      return OMX_ErrorInsufficientResources;
    }
  }

  m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
  if (m_desc_buffer_ptr[index].buf_addr == NULL)
  {
    DEBUG_PRINT_ERROR("\ndesc buffer Allocation failed ");
    return OMX_ErrorInsufficientResources;
  }

  return eRet;
}

void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
{
  DEBUG_PRINT_LOW("Inserting address offset (%d) at idx (%d)", address_offset,m_demux_entries);
  if (m_demux_entries < 8192)
  {
    m_demux_offsets[m_demux_entries++] = address_offset;
  }
  return;
}

void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
{
  OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
  OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
  OMX_U32 index = 0;

  m_demux_entries = 0;

  while (index < bytes_to_parse)
  {
    if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
          (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
         ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
          (buf[index+2] == 0x01)) )
    {
      //Found start code, insert address offset
      insert_demux_addr_offset(index);
      if (buf[index+2] == 0x01) // 3 byte start code
        index += 3;
      else                      //4 byte start code
        index += 4;
    }
    else
      index++;
  }
  DEBUG_PRINT_LOW("Extracted (%d) demux entry offsets",m_demux_entries);
  return;
}

OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
{
  //fix this, handle 3 byte start code, vc1 terminator entry
  OMX_U8 *p_demux_data = NULL;
  OMX_U32 desc_data = 0;
  OMX_U32 start_addr = 0;
  OMX_U32 nal_size = 0;
  OMX_U32 suffix_byte = 0;
  OMX_U32 demux_index = 0;
  OMX_U32 buffer_index = 0;

  if (m_desc_buffer_ptr == NULL)
  {
    DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
    return OMX_ErrorBadParameter;
  }

  buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
  if (buffer_index > drv_ctx.ip_buf.actualcount)
  {
    DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%d)", buffer_index);
    return OMX_ErrorBadParameter;
  }

  p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;

  if ( ((OMX_U8*)p_demux_data == NULL) ||
      ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE)
  {
    DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
    return OMX_ErrorBadParameter;
  }
  else
  {
    for (; demux_index < m_demux_entries; demux_index++)
    {
      desc_data = 0;
      start_addr = m_demux_offsets[demux_index];
      if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01)
      {
        suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
      }
      else
      {
        suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
      }
      if (demux_index < (m_demux_entries - 1))
      {
        nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
      }
      else
      {
        nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
      }
      DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%d),demux_index(%d)",
                        start_addr,
                        suffix_byte,
                        nal_size,
                        demux_index);
      desc_data = (start_addr >> 3) << 1;
      desc_data |= (start_addr & 7) << 21;
      desc_data |= suffix_byte << 24;

      memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
      memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
      memset(p_demux_data + 8, 0, sizeof(OMX_U32));
      memset(p_demux_data + 12, 0, sizeof(OMX_U32));

      p_demux_data += 16;
    }
    if (codec_type_parse == CODEC_TYPE_VC1)
    {
      DEBUG_PRINT_LOW("VC1 terminator entry");
      desc_data = 0;
      desc_data = 0x82 << 24;
      memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
      memset(p_demux_data + 4, 0, sizeof(OMX_U32));
      memset(p_demux_data + 8, 0, sizeof(OMX_U32));
      memset(p_demux_data + 12, 0, sizeof(OMX_U32));
      p_demux_data += 16;
      m_demux_entries++;
    }
    //Add zero word to indicate end of descriptors
    memset(p_demux_data, 0, sizeof(OMX_U32));

    m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
    DEBUG_PRINT_LOW("desc table data size=%d", m_desc_buffer_ptr[buffer_index].desc_data_size);
  }
  memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
  m_demux_entries = 0;
  DEBUG_PRINT_LOW("Demux table complete!");
  return OMX_ErrorNone;
}

#ifdef MAX_RES_1080P
OMX_ERRORTYPE omx_vdec::vdec_alloc_h264_mv()
{
  OMX_U32 pmem_fd = -1;
  OMX_U32 width, height, size, alignment;
  void *buf_addr = NULL;
  struct vdec_ioctl_msg ioctl_msg;
#ifndef USE_ION
  struct pmem_allocation allocation;
#endif
  struct vdec_h264_mv h264_mv;
  struct vdec_mv_buff_size mv_buff_size;

  mv_buff_size.width = drv_ctx.video_resolution.stride;
  mv_buff_size.height = drv_ctx.video_resolution.scan_lines>>2;

  ioctl_msg.in = NULL;
  ioctl_msg.out = (void*)&mv_buff_size;

  if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_GET_MV_BUFFER_SIZE, (void*)&ioctl_msg) < 0)
  {
    DEBUG_PRINT_ERROR("\n GET_MV_BUFFER_SIZE Failed for width: %d, Height %d" ,
      mv_buff_size.width, mv_buff_size.height);
    return OMX_ErrorInsufficientResources;
  }

  DEBUG_PRINT_ERROR("GET_MV_BUFFER_SIZE returned: Size: %d and alignment: %d",
                    mv_buff_size.size, mv_buff_size.alignment);

  size = mv_buff_size.size * drv_ctx.op_buf.actualcount;
  alignment = mv_buff_size.alignment;

  DEBUG_PRINT_LOW("Entered vdec_alloc_h264_mv act_width: %d, act_height: %d, size: %d, alignment %d\n",
                   drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height,size,alignment);


#ifdef USE_ION
 drv_ctx.h264_mv.ion_device_fd = alloc_map_ion_memory(
                    size, 8192,
                    &drv_ctx.h264_mv.ion_alloc_data,
                    &drv_ctx.h264_mv.fd_ion_data,ION_FLAG_CACHED);
  if (drv_ctx.h264_mv.ion_device_fd < 0) {
        return OMX_ErrorInsufficientResources;
  }
  pmem_fd = drv_ctx.h264_mv.fd_ion_data.fd;
#else
  allocation.size = size;
  allocation.align = clip2(alignment);
  if (allocation.align != 8192)
    allocation.align = 8192;

  pmem_fd = open(MEM_DEVICE, O_RDWR);

  if ((int)(pmem_fd) < 0)
      return OMX_ErrorInsufficientResources;

  if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0)
  {
    DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)",
      allocation.align, allocation.size);
    return OMX_ErrorInsufficientResources;
  }
#endif
  if(!secure_mode) {
      buf_addr = mmap(NULL, size,
                   PROT_READ | PROT_WRITE,
                   MAP_SHARED, pmem_fd, 0);

      if (buf_addr == (void*) MAP_FAILED)
      {
        close(pmem_fd);
#ifdef USE_ION
        free_ion_memory(&drv_ctx.h264_mv);
#endif
        pmem_fd = -1;
        DEBUG_PRINT_ERROR("Error returned in allocating recon buffers buf_addr: %p\n",buf_addr);
        return OMX_ErrorInsufficientResources;
      }
   } else
      buf_addr =(unsigned char *) (pmem_fd + 1234);
  DEBUG_PRINT_LOW("\n Allocated virt:%p, FD: %d of size %d count: %d \n", buf_addr,
                   pmem_fd, size, drv_ctx.op_buf.actualcount);

  h264_mv.size = size;
  h264_mv.count = drv_ctx.op_buf.actualcount;
  h264_mv.pmem_fd = pmem_fd;
  h264_mv.offset = 0;

  ioctl_msg.in = (void*)&h264_mv;
  ioctl_msg.out = NULL;

  if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_H264_MV_BUFFER, (void*)&ioctl_msg) < 0)
  {
    DEBUG_PRINT_ERROR("Failed to set the H264_mv_buffers\n");
    return OMX_ErrorInsufficientResources;
  }

  h264_mv_buff.buffer = (unsigned char *) buf_addr;
  h264_mv_buff.size = size;
  h264_mv_buff.count = drv_ctx.op_buf.actualcount;
  h264_mv_buff.offset = 0;
  h264_mv_buff.pmem_fd = pmem_fd;
  DEBUG_PRINT_LOW("\n Saving virt:%p, FD: %d of size %d count: %d \n", h264_mv_buff.buffer,
                   h264_mv_buff.pmem_fd, h264_mv_buff.size, drv_ctx.op_buf.actualcount);
  return OMX_ErrorNone;
}

void omx_vdec::vdec_dealloc_h264_mv()
{
    if(h264_mv_buff.pmem_fd > 0)
    {
      if(ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_FREE_H264_MV_BUFFER,NULL) < 0)
        DEBUG_PRINT_ERROR("VDEC_IOCTL_FREE_H264_MV_BUFFER failed");
      if(!secure_mode)
          munmap(h264_mv_buff.buffer, h264_mv_buff.size);
      close(h264_mv_buff.pmem_fd);
#ifdef USE_ION
      free_ion_memory(&drv_ctx.h264_mv);
#endif
      DEBUG_PRINT_LOW("\n Cleaning H264_MV buffer of size %d \n",h264_mv_buff.size);
      h264_mv_buff.pmem_fd = -1;
      h264_mv_buff.offset = 0;
      h264_mv_buff.size = 0;
      h264_mv_buff.count = 0;
      h264_mv_buff.buffer = NULL;
    }
}

#endif

#ifdef _ANDROID_
OMX_ERRORTYPE omx_vdec::createDivxDrmContext()
{
     OMX_ERRORTYPE err = OMX_ErrorNone;
     iDivXDrmDecrypt = DivXDrmDecrypt::Create();
     if (iDivXDrmDecrypt) {
          OMX_ERRORTYPE err = iDivXDrmDecrypt->Init();
          if(err!=OMX_ErrorNone) {
            DEBUG_PRINT_ERROR("\nERROR :iDivXDrmDecrypt->Init %d", err);
            delete iDivXDrmDecrypt;
            iDivXDrmDecrypt = NULL;
          }
     }
     else {
          DEBUG_PRINT_ERROR("\nUnable to Create DIVX DRM");
          err = OMX_ErrorUndefined;
     }
     return err;
}
#endif //_ANDROID_

omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
{
  enabled = false;
  omx = NULL;
  init_members();
  ColorFormat = OMX_COLOR_FormatMax;
}

void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
{
  omx = reinterpret_cast<omx_vdec*>(client);
}

void omx_vdec::allocate_color_convert_buf::init_members() {
  allocated_count = 0;
  buffer_size_req = 0;
  buffer_alignment_req = 0;
  memset(m_platform_list_client,0,sizeof(m_platform_list_client));
  memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
  memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
  memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
  memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
  for (int i = 0; i < MAX_COUNT;i++)
    pmem_fd[i] = -1;
}

omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf() {
  c2d.destroy();
}

bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
{
  bool status = true;
  unsigned int src_size = 0, destination_size = 0;
  OMX_COLOR_FORMATTYPE drv_color_format;
  if (!omx){
    DEBUG_PRINT_ERROR("\n Invalid client in color convert");
    return false;
  }
  if (!enabled){
    DEBUG_PRINT_ERROR("\n No color conversion required");
    return status;
  }
  if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_TILE_4x2 &&
      ColorFormat != OMX_COLOR_FormatYUV420Planar) {
    DEBUG_PRINT_ERROR("\nupdate_buffer_req: Unsupported color conversion");
    return false;
  }
  c2d.close();
  status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
                    omx->drv_ctx.video_resolution.frame_width,
                    YCbCr420Tile,YCbCr420P);
  if (status) {
    status = c2d.get_buffer_size(C2D_INPUT,src_size);
    if (status)
      status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
  }
  if (status) {
    if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
        !destination_size) {
      DEBUG_PRINT_ERROR("\nERROR: Size mismatch in C2D src_size %d"
            "driver size %d destination size %d",
             src_size,omx->drv_ctx.op_buf.buffer_size,destination_size);
      status = false;
      c2d.close();
      buffer_size_req = 0;
    } else {
      buffer_size_req = destination_size;
      if (buffer_size_req < omx->drv_ctx.op_buf.buffer_size)
	     buffer_size_req = omx->drv_ctx.op_buf.buffer_size;
      if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
            buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
    }
  }
  return status;
}

bool omx_vdec::allocate_color_convert_buf::set_color_format(
  OMX_COLOR_FORMATTYPE dest_color_format)
{
  bool status = true;
  OMX_COLOR_FORMATTYPE drv_color_format;
  if (!omx){
    DEBUG_PRINT_ERROR("\n Invalid client in color convert");
    return false;
  }
  if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_TILE_4x2)
    drv_color_format = (OMX_COLOR_FORMATTYPE)
    QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
  else {
    DEBUG_PRINT_ERROR("\n Incorrect color format");
    status = false;
  }
  if (status && (drv_color_format != dest_color_format)) {
    if (dest_color_format != OMX_COLOR_FormatYUV420Planar) {
      DEBUG_PRINT_ERROR("\n Unsupported color format for c2d");
      status = false;
    } else {
      DEBUG_PRINT_HIGH("\n Planar color format set");
      ColorFormat = OMX_COLOR_FormatYUV420Planar;
      if (enabled)
        c2d.destroy();
      enabled = false;
      if (!c2d.init()) {
        DEBUG_PRINT_ERROR("\n open failed for c2d");
        status = false;
      } else
        enabled = true;
    }
  } else {
    if (enabled)
      c2d.destroy();
    enabled = false;
  }
  return status;
}

OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
{
  if (!omx){
    DEBUG_PRINT_ERROR("\n Invalid param get_buf_hdr");
    return NULL;
  }
  if (!enabled)
    return omx->m_out_mem_ptr;
  return m_out_mem_ptr_client;
}

OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
       (OMX_BUFFERHEADERTYPE *bufadd)
{
  if (!omx){
    DEBUG_PRINT_ERROR("\n Invalid param get_buf_hdr");
    return NULL;
  }
  if (!enabled)
    return bufadd;
  unsigned index = 0;
  index = bufadd - omx->m_out_mem_ptr;
  if (index < omx->drv_ctx.op_buf.actualcount) {
    m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
    m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
    bool status;
    if (!omx->in_reconfig && !omx->output_flush_progress) {
      status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
                  bufadd->pBuffer,pmem_fd[index],pmem_baseaddress[index]);
      m_out_mem_ptr_client[index].nFilledLen = buffer_size_req;
      if (!status){
        DEBUG_PRINT_ERROR("\n Failed color conversion %d", status);
        return NULL;
      }
    } else
      m_out_mem_ptr_client[index].nFilledLen = 0;
    return &m_out_mem_ptr_client[index];
  }
  DEBUG_PRINT_ERROR("\n Index messed up in the get_il_buf_hdr");
  return NULL;
}

OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
                                              (OMX_BUFFERHEADERTYPE *bufadd)
{
  if (!omx){
    DEBUG_PRINT_ERROR("\n Invalid param get_buf_hdr");
    return NULL;
  }
  if (!enabled)
    return bufadd;
  unsigned index = 0;
  index = bufadd - m_out_mem_ptr_client;
  if (index < omx->drv_ctx.op_buf.actualcount) {
    return &omx->m_out_mem_ptr[index];
  }
  DEBUG_PRINT_ERROR("\n Index messed up in the get_dr_buf_hdr");
  return NULL;
}
bool omx_vdec::allocate_color_convert_buf::get_buffer_req
          (unsigned int &buffer_size)
{
  if (!enabled)
    buffer_size = omx->drv_ctx.op_buf.buffer_size;
  else
    if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
      DEBUG_PRINT_ERROR("\n Get buffer size failed");
      return false;
  }
  if (buffer_size < omx->drv_ctx.op_buf.buffer_size)
        buffer_size = omx->drv_ctx.op_buf.buffer_size;
  if (buffer_alignment_req < omx->drv_ctx.op_buf.alignment)
	  buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
    return true;
}
OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
  OMX_BUFFERHEADERTYPE *bufhdr) {
  unsigned int index = 0;

  if (!enabled)
    return omx->free_output_buffer(bufhdr);
  if (enabled && omx->is_component_secure())
    return OMX_ErrorNone;
  if (!allocated_count || !bufhdr) {
    DEBUG_PRINT_ERROR("\n Color convert no buffer to be freed %p",bufhdr);
    return OMX_ErrorBadParameter;
  }
  index = bufhdr - m_out_mem_ptr_client;
  if (index >= omx->drv_ctx.op_buf.actualcount){
    DEBUG_PRINT_ERROR("\n Incorrect index color convert free_output_buffer");
    return OMX_ErrorBadParameter;
  }
  if (pmem_fd[index] > 0) {
    munmap(pmem_baseaddress[index], buffer_size_req);
    close(pmem_fd[index]);
  }
  pmem_fd[index] = -1;
  omx->free_ion_memory(&op_buf_ion_info[index]);
  m_heap_ptr[index].video_heap_ptr = NULL;
  if (allocated_count > 0)
    allocated_count--;
  else
    allocated_count = 0;
  if (!allocated_count) {
    c2d.close();
    init_members();
  }
  return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
}

OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
  OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
{
  OMX_ERRORTYPE eRet = OMX_ErrorNone;
  if (!enabled){
    eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
    return eRet;
  }
  if (enabled && omx->is_component_secure()) {
    DEBUG_PRINT_ERROR("\nNotin color convert mode secure_mode %d",
                      omx->is_component_secure());
    return OMX_ErrorUnsupportedSetting;
  }
  if (!bufferHdr || bytes > buffer_size_req) {
    DEBUG_PRINT_ERROR("\n Invalid params allocate_buffers_color_convert %p", bufferHdr);
    DEBUG_PRINT_ERROR("\n color_convert buffer_size_req %d bytes %d",
                      buffer_size_req,bytes);
    return OMX_ErrorBadParameter;
  }
  if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
    DEBUG_PRINT_ERROR("\n Actual count err in allocate_buffers_color_convert");
    return OMX_ErrorInsufficientResources;
  }
  OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
  eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
         port,appData,omx->drv_ctx.op_buf.buffer_size);
  if (eRet != OMX_ErrorNone || !temp_bufferHdr){
    DEBUG_PRINT_ERROR("\n Buffer allocation failed color_convert");
    return eRet;
  }
  if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
      omx->drv_ctx.op_buf.actualcount) {
    DEBUG_PRINT_ERROR("\n Invalid header index %d",
             (temp_bufferHdr - omx->m_out_mem_ptr));
    return OMX_ErrorUndefined;
  }
  unsigned int i = allocated_count;
  op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
    buffer_size_req,buffer_alignment_req,
    &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
    ION_FLAG_CACHED);

  pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
  if (op_buf_ion_info[i].ion_device_fd < 0) {
    DEBUG_PRINT_ERROR("\n alloc_map_ion failed in color_convert");
    return OMX_ErrorInsufficientResources;
  }
  pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
                     PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);

  if (pmem_baseaddress[i] == MAP_FAILED) {
    DEBUG_PRINT_ERROR("\n MMAP failed for Size %d",buffer_size_req);
    close(pmem_fd[i]);
    omx->free_ion_memory(&op_buf_ion_info[i]);
    return OMX_ErrorInsufficientResources;
  }
  m_heap_ptr[i].video_heap_ptr = new VideoHeap (
    op_buf_ion_info[i].ion_device_fd,buffer_size_req,
    pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
  m_pmem_info_client[i].pmem_fd = (OMX_U32)m_heap_ptr[i].video_heap_ptr.get();
  m_pmem_info_client[i].offset = 0;
  m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
  m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
  m_platform_list_client[i].nEntries = 1;
  m_platform_list_client[i].entryList = &m_platform_entry_client[i];
  m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
  m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
  m_out_mem_ptr_client[i].nFilledLen = 0;
  m_out_mem_ptr_client[i].nFlags = 0;
  m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
  m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
  m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
  m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
  m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
  m_out_mem_ptr_client[i].pAppPrivate = appData;
  *bufferHdr = &m_out_mem_ptr_client[i];
  DEBUG_PRINT_ERROR("\n IL client buffer header %p", *bufferHdr);
  allocated_count++;
  return eRet;
}

bool omx_vdec::is_component_secure()
{
  return secure_mode;
}

bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
{
  bool status = true;
  if (!enabled) {
    if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_TILE_4x2)
     dest_color_format =  (OMX_COLOR_FORMATTYPE)
            QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
    else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
      dest_color_format = OMX_COLOR_FormatYUV420SemiPlanar;
    else
      status = false;
  } else {
    if (ColorFormat != OMX_COLOR_FormatYUV420Planar) {
      status = false;
    } else
      dest_color_format = OMX_COLOR_FormatYUV420Planar;
  }
  return status;
}

int omx_vdec::secureDisplay(int mode) {
    if (m_secure_display == true) {
        return 0;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<qService::IQService> displayBinder =
        interface_cast<qService::IQService>(sm->getService(String16("display.qservice")));

    if (displayBinder != NULL) {
        displayBinder->securing(mode);
        if (mode == qService::IQService::END) {
            m_secure_display = true;
        }
    }
    else {
        DEBUG_PRINT_ERROR("secureDisplay(%d) display.qservice unavailable", mode);
    }
    return 0;
}

int omx_vdec::unsecureDisplay(int mode) {
    if (m_secure_display == false) {
        return 0;
    }

    if (mode == qService::IQService::END) {
        m_secure_display = false;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<qService::IQService> displayBinder =
        interface_cast<qService::IQService>(sm->getService(String16("display.qservice")));

    if (displayBinder != NULL)
        displayBinder->unsecuring(mode);
    else
        DEBUG_PRINT_ERROR("unsecureDisplay(%d) display.qservice unavailable", mode);
    return 0;
}

OMX_ERRORTYPE omx_vdec::update_color_format(OMX_COLOR_FORMATTYPE eColorFormat)
{
   struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
   OMX_ERRORTYPE eRet = OMX_ErrorNone;
   enum vdec_output_fromat op_format;
   if(eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)
     op_format = VDEC_YUV_FORMAT_NV12;
   else if(eColorFormat ==
           QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka ||
           eColorFormat == OMX_COLOR_FormatYUV420Planar)
      op_format = VDEC_YUV_FORMAT_TILE_4x2;
   else
      eRet = OMX_ErrorBadParameter;

   if(eRet == OMX_ErrorNone && drv_ctx.output_format != op_format) {
      /*Set the output format*/
      drv_ctx.output_format = op_format;
      ioctl_msg.in = &drv_ctx.output_format;
      ioctl_msg.out = NULL;
      if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_OUTPUT_FORMAT,
              (void*)&ioctl_msg) < 0) {
        DEBUG_PRINT_ERROR("\n Set output format failed for %u with err %s",
                          eColorFormat, strerror(errno));
        eRet = OMX_ErrorUnsupportedSetting;
      }
      else
         eRet = get_buffer_req(&drv_ctx.op_buf);
   }
   if (eRet == OMX_ErrorNone){
      if (!client_buffers.set_color_format(eColorFormat)) {
          DEBUG_PRINT_ERROR("\n Set color format failed for %u", eColorFormat);
          eRet = OMX_ErrorBadParameter;
       }
    }
   if (!client_buffers.update_buffer_req()) {
      DEBUG_PRINT_ERROR("\n Update bufreq in color format failed for %u", eColorFormat);
      eRet = OMX_ErrorBadParameter;
   }
   return eRet;
}