blob: 8200365f640de01916db2ad48be15edadcc04a8a [file] [log] [blame]
/*--------------------------------------------------------------------------
Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Linux Foundation nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/
/*============================================================================
@file omx_aenc_evrc.c
This module contains the implementation of the OpenMAX core & component.
*//*========================================================================*/
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
#include<string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "omx_evrc_aenc.h"
#include <errno.h>
using namespace std;
#define SLEEP_MS 100
// omx_cmd_queue destructor
omx_evrc_aenc::omx_cmd_queue::~omx_cmd_queue()
{
// Nothing to do
}
// omx cmd queue constructor
omx_evrc_aenc::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_evrc_aenc::omx_cmd_queue::insert_entry(unsigned long p1,
unsigned long p2,
unsigned char id)
{
bool ret = true;
if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE)
{
m_q[m_write].id = id;
m_q[m_write].param1 = p1;
m_q[m_write].param2 = p2;
m_write++;
m_size ++;
if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE)
{
m_write = 0;
}
} else
{
ret = false;
DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full");
}
return ret;
}
bool omx_evrc_aenc::omx_cmd_queue::pop_entry(unsigned long *p1,
unsigned long *p2, unsigned char *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;
DEBUG_PRINT_ERROR("ERROR Delete!!! Command Queue Empty");
}
return ret;
}
// factory function executed by the core to create instances
void *get_omx_component_factory_fn(void)
{
return(new omx_evrc_aenc);
}
bool omx_evrc_aenc::omx_cmd_queue::get_msg_id(unsigned char *id)
{
if(m_size > 0)
{
*id = m_q[m_read].id;
DEBUG_PRINT("get_msg_id=%d\n",*id);
}
else{
return false;
}
return true;
}
/*=============================================================================
FUNCTION:
wait_for_event
DESCRIPTION:
waits for a particular event
INPUT/OUTPUT PARAMETERS:
None
RETURN VALUE:
None
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
void omx_evrc_aenc::wait_for_event()
{
int rc;
struct timespec ts;
pthread_mutex_lock(&m_event_lock);
while (0 == m_is_event_done)
{
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += (SLEEP_MS/1000);
ts.tv_nsec += ((SLEEP_MS%1000) * 1000000);
rc = pthread_cond_timedwait(&cond, &m_event_lock, &ts);
if (rc == ETIMEDOUT && !m_is_event_done) {
DEBUG_PRINT("Timed out waiting for flush");
if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1)
DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n",
errno);
}
}
m_is_event_done = 0;
pthread_mutex_unlock(&m_event_lock);
}
/*=============================================================================
FUNCTION:
event_complete
DESCRIPTION:
informs about the occurance of an event
INPUT/OUTPUT PARAMETERS:
None
RETURN VALUE:
None
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
void omx_evrc_aenc::event_complete()
{
pthread_mutex_lock(&m_event_lock);
if (0 == m_is_event_done)
{
m_is_event_done = 1;
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&m_event_lock);
}
// All this non-sense because of a single evrc object
void omx_evrc_aenc::in_th_goto_sleep()
{
pthread_mutex_lock(&m_in_th_lock);
while (0 == m_is_in_th_sleep)
{
pthread_cond_wait(&in_cond, &m_in_th_lock);
}
m_is_in_th_sleep = 0;
pthread_mutex_unlock(&m_in_th_lock);
}
void omx_evrc_aenc::in_th_wakeup()
{
pthread_mutex_lock(&m_in_th_lock);
if (0 == m_is_in_th_sleep)
{
m_is_in_th_sleep = 1;
pthread_cond_signal(&in_cond);
}
pthread_mutex_unlock(&m_in_th_lock);
}
void omx_evrc_aenc::out_th_goto_sleep()
{
pthread_mutex_lock(&m_out_th_lock);
while (0 == m_is_out_th_sleep)
{
pthread_cond_wait(&out_cond, &m_out_th_lock);
}
m_is_out_th_sleep = 0;
pthread_mutex_unlock(&m_out_th_lock);
}
void omx_evrc_aenc::out_th_wakeup()
{
pthread_mutex_lock(&m_out_th_lock);
if (0 == m_is_out_th_sleep)
{
m_is_out_th_sleep = 1;
pthread_cond_signal(&out_cond);
}
pthread_mutex_unlock(&m_out_th_lock);
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::omx_evrc_aenc
DESCRIPTION
Constructor
PARAMETERS
None
RETURN VALUE
None.
========================================================================== */
omx_evrc_aenc::omx_evrc_aenc(): m_tmp_meta_buf(NULL),
m_tmp_out_meta_buf(NULL),
m_flush_cnt(255),
m_comp_deinit(0),
m_volume(25),
m_app_data(NULL),
nNumInputBuf(0),
nNumOutputBuf(0),
m_drv_fd(-1),
bFlushinprogress(0),
is_in_th_sleep(false),
is_out_th_sleep(false),
m_flags(0),
nTimestamp(0),
m_inp_act_buf_count (OMX_CORE_NUM_INPUT_BUFFERS),
m_out_act_buf_count (OMX_CORE_NUM_OUTPUT_BUFFERS),
m_inp_current_buf_count(0),
m_out_current_buf_count(0),
output_buffer_size((OMX_U32)OMX_EVRC_OUTPUT_BUFFER_SIZE),
input_buffer_size(OMX_CORE_INPUT_BUFFER_SIZE),
m_inp_bEnabled(OMX_TRUE),
m_out_bEnabled(OMX_TRUE),
m_inp_bPopulated(OMX_FALSE),
m_out_bPopulated(OMX_FALSE),
m_is_event_done(0),
m_state(OMX_StateInvalid),
m_ipc_to_in_th(NULL),
m_ipc_to_out_th(NULL),
m_ipc_to_cmd_th(NULL)
{
int cond_ret = 0;
memset(&m_cmp, 0, sizeof(m_cmp));
memset(&m_cb, 0, sizeof(m_cb));
memset(&m_evrc_param, 0, sizeof(m_evrc_param));
memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier));
memset(&m_evrc_pb_stats, 0, sizeof(m_evrc_pb_stats));
memset(&m_pcm_param, 0, sizeof(m_pcm_param));
memset(&m_priority_mgm, 0, sizeof(m_priority_mgm));
pthread_mutexattr_init(&m_lock_attr);
pthread_mutex_init(&m_lock, &m_lock_attr);
pthread_mutexattr_init(&m_commandlock_attr);
pthread_mutex_init(&m_commandlock, &m_commandlock_attr);
pthread_mutexattr_init(&m_outputlock_attr);
pthread_mutex_init(&m_outputlock, &m_outputlock_attr);
pthread_mutexattr_init(&m_state_attr);
pthread_mutex_init(&m_state_lock, &m_state_attr);
pthread_mutexattr_init(&m_event_attr);
pthread_mutex_init(&m_event_lock, &m_event_attr);
pthread_mutexattr_init(&m_flush_attr);
pthread_mutex_init(&m_flush_lock, &m_flush_attr);
pthread_mutexattr_init(&m_event_attr);
pthread_mutex_init(&m_event_lock, &m_event_attr);
pthread_mutexattr_init(&m_in_th_attr);
pthread_mutex_init(&m_in_th_lock, &m_in_th_attr);
pthread_mutexattr_init(&m_out_th_attr);
pthread_mutex_init(&m_out_th_lock, &m_out_th_attr);
pthread_mutexattr_init(&m_in_th_attr_1);
pthread_mutex_init(&m_in_th_lock_1, &m_in_th_attr_1);
pthread_mutexattr_init(&m_out_th_attr_1);
pthread_mutex_init(&m_out_th_lock_1, &m_out_th_attr_1);
pthread_mutexattr_init(&out_buf_count_lock_attr);
pthread_mutex_init(&out_buf_count_lock, &out_buf_count_lock_attr);
pthread_mutexattr_init(&in_buf_count_lock_attr);
pthread_mutex_init(&in_buf_count_lock, &in_buf_count_lock_attr);
if ((cond_ret = pthread_cond_init (&cond, NULL)) != 0)
{
DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for cond\n");
if (cond_ret == EAGAIN)
DEBUG_PRINT_ERROR("The system lacked necessary \
resources(other than mem)\n");
else if (cond_ret == ENOMEM)
DEBUG_PRINT_ERROR("Insufficient memory to initialise \
condition variable\n");
}
if ((cond_ret = pthread_cond_init (&in_cond, NULL)) != 0)
{
DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for in_cond\n");
if (cond_ret == EAGAIN)
DEBUG_PRINT_ERROR("The system lacked necessary \
resources(other than mem)\n");
else if (cond_ret == ENOMEM)
DEBUG_PRINT_ERROR("Insufficient memory to initialise \
condition variable\n");
}
if ((cond_ret = pthread_cond_init (&out_cond, NULL)) != 0)
{
DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for out_cond\n");
if (cond_ret == EAGAIN)
DEBUG_PRINT_ERROR("The system lacked necessary \
resources(other than mem)\n");
else if (cond_ret == ENOMEM)
DEBUG_PRINT_ERROR("Insufficient memory to initialise \
condition variable\n");
}
sem_init(&sem_read_msg,0, 0);
sem_init(&sem_write_msg,0, 0);
sem_init(&sem_States,0, 0);
return;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::~omx_evrc_aenc
DESCRIPTION
Destructor
PARAMETERS
None
RETURN VALUE
None.
========================================================================== */
omx_evrc_aenc::~omx_evrc_aenc()
{
DEBUG_PRINT_ERROR("EVRC Object getting destroyed comp-deinit=%d\n",
m_comp_deinit);
if ( !m_comp_deinit )
{
deinit_encoder();
}
pthread_mutexattr_destroy(&m_lock_attr);
pthread_mutex_destroy(&m_lock);
pthread_mutexattr_destroy(&m_commandlock_attr);
pthread_mutex_destroy(&m_commandlock);
pthread_mutexattr_destroy(&m_outputlock_attr);
pthread_mutex_destroy(&m_outputlock);
pthread_mutexattr_destroy(&m_state_attr);
pthread_mutex_destroy(&m_state_lock);
pthread_mutexattr_destroy(&m_event_attr);
pthread_mutex_destroy(&m_event_lock);
pthread_mutexattr_destroy(&m_flush_attr);
pthread_mutex_destroy(&m_flush_lock);
pthread_mutexattr_destroy(&m_in_th_attr);
pthread_mutex_destroy(&m_in_th_lock);
pthread_mutexattr_destroy(&m_out_th_attr);
pthread_mutex_destroy(&m_out_th_lock);
pthread_mutexattr_destroy(&out_buf_count_lock_attr);
pthread_mutex_destroy(&out_buf_count_lock);
pthread_mutexattr_destroy(&in_buf_count_lock_attr);
pthread_mutex_destroy(&in_buf_count_lock);
pthread_mutexattr_destroy(&m_in_th_attr_1);
pthread_mutex_destroy(&m_in_th_lock_1);
pthread_mutexattr_destroy(&m_out_th_attr_1);
pthread_mutex_destroy(&m_out_th_lock_1);
pthread_mutex_destroy(&out_buf_count_lock);
pthread_mutex_destroy(&in_buf_count_lock);
pthread_cond_destroy(&cond);
pthread_cond_destroy(&in_cond);
pthread_cond_destroy(&out_cond);
sem_destroy (&sem_read_msg);
sem_destroy (&sem_write_msg);
sem_destroy (&sem_States);
DEBUG_PRINT_ERROR("OMX EVRC component destroyed\n");
return;
}
/**
@brief memory function for sending EmptyBufferDone event
back to IL client
@param bufHdr OMX buffer header to be passed back to IL client
@return none
*/
void omx_evrc_aenc::buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr)
{
if (m_cb.EmptyBufferDone)
{
PrintFrameHdr(OMX_COMPONENT_GENERATE_BUFFER_DONE,bufHdr);
bufHdr->nFilledLen = 0;
m_cb.EmptyBufferDone(&m_cmp, m_app_data, bufHdr);
pthread_mutex_lock(&in_buf_count_lock);
m_evrc_pb_stats.ebd_cnt++;
nNumInputBuf--;
DEBUG_DETAIL("EBD CB:: in_buf_len=%d nNumInputBuf=%d %d ebd_cnt %d \n",\
m_evrc_pb_stats.tot_in_buf_len,
nNumInputBuf, m_evrc_pb_stats.ebd_cnt);
pthread_mutex_unlock(&in_buf_count_lock);
}
return;
}
/*=============================================================================
FUNCTION:
flush_ack
DESCRIPTION:
INPUT/OUTPUT PARAMETERS:
None
RETURN VALUE:
None
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
void omx_evrc_aenc::flush_ack()
{
// Decrement the FLUSH ACK count and notify the waiting recepients
pthread_mutex_lock(&m_flush_lock);
--m_flush_cnt;
if (0 == m_flush_cnt)
{
event_complete();
}
DEBUG_PRINT("Rxed FLUSH ACK cnt=%d\n",m_flush_cnt);
pthread_mutex_unlock(&m_flush_lock);
}
void omx_evrc_aenc::frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr)
{
if (m_cb.FillBufferDone)
{
PrintFrameHdr(OMX_COMPONENT_GENERATE_FRAME_DONE,bufHdr);
m_evrc_pb_stats.fbd_cnt++;
pthread_mutex_lock(&out_buf_count_lock);
nNumOutputBuf--;
DEBUG_PRINT("FBD CB:: nNumOutputBuf=%d out_buf_len=%u fbd_cnt=%u\n",\
nNumOutputBuf,
m_evrc_pb_stats.tot_out_buf_len,
m_evrc_pb_stats.fbd_cnt);
m_evrc_pb_stats.tot_out_buf_len += bufHdr->nFilledLen;
m_evrc_pb_stats.tot_pb_time = bufHdr->nTimeStamp;
DEBUG_PRINT("FBD:in_buf_len=%u out_buf_len=%u\n",
m_evrc_pb_stats.tot_in_buf_len,
m_evrc_pb_stats.tot_out_buf_len);
pthread_mutex_unlock(&out_buf_count_lock);
m_cb.FillBufferDone(&m_cmp, m_app_data, bufHdr);
}
return;
}
/*=============================================================================
FUNCTION:
process_out_port_msg
DESCRIPTION:
Function for handling all commands from IL client
IL client commands are processed and callbacks are generated through
this routine Audio Command Server provides the thread context for this routine
INPUT/OUTPUT PARAMETERS:
[INOUT] client_data
[IN] id
RETURN VALUE:
None
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
void omx_evrc_aenc::process_out_port_msg(void *client_data, unsigned char id)
{
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned char ident = 0;
unsigned qsize = 0; // qsize
unsigned tot_qsize = 0;
omx_evrc_aenc *pThis = (omx_evrc_aenc *) client_data;
OMX_STATETYPE state;
loopback_out:
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
if ( state == OMX_StateLoaded )
{
DEBUG_PRINT(" OUT: IN LOADED STATE RETURN\n");
return;
}
pthread_mutex_lock(&pThis->m_outputlock);
qsize = pThis->m_output_ctrl_cmd_q.m_size;
tot_qsize = pThis->m_output_ctrl_cmd_q.m_size;
tot_qsize += pThis->m_output_ctrl_fbd_q.m_size;
tot_qsize += pThis->m_output_q.m_size;
if ( 0 == tot_qsize )
{
pthread_mutex_unlock(&pThis->m_outputlock);
DEBUG_DETAIL("OUT-->BREAK FROM LOOP...%d\n",tot_qsize);
return;
}
if ( (state != OMX_StateExecuting) && !qsize )
{
pthread_mutex_unlock(&pThis->m_outputlock);
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
if ( state == OMX_StateLoaded )
return;
DEBUG_DETAIL("OUT:1.SLEEPING OUT THREAD\n");
pthread_mutex_lock(&pThis->m_out_th_lock_1);
pThis->is_out_th_sleep = true;
pthread_mutex_unlock(&pThis->m_out_th_lock_1);
pThis->out_th_goto_sleep();
/* Get the updated state */
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
}
if ( ((!pThis->m_output_ctrl_cmd_q.m_size) && !pThis->m_out_bEnabled) )
{
// case where no port reconfig and nothing in the flush q
DEBUG_DETAIL("No flush/port reconfig qsize=%d tot_qsize=%d",\
qsize,tot_qsize);
pthread_mutex_unlock(&pThis->m_outputlock);
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
if ( state == OMX_StateLoaded )
return;
if(pThis->m_output_ctrl_cmd_q.m_size || !(pThis->bFlushinprogress))
{
DEBUG_PRINT("OUT:2. SLEEPING OUT THREAD \n");
pthread_mutex_lock(&pThis->m_out_th_lock_1);
pThis->is_out_th_sleep = true;
pthread_mutex_unlock(&pThis->m_out_th_lock_1);
pThis->out_th_goto_sleep();
}
/* Get the updated state */
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
}
qsize = pThis->m_output_ctrl_cmd_q.m_size;
tot_qsize = pThis->m_output_ctrl_cmd_q.m_size;
tot_qsize += pThis->m_output_ctrl_fbd_q.m_size;
tot_qsize += pThis->m_output_q.m_size;
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
DEBUG_DETAIL("OUT-->QSIZE-flush=%d,fbd=%d QSIZE=%d state=%d\n",\
pThis->m_output_ctrl_cmd_q.m_size,
pThis->m_output_ctrl_fbd_q.m_size,
pThis->m_output_q.m_size,state);
if (qsize)
{
// process FLUSH message
pThis->m_output_ctrl_cmd_q.pop_entry(&p1,&p2,&ident);
} else if ( (qsize = pThis->m_output_ctrl_fbd_q.m_size) &&
(pThis->m_out_bEnabled) && (state == OMX_StateExecuting) )
{
// then process EBD's
pThis->m_output_ctrl_fbd_q.pop_entry(&p1,&p2,&ident);
} else if ( (qsize = pThis->m_output_q.m_size) &&
(pThis->m_out_bEnabled) && (state == OMX_StateExecuting) )
{
// if no FLUSH and FBD's then process FTB's
pThis->m_output_q.pop_entry(&p1,&p2,&ident);
} else if ( state == OMX_StateLoaded )
{
pthread_mutex_unlock(&pThis->m_outputlock);
DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n");
return ;
} else
{
qsize = 0;
DEBUG_PRINT("OUT--> Empty Queue state=%d %d %d %d\n",state,
pThis->m_output_ctrl_cmd_q.m_size,
pThis->m_output_ctrl_fbd_q.m_size,
pThis->m_output_q.m_size);
if(state == OMX_StatePause)
{
DEBUG_DETAIL("OUT: SLEEPING AGAIN OUT THREAD\n");
pthread_mutex_lock(&pThis->m_out_th_lock_1);
pThis->is_out_th_sleep = true;
pthread_mutex_unlock(&pThis->m_out_th_lock_1);
pthread_mutex_unlock(&pThis->m_outputlock);
pThis->out_th_goto_sleep();
goto loopback_out;
}
}
pthread_mutex_unlock(&pThis->m_outputlock);
if ( qsize > 0 )
{
id = ident;
ident = 0;
DEBUG_DETAIL("OUT->state[%d]ident[%d]flushq[%d]fbd[%d]dataq[%d]\n",\
pThis->m_state,
ident,
pThis->m_output_ctrl_cmd_q.m_size,
pThis->m_output_ctrl_fbd_q.m_size,
pThis->m_output_q.m_size);
if ( OMX_COMPONENT_GENERATE_FRAME_DONE == id )
{
pThis->frame_done_cb((OMX_BUFFERHEADERTYPE *)p2);
} else if ( OMX_COMPONENT_GENERATE_FTB == id )
{
pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,
(OMX_BUFFERHEADERTYPE *)p2);
} else if ( OMX_COMPONENT_GENERATE_EOS == id )
{
pThis->m_cb.EventHandler(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventBufferFlag,
1, 1, NULL );
}
else if(id == OMX_COMPONENT_RESUME)
{
DEBUG_PRINT("RESUMED...\n");
}
else if(id == OMX_COMPONENT_GENERATE_COMMAND)
{
// Execute FLUSH command
if ( OMX_CommandFlush == p1 )
{
DEBUG_DETAIL("Executing FLUSH command on Output port\n");
pThis->execute_output_omx_flush();
} else
{
DEBUG_DETAIL("Invalid command[%lu]\n",p1);
}
} else
{
DEBUG_PRINT_ERROR("ERROR:OUT-->Invalid Id[%d]\n",id);
}
} else
{
DEBUG_DETAIL("ERROR: OUT--> Empty OUTPUTQ\n");
}
return;
}
/*=============================================================================
FUNCTION:
process_command_msg
DESCRIPTION:
INPUT/OUTPUT PARAMETERS:
[INOUT] client_data
[IN] id
RETURN VALUE:
None
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
void omx_evrc_aenc::process_command_msg(void *client_data, unsigned char id)
{
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned char ident = 0;
unsigned qsize = 0;
omx_evrc_aenc *pThis = (omx_evrc_aenc*)client_data;
pthread_mutex_lock(&pThis->m_commandlock);
qsize = pThis->m_command_q.m_size;
DEBUG_DETAIL("CMD-->QSIZE=%d state=%d\n",pThis->m_command_q.m_size,
pThis->m_state);
if (!qsize)
{
DEBUG_DETAIL("CMD-->BREAKING FROM LOOP\n");
pthread_mutex_unlock(&pThis->m_commandlock);
return;
} else
{
pThis->m_command_q.pop_entry(&p1,&p2,&ident);
}
pthread_mutex_unlock(&pThis->m_commandlock);
id = ident;
DEBUG_DETAIL("CMD->state[%d]id[%d]cmdq[%d]n",\
pThis->m_state,ident, \
pThis->m_command_q.m_size);
if (OMX_COMPONENT_GENERATE_EVENT == id)
{
if (pThis->m_cb.EventHandler)
{
if (OMX_CommandStateSet == p1)
{
pthread_mutex_lock(&pThis->m_state_lock);
pThis->m_state = (OMX_STATETYPE) p2;
pthread_mutex_unlock(&pThis->m_state_lock);
DEBUG_PRINT("CMD:Process->state set to %d \n", \
pThis->m_state);
if (pThis->m_state == OMX_StateExecuting ||
pThis->m_state == OMX_StateLoaded)
{
pthread_mutex_lock(&pThis->m_in_th_lock_1);
if (pThis->is_in_th_sleep)
{
pThis->is_in_th_sleep = false;
DEBUG_DETAIL("CMD:WAKING UP IN THREADS\n");
pThis->in_th_wakeup();
}
pthread_mutex_unlock(&pThis->m_in_th_lock_1);
pthread_mutex_lock(&pThis->m_out_th_lock_1);
if (pThis->is_out_th_sleep)
{
DEBUG_DETAIL("CMD:WAKING UP OUT THREADS\n");
pThis->is_out_th_sleep = false;
pThis->out_th_wakeup();
}
pthread_mutex_unlock(&pThis->m_out_th_lock_1);
}
}
if (OMX_StateInvalid == pThis->m_state)
{
pThis->m_cb.EventHandler(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventError,
OMX_ErrorInvalidState,
0, NULL );
} else if ((signed)p2 == OMX_ErrorPortUnpopulated)
{
pThis->m_cb.EventHandler(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventError,
(OMX_U32)p2,
0,
0 );
} else
{
pThis->m_cb.EventHandler(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventCmdComplete,
(OMX_U32)p1, (OMX_U32)p2, NULL );
}
} else
{
DEBUG_PRINT_ERROR("ERROR:CMD-->EventHandler NULL \n");
}
} else if (OMX_COMPONENT_GENERATE_COMMAND == id)
{
pThis->send_command_proxy(&pThis->m_cmp,
(OMX_COMMANDTYPE)p1,
(OMX_U32)p2,(OMX_PTR)NULL);
} else if (OMX_COMPONENT_PORTSETTINGS_CHANGED == id)
{
DEBUG_DETAIL("CMD-->RXED PORTSETTINGS_CHANGED");
pThis->m_cb.EventHandler(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventPortSettingsChanged,
1, 1, NULL );
}
else
{
DEBUG_PRINT_ERROR("CMD->state[%d]id[%d]\n",pThis->m_state,ident);
}
return;
}
/*=============================================================================
FUNCTION:
process_in_port_msg
DESCRIPTION:
INPUT/OUTPUT PARAMETERS:
[INOUT] client_data
[IN] id
RETURN VALUE:
None
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
void omx_evrc_aenc::process_in_port_msg(void *client_data, unsigned char id)
{
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned char ident = 0;
unsigned qsize = 0;
unsigned tot_qsize = 0;
omx_evrc_aenc *pThis = (omx_evrc_aenc *) client_data;
OMX_STATETYPE state;
if (!pThis)
{
DEBUG_PRINT_ERROR("ERROR:IN--> Invalid Obj \n");
return;
}
loopback_in:
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
if ( state == OMX_StateLoaded )
{
DEBUG_PRINT(" IN: IN LOADED STATE RETURN\n");
return;
}
// Protect the shared queue data structure
pthread_mutex_lock(&pThis->m_lock);
qsize = pThis->m_input_ctrl_cmd_q.m_size;
tot_qsize = qsize;
tot_qsize += pThis->m_input_ctrl_ebd_q.m_size;
tot_qsize += pThis->m_input_q.m_size;
if ( 0 == tot_qsize )
{
DEBUG_DETAIL("IN-->BREAKING FROM IN LOOP");
pthread_mutex_unlock(&pThis->m_lock);
return;
}
if ( (state != OMX_StateExecuting) && ! (pThis->m_input_ctrl_cmd_q.m_size))
{
pthread_mutex_unlock(&pThis->m_lock);
DEBUG_DETAIL("SLEEPING IN THREAD\n");
pthread_mutex_lock(&pThis->m_in_th_lock_1);
pThis->is_in_th_sleep = true;
pthread_mutex_unlock(&pThis->m_in_th_lock_1);
pThis->in_th_goto_sleep();
/* Get the updated state */
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
}
else if ((state == OMX_StatePause))
{
if(!(pThis->m_input_ctrl_cmd_q.m_size))
{
pthread_mutex_unlock(&pThis->m_lock);
DEBUG_DETAIL("IN: SLEEPING IN THREAD\n");
pthread_mutex_lock(&pThis->m_in_th_lock_1);
pThis->is_in_th_sleep = true;
pthread_mutex_unlock(&pThis->m_in_th_lock_1);
pThis->in_th_goto_sleep();
pthread_mutex_lock(&pThis->m_state_lock);
pThis->get_state(&pThis->m_cmp, &state);
pthread_mutex_unlock(&pThis->m_state_lock);
}
}
qsize = pThis->m_input_ctrl_cmd_q.m_size;
tot_qsize = qsize;
tot_qsize += pThis->m_input_ctrl_ebd_q.m_size;
tot_qsize += pThis->m_input_q.m_size;
DEBUG_DETAIL("Input-->QSIZE-flush=%d,ebd=%d QSIZE=%d state=%d\n",\
pThis->m_input_ctrl_cmd_q.m_size,
pThis->m_input_ctrl_ebd_q.m_size,
pThis->m_input_q.m_size, state);
if ( qsize )
{
// process FLUSH message
pThis->m_input_ctrl_cmd_q.pop_entry(&p1,&p2,&ident);
} else if ( (qsize = pThis->m_input_ctrl_ebd_q.m_size) &&
(state == OMX_StateExecuting) )
{
// then process EBD's
pThis->m_input_ctrl_ebd_q.pop_entry(&p1,&p2,&ident);
} else if ((qsize = pThis->m_input_q.m_size) &&
(state == OMX_StateExecuting))
{
// if no FLUSH and EBD's then process ETB's
pThis->m_input_q.pop_entry(&p1, &p2, &ident);
} else if ( state == OMX_StateLoaded )
{
pthread_mutex_unlock(&pThis->m_lock);
DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n");
return ;
} else
{
qsize = 0;
DEBUG_PRINT("IN-->state[%d]cmdq[%d]ebdq[%d]in[%d]\n",\
state,pThis->m_input_ctrl_cmd_q.m_size,
pThis->m_input_ctrl_ebd_q.m_size,
pThis->m_input_q.m_size);
if(state == OMX_StatePause)
{
DEBUG_DETAIL("IN: SLEEPING AGAIN IN THREAD\n");
pthread_mutex_lock(&pThis->m_in_th_lock_1);
pThis->is_in_th_sleep = true;
pthread_mutex_unlock(&pThis->m_in_th_lock_1);
pthread_mutex_unlock(&pThis->m_lock);
pThis->in_th_goto_sleep();
goto loopback_in;
}
}
pthread_mutex_unlock(&pThis->m_lock);
if ( qsize > 0 )
{
id = ident;
DEBUG_DETAIL("Input->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\
pThis->m_state,
ident,
pThis->m_input_ctrl_cmd_q.m_size,
pThis->m_input_ctrl_ebd_q.m_size,
pThis->m_input_q.m_size);
if ( OMX_COMPONENT_GENERATE_BUFFER_DONE == id )
{
pThis->buffer_done_cb((OMX_BUFFERHEADERTYPE *)p2);
}
else if(id == OMX_COMPONENT_GENERATE_EOS)
{
pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventBufferFlag, 0, 1, NULL );
} else if ( OMX_COMPONENT_GENERATE_ETB == id )
{
pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,
(OMX_BUFFERHEADERTYPE *)p2);
} else if ( OMX_COMPONENT_GENERATE_COMMAND == id )
{
// Execute FLUSH command
if ( OMX_CommandFlush == p1 )
{
DEBUG_DETAIL(" Executing FLUSH command on Input port\n");
pThis->execute_input_omx_flush();
} else
{
DEBUG_DETAIL("Invalid command[%lu]\n",p1);
}
}
else
{
DEBUG_PRINT_ERROR("ERROR:IN-->Invalid Id[%u]\n",id);
}
} else
{
DEBUG_DETAIL("ERROR:IN-->Empty INPUT Q\n");
}
return;
}
/**
@brief member function for performing component initialization
@param role C string mandating role of this component
@return Error status
*/
OMX_ERRORTYPE omx_evrc_aenc::component_init(OMX_STRING role)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
m_state = OMX_StateLoaded;
/* DSP does not give information about the bitstream
randomly assign the value right now. Query will result in
incorrect param */
memset(&m_evrc_param, 0, sizeof(m_evrc_param));
m_evrc_param.nSize = (OMX_U32)sizeof(m_evrc_param);
m_evrc_param.nChannels = OMX_EVRC_DEFAULT_CH_CFG;
//Current DSP does not have config
m_evrc_param.eCDMARate = OMX_AUDIO_CDMARateFull;
m_evrc_param.nMinBitRate = OMX_EVRC_DEFAULT_MINRATE;
m_evrc_param.nMaxBitRate = OMX_EVRC_DEFAULT_MAXRATE;
m_volume = OMX_EVRC_DEFAULT_VOL; /* Close to unity gain */
memset(&m_evrc_pb_stats,0,sizeof(EVRC_PB_STATS));
memset(&m_pcm_param, 0, sizeof(m_pcm_param));
m_pcm_param.nSize = (OMX_U32)sizeof(m_pcm_param);
m_pcm_param.nChannels = OMX_EVRC_DEFAULT_CH_CFG;
m_pcm_param.nSamplingRate = OMX_EVRC_DEFAULT_SF;
nTimestamp = 0;
nNumInputBuf = 0;
nNumOutputBuf = 0;
m_ipc_to_in_th = NULL; // Command server instance
m_ipc_to_out_th = NULL; // Client server instance
m_ipc_to_cmd_th = NULL; // command instance
m_is_out_th_sleep = 0;
m_is_in_th_sleep = 0;
is_out_th_sleep= false;
is_in_th_sleep=false;
memset(&m_priority_mgm, 0, sizeof(m_priority_mgm));
m_priority_mgm.nGroupID =0;
m_priority_mgm.nGroupPriority=0;
memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier));
m_buffer_supplier.nPortIndex=OMX_BufferSupplyUnspecified;
DEBUG_PRINT_ERROR(" component init: role = %s\n",role);
DEBUG_PRINT(" component init: role = %s\n",role);
component_Role.nVersion.nVersion = OMX_SPEC_VERSION;
if (!strcmp(role,"OMX.qcom.audio.encoder.evrc"))
{
pcm_input = 1;
component_Role.nSize = (OMX_U32)sizeof(role);
strlcpy((char *)component_Role.cRole,
(const char*)role, sizeof(component_Role.cRole));
DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role);
} else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.evrc"))
{
pcm_input = 0;
component_Role.nSize = (OMX_U32)sizeof(role);
strlcpy((char *)component_Role.cRole,
(const char*)role, sizeof(component_Role.cRole));
DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role);
} else
{
component_Role.nSize = (OMX_U32)sizeof("\0");
strlcpy((char *)component_Role.cRole,
(const char*)"\0",sizeof(component_Role.cRole));
DEBUG_PRINT("\ncomponent_init: Component %s LOADED is invalid\n", role);
}
if(pcm_input)
{
m_tmp_meta_buf = (OMX_U8*) malloc(sizeof(OMX_U8) *
(OMX_CORE_INPUT_BUFFER_SIZE + sizeof(META_IN)));
if (m_tmp_meta_buf == NULL){
DEBUG_PRINT_ERROR("Mem alloc failed for in meta buf\n");
return OMX_ErrorInsufficientResources;
}
}
m_tmp_out_meta_buf =
(OMX_U8*)malloc(sizeof(OMX_U8)*OMX_EVRC_OUTPUT_BUFFER_SIZE);
if ( m_tmp_out_meta_buf == NULL ) {
DEBUG_PRINT_ERROR("Mem alloc failed for out meta buf\n");
return OMX_ErrorInsufficientResources;
}
if(0 == pcm_input)
{
m_drv_fd = open("/dev/msm_evrc_in",O_RDONLY);
DEBUG_PRINT("Driver in Tunnel mode open\n");
}
else
{
m_drv_fd = open("/dev/msm_evrc_in",O_RDWR);
DEBUG_PRINT("Driver in Non Tunnel mode open\n");
}
if (m_drv_fd < 0)
{
DEBUG_PRINT_ERROR("Component_init Open Failed[%d] errno[%d]",\
m_drv_fd,errno);
return OMX_ErrorInsufficientResources;
}
if(ioctl(m_drv_fd, AUDIO_GET_SESSION_ID,&m_session_id) == -1)
{
DEBUG_PRINT_ERROR("AUDIO_GET_SESSION_ID FAILED\n");
}
if(pcm_input)
{
if (!m_ipc_to_in_th)
{
m_ipc_to_in_th = omx_evrc_thread_create(process_in_port_msg,
this, (char *)"INPUT_THREAD");
if (!m_ipc_to_in_th)
{
DEBUG_PRINT_ERROR("ERROR!!! Failed to start \
Input port thread\n");
return OMX_ErrorInsufficientResources;
}
}
}
if (!m_ipc_to_cmd_th)
{
m_ipc_to_cmd_th = omx_evrc_thread_create(process_command_msg,
this, (char *)"CMD_THREAD");
if (!m_ipc_to_cmd_th)
{
DEBUG_PRINT_ERROR("ERROR!!!Failed to start "
"command message thread\n");
return OMX_ErrorInsufficientResources;
}
}
if (!m_ipc_to_out_th)
{
m_ipc_to_out_th = omx_evrc_thread_create(process_out_port_msg,
this, (char *)"OUTPUT_THREAD");
if (!m_ipc_to_out_th)
{
DEBUG_PRINT_ERROR("ERROR!!! Failed to start output "
"port thread\n");
return OMX_ErrorInsufficientResources;
}
}
return eRet;
}
/**
@brief member function to retrieve version of component
@param hComp handle to this component instance
@param componentName name of component
@param componentVersion pointer to memory space which stores the
version number
@param specVersion pointer to memory sapce which stores version of
openMax specification
@param componentUUID
@return Error status
*/
OMX_ERRORTYPE omx_evrc_aenc::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((hComp == NULL) || (componentName == NULL) ||
(specVersion == NULL) || (componentUUID == NULL))
{
componentVersion = NULL;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n");
return OMX_ErrorInvalidState;
}
componentVersion->nVersion = OMX_SPEC_VERSION;
specVersion->nVersion = OMX_SPEC_VERSION;
return OMX_ErrorNone;
}
/**
@brief member function handles command from IL client
This function simply queue up commands from IL client.
Commands will be processed in command server thread context later
@param hComp handle to component instance
@param cmd type of command
@param param1 parameters associated with the command type
@param cmdData
@return Error status
*/
OMX_ERRORTYPE omx_evrc_aenc::send_command(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_COMMANDTYPE cmd,
OMX_IN OMX_U32 param1,
OMX_IN OMX_PTR cmdData)
{
int portIndex = (int)param1;
if(hComp == NULL)
{
cmdData = cmdData;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (OMX_StateInvalid == m_state)
{
return OMX_ErrorInvalidState;
}
if ( (cmd == OMX_CommandFlush) && (portIndex > 1) )
{
return OMX_ErrorBadPortIndex;
}
post_command((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
DEBUG_PRINT("Send Command : returns with OMX_ErrorNone \n");
DEBUG_PRINT("send_command : recieved state before semwait= %u\n",param1);
sem_wait (&sem_States);
DEBUG_PRINT("send_command : recieved state after semwait\n");
return OMX_ErrorNone;
}
/**
@brief member function performs actual processing of commands excluding
empty buffer call
@param hComp handle to component
@param cmd command type
@param param1 parameter associated with the command
@param cmdData
@return error status
*/
OMX_ERRORTYPE omx_evrc_aenc::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;
// Handle only IDLE and executing
OMX_STATETYPE eState = (OMX_STATETYPE) param1;
int bFlag = 1;
nState = eState;
if(hComp == NULL)
{
cmdData = cmdData;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (OMX_CommandStateSet == cmd)
{
/***************************/
/* Current State is Loaded */
/***************************/
if (OMX_StateLoaded == m_state)
{
if (OMX_StateIdle == eState)
{
if (allocate_done() ||
(m_inp_bEnabled == OMX_FALSE
&& m_out_bEnabled == OMX_FALSE))
{
DEBUG_PRINT("SCP-->Allocate Done Complete\n");
}
else
{
DEBUG_PRINT("SCP-->Loaded to Idle-Pending\n");
BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
bFlag = 0;
}
} else if (eState == OMX_StateLoaded)
{
DEBUG_PRINT("OMXCORE-SM: Loaded-->Loaded\n");
m_cb.EventHandler(&this->m_cmp,
this->m_app_data,
OMX_EventError,
OMX_ErrorSameState,
0, NULL );
eRet = OMX_ErrorSameState;
}
else if (eState == OMX_StateWaitForResources)
{
DEBUG_PRINT("OMXCORE-SM: Loaded-->WaitForResources\n");
eRet = OMX_ErrorNone;
}
else if (eState == OMX_StateExecuting)
{
DEBUG_PRINT("OMXCORE-SM: Loaded-->Executing\n");
m_cb.EventHandler(&this->m_cmp,
this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
}
else if (eState == OMX_StatePause)
{
DEBUG_PRINT("OMXCORE-SM: Loaded-->Pause\n");
m_cb.EventHandler(&this->m_cmp,
this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
}
else if (eState == OMX_StateInvalid)
{
DEBUG_PRINT("OMXCORE-SM: Loaded-->Invalid\n");
m_cb.EventHandler(&this->m_cmp,
this->m_app_data,
OMX_EventError,
OMX_ErrorInvalidState,
0, NULL );
m_state = OMX_StateInvalid;
eRet = OMX_ErrorInvalidState;
} else
{
DEBUG_PRINT_ERROR("SCP-->Loaded to Invalid(%d))\n",eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is IDLE */
/***************************/
else if (OMX_StateIdle == m_state)
{
if (OMX_StateLoaded == eState)
{
if (release_done(-1))
{
if (ioctl(m_drv_fd, AUDIO_STOP, 0) == -1)
{
DEBUG_PRINT_ERROR("SCP:Idle->Loaded,\
ioctl stop failed %d\n", errno);
}
nTimestamp=0;
DEBUG_PRINT("SCP-->Idle to Loaded\n");
} else
{
DEBUG_PRINT("SCP--> Idle to Loaded-Pending\n");
BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
// Skip the event notification
bFlag = 0;
}
}
else if (OMX_StateExecuting == eState)
{
struct msm_audio_evrc_enc_config drv_evrc_enc_config;
struct msm_audio_stream_config drv_stream_config;
struct msm_audio_buf_cfg buf_cfg;
struct msm_audio_config pcm_cfg;
if(ioctl(m_drv_fd, AUDIO_GET_STREAM_CONFIG, &drv_stream_config)
== -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_GET_STREAM_CONFIG failed, \
errno[%d]\n", errno);
}
if(ioctl(m_drv_fd, AUDIO_SET_STREAM_CONFIG, &drv_stream_config)
== -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_SET_STREAM_CONFIG failed, \
errno[%d]\n", errno);
}
if(ioctl(m_drv_fd, AUDIO_GET_EVRC_ENC_CONFIG,
&drv_evrc_enc_config) == -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_GET_EVRC_ENC_CONFIG failed,\
errno[%d]\n", errno);
}
drv_evrc_enc_config.min_bit_rate = m_evrc_param.nMinBitRate;
drv_evrc_enc_config.max_bit_rate = m_evrc_param.nMaxBitRate;
if(ioctl(m_drv_fd, AUDIO_SET_EVRC_ENC_CONFIG, &drv_evrc_enc_config)
== -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_SET_EVRC_ENC_CONFIG failed,\
errno[%d]\n", errno);
}
if (ioctl(m_drv_fd, AUDIO_GET_BUF_CFG, &buf_cfg) == -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_GET_BUF_CFG, errno[%d]\n",
errno);
}
buf_cfg.meta_info_enable = 1;
buf_cfg.frames_per_buf = NUMOFFRAMES;
if (ioctl(m_drv_fd, AUDIO_SET_BUF_CFG, &buf_cfg) == -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_SET_BUF_CFG, errno[%d]\n",
errno);
}
if(pcm_input)
{
if (ioctl(m_drv_fd, AUDIO_GET_CONFIG, &pcm_cfg) == -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_GET_CONFIG, errno[%d]\n",
errno);
}
pcm_cfg.channel_count = m_pcm_param.nChannels;
pcm_cfg.sample_rate = m_pcm_param.nSamplingRate;
DEBUG_PRINT("pcm config %u %u\n",m_pcm_param.nChannels,
m_pcm_param.nSamplingRate);
if (ioctl(m_drv_fd, AUDIO_SET_CONFIG, &pcm_cfg) == -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_SET_CONFIG, errno[%d]\n",
errno);
}
}
if(ioctl(m_drv_fd, AUDIO_START, 0) == -1)
{
DEBUG_PRINT_ERROR("ioctl AUDIO_START failed, errno[%d]\n",
errno);
m_state = OMX_StateInvalid;
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorInvalidState,
0, NULL );
eRet = OMX_ErrorInvalidState;
}
DEBUG_PRINT("SCP-->Idle to Executing\n");
nState = eState;
} else if (eState == OMX_StateIdle)
{
DEBUG_PRINT("OMXCORE-SM: Idle-->Idle\n");
m_cb.EventHandler(&this->m_cmp,
this->m_app_data,
OMX_EventError,
OMX_ErrorSameState,
0, NULL );
eRet = OMX_ErrorSameState;
} else if (eState == OMX_StateWaitForResources)
{
DEBUG_PRINT("OMXCORE-SM: Idle-->WaitForResources\n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
}
else if (eState == OMX_StatePause)
{
DEBUG_PRINT("OMXCORE-SM: Idle-->Pause\n");
}
else if (eState == OMX_StateInvalid)
{
DEBUG_PRINT("OMXCORE-SM: Idle-->Invalid\n");
m_state = OMX_StateInvalid;
this->m_cb.EventHandler(&this->m_cmp,
this->m_app_data,
OMX_EventError,
OMX_ErrorInvalidState,
0, NULL );
eRet = OMX_ErrorInvalidState;
} else
{
DEBUG_PRINT_ERROR("SCP--> Idle to %d Not Handled\n",eState);
eRet = OMX_ErrorBadParameter;
}
}
/******************************/
/* Current State is Executing */
/******************************/
else if (OMX_StateExecuting == m_state)
{
if (OMX_StateIdle == eState)
{
DEBUG_PRINT("SCP-->Executing to Idle \n");
if(pcm_input)
execute_omx_flush(-1,false);
else
execute_omx_flush(1,false);
} else if (OMX_StatePause == eState)
{
DEBUG_DETAIL("*************************\n");
DEBUG_PRINT("SCP-->RXED PAUSE STATE\n");
DEBUG_DETAIL("*************************\n");
//ioctl(m_drv_fd, AUDIO_PAUSE, 0);
} else if (eState == OMX_StateLoaded)
{
DEBUG_PRINT("\n OMXCORE-SM: Executing --> Loaded \n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
} else if (eState == OMX_StateWaitForResources)
{
DEBUG_PRINT("\n OMXCORE-SM: Executing --> WaitForResources \n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
} else if (eState == OMX_StateExecuting)
{
DEBUG_PRINT("\n OMXCORE-SM: Executing --> Executing \n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorSameState,
0, NULL );
eRet = OMX_ErrorSameState;
} else if (eState == OMX_StateInvalid)
{
DEBUG_PRINT("\n OMXCORE-SM: Executing --> Invalid \n");
m_state = OMX_StateInvalid;
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorInvalidState,
0, NULL );
eRet = OMX_ErrorInvalidState;
} else
{
DEBUG_PRINT_ERROR("SCP--> Executing to %d Not Handled\n",
eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is Pause */
/***************************/
else if (OMX_StatePause == m_state)
{
if( (eState == OMX_StateExecuting || eState == OMX_StateIdle) )
{
pthread_mutex_lock(&m_out_th_lock_1);
if(is_out_th_sleep)
{
DEBUG_DETAIL("PE: WAKING UP OUT THREAD\n");
is_out_th_sleep = false;
out_th_wakeup();
}
pthread_mutex_unlock(&m_out_th_lock_1);
}
if ( OMX_StateExecuting == eState )
{
nState = eState;
} else if ( OMX_StateIdle == eState )
{
DEBUG_PRINT("SCP-->Paused to Idle \n");
DEBUG_PRINT ("\n Internal flush issued");
pthread_mutex_lock(&m_flush_lock);
m_flush_cnt = 2;
pthread_mutex_unlock(&m_flush_lock);
if(pcm_input)
execute_omx_flush(-1,false);
else
execute_omx_flush(1,false);
} else if ( eState == OMX_StateLoaded )
{
DEBUG_PRINT("\n Pause --> loaded \n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
} else if (eState == OMX_StateWaitForResources)
{
DEBUG_PRINT("\n Pause --> WaitForResources \n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
} else if (eState == OMX_StatePause)
{
DEBUG_PRINT("\n Pause --> Pause \n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorSameState,
0, NULL );
eRet = OMX_ErrorSameState;
} else if (eState == OMX_StateInvalid)
{
DEBUG_PRINT("\n Pause --> Invalid \n");
m_state = OMX_StateInvalid;
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorInvalidState,
0, NULL );
eRet = OMX_ErrorInvalidState;
} else
{
DEBUG_PRINT("SCP-->Paused to %d Not Handled\n",eState);
eRet = OMX_ErrorBadParameter;
}
}
/**************************************/
/* Current State is WaitForResources */
/**************************************/
else if (m_state == OMX_StateWaitForResources)
{
if (eState == OMX_StateLoaded)
{
DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Loaded\n");
} else if (eState == OMX_StateWaitForResources)
{
DEBUG_PRINT("OMXCORE-SM: \
WaitForResources-->WaitForResources\n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorSameState,
0, NULL );
eRet = OMX_ErrorSameState;
} else if (eState == OMX_StateExecuting)
{
DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Executing\n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
} else if (eState == OMX_StatePause)
{
DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Pause\n");
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorIncorrectStateTransition,
0, NULL );
eRet = OMX_ErrorIncorrectStateTransition;
} else if (eState == OMX_StateInvalid)
{
DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Invalid\n");
m_state = OMX_StateInvalid;
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError,
OMX_ErrorInvalidState,
0, NULL );
eRet = OMX_ErrorInvalidState;
} else
{
DEBUG_PRINT_ERROR("SCP--> %d to %d(Not Handled)\n",
m_state,eState);
eRet = OMX_ErrorBadParameter;
}
}
/****************************/
/* Current State is Invalid */
/****************************/
else if (m_state == OMX_StateInvalid)
{
if (OMX_StateLoaded == eState || OMX_StateWaitForResources == eState
|| OMX_StateIdle == eState || OMX_StateExecuting == eState
|| OMX_StatePause == eState || OMX_StateInvalid == eState)
{
DEBUG_PRINT("OMXCORE-SM: Invalid-->Loaded/Idle/Executing"
"/Pause/Invalid/WaitForResources\n");
m_state = OMX_StateInvalid;
this->m_cb.EventHandler(&this->m_cmp, this->m_app_data,
OMX_EventError, OMX_ErrorInvalidState,
0, NULL );
eRet = OMX_ErrorInvalidState;
}
} else
{
DEBUG_PRINT_ERROR("OMXCORE-SM: %d --> %d(Not Handled)\n",\
m_state,eState);
eRet = OMX_ErrorBadParameter;
}
} else if (OMX_CommandFlush == cmd)
{
DEBUG_DETAIL("*************************\n");
DEBUG_PRINT("SCP-->RXED FLUSH COMMAND port=%u\n",param1);
DEBUG_DETAIL("*************************\n");
bFlag = 0;
if ( param1 == OMX_CORE_INPUT_PORT_INDEX ||
param1 == OMX_CORE_OUTPUT_PORT_INDEX ||
(signed)param1 == -1 )
{
execute_omx_flush(param1);
} else
{
eRet = OMX_ErrorBadPortIndex;
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
OMX_CommandFlush, OMX_ErrorBadPortIndex, NULL );
}
} else if ( cmd == OMX_CommandPortDisable )
{
bFlag = 0;
if ( param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL )
{
DEBUG_PRINT("SCP: Disabling Input port Indx\n");
m_inp_bEnabled = OMX_FALSE;
if ( (m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
&& release_done(0) )
{
DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\
OMX_CORE_INPUT_PORT_INDEX:release_done \n");
DEBUG_PRINT("************* OMX_CommandPortDisable:\
m_inp_bEnabled = %d********\n",m_inp_bEnabled);
post_command(OMX_CommandPortDisable,
OMX_CORE_INPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
}
else
{
if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
{
DEBUG_PRINT("SCP: execute_omx_flush in Disable in "\
" param1=%u m_state=%d \n",param1, m_state);
execute_omx_flush(param1);
}
DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\
OMX_CORE_INPUT_PORT_INDEX \n");
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
// Skip the event notification
}
}
if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
{
DEBUG_PRINT("SCP: Disabling Output port Indx\n");
m_out_bEnabled = OMX_FALSE;
if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
&& release_done(1))
{
DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\
OMX_CORE_OUTPUT_PORT_INDEX:release_done \n");
DEBUG_PRINT("************* OMX_CommandPortDisable:\
m_out_bEnabled = %d********\n",m_inp_bEnabled);
post_command(OMX_CommandPortDisable,
OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
} else
{
if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
{
DEBUG_PRINT("SCP: execute_omx_flush in Disable out "\
"param1=%u m_state=%d \n",param1, m_state);
execute_omx_flush(param1);
}
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
// Skip the event notification
}
} else
{
DEBUG_PRINT_ERROR("OMX_CommandPortDisable: disable wrong port ID");
}
} else if (cmd == OMX_CommandPortEnable)
{
bFlag = 0;
if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
{
m_inp_bEnabled = OMX_TRUE;
DEBUG_PRINT("SCP: Enabling Input port Indx\n");
if ((m_state == OMX_StateLoaded
&& !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
|| (m_state == OMX_StateWaitForResources)
|| (m_inp_bPopulated == OMX_TRUE))
{
post_command(OMX_CommandPortEnable,
OMX_CORE_INPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
} else
{
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
// Skip the event notification
}
}
if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
{
DEBUG_PRINT("SCP: Enabling Output port Indx\n");
m_out_bEnabled = OMX_TRUE;
if ((m_state == OMX_StateLoaded
&& !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
|| (m_state == OMX_StateWaitForResources)
|| (m_out_bPopulated == OMX_TRUE))
{
post_command(OMX_CommandPortEnable,
OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
} else
{
DEBUG_PRINT("send_command_proxy:OMX_CommandPortEnable:\
OMX_CORE_OUTPUT_PORT_INDEX:release_done \n");
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
// Skip the event notification
}
pthread_mutex_lock(&m_in_th_lock_1);
if(is_in_th_sleep)
{
is_in_th_sleep = false;
DEBUG_DETAIL("SCP:WAKING UP IN THREADS\n");
in_th_wakeup();
}
pthread_mutex_unlock(&m_in_th_lock_1);
pthread_mutex_lock(&m_out_th_lock_1);
if (is_out_th_sleep)
{
is_out_th_sleep = false;
DEBUG_PRINT("SCP:WAKING OUT THR, OMX_CommandPortEnable\n");
out_th_wakeup();
}
pthread_mutex_unlock(&m_out_th_lock_1);
} else
{
DEBUG_PRINT_ERROR("OMX_CommandPortEnable: disable wrong port ID");
}
} else
{
DEBUG_PRINT_ERROR("SCP-->ERROR: Invali Command [%d]\n",cmd);
eRet = OMX_ErrorNotImplemented;
}
DEBUG_PRINT("posting sem_States\n");
sem_post (&sem_States);
if (eRet == OMX_ErrorNone && bFlag)
{
post_command(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
}
return eRet;
}
/*=============================================================================
FUNCTION:
execute_omx_flush
DESCRIPTION:
Function that flushes buffers that are pending to be written to driver
INPUT/OUTPUT PARAMETERS:
[IN] param1
[IN] cmd_cmpl
RETURN VALUE:
true
false
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
bool omx_evrc_aenc::execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl)
{
bool bRet = true;
DEBUG_PRINT("Execute_omx_flush Port[%u]", param1);
struct timespec abs_timeout;
abs_timeout.tv_sec = 1;
abs_timeout.tv_nsec = 0;
if ((signed)param1 == -1)
{
bFlushinprogress = true;
DEBUG_PRINT("Execute flush for both I/p O/p port\n");
pthread_mutex_lock(&m_flush_lock);
m_flush_cnt = 2;
pthread_mutex_unlock(&m_flush_lock);
// Send Flush commands to input and output threads
post_input(OMX_CommandFlush,
OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND);
post_output(OMX_CommandFlush,
OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND);
// Send Flush to the kernel so that the in and out buffers are released
if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1)
DEBUG_PRINT_ERROR("FLush:ioctl flush failed errno=%d\n",errno);
DEBUG_DETAIL("****************************************");
DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\
is_in_th_sleep,is_out_th_sleep);
DEBUG_DETAIL("****************************************");
pthread_mutex_lock(&m_in_th_lock_1);
if (is_in_th_sleep)
{
is_in_th_sleep = false;
DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n");
in_th_wakeup();
}
pthread_mutex_unlock(&m_in_th_lock_1);
pthread_mutex_lock(&m_out_th_lock_1);
if (is_out_th_sleep)
{
is_out_th_sleep = false;
DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n");
out_th_wakeup();
}
pthread_mutex_unlock(&m_out_th_lock_1);
// sleep till the FLUSH ACK are done by both the input and
// output threads
DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1);
wait_for_event();
DEBUG_PRINT("RECIEVED BOTH FLUSH ACK's param1=%u cmd_cmpl=%d",\
param1,cmd_cmpl);
// If not going to idle state, Send FLUSH complete message
// to the Client, now that FLUSH ACK's have been recieved.
if (cmd_cmpl)
{
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete,
OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX,
NULL );
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete,
OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX,
NULL );
DEBUG_PRINT("Inside FLUSH.. sending FLUSH CMPL\n");
}
bFlushinprogress = false;
}
else if (param1 == OMX_CORE_INPUT_PORT_INDEX)
{
DEBUG_PRINT("Execute FLUSH for I/p port\n");
pthread_mutex_lock(&m_flush_lock);
m_flush_cnt = 1;
pthread_mutex_unlock(&m_flush_lock);
post_input(OMX_CommandFlush,
OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND);
if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1)
DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n",
errno);
DEBUG_DETAIL("****************************************");
DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\
is_in_th_sleep,is_out_th_sleep);
DEBUG_DETAIL("****************************************");
if (is_in_th_sleep)
{
pthread_mutex_lock(&m_in_th_lock_1);
is_in_th_sleep = false;
pthread_mutex_unlock(&m_in_th_lock_1);
DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n");
in_th_wakeup();
}
if (is_out_th_sleep)
{
pthread_mutex_lock(&m_out_th_lock_1);
is_out_th_sleep = false;
pthread_mutex_unlock(&m_out_th_lock_1);
DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n");
out_th_wakeup();
}
//sleep till the FLUSH ACK are done by both the input and output threads
DEBUG_DETAIL("Executing FLUSH for I/p port\n");
DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1);
wait_for_event();
DEBUG_DETAIL(" RECIEVED FLUSH ACK FOR I/P PORT param1=%d",param1);
// Send FLUSH complete message to the Client,
// now that FLUSH ACK's have been recieved.
if (cmd_cmpl)
{
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete,
OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX,
NULL );
}
} else if (OMX_CORE_OUTPUT_PORT_INDEX == param1)
{
DEBUG_PRINT("Executing FLUSH for O/p port\n");
pthread_mutex_lock(&m_flush_lock);
m_flush_cnt = 1;
pthread_mutex_unlock(&m_flush_lock);
DEBUG_DETAIL("Executing FLUSH for O/p port\n");
DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1);
post_output(OMX_CommandFlush,
OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND);
if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) ==-1)
DEBUG_PRINT_ERROR("Flush:Output port, ioctl flush failed %d\n",
errno);
DEBUG_DETAIL("****************************************");
DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\
is_in_th_sleep,is_out_th_sleep);
DEBUG_DETAIL("****************************************");
if (is_in_th_sleep)
{
pthread_mutex_lock(&m_in_th_lock_1);
is_in_th_sleep = false;
pthread_mutex_unlock(&m_in_th_lock_1);
DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n");
in_th_wakeup();
}
if (is_out_th_sleep)
{
pthread_mutex_lock(&m_out_th_lock_1);
is_out_th_sleep = false;
pthread_mutex_unlock(&m_out_th_lock_1);
DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n");
out_th_wakeup();
}
// sleep till the FLUSH ACK are done by both the input and
// output threads
wait_for_event();
// Send FLUSH complete message to the Client,
// now that FLUSH ACK's have been recieved.
if (cmd_cmpl)
{
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete,
OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX,
NULL );
}
DEBUG_DETAIL("RECIEVED FLUSH ACK FOR O/P PORT param1=%d",param1);
} else
{
DEBUG_PRINT("Invalid Port ID[%u]",param1);
}
return bRet;
}
/*=============================================================================
FUNCTION:
execute_input_omx_flush
DESCRIPTION:
Function that flushes buffers that are pending to be written to driver
INPUT/OUTPUT PARAMETERS:
None
RETURN VALUE:
true
false
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
bool omx_evrc_aenc::execute_input_omx_flush()
{
OMX_BUFFERHEADERTYPE *omx_buf;
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned char ident = 0;
unsigned qsize=0; // qsize
unsigned tot_qsize=0; // qsize
DEBUG_PRINT("Execute_omx_flush on input port");
pthread_mutex_lock(&m_lock);
do
{
qsize = m_input_q.m_size;
tot_qsize = qsize;
tot_qsize += m_input_ctrl_ebd_q.m_size;
DEBUG_DETAIL("Input FLUSH-->flushq[%d] ebd[%d]dataq[%d]",\
m_input_ctrl_cmd_q.m_size,
m_input_ctrl_ebd_q.m_size,qsize);
if (!tot_qsize)
{
DEBUG_DETAIL("Input-->BREAKING FROM execute_input_flush LOOP");
pthread_mutex_unlock(&m_lock);
break;
}
if (qsize)
{
m_input_q.pop_entry(&p1, &p2, &ident);
if ((ident == OMX_COMPONENT_GENERATE_ETB) ||
(ident == OMX_COMPONENT_GENERATE_BUFFER_DONE))
{
omx_buf = (OMX_BUFFERHEADERTYPE *) p2;
DEBUG_DETAIL("Flush:Input dataq=%p \n", omx_buf);
omx_buf->nFilledLen = 0;
buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf);
}
} else if (m_input_ctrl_ebd_q.m_size)
{
m_input_ctrl_ebd_q.pop_entry(&p1, &p2, &ident);
if (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE)
{
omx_buf = (OMX_BUFFERHEADERTYPE *) p2;
omx_buf->nFilledLen = 0;
DEBUG_DETAIL("Flush:ctrl dataq=%p \n", omx_buf);
buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf);
}
} else
{
}
}while (tot_qsize>0);
DEBUG_DETAIL("*************************\n");
DEBUG_DETAIL("IN-->FLUSHING DONE\n");
DEBUG_DETAIL("*************************\n");
flush_ack();
pthread_mutex_unlock(&m_lock);
return true;
}
/*=============================================================================
FUNCTION:
execute_output_omx_flush
DESCRIPTION:
Function that flushes buffers that are pending to be written to driver
INPUT/OUTPUT PARAMETERS:
None
RETURN VALUE:
true
false
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
bool omx_evrc_aenc::execute_output_omx_flush()
{
OMX_BUFFERHEADERTYPE *omx_buf;
unsigned long p1; // Parameter - 1
unsigned long p2; // Parameter - 2
unsigned char ident = 0;
unsigned qsize=0; // qsize
unsigned tot_qsize=0; // qsize
DEBUG_PRINT("Execute_omx_flush on output port");
pthread_mutex_lock(&m_outputlock);
do
{
qsize = m_output_q.m_size;
DEBUG_DETAIL("OUT FLUSH-->flushq[%d] fbd[%d]dataq[%d]",\
m_output_ctrl_cmd_q.m_size,
m_output_ctrl_fbd_q.m_size,qsize);
tot_qsize = qsize;
tot_qsize += m_output_ctrl_fbd_q.m_size;
if (!tot_qsize)
{
DEBUG_DETAIL("OUT-->BREAKING FROM execute_input_flush LOOP");
pthread_mutex_unlock(&m_outputlock);
break;
}
if (qsize)
{
m_output_q.pop_entry(&p1,&p2,&ident);
if ( (OMX_COMPONENT_GENERATE_FTB == ident) ||
(OMX_COMPONENT_GENERATE_FRAME_DONE == ident))
{
omx_buf = (OMX_BUFFERHEADERTYPE *) p2;
DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n",\
omx_buf,nTimestamp);
omx_buf->nTimeStamp = nTimestamp;
omx_buf->nFilledLen = 0;
frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf);
DEBUG_DETAIL("CALLING FBD FROM FLUSH");
}
} else if ((qsize = m_output_ctrl_fbd_q.m_size))
{
m_output_ctrl_fbd_q.pop_entry(&p1, &p2, &ident);
if (OMX_COMPONENT_GENERATE_FRAME_DONE == ident)
{
omx_buf = (OMX_BUFFERHEADERTYPE *) p2;
DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n", \
omx_buf,nTimestamp);
omx_buf->nTimeStamp = nTimestamp;
omx_buf->nFilledLen = 0;
frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf);
DEBUG_DETAIL("CALLING FROM CTRL-FBDQ FROM FLUSH");
}
}
}while (qsize>0);
DEBUG_DETAIL("*************************\n");
DEBUG_DETAIL("OUT-->FLUSHING DONE\n");
DEBUG_DETAIL("*************************\n");
flush_ack();
pthread_mutex_unlock(&m_outputlock);
return true;
}
/*=============================================================================
FUNCTION:
post_input
DESCRIPTION:
Function that posts command in the command queue
INPUT/OUTPUT PARAMETERS:
[IN] p1
[IN] p2
[IN] id - command ID
[IN] lock - self-locking mode
RETURN VALUE:
true
false
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
bool omx_evrc_aenc::post_input(unsigned long p1,
unsigned long p2,
unsigned char id)
{
bool bRet = false;
pthread_mutex_lock(&m_lock);
if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND))
{
// insert flush message and ebd
m_input_ctrl_cmd_q.insert_entry(p1,p2,id);
} else if ((OMX_COMPONENT_GENERATE_BUFFER_DONE == id))
{
// insert ebd
m_input_ctrl_ebd_q.insert_entry(p1,p2,id);
} else
{
// ETBS in this queue
m_input_q.insert_entry(p1,p2,id);
}
if (m_ipc_to_in_th)
{
bRet = true;
omx_evrc_post_msg(m_ipc_to_in_th, id);
}
DEBUG_DETAIL("PostInput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d] \n",\
m_state,
id,
m_input_ctrl_cmd_q.m_size,
m_input_ctrl_ebd_q.m_size,
m_input_q.m_size);
pthread_mutex_unlock(&m_lock);
return bRet;
}
/*=============================================================================
FUNCTION:
post_command
DESCRIPTION:
Function that posts command in the command queue
INPUT/OUTPUT PARAMETERS:
[IN] p1
[IN] p2
[IN] id - command ID
[IN] lock - self-locking mode
RETURN VALUE:
true
false
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
bool omx_evrc_aenc::post_command(unsigned int p1,
unsigned int p2,
unsigned char id)
{
bool bRet = false;
pthread_mutex_lock(&m_commandlock);
m_command_q.insert_entry(p1,p2,id);
if (m_ipc_to_cmd_th)
{
bRet = true;
omx_evrc_post_msg(m_ipc_to_cmd_th, id);
}
DEBUG_DETAIL("PostCmd-->state[%d]id[%d]cmdq[%d]flags[%x]\n",\
m_state,
id,
m_command_q.m_size,
m_flags >> 3);
pthread_mutex_unlock(&m_commandlock);
return bRet;
}
/*=============================================================================
FUNCTION:
post_output
DESCRIPTION:
Function that posts command in the command queue
INPUT/OUTPUT PARAMETERS:
[IN] p1
[IN] p2
[IN] id - command ID
[IN] lock - self-locking mode
RETURN VALUE:
true
false
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
bool omx_evrc_aenc::post_output(unsigned long p1,
unsigned long p2,
unsigned char id)
{
bool bRet = false;
pthread_mutex_lock(&m_outputlock);
if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND)
|| (id == OMX_COMPONENT_RESUME))
{
// insert flush message and fbd
m_output_ctrl_cmd_q.insert_entry(p1,p2,id);
} else if ( (OMX_COMPONENT_GENERATE_FRAME_DONE == id) )
{
// insert flush message and fbd
m_output_ctrl_fbd_q.insert_entry(p1,p2,id);
} else
{
m_output_q.insert_entry(p1,p2,id);
}
if ( m_ipc_to_out_th )
{
bRet = true;
omx_evrc_post_msg(m_ipc_to_out_th, id);
}
DEBUG_DETAIL("PostOutput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\
m_state,
id,
m_output_ctrl_cmd_q.m_size,
m_output_ctrl_fbd_q.m_size,
m_output_q.m_size);
pthread_mutex_unlock(&m_outputlock);
return bRet;
}
/**
@brief member function that return parameters to IL client
@param hComp handle to component instance
@param paramIndex Parameter type
@param paramData pointer to memory space which would hold the
paramter
@return error status
*/
OMX_ERRORTYPE omx_evrc_aenc::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE paramIndex,
OMX_INOUT OMX_PTR paramData)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT_ERROR("Get Param in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (paramData == NULL)
{
DEBUG_PRINT("get_parameter: paramData is NULL\n");
return OMX_ErrorBadParameter;
}
switch ((int)paramIndex)
{
case OMX_IndexParamPortDefinition:
{
OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
DEBUG_PRINT("OMX_IndexParamPortDefinition " \
"portDefn->nPortIndex = %u\n",
portDefn->nPortIndex);
portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
portDefn->nSize = (OMX_U32)sizeof(portDefn);
portDefn->eDomain = OMX_PortDomainAudio;
if (0 == portDefn->nPortIndex)
{
portDefn->eDir = OMX_DirInput;
portDefn->bEnabled = m_inp_bEnabled;
portDefn->bPopulated = m_inp_bPopulated;
portDefn->nBufferCountActual = m_inp_act_buf_count;
portDefn->nBufferCountMin = OMX_CORE_NUM_INPUT_BUFFERS;
portDefn->nBufferSize = input_buffer_size;
portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE;
portDefn->format.audio.eEncoding = OMX_AUDIO_CodingPCM;
portDefn->format.audio.pNativeRender = 0;
} else if (1 == portDefn->nPortIndex)
{
portDefn->eDir = OMX_DirOutput;
portDefn->bEnabled = m_out_bEnabled;
portDefn->bPopulated = m_out_bPopulated;
portDefn->nBufferCountActual = m_out_act_buf_count;
portDefn->nBufferCountMin = OMX_CORE_NUM_OUTPUT_BUFFERS;
portDefn->nBufferSize = output_buffer_size;
portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE;
portDefn->format.audio.eEncoding = OMX_AUDIO_CodingEVRC;
portDefn->format.audio.pNativeRender = 0;
} else
{
portDefn->eDir = OMX_DirMax;
DEBUG_PRINT_ERROR("Bad Port idx %d\n",\
(int)portDefn->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamAudioInit:
{
OMX_PORT_PARAM_TYPE *portParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT("OMX_IndexParamAudioInit\n");
portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
portParamType->nSize = (OMX_U32)sizeof(portParamType);
portParamType->nPorts = 2;
portParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamAudioPortFormat:
{
OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType =
(OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData;
DEBUG_PRINT("OMX_IndexParamAudioPortFormat\n");
portFormatType->nVersion.nVersion = OMX_SPEC_VERSION;
portFormatType->nSize = (OMX_U32)sizeof(portFormatType);
if (OMX_CORE_INPUT_PORT_INDEX == portFormatType->nPortIndex)
{
portFormatType->eEncoding = OMX_AUDIO_CodingPCM;
} else if (OMX_CORE_OUTPUT_PORT_INDEX==
portFormatType->nPortIndex)
{
DEBUG_PRINT("get_parameter: OMX_IndexParamAudioFormat: "\
"%u\n", portFormatType->nIndex);
portFormatType->eEncoding = OMX_AUDIO_CodingEVRC;
} else
{
DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n",
(int)portFormatType->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamAudioEvrc:
{
OMX_AUDIO_PARAM_EVRCTYPE *evrcParam =
(OMX_AUDIO_PARAM_EVRCTYPE *) paramData;
DEBUG_PRINT("OMX_IndexParamAudioEvrc\n");
if (OMX_CORE_OUTPUT_PORT_INDEX== evrcParam->nPortIndex)
{
memcpy(evrcParam,&m_evrc_param,
sizeof(OMX_AUDIO_PARAM_EVRCTYPE));
} else
{
DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioEvrc "\
"OMX_ErrorBadPortIndex %d\n", \
(int)evrcParam->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case QOMX_IndexParamAudioSessionId:
{
QOMX_AUDIO_STREAM_INFO_DATA *streaminfoparam =
(QOMX_AUDIO_STREAM_INFO_DATA *) paramData;
streaminfoparam->sessionId = (OMX_U8)m_session_id;
break;
}
case OMX_IndexParamAudioPcm:
{
OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam =
(OMX_AUDIO_PARAM_PCMMODETYPE *) paramData;
if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex)
{
memcpy(pcmparam,&m_pcm_param,\
sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
DEBUG_PRINT("get_parameter: Sampling rate %u",\
pcmparam->nSamplingRate);
DEBUG_PRINT("get_parameter: Number of channels %u",\
pcmparam->nChannels);
} else
{
DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioPcm "\
"OMX_ErrorBadPortIndex %d\n", \
(int)pcmparam->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamComponentSuspended:
{
OMX_PARAM_SUSPENSIONTYPE *suspend =
(OMX_PARAM_SUSPENSIONTYPE *) paramData;
DEBUG_PRINT("get_parameter: OMX_IndexParamComponentSuspended %p\n",
suspend);
break;
}
case OMX_IndexParamVideoInit:
{
OMX_PORT_PARAM_TYPE *portParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT("get_parameter: OMX_IndexParamVideoInit\n");
portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
portParamType->nSize = (OMX_U32)sizeof(portParamType);
portParamType->nPorts = 0;
portParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamPriorityMgmt:
{
OMX_PRIORITYMGMTTYPE *priorityMgmtType =
(OMX_PRIORITYMGMTTYPE*)paramData;
DEBUG_PRINT("get_parameter: OMX_IndexParamPriorityMgmt\n");
priorityMgmtType->nSize = (OMX_U32)sizeof(priorityMgmtType);
priorityMgmtType->nVersion.nVersion = OMX_SPEC_VERSION;
priorityMgmtType->nGroupID = m_priority_mgm.nGroupID;
priorityMgmtType->nGroupPriority =
m_priority_mgm.nGroupPriority;
break;
}
case OMX_IndexParamImageInit:
{
OMX_PORT_PARAM_TYPE *portParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT("get_parameter: OMX_IndexParamImageInit\n");
portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
portParamType->nSize = (OMX_U32)sizeof(portParamType);
portParamType->nPorts = 0;
portParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamCompBufferSupplier:
{
DEBUG_PRINT("get_parameter: \
OMX_IndexParamCompBufferSupplier\n");
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType
= (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
DEBUG_PRINT("get_parameter: \
OMX_IndexParamCompBufferSupplier\n");
bufferSupplierType->nSize = (OMX_U32)sizeof(bufferSupplierType);
bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
if (OMX_CORE_INPUT_PORT_INDEX ==
bufferSupplierType->nPortIndex)
{
bufferSupplierType->nPortIndex =
OMX_BufferSupplyUnspecified;
} else if (OMX_CORE_OUTPUT_PORT_INDEX ==
bufferSupplierType->nPortIndex)
{
bufferSupplierType->nPortIndex =
OMX_BufferSupplyUnspecified;
} else
{
DEBUG_PRINT_ERROR("get_parameter:"\
"OMX_IndexParamCompBufferSupplier eRet"\
"%08x\n", eRet);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
/*Component should support this port definition*/
case OMX_IndexParamOtherInit:
{
OMX_PORT_PARAM_TYPE *portParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT("get_parameter: OMX_IndexParamOtherInit\n");
portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
portParamType->nSize = (OMX_U32)sizeof(portParamType);
portParamType->nPorts = 0;
portParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamStandardComponentRole:
{
OMX_PARAM_COMPONENTROLETYPE *componentRole;
componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData;
componentRole->nSize = component_Role.nSize;
componentRole->nVersion = component_Role.nVersion;
strlcpy((char *)componentRole->cRole,
(const char*)component_Role.cRole,
sizeof(componentRole->cRole));
DEBUG_PRINT_ERROR("nSize = %d , nVersion = %d, cRole = %s\n",
component_Role.nSize,
component_Role.nVersion,
component_Role.cRole);
break;
}
default:
{
DEBUG_PRINT_ERROR("unknown param %08x\n", paramIndex);
eRet = OMX_ErrorUnsupportedIndex;
}
}
return eRet;
}
/**
@brief member function that set paramter from IL client
@param hComp handle to component instance
@param paramIndex parameter type
@param paramData pointer to memory space which holds the paramter
@return error status
*/
OMX_ERRORTYPE omx_evrc_aenc::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE paramIndex,
OMX_IN OMX_PTR paramData)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state != OMX_StateLoaded)
{
DEBUG_PRINT_ERROR("set_parameter is not in proper state\n");
return OMX_ErrorIncorrectStateOperation;
}
if (paramData == NULL)
{
DEBUG_PRINT("param data is NULL");
return OMX_ErrorBadParameter;
}
switch (paramIndex)
{
case OMX_IndexParamAudioEvrc:
{
DEBUG_PRINT("OMX_IndexParamAudioEvrc");
OMX_AUDIO_PARAM_AMRTYPE *evrcparam
= (OMX_AUDIO_PARAM_AMRTYPE *) paramData;
memcpy(&m_evrc_param,evrcparam,
sizeof(OMX_AUDIO_PARAM_EVRCTYPE));
break;
}
case OMX_IndexParamPortDefinition:
{
OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
if (((m_state == OMX_StateLoaded)&&
!BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
|| (m_state == OMX_StateWaitForResources &&
((OMX_DirInput == portDefn->eDir &&
m_inp_bEnabled == true)||
(OMX_DirInput == portDefn->eDir &&
m_out_bEnabled == true)))
||(((OMX_DirInput == portDefn->eDir &&
m_inp_bEnabled == false)||
(OMX_DirInput == portDefn->eDir &&
m_out_bEnabled == false)) &&
(m_state != OMX_StateWaitForResources)))
{
DEBUG_PRINT("Set Parameter called in valid state\n");
} else
{
DEBUG_PRINT_ERROR("Set Parameter called in \
Invalid State\n");
return OMX_ErrorIncorrectStateOperation;
}
DEBUG_PRINT("OMX_IndexParamPortDefinition portDefn->nPortIndex "
"= %u\n",portDefn->nPortIndex);
if (OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex)
{
if ( portDefn->nBufferCountActual >
OMX_CORE_NUM_INPUT_BUFFERS )
{
m_inp_act_buf_count = portDefn->nBufferCountActual;
} else
{
m_inp_act_buf_count =OMX_CORE_NUM_INPUT_BUFFERS;
}
input_buffer_size = portDefn->nBufferSize;
} else if (OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex)
{
if ( portDefn->nBufferCountActual >
OMX_CORE_NUM_OUTPUT_BUFFERS )
{
m_out_act_buf_count = portDefn->nBufferCountActual;
} else
{
m_out_act_buf_count =OMX_CORE_NUM_OUTPUT_BUFFERS;
}
output_buffer_size = portDefn->nBufferSize;
} else
{
DEBUG_PRINT(" set_parameter: Bad Port idx %d",\
(int)portDefn->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamPriorityMgmt:
{
DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt\n");
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("set_parameter: OMX_IndexParamPriorityMgmt %u\n",
priorityMgmtype->nGroupID);
DEBUG_PRINT("set_parameter: priorityMgmtype %u\n",
priorityMgmtype->nGroupPriority);
m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
break;
}
case OMX_IndexParamAudioPortFormat:
{
OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType =
(OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData;
DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPortFormat\n");
if (OMX_CORE_INPUT_PORT_INDEX== portFormatType->nPortIndex)
{
portFormatType->eEncoding = OMX_AUDIO_CodingPCM;
} else if (OMX_CORE_OUTPUT_PORT_INDEX ==
portFormatType->nPortIndex)
{
DEBUG_PRINT("set_parameter: OMX_IndexParamAudioFormat:"\
" %u\n", portFormatType->nIndex);
portFormatType->eEncoding = OMX_AUDIO_CodingEVRC;
} else
{
DEBUG_PRINT_ERROR("set_parameter: Bad port index %d\n", \
(int)portFormatType->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamCompBufferSupplier:
{
DEBUG_PRINT("set_parameter: \
OMX_IndexParamCompBufferSupplier\n");
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType
= (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
DEBUG_PRINT("set_param: OMX_IndexParamCompBufferSupplier %d",\
bufferSupplierType->eBufferSupplier);
if (bufferSupplierType->nPortIndex == OMX_CORE_INPUT_PORT_INDEX
|| bufferSupplierType->nPortIndex ==
OMX_CORE_OUTPUT_PORT_INDEX)
{
DEBUG_PRINT("set_parameter:\
OMX_IndexParamCompBufferSupplier\n");
m_buffer_supplier.eBufferSupplier =
bufferSupplierType->eBufferSupplier;
} else
{
DEBUG_PRINT_ERROR("set_param:\
IndexParamCompBufferSup %08x\n", eRet);
eRet = OMX_ErrorBadPortIndex;
}
break; }
case OMX_IndexParamAudioPcm:
{
DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPcm\n");
OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam
= (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData;
if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex)
{
memcpy(&m_pcm_param,pcmparam,\
sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
DEBUG_PRINT("set_pcm_parameter: %u %u",\
m_pcm_param.nChannels,
m_pcm_param.nSamplingRate);
} else
{
DEBUG_PRINT_ERROR("Set_parameter:OMX_IndexParamAudioPcm "
"OMX_ErrorBadPortIndex %d\n",
(int)pcmparam->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamSuspensionPolicy:
{
eRet = OMX_ErrorNotImplemented;
break;
}
case OMX_IndexParamStandardComponentRole:
{
OMX_PARAM_COMPONENTROLETYPE *componentRole;
componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData;
component_Role.nSize = componentRole->nSize;
component_Role.nVersion = componentRole->nVersion;
strlcpy((char *)component_Role.cRole,
(const char*)componentRole->cRole,
sizeof(component_Role.cRole));
break;
}
default:
{
DEBUG_PRINT_ERROR("unknown param %d\n", paramIndex);
eRet = OMX_ErrorUnsupportedIndex;
}
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::GetConfig
DESCRIPTION
OMX Get Config Method implementation.
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None if successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::get_config(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE configIndex,
OMX_INOUT OMX_PTR configData)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
return OMX_ErrorInvalidState;
}
switch (configIndex)
{
case OMX_IndexConfigAudioVolume:
{
OMX_AUDIO_CONFIG_VOLUMETYPE *volume =
(OMX_AUDIO_CONFIG_VOLUMETYPE*) configData;
if (OMX_CORE_INPUT_PORT_INDEX == volume->nPortIndex)
{
volume->nSize = (OMX_U32)sizeof(volume);
volume->nVersion.nVersion = OMX_SPEC_VERSION;
volume->bLinear = OMX_TRUE;
volume->sVolume.nValue = m_volume;
volume->sVolume.nMax = OMX_AENC_MAX;
volume->sVolume.nMin = OMX_AENC_MIN;
} else
{
eRet = OMX_ErrorBadPortIndex;
}
}
break;
case OMX_IndexConfigAudioMute:
{
OMX_AUDIO_CONFIG_MUTETYPE *mute =
(OMX_AUDIO_CONFIG_MUTETYPE*) configData;
if (OMX_CORE_INPUT_PORT_INDEX == mute->nPortIndex)
{
mute->nSize = (OMX_U32)sizeof(mute);
mute->nVersion.nVersion = OMX_SPEC_VERSION;
mute->bMute = (BITMASK_PRESENT(&m_flags,
OMX_COMPONENT_MUTED)?OMX_TRUE:OMX_FALSE);
} else
{
eRet = OMX_ErrorBadPortIndex;
}
}
break;
default:
eRet = OMX_ErrorUnsupportedIndex;
break;
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::SetConfig
DESCRIPTION
OMX Set Config method implementation
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None if successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::set_config(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE configIndex,
OMX_IN OMX_PTR configData)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT_ERROR("Set Config in Invalid State\n");
return OMX_ErrorInvalidState;
}
if ( m_state == OMX_StateExecuting)
{
DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n");
return OMX_ErrorInvalidState;
}
switch (configIndex)
{
case OMX_IndexConfigAudioVolume:
{
OMX_AUDIO_CONFIG_VOLUMETYPE *vol =
(OMX_AUDIO_CONFIG_VOLUMETYPE*)configData;
if (vol->nPortIndex == OMX_CORE_INPUT_PORT_INDEX)
{
if ((vol->sVolume.nValue <= OMX_AENC_MAX) &&
(vol->sVolume.nValue >= OMX_AENC_MIN))
{
m_volume = vol->sVolume.nValue;
if (BITMASK_ABSENT(&m_flags, OMX_COMPONENT_MUTED))
{
/* ioctl(m_drv_fd, AUDIO_VOLUME,
m_volume * OMX_AENC_VOLUME_STEP); */
}
} else
{
eRet = OMX_ErrorBadParameter;
}
} else
{
eRet = OMX_ErrorBadPortIndex;
}
}
break;
case OMX_IndexConfigAudioMute:
{
OMX_AUDIO_CONFIG_MUTETYPE *mute = (OMX_AUDIO_CONFIG_MUTETYPE*)
configData;
if (mute->nPortIndex == OMX_CORE_INPUT_PORT_INDEX)
{
if (mute->bMute == OMX_TRUE)
{
BITMASK_SET(&m_flags, OMX_COMPONENT_MUTED);
/* ioctl(m_drv_fd, AUDIO_VOLUME, 0); */
} else
{
BITMASK_CLEAR(&m_flags, OMX_COMPONENT_MUTED);
/* ioctl(m_drv_fd, AUDIO_VOLUME,
m_volume * OMX_AENC_VOLUME_STEP); */
}
} else
{
eRet = OMX_ErrorBadPortIndex;
}
}
break;
default:
eRet = OMX_ErrorUnsupportedIndex;
break;
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::GetExtensionIndex
DESCRIPTION
OMX GetExtensionIndex method implementaion. <TBD>
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None if everything successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::get_extension_index(
OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_STRING paramName,
OMX_OUT OMX_INDEXTYPE* indexType)
{
if((hComp == NULL) || (paramName == NULL) || (indexType == NULL))
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n");
return OMX_ErrorInvalidState;
}
if(strncmp(paramName,"OMX.Qualcomm.index.audio.sessionId",
strlen("OMX.Qualcomm.index.audio.sessionId")) == 0)
{
*indexType =(OMX_INDEXTYPE)QOMX_IndexParamAudioSessionId;
DEBUG_PRINT("Extension index type - %d\n", *indexType);
}
else
{
return OMX_ErrorBadParameter;
}
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::GetState
DESCRIPTION
Returns the state information back to the caller.<TBD>
PARAMETERS
<TBD>.
RETURN VALUE
Error None if everything is successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::get_state(OMX_IN OMX_HANDLETYPE hComp,
OMX_OUT OMX_STATETYPE* state)
{
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
*state = m_state;
DEBUG_PRINT("Returning the state %d\n",*state);
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::ComponentTunnelRequest
DESCRIPTION
OMX Component Tunnel Request method implementation. <TBD>
PARAMETERS
None.
RETURN VALUE
OMX Error None if everything successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::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");
if((hComp == NULL) || (peerComponent == NULL) || (tunnelSetup == NULL))
{
port = port;
peerPort = peerPort;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
return OMX_ErrorNotImplemented;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::AllocateInputBuffer
DESCRIPTION
Helper function for allocate buffer in the input pin
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::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;
OMX_BUFFERHEADERTYPE *bufHdr;
unsigned nBufSize = MAX(bytes, input_buffer_size);
char *buf_ptr;
if(m_inp_current_buf_count < m_inp_act_buf_count)
{
buf_ptr = (char *) calloc((nBufSize + \
sizeof(OMX_BUFFERHEADERTYPE)+sizeof(META_IN)) , 1);
if(hComp == NULL)
{
port = port;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
free(buf_ptr);
return OMX_ErrorBadParameter;
}
if (buf_ptr != NULL)
{
bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr;
*bufferHdr = bufHdr;
memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + sizeof(META_IN)+
sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
bufHdr->nAllocLen = nBufSize;
bufHdr->pAppPrivate = appData;
bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
m_input_buf_hdrs.insert(bufHdr, NULL);
m_inp_current_buf_count++;
DEBUG_PRINT("AIB:bufHdr %p bufHdr->pBuffer %p m_inp_buf_cnt=%u \
bytes=%u", bufHdr, bufHdr->pBuffer,
m_inp_current_buf_count, bytes);
} else
{
DEBUG_PRINT("Input buffer memory allocation failed 1 \n");
eRet = OMX_ErrorInsufficientResources;
}
}
else
{
DEBUG_PRINT("Input buffer memory allocation failed 2\n");
eRet = OMX_ErrorInsufficientResources;
}
return eRet;
}
OMX_ERRORTYPE omx_evrc_aenc::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;
unsigned nBufSize = MAX(bytes,output_buffer_size);
char *buf_ptr;
if(hComp == NULL)
{
port = port;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_out_current_buf_count < m_out_act_buf_count)
{
buf_ptr = (char *) calloc( (nBufSize + sizeof(OMX_BUFFERHEADERTYPE)),1);
if (buf_ptr != NULL)
{
bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr;
*bufferHdr = bufHdr;
memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) +
sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
bufHdr->nAllocLen = nBufSize;
bufHdr->pAppPrivate = appData;
bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
m_output_buf_hdrs.insert(bufHdr, NULL);
m_out_current_buf_count++;
DEBUG_PRINT("AOB::bufHdr %p bufHdr->pBuffer %p m_out_buf_cnt=%d "\
"bytes=%u",bufHdr, bufHdr->pBuffer,\
m_out_current_buf_count, bytes);
} else
{
DEBUG_PRINT("Output buffer memory allocation failed 1 \n");
eRet = OMX_ErrorInsufficientResources;
}
} else
{
DEBUG_PRINT("Output buffer memory allocation failed\n");
eRet = OMX_ErrorInsufficientResources;
}
return eRet;
}
// AllocateBuffer -- API Call
/* ======================================================================
FUNCTION
omx_evrc_aenc::AllocateBuffer
DESCRIPTION
Returns zero if all the buffers released..
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::allocate_buffer
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
OMX_IN OMX_U32 port,
OMX_IN OMX_PTR appData,
OMX_IN OMX_U32 bytes)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n");
return OMX_ErrorInvalidState;
}
// What if the client calls again.
if (OMX_CORE_INPUT_PORT_INDEX == port)
{
eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
} else if (OMX_CORE_OUTPUT_PORT_INDEX == port)
{
eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
} else
{
DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",
(int)port);
eRet = OMX_ErrorBadPortIndex;
}
if (eRet == OMX_ErrorNone)
{
DEBUG_PRINT("allocate_buffer: before allocate_done \n");
if (allocate_done())
{
DEBUG_PRINT("allocate_buffer: after allocate_done \n");
if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
{
BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING);
post_command(OMX_CommandStateSet,OMX_StateIdle,
OMX_COMPONENT_GENERATE_EVENT);
DEBUG_PRINT("allocate_buffer: post idle transition event \n");
}
DEBUG_PRINT("allocate_buffer: complete \n");
}
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_command(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);
m_out_bEnabled = OMX_TRUE;
DEBUG_PRINT("AllocBuf-->is_out_th_sleep=%d\n",is_out_th_sleep);
pthread_mutex_lock(&m_out_th_lock_1);
if (is_out_th_sleep)
{
is_out_th_sleep = false;
DEBUG_DETAIL("AllocBuf:WAKING UP OUT THREADS\n");
out_th_wakeup();
}
pthread_mutex_unlock(&m_out_th_lock_1);
pthread_mutex_lock(&m_in_th_lock_1);
if(is_in_th_sleep)
{
is_in_th_sleep = false;
DEBUG_DETAIL("AB:WAKING UP IN THREADS\n");
in_th_wakeup();
}
pthread_mutex_unlock(&m_in_th_lock_1);
post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
}
}
}
DEBUG_PRINT("Allocate Buffer exit with ret Code %d\n", eRet);
return eRet;
}
/*=============================================================================
FUNCTION:
use_buffer
DESCRIPTION:
OMX Use Buffer method implementation.
INPUT/OUTPUT PARAMETERS:
[INOUT] bufferHdr
[IN] hComp
[IN] port
[IN] appData
[IN] bytes
[IN] buffer
RETURN VALUE:
OMX_ERRORTYPE
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
OMX_ERRORTYPE omx_evrc_aenc::use_buffer
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
OMX_IN OMX_U32 port,
OMX_IN OMX_PTR appData,
OMX_IN OMX_U32 bytes,
OMX_IN OMX_U8* buffer)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if (OMX_CORE_INPUT_PORT_INDEX == port)
{
eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
} else if (OMX_CORE_OUTPUT_PORT_INDEX == port)
{
eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
} else
{
DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
eRet = OMX_ErrorBadPortIndex;
}
if (eRet == OMX_ErrorNone)
{
DEBUG_PRINT("Checking for Output Allocate buffer Done");
if (allocate_done())
{
if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
{
BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING);
post_command(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_command(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_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
pthread_mutex_lock(&m_out_th_lock_1);
if (is_out_th_sleep)
{
is_out_th_sleep = false;
DEBUG_DETAIL("UseBuf:WAKING UP OUT THREADS\n");
out_th_wakeup();
}
pthread_mutex_unlock(&m_out_th_lock_1);
pthread_mutex_lock(&m_in_th_lock_1);
if(is_in_th_sleep)
{
is_in_th_sleep = false;
DEBUG_DETAIL("UB:WAKING UP IN THREADS\n");
in_th_wakeup();
}
pthread_mutex_unlock(&m_in_th_lock_1);
}
}
}
DEBUG_PRINT("Use Buffer for port[%u] eRet[%d]\n", port,eRet);
return eRet;
}
/*=============================================================================
FUNCTION:
use_input_buffer
DESCRIPTION:
Helper function for Use buffer in the input pin
INPUT/OUTPUT PARAMETERS:
[INOUT] bufferHdr
[IN] hComp
[IN] port
[IN] appData
[IN] bytes
[IN] buffer
RETURN VALUE:
OMX_ERRORTYPE
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
OMX_ERRORTYPE omx_evrc_aenc::use_input_buffer
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
OMX_IN OMX_U32 port,
OMX_IN OMX_PTR appData,
OMX_IN OMX_U32 bytes,
OMX_IN OMX_U8* buffer)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_BUFFERHEADERTYPE *bufHdr;
unsigned nBufSize = MAX(bytes, input_buffer_size);
char *buf_ptr;
if(hComp == NULL)
{
port = port;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if(bytes < input_buffer_size)
{
/* return if i\p buffer size provided by client
is less than min i\p buffer size supported by omx component*/
return OMX_ErrorInsufficientResources;
}
if (m_inp_current_buf_count < m_inp_act_buf_count)
{
buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1);
if (buf_ptr != NULL)
{
bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr;
*bufferHdr = bufHdr;
memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->pBuffer = (OMX_U8 *)(buffer);
DEBUG_PRINT("use_input_buffer:bufHdr %p bufHdr->pBuffer %p \
bytes=%u", bufHdr, bufHdr->pBuffer,bytes);
bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
bufHdr->nAllocLen = nBufSize;
input_buffer_size = nBufSize;
bufHdr->pAppPrivate = appData;
bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
bufHdr->nOffset = 0;
m_input_buf_hdrs.insert(bufHdr, NULL);
m_inp_current_buf_count++;
} else
{
DEBUG_PRINT("Input buffer memory allocation failed 1 \n");
eRet = OMX_ErrorInsufficientResources;
}
} else
{
DEBUG_PRINT("Input buffer memory allocation failed\n");
eRet = OMX_ErrorInsufficientResources;
}
return eRet;
}
/*=============================================================================
FUNCTION:
use_output_buffer
DESCRIPTION:
Helper function for Use buffer in the output pin
INPUT/OUTPUT PARAMETERS:
[INOUT] bufferHdr
[IN] hComp
[IN] port
[IN] appData
[IN] bytes
[IN] buffer
RETURN VALUE:
OMX_ERRORTYPE
Dependency:
None
SIDE EFFECTS:
None
=============================================================================*/
OMX_ERRORTYPE omx_evrc_aenc::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;
unsigned nBufSize = MAX(bytes,output_buffer_size);
char *buf_ptr;
if(hComp == NULL)
{
port = port;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (bytes < output_buffer_size)
{
/* return if o\p buffer size provided by client
is less than min o\p buffer size supported by omx component*/
return OMX_ErrorInsufficientResources;
}
DEBUG_PRINT("Inside omx_evrc_aenc::use_output_buffer");
if (m_out_current_buf_count < m_out_act_buf_count)
{
buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1);
if (buf_ptr != NULL)
{
bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr;
DEBUG_PRINT("BufHdr=%p buffer=%p\n",bufHdr,buffer);
*bufferHdr = bufHdr;
memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->pBuffer = (OMX_U8 *)(buffer);
DEBUG_PRINT("use_output_buffer:bufHdr %p bufHdr->pBuffer %p \
len=%u\n", bufHdr, bufHdr->pBuffer,bytes);
bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
bufHdr->nAllocLen = nBufSize;
output_buffer_size = nBufSize;
bufHdr->pAppPrivate = appData;
bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
bufHdr->nOffset = 0;
m_output_buf_hdrs.insert(bufHdr, NULL);
m_out_current_buf_count++;
} else
{
DEBUG_PRINT("Output buffer memory allocation failed\n");
eRet = OMX_ErrorInsufficientResources;
}
} else
{
DEBUG_PRINT("Output buffer memory allocation failed 2\n");
eRet = OMX_ErrorInsufficientResources;
}
return eRet;
}
/**
@brief member function that searches for caller buffer
@param buffer pointer to buffer header
@return bool value indicating whether buffer is found
*/
bool omx_evrc_aenc::search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer)
{
bool eRet = false;
OMX_BUFFERHEADERTYPE *temp = NULL;
//access only in IL client context
temp = m_input_buf_hdrs.find_ele(buffer);
if (buffer && temp)
{
DEBUG_DETAIL("search_input_bufhdr %p \n", buffer);
eRet = true;
}
return eRet;
}
/**
@brief member function that searches for caller buffer
@param buffer pointer to buffer header
@return bool value indicating whether buffer is found
*/
bool omx_evrc_aenc::search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer)
{
bool eRet = false;
OMX_BUFFERHEADERTYPE *temp = NULL;
//access only in IL client context
temp = m_output_buf_hdrs.find_ele(buffer);
if (buffer && temp)
{
DEBUG_DETAIL("search_output_bufhdr %p \n", buffer);
eRet = true;
}
return eRet;
}
// Free Buffer - API call
/**
@brief member function that handles free buffer command from IL client
This function is a block-call function that handles IL client request to
freeing the buffer
@param hComp handle to component instance
@param port id of port which holds the buffer
@param buffer buffer header
@return Error status
*/
OMX_ERRORTYPE omx_evrc_aenc::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_U32 port,
OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
DEBUG_PRINT("Free_Buffer buf %p\n", buffer);
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateIdle &&
(BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
{
DEBUG_PRINT(" 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("Free Buffer while port %u disabled\n", port);
} else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause)
{
DEBUG_PRINT("Invalid state to free buffer,ports need to be disabled:\
OMX_ErrorPortUnpopulated\n");
post_command(OMX_EventError,
OMX_ErrorPortUnpopulated,
OMX_COMPONENT_GENERATE_EVENT);
return eRet;
} else
{
DEBUG_PRINT("free_buffer: Invalid state to free buffer,ports need to be\
disabled:OMX_ErrorPortUnpopulated\n");
post_command(OMX_EventError,
OMX_ErrorPortUnpopulated,
OMX_COMPONENT_GENERATE_EVENT);
}
if (OMX_CORE_INPUT_PORT_INDEX == port)
{
if (m_inp_current_buf_count != 0)
{
m_inp_bPopulated = OMX_FALSE;
if (true == search_input_bufhdr(buffer))
{
/* Buffer exist */
//access only in IL client context
DEBUG_PRINT("Free_Buf:in_buffer[%p]\n",buffer);
m_input_buf_hdrs.erase(buffer);
free(buffer);
m_inp_current_buf_count--;
} else
{
DEBUG_PRINT_ERROR("Free_Buf:Error-->free_buffer, \
Invalid Input buffer header\n");
eRet = OMX_ErrorBadParameter;
}
} else
{
DEBUG_PRINT_ERROR("Error: free_buffer,Port Index calculation \
came out Invalid\n");
eRet = OMX_ErrorBadPortIndex;
}
if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
&& release_done(0))
{
DEBUG_PRINT("INPUT PORT MOVING TO DISABLED STATE \n");
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
post_command(OMX_CommandPortDisable,
OMX_CORE_INPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
}
} else if (OMX_CORE_OUTPUT_PORT_INDEX == port)
{
if (m_out_current_buf_count != 0)
{
m_out_bPopulated = OMX_FALSE;
if (true == search_output_bufhdr(buffer))
{
/* Buffer exist */
//access only in IL client context
DEBUG_PRINT("Free_Buf:out_buffer[%p]\n",buffer);
m_output_buf_hdrs.erase(buffer);
free(buffer);
m_out_current_buf_count--;
} else
{
DEBUG_PRINT("Free_Buf:Error-->free_buffer , \
Invalid Output buffer header\n");
eRet = OMX_ErrorBadParameter;
}
} else
{
eRet = OMX_ErrorBadPortIndex;
}
if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
&& release_done(1))
{
DEBUG_PRINT("OUTPUT PORT MOVING TO DISABLED STATE \n");
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
post_command(OMX_CommandPortDisable,
OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
}
} else
{
eRet = OMX_ErrorBadPortIndex;
}
if ((OMX_ErrorNone == eRet) &&
(BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
{
if (release_done(-1))
{
if(ioctl(m_drv_fd, AUDIO_STOP, 0) < 0)
DEBUG_PRINT_ERROR("AUDIO STOP in free buffer failed\n");
else
DEBUG_PRINT("AUDIO STOP in free buffer passed\n");
DEBUG_PRINT("Free_Buf: Free buffer\n");
// Send the callback now
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
DEBUG_PRINT("Before OMX_StateLoaded \
OMX_COMPONENT_GENERATE_EVENT\n");
post_command(OMX_CommandStateSet,
OMX_StateLoaded,OMX_COMPONENT_GENERATE_EVENT);
DEBUG_PRINT("After OMX_StateLoaded OMX_COMPONENT_GENERATE_EVENT\n");
}
}
return eRet;
}
/**
@brief member function that that handles empty this buffer command
This function meremly queue up the command and data would be consumed
in command server thread context
@param hComp handle to component instance
@param buffer pointer to buffer header
@return error status
*/
OMX_ERRORTYPE omx_evrc_aenc::empty_this_buffer(
OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
DEBUG_PRINT("ETB:Buf:%p Len %u TS %lld numInBuf=%d\n", \
buffer, buffer->nFilledLen, buffer->nTimeStamp, (nNumInputBuf));
if (m_state == OMX_StateInvalid)
{
DEBUG_PRINT("Empty this buffer in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (!m_inp_bEnabled)
{
DEBUG_PRINT("empty_this_buffer OMX_ErrorIncorrectStateOperation "\
"Port Status %d \n", m_inp_bEnabled);
return OMX_ErrorIncorrectStateOperation;
}
if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))
{
DEBUG_PRINT("omx_evrc_aenc::etb--> Buffer Size Invalid\n");
return OMX_ErrorBadParameter;
}
if (buffer->nVersion.nVersion != OMX_SPEC_VERSION)
{
DEBUG_PRINT("omx_evrc_aenc::etb--> OMX Version Invalid\n");
return OMX_ErrorVersionMismatch;
}
if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX)
{
return OMX_ErrorBadPortIndex;
}
if ((m_state != OMX_StateExecuting) &&
(m_state != OMX_StatePause))
{
DEBUG_PRINT_ERROR("Invalid state\n");
eRet = OMX_ErrorInvalidState;
}
if (OMX_ErrorNone == eRet)
{
if (search_input_bufhdr(buffer) == true)
{
post_input((unsigned long)hComp,
(unsigned long) buffer,OMX_COMPONENT_GENERATE_ETB);
} else
{
DEBUG_PRINT_ERROR("Bad header %p \n", buffer);
eRet = OMX_ErrorBadParameter;
}
}
pthread_mutex_lock(&in_buf_count_lock);
nNumInputBuf++;
m_evrc_pb_stats.etb_cnt++;
pthread_mutex_unlock(&in_buf_count_lock);
return eRet;
}
/**
@brief member function that writes data to kernel driver
@param hComp handle to component instance
@param buffer pointer to buffer header
@return error status
*/
OMX_ERRORTYPE omx_evrc_aenc::empty_this_buffer_proxy
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_BUFFERHEADERTYPE* buffer)
{
OMX_STATETYPE state;
META_IN meta_in;
//Pointer to the starting location of the data to be transcoded
OMX_U8 *srcStart;
//The total length of the data to be transcoded
srcStart = buffer->pBuffer;
OMX_U8 *data = NULL;
PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer);
memset(&meta_in,0,sizeof(meta_in));
if ( search_input_bufhdr(buffer) == false )
{
DEBUG_PRINT("ETBP: INVALID BUF HDR\n");
buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
return OMX_ErrorBadParameter;
}
if (m_tmp_meta_buf)
{
data = m_tmp_meta_buf;
// copy the metadata info from the BufHdr and insert to payload
meta_in.offsetVal = (OMX_U16)sizeof(META_IN);
meta_in.nTimeStamp.LowPart =
(unsigned int) ((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) & 0xFFFFFFFF);
meta_in.nTimeStamp.HighPart =
(unsigned int) (((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) >> 32) & 0xFFFFFFFF);
meta_in.nFlags &= ~OMX_BUFFERFLAG_EOS;
if(buffer->nFlags & OMX_BUFFERFLAG_EOS)
{
DEBUG_PRINT("EOS OCCURED \n");
meta_in.nFlags |= OMX_BUFFERFLAG_EOS;
}
memcpy(data,&meta_in, meta_in.offsetVal);
DEBUG_PRINT("meta_in.nFlags = %d\n",meta_in.nFlags);
}
memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen);
write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN));
pthread_mutex_lock(&m_state_lock);
get_state(&m_cmp, &state);
pthread_mutex_unlock(&m_state_lock);
if (OMX_StateExecuting == state)
{
DEBUG_DETAIL("In Exe state, EBD CB");
buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
} else
{
/* Assume empty this buffer function has already checked
validity of buffer */
DEBUG_PRINT("Empty buffer %p to kernel driver\n", buffer);
post_input((unsigned long) & hComp,(unsigned long) buffer,
OMX_COMPONENT_GENERATE_BUFFER_DONE);
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_evrc_aenc::fill_this_buffer_proxy
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_BUFFERHEADERTYPE* buffer)
{
OMX_STATETYPE state;
ENC_META_OUT *meta_out = NULL;
ssize_t nReadbytes = 0;
pthread_mutex_lock(&m_state_lock);
get_state(&m_cmp, &state);
pthread_mutex_unlock(&m_state_lock);
if (true == search_output_bufhdr(buffer))
{
DEBUG_PRINT("\nBefore Read..m_drv_fd = %d,\n",m_drv_fd);
nReadbytes = read(m_drv_fd,buffer->pBuffer,output_buffer_size );
DEBUG_DETAIL("FTBP->Al_len[%lu]buf[%p]size[%d]numOutBuf[%d]\n",\
buffer->nAllocLen,buffer->pBuffer,
nReadbytes,nNumOutputBuf);
if (nReadbytes <= 0) {
buffer->nFilledLen = 0;
buffer->nOffset = 0;
buffer->nTimeStamp = nTimestamp;
frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
return OMX_ErrorNone;
} else
DEBUG_PRINT("Read bytes %d\n",nReadbytes);
// Buffer from Driver will have
// 1 byte => Nr of frame field
// (sizeof(ENC_META_OUT) * Nr of frame) bytes => meta_out->offset_to_frame
// Frame Size * Nr of frame =>
meta_out = (ENC_META_OUT *)(buffer->pBuffer + sizeof(unsigned char));
buffer->nTimeStamp = (((OMX_TICKS) meta_out->msw_ts << 32)+
meta_out->lsw_ts);
buffer->nFlags |= meta_out->nflags;
buffer->nOffset = (OMX_U32)(meta_out->offset_to_frame +
sizeof(unsigned char));
buffer->nFilledLen = (OMX_U32)(nReadbytes - buffer->nOffset);
nTimestamp = buffer->nTimeStamp;
DEBUG_PRINT("nflags %d frame_size %d offset_to_frame %d \
timestamp %lld\n", meta_out->nflags,
meta_out->frame_size, meta_out->offset_to_frame,
buffer->nTimeStamp);
if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS )
{
buffer->nFilledLen = 0;
buffer->nOffset = 0;
buffer->nTimeStamp = nTimestamp;
frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS )
{
DEBUG_PRINT("FTBP: Now, Send EOS flag to Client \n");
m_cb.EventHandler(&m_cmp,
m_app_data,
OMX_EventBufferFlag,
1, 1, NULL );
}
return OMX_ErrorNone;
}
DEBUG_PRINT("nState %d \n",nState );
pthread_mutex_lock(&m_state_lock);
get_state(&m_cmp, &state);
pthread_mutex_unlock(&m_state_lock);
if (state == OMX_StatePause)
{
DEBUG_PRINT("FTBP:Post the FBD to event thread currstate=%d\n",\
state);
post_output((unsigned long) & hComp,(unsigned long) buffer,
OMX_COMPONENT_GENERATE_FRAME_DONE);
}
else
{
frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer);
}
}
else
DEBUG_PRINT("\n FTBP-->Invalid buffer in FTB \n");
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::FillThisBuffer
DESCRIPTION
IL client uses this method to release the frame buffer
after displaying them.
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::fill_this_buffer
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_BUFFERHEADERTYPE* buffer)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))
{
DEBUG_PRINT("omx_evrc_aenc::ftb--> Buffer Size Invalid\n");
return OMX_ErrorBadParameter;
}
if (m_out_bEnabled == OMX_FALSE)
{
return OMX_ErrorIncorrectStateOperation;
}
if (buffer->nVersion.nVersion != OMX_SPEC_VERSION)
{
DEBUG_PRINT("omx_evrc_aenc::ftb--> OMX Version Invalid\n");
return OMX_ErrorVersionMismatch;
}
if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX)
{
return OMX_ErrorBadPortIndex;
}
pthread_mutex_lock(&out_buf_count_lock);
nNumOutputBuf++;
m_evrc_pb_stats.ftb_cnt++;
DEBUG_DETAIL("FTB:nNumOutputBuf is %d", nNumOutputBuf);
pthread_mutex_unlock(&out_buf_count_lock);
post_output((unsigned long)hComp,
(unsigned long) buffer,OMX_COMPONENT_GENERATE_FTB);
return eRet;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::SetCallbacks
DESCRIPTION
Set the callbacks.
PARAMETERS
None.
RETURN VALUE
OMX Error None if everything successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_CALLBACKTYPE* callbacks,
OMX_IN OMX_PTR appData)
{
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
m_cb = *callbacks;
m_app_data = appData;
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::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_evrc_aenc::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
{
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (OMX_StateLoaded != m_state && OMX_StateInvalid != m_state)
{
DEBUG_PRINT_ERROR("Warning: Rxed DeInit when not in LOADED state %d\n",
m_state);
}
deinit_encoder();
DEBUG_PRINT_ERROR("%s:COMPONENT DEINIT...\n", __FUNCTION__);
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::deinit_encoder
DESCRIPTION
Closes all the threads and release memory allocated to the heap.
PARAMETERS
None.
RETURN VALUE
None.
========================================================================== */
void omx_evrc_aenc::deinit_encoder()
{
DEBUG_PRINT("Component-deinit being processed\n");
DEBUG_PRINT("********************************\n");
DEBUG_PRINT("STATS: in-buf-len[%u]out-buf-len[%u] tot-pb-time[%lld]",\
m_evrc_pb_stats.tot_in_buf_len,
m_evrc_pb_stats.tot_out_buf_len,
m_evrc_pb_stats.tot_pb_time);
DEBUG_PRINT("STATS: fbd-cnt[%u]ftb-cnt[%u]etb-cnt[%u]ebd-cnt[%u]",\
m_evrc_pb_stats.fbd_cnt,m_evrc_pb_stats.ftb_cnt,
m_evrc_pb_stats.etb_cnt,
m_evrc_pb_stats.ebd_cnt);
memset(&m_evrc_pb_stats,0,sizeof(EVRC_PB_STATS));
if((OMX_StateLoaded != m_state) && (OMX_StateInvalid != m_state))
{
DEBUG_PRINT_ERROR("%s,Deinit called in state[%d]\n",__FUNCTION__,\
m_state);
// Get back any buffers from driver
if(pcm_input)
execute_omx_flush(-1,false);
else
execute_omx_flush(1,false);
// force state change to loaded so that all threads can be exited
pthread_mutex_lock(&m_state_lock);
m_state = OMX_StateLoaded;
pthread_mutex_unlock(&m_state_lock);
DEBUG_PRINT_ERROR("Freeing Buf:inp_current_buf_count[%d][%d]\n",\
m_inp_current_buf_count,
m_input_buf_hdrs.size());
m_input_buf_hdrs.eraseall();
DEBUG_PRINT_ERROR("Freeing Buf:out_current_buf_count[%d][%d]\n",\
m_out_current_buf_count,
m_output_buf_hdrs.size());
m_output_buf_hdrs.eraseall();
}
if(pcm_input)
{
pthread_mutex_lock(&m_in_th_lock_1);
if (is_in_th_sleep)
{
is_in_th_sleep = false;
DEBUG_DETAIL("Deinit:WAKING UP IN THREADS\n");
in_th_wakeup();
}
pthread_mutex_unlock(&m_in_th_lock_1);
}
pthread_mutex_lock(&m_out_th_lock_1);
if (is_out_th_sleep)
{
is_out_th_sleep = false;
DEBUG_DETAIL("SCP:WAKING UP OUT THREADS\n");
out_th_wakeup();
}
pthread_mutex_unlock(&m_out_th_lock_1);
if(pcm_input)
{
if (m_ipc_to_in_th != NULL)
{
omx_evrc_thread_stop(m_ipc_to_in_th);
m_ipc_to_in_th = NULL;
}
}
if (m_ipc_to_cmd_th != NULL)
{
omx_evrc_thread_stop(m_ipc_to_cmd_th);
m_ipc_to_cmd_th = NULL;
}
if (m_ipc_to_out_th != NULL)
{
DEBUG_DETAIL("Inside omx_evrc_thread_stop\n");
omx_evrc_thread_stop(m_ipc_to_out_th);
m_ipc_to_out_th = NULL;
}
if(ioctl(m_drv_fd, AUDIO_STOP, 0) <0)
DEBUG_PRINT_ERROR("De-init: AUDIO_STOP FAILED\n");
if(pcm_input && m_tmp_meta_buf )
{
free(m_tmp_meta_buf);
}
if(m_tmp_out_meta_buf)
{
free(m_tmp_out_meta_buf);
}
nNumInputBuf = 0;
nNumOutputBuf = 0;
bFlushinprogress = 0;
m_inp_current_buf_count=0;
m_out_current_buf_count=0;
m_out_act_buf_count = 0;
m_inp_act_buf_count = 0;
m_inp_bEnabled = OMX_FALSE;
m_out_bEnabled = OMX_FALSE;
m_inp_bPopulated = OMX_FALSE;
m_out_bPopulated = OMX_FALSE;
if ( m_drv_fd >= 0 )
{
if(close(m_drv_fd) < 0)
DEBUG_PRINT("De-init: Driver Close Failed \n");
m_drv_fd = -1;
}
else
{
DEBUG_PRINT_ERROR(" EVRC device already closed\n");
}
m_comp_deinit=1;
m_is_out_th_sleep = 1;
m_is_in_th_sleep = 1;
DEBUG_PRINT("************************************\n");
DEBUG_PRINT(" DEINIT COMPLETED");
DEBUG_PRINT("************************************\n");
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::UseEGLImage
DESCRIPTION
OMX Use EGL Image method implementation <TBD>.
PARAMETERS
<TBD>.
RETURN VALUE
Not Implemented error.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::use_EGL_image
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
OMX_IN OMX_U32 port,
OMX_IN OMX_PTR appData,
OMX_IN void* eglImage)
{
DEBUG_PRINT_ERROR("Error : use_EGL_image: Not Implemented \n");
if((hComp == NULL) || (appData == NULL) || (eglImage == NULL))
{
bufferHdr = bufferHdr;
port = port;
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
return OMX_ErrorNotImplemented;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::ComponentRoleEnum
DESCRIPTION
OMX Component Role Enum method implementation.
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None if everything is successful.
========================================================================== */
OMX_ERRORTYPE omx_evrc_aenc::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
OMX_OUT OMX_U8* role,
OMX_IN OMX_U32 index)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
const char *cmp_role = "audio_encoder.evrc";
if(hComp == NULL)
{
DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n");
return OMX_ErrorBadParameter;
}
if (index == 0 && role)
{
memcpy(role, cmp_role, strlen(cmp_role));
*(((char *) role) + strlen(cmp_role) + 1) = '\0';
} else
{
eRet = OMX_ErrorNoMore;
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::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_evrc_aenc::allocate_done(void)
{
OMX_BOOL bRet = OMX_FALSE;
if (pcm_input==1)
{
if ((m_inp_act_buf_count == m_inp_current_buf_count)
&&(m_out_act_buf_count == m_out_current_buf_count))
{
bRet=OMX_TRUE;
}
if ((m_inp_act_buf_count == m_inp_current_buf_count) && m_inp_bEnabled )
{
m_inp_bPopulated = OMX_TRUE;
}
if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled )
{
m_out_bPopulated = OMX_TRUE;
}
} else if (pcm_input==0)
{
if (m_out_act_buf_count == m_out_current_buf_count)
{
bRet=OMX_TRUE;
}
if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled )
{
m_out_bPopulated = OMX_TRUE;
}
}
return bRet;
}
/* ======================================================================
FUNCTION
omx_evrc_aenc::ReleaseDone
DESCRIPTION
Checks if IL client has released all the buffers.
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
bool omx_evrc_aenc::release_done(OMX_U32 param1)
{
DEBUG_PRINT("Inside omx_evrc_aenc::release_done");
OMX_BOOL bRet = OMX_FALSE;
if (param1 == OMX_ALL)
{
if ((0 == m_inp_current_buf_count)&&(0 == m_out_current_buf_count))
{
bRet=OMX_TRUE;
}
} else if (param1 == OMX_CORE_INPUT_PORT_INDEX )
{
if ((0 == m_inp_current_buf_count))
{
bRet=OMX_TRUE;
}
} else if (param1 == OMX_CORE_OUTPUT_PORT_INDEX)
{
if ((0 == m_out_current_buf_count))
{
bRet=OMX_TRUE;
}
}
return bRet;
}