/*-------------------------------------------------------------------------- | |
Copyright (c) 2010, Code Aurora Forum. All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
* Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
* Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
* Neither the name of Code Aurora nor | |
the names of its contributors may be used to endorse or promote | |
products derived from this software without specific prior written | |
permission. | |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
--------------------------------------------------------------------------*/ | |
/*============================================================================ | |
O p e n M A X w r a p p e r s | |
O p e n M A X C o r e | |
*//** @file omx_video_base.cpp | |
This module contains the implementation of the OpenMAX core & component. | |
*//*========================================================================*/ | |
////////////////////////////////////////////////////////////////////////////// | |
// Include Files | |
////////////////////////////////////////////////////////////////////////////// | |
#include <string.h> | |
#include "omx_video_base.h" | |
#include <stdlib.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#define H264_SUPPORTED_WIDTH (480) | |
#define H264_SUPPORTED_HEIGHT (368) | |
#define MPEG4_SUPPORTED_WIDTH (480) | |
#define MPEG4_SUPPORTED_HEIGHT (368) | |
#define VC1_SP_MP_START_CODE 0xC5000000 | |
#define VC1_SP_MP_START_CODE_MASK 0xFF000000 | |
#define VC1_AP_START_CODE 0x00000100 | |
#define VC1_AP_START_CODE_MASK 0xFFFFFF00 | |
#define VC1_STRUCT_C_PROFILE_MASK 0xF0 | |
#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 | |
#define VC1_SIMPLE_PROFILE 0 | |
#define VC1_MAIN_PROFILE 1 | |
#define VC1_ADVANCE_PROFILE 3 | |
#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 | |
#define VC1_SIMPLE_PROFILE_MED_LEVEL 2 | |
#define VC1_STRUCT_C_LEN 4 | |
#define VC1_STRUCT_C_POS 8 | |
#define VC1_STRUCT_A_POS 12 | |
#define VC1_STRUCT_B_POS 24 | |
#define VC1_SEQ_LAYER_SIZE 36 | |
typedef struct OMXComponentCapabilityFlagsType | |
{ | |
////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS | |
OMX_BOOL iIsOMXComponentMultiThreaded; | |
OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc; | |
OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc; | |
OMX_BOOL iOMXComponentSupportsMovableInputBuffers; | |
OMX_BOOL iOMXComponentSupportsPartialFrames; | |
OMX_BOOL iOMXComponentUsesNALStartCodes; | |
OMX_BOOL iOMXComponentCanHandleIncompleteFrames; | |
OMX_BOOL iOMXComponentUsesFullAVCFrames; | |
} OMXComponentCapabilityFlagsType; | |
#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347 | |
void* message_thread(void *input) | |
{ | |
omx_video* omx = reinterpret_cast<omx_video*>(input); | |
unsigned char id; | |
int n; | |
DEBUG_PRINT_LOW("omx_venc: message thread start\n"); | |
while(1) | |
{ | |
n = read(omx->m_pipe_in, &id, 1); | |
if(0 == n) | |
{ | |
break; | |
} | |
if(1 == n) | |
{ | |
omx->process_event_cb(omx, id); | |
} | |
#ifdef QLE_BUILD | |
if(n < 0) break; | |
#else | |
if((n < 0) && (errno != EINTR)) break; | |
#endif | |
} | |
DEBUG_PRINT_LOW("omx_venc: message thread stop\n"); | |
return 0; | |
} | |
void post_message(omx_video *omx, unsigned char id) | |
{ | |
DEBUG_PRINT_LOW("omx_venc: post_message %d\n", id); | |
write(omx->m_pipe_out, &id, 1); | |
} | |
// omx_cmd_queue destructor | |
omx_video::omx_cmd_queue::~omx_cmd_queue() | |
{ | |
// Nothing to do | |
} | |
// omx cmd queue constructor | |
omx_video::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) | |
{ | |
memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); | |
} | |
// omx cmd queue insert | |
bool omx_video::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) | |
{ | |
bool ret = true; | |
if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) | |
{ | |
m_q[m_write].id = id; | |
m_q[m_write].param1 = p1; | |
m_q[m_write].param2 = p2; | |
m_write++; | |
m_size ++; | |
if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) | |
{ | |
m_write = 0; | |
} | |
} | |
else | |
{ | |
ret = false; | |
DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full\n"); | |
} | |
return ret; | |
} | |
// omx cmd queue pop | |
bool omx_video::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) | |
{ | |
bool ret = true; | |
if(m_size > 0) | |
{ | |
*id = m_q[m_read].id; | |
*p1 = m_q[m_read].param1; | |
*p2 = m_q[m_read].param2; | |
// Move the read pointer ahead | |
++m_read; | |
--m_size; | |
if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) | |
{ | |
m_read = 0; | |
} | |
} | |
else | |
{ | |
ret = false; | |
} | |
return ret; | |
} | |
// Retrieve the first mesg type in the queue | |
unsigned omx_video::omx_cmd_queue::get_q_msg_type() | |
{ | |
return m_q[m_read].id; | |
} | |
#ifdef _ANDROID_ | |
VideoHeap::VideoHeap(int fd, size_t size, void* base) | |
{ | |
// dup file descriptor, map once, use pmem | |
init(dup(fd), base, size, 0 , "/dev/pmem_adsp"); | |
} | |
#endif // _ANDROID_ | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::omx_venc | |
DESCRIPTION | |
Constructor | |
PARAMETERS | |
None | |
RETURN VALUE | |
None. | |
========================================================================== */ | |
omx_video::omx_video(): m_state(OMX_StateInvalid), | |
m_app_data(NULL), | |
m_inp_mem_ptr(NULL), | |
m_out_mem_ptr(NULL), | |
pending_input_buffers(0), | |
pending_output_buffers(0), | |
m_out_bm_count(0), | |
m_inp_bm_count(0), | |
m_flags(0), | |
m_event_port_settings_sent(false), | |
output_flush_progress (false), | |
input_flush_progress (false), | |
input_use_buffer (false), | |
output_use_buffer (false), | |
m_use_input_pmem(OMX_FALSE), | |
m_use_output_pmem(OMX_FALSE), | |
m_etb_count(0), | |
m_fbd_count(0) | |
{ | |
DEBUG_PRINT_HIGH("\n omx_video(): Inside Constructor()"); | |
memset(&m_cmp,0,sizeof(m_cmp)); | |
memset(&m_pCallbacks,0,sizeof(m_pCallbacks)); | |
pthread_mutex_init(&m_lock, NULL); | |
sem_init(&m_cmd_lock,0,0); | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::~omx_venc | |
DESCRIPTION | |
Destructor | |
PARAMETERS | |
None | |
RETURN VALUE | |
None. | |
========================================================================== */ | |
omx_video::~omx_video() | |
{ | |
DEBUG_PRINT_HIGH("\n ~omx_video(): Inside Destructor()"); | |
if(m_pipe_in) close(m_pipe_in); | |
if(m_pipe_out) close(m_pipe_out); | |
DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit\n"); | |
pthread_join(msg_thread_id,NULL); | |
DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit\n"); | |
pthread_join(async_thread_id,NULL); | |
pthread_mutex_destroy(&m_lock); | |
sem_destroy(&m_cmd_lock); | |
DEBUG_PRINT_HIGH("\n m_etb_count = %u, m_fbd_count = %u\n", m_etb_count, | |
m_fbd_count); | |
DEBUG_PRINT_HIGH("omx_video: Destructor exit\n"); | |
DEBUG_PRINT_HIGH("Exiting 7x30 OMX Video Encoder ...\n"); | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::OMXCntrlProcessMsgCb | |
DESCRIPTION | |
IL Client callbacks are generated through this routine. The decoder | |
provides the thread context for this routine. | |
PARAMETERS | |
ctxt -- Context information related to the self. | |
id -- Event identifier. This could be any of the following: | |
1. Command completion event | |
2. Buffer done callback event | |
3. Frame done callback event | |
RETURN VALUE | |
None. | |
========================================================================== */ | |
void omx_video::process_event_cb(void *ctxt, unsigned char id) | |
{ | |
unsigned p1; // Parameter - 1 | |
unsigned p2; // Parameter - 2 | |
unsigned ident; | |
unsigned qsize=0; // qsize | |
omx_video *pThis = (omx_video *) ctxt; | |
if(!pThis) | |
{ | |
DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out\n"); | |
return; | |
} | |
// Protect the shared queue data structure | |
do | |
{ | |
/*Read the message id's from the queue*/ | |
pthread_mutex_lock(&pThis->m_lock); | |
qsize = pThis->m_cmd_q.m_size; | |
if(qsize) | |
{ | |
pThis->m_cmd_q.pop_entry(&p1,&p2,&ident); | |
} | |
if(qsize == 0) | |
{ | |
qsize = pThis->m_ftb_q.m_size; | |
if(qsize) | |
{ | |
pThis->m_ftb_q.pop_entry(&p1,&p2,&ident); | |
} | |
} | |
if(qsize == 0) | |
{ | |
qsize = pThis->m_etb_q.m_size; | |
if(qsize) | |
{ | |
pThis->m_etb_q.pop_entry(&p1,&p2,&ident); | |
} | |
} | |
pthread_mutex_unlock(&pThis->m_lock); | |
/*process message if we have one*/ | |
if(qsize > 0) | |
{ | |
id = ident; | |
switch(id) | |
{ | |
case OMX_COMPONENT_GENERATE_EVENT: | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
switch(p1) | |
{ | |
case OMX_CommandStateSet: | |
pThis->m_state = (OMX_STATETYPE) p2; | |
DEBUG_PRINT_LOW("Process -> state set to %d \n", pThis->m_state); | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete, p1, p2, NULL); | |
break; | |
case OMX_EventError: | |
DEBUG_PRINT_ERROR("\nERROR: OMX_EventError: p2 = %d\n", p2); | |
if(p2 == OMX_StateInvalid) | |
{ | |
pThis->m_state = (OMX_STATETYPE) p2; | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventError, OMX_ErrorInvalidState, p2, NULL); | |
} | |
else if(p2 == OMX_ErrorHardware) | |
{ | |
pThis->m_state = OMX_StateInvalid; | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventError,OMX_ErrorHardware,0,NULL); | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventError, OMX_ErrorInvalidState, p2, NULL); | |
} | |
else | |
{ | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventError, p2, NULL, NULL ); | |
} | |
break; | |
case OMX_CommandPortDisable: | |
DEBUG_PRINT_LOW("Process -> Port %d set to PORT_STATE_DISABLED" \ | |
"state \n", p2); | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete, p1, p2, NULL ); | |
break; | |
case OMX_CommandPortEnable: | |
DEBUG_PRINT_LOW("Process ->Port %d set PORT_STATE_ENABLED state\n" \ | |
, p2); | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ | |
OMX_EventCmdComplete, p1, p2, NULL ); | |
break; | |
default: | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete, p1, p2, NULL ); | |
break; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks\n"); | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_ETB: | |
if(pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ | |
(OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n"); | |
pThis->omx_report_error (); | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_FTB: | |
if( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ | |
(OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: FTBProxy() failed!\n"); | |
pThis->omx_report_error (); | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_COMMAND: | |
pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ | |
(OMX_U32)p2,(OMX_PTR)NULL); | |
break; | |
case OMX_COMPONENT_GENERATE_EBD: | |
if( pThis->empty_buffer_done(&pThis->m_cmp, | |
(OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); | |
pThis->omx_report_error (); | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_FBD: | |
if( pThis->fill_buffer_done(&pThis->m_cmp, | |
(OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); | |
pThis->omx_report_error (); | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: | |
pThis->input_flush_progress = false; | |
DEBUG_PRINT_HIGH("\nm_etb_count at i/p flush = %u", m_etb_count); | |
m_etb_count = 0; | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
/*Check if we need generate event for Flush done*/ | |
if(BITMASK_PRESENT(&pThis->m_flags, | |
OMX_COMPONENT_INPUT_FLUSH_PENDING)) | |
{ | |
BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete,OMX_CommandFlush, | |
PORT_INDEX_IN,NULL ); | |
} | |
else if(BITMASK_PRESENT(&pThis->m_flags, | |
OMX_COMPONENT_IDLE_PENDING)) | |
{ | |
if(!pThis->output_flush_progress) | |
{ | |
printf("\n dev_stop called after input flush complete\n"); | |
if(dev_stop() != 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in i/p flush!\n"); | |
pThis->omx_report_error (); | |
} | |
} | |
} | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: | |
pThis->output_flush_progress = false; | |
DEBUG_PRINT_HIGH("\nm_fbd_count at o/p flush = %u", m_fbd_count); | |
m_fbd_count = 0; | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
/*Check if we need generate event for Flush done*/ | |
if(BITMASK_PRESENT(&pThis->m_flags, | |
OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) | |
{ | |
BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete,OMX_CommandFlush, | |
PORT_INDEX_OUT,NULL ); | |
} | |
else if(BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) | |
{ | |
printf("\n dev_stop called after Output flush complete\n"); | |
if(!pThis->input_flush_progress) | |
{ | |
if(dev_stop() != 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in o/p flush!\n"); | |
pThis->omx_report_error (); | |
} | |
} | |
} | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_START_DONE: | |
DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE msg"); | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success"); | |
if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) | |
{ | |
DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Move to \ | |
executing"); | |
// Send the callback now | |
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); | |
pThis->m_state = OMX_StateExecuting; | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete,OMX_CommandStateSet, | |
OMX_StateExecuting, NULL); | |
} | |
else if(BITMASK_PRESENT(&pThis->m_flags, | |
OMX_COMPONENT_PAUSE_PENDING)) | |
{ | |
if(dev_pause()) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in Start Done!\n"); | |
pThis->omx_report_error (); | |
} | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("\n Event Handler callback is NULL"); | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_PAUSE_DONE: | |
DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE msg"); | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) | |
{ | |
//Send the callback now | |
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); | |
pThis->m_state = OMX_StatePause; | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete,OMX_CommandStateSet, | |
OMX_StatePause, NULL); | |
} | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_RESUME_DONE: | |
DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_RESUME_DONE msg"); | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) | |
{ | |
// Send the callback now | |
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); | |
pThis->m_state = OMX_StateExecuting; | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, | |
OMX_EventCmdComplete,OMX_CommandStateSet, | |
OMX_StateExecuting,NULL); | |
} | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_STOP_DONE: | |
DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE msg"); | |
if(pThis->m_pCallbacks.EventHandler) | |
{ | |
if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) | |
{ | |
// Send the callback now | |
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); | |
pThis->m_state = OMX_StateIdle; | |
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data, | |
OMX_EventCmdComplete,OMX_CommandStateSet, | |
OMX_StateIdle,NULL); | |
} | |
} | |
break; | |
case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: | |
DEBUG_PRINT_ERROR("\nERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!\n"); | |
pThis->omx_report_error (); | |
break; | |
default: | |
break; | |
} | |
} | |
pthread_mutex_lock(&pThis->m_lock); | |
qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\ | |
pThis->m_etb_q.m_size; | |
pthread_mutex_unlock(&pThis->m_lock); | |
} | |
while(qsize>0); | |
printf("\n exited the while loop\n"); | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::GetComponentVersion | |
DESCRIPTION | |
Returns the component version. | |
PARAMETERS | |
TBD. | |
RETURN VALUE | |
OMX_ErrorNone. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::get_component_version | |
( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_OUT OMX_STRING componentName, | |
OMX_OUT OMX_VERSIONTYPE* componentVersion, | |
OMX_OUT OMX_VERSIONTYPE* specVersion, | |
OMX_OUT OMX_UUIDTYPE* componentUUID | |
) | |
{ | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
/* TBD -- Return the proper version */ | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::SendCommand | |
DESCRIPTION | |
Returns zero if all the buffers released.. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_COMMANDTYPE cmd, | |
OMX_IN OMX_U32 param1, | |
OMX_IN OMX_PTR cmdData | |
) | |
{ | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
if(cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) | |
{ | |
if((param1 != PORT_INDEX_IN) && (param1 != PORT_INDEX_OUT) && (param1 != PORT_INDEX_BOTH)) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index\n"); | |
return OMX_ErrorBadPortIndex; | |
} | |
} | |
if(cmd == OMX_CommandMarkBuffer) | |
{ | |
if(param1 != PORT_INDEX_IN) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index \n"); | |
return OMX_ErrorBadPortIndex; | |
} | |
if(!cmdData) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null"); | |
return OMX_ErrorBadParameter; | |
} | |
} | |
post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); | |
sem_wait(&m_cmd_lock); | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::SendCommand | |
DESCRIPTION | |
Returns zero if all the buffers released.. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_COMMANDTYPE cmd, | |
OMX_IN OMX_U32 param1, | |
OMX_IN OMX_PTR cmdData | |
) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
OMX_STATETYPE eState = (OMX_STATETYPE) param1; | |
int bFlag = 1; | |
if(cmd == OMX_CommandStateSet) | |
{ | |
/***************************/ | |
/* Current State is Loaded */ | |
/***************************/ | |
if(m_state == OMX_StateLoaded) | |
{ | |
if(eState == OMX_StateIdle) | |
{ | |
//if all buffers are allocated or all ports disabled | |
if(allocate_done() || | |
( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE)) | |
{ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle\n"); | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending\n"); | |
BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); | |
// Skip the event notification | |
bFlag = 0; | |
} | |
} | |
/* Requesting transition from Loaded to Loaded */ | |
else if(eState == OMX_StateLoaded) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded\n"); | |
post_event(OMX_EventError,OMX_ErrorSameState,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorSameState; | |
} | |
/* Requesting transition from Loaded to WaitForResources */ | |
else if(eState == OMX_StateWaitForResources) | |
{ | |
/* Since error is None , we will post an event | |
at the end of this function definition */ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources\n"); | |
} | |
/* Requesting transition from Loaded to Executing */ | |
else if(eState == OMX_StateExecuting) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing\n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Loaded to Pause */ | |
else if(eState == OMX_StatePause) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause\n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Loaded to Invalid */ | |
else if(eState == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid\n"); | |
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorInvalidState; | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid(%d Not Handled)\n",\ | |
eState); | |
eRet = OMX_ErrorBadParameter; | |
} | |
} | |
/***************************/ | |
/* Current State is IDLE */ | |
/***************************/ | |
else if(m_state == OMX_StateIdle) | |
{ | |
if(eState == OMX_StateLoaded) | |
{ | |
if(release_done()) | |
{ | |
/* | |
Since error is None , we will post an event at the end | |
of this function definition | |
*/ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded\n"); | |
if(dev_stop() != 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed at Idle --> Loaded"); | |
eRet = OMX_ErrorHardware; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending\n"); | |
BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); | |
// Skip the event notification | |
bFlag = 0; | |
} | |
} | |
/* Requesting transition from Idle to Executing */ | |
else if(eState == OMX_StateExecuting) | |
{ | |
if( dev_start() ) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Exe\n"); | |
omx_report_error (); | |
eRet = OMX_ErrorHardware; | |
} | |
else | |
{ | |
BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); | |
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n"); | |
bFlag = 0; | |
} | |
} | |
/* Requesting transition from Idle to Idle */ | |
else if(eState == OMX_StateIdle) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle\n"); | |
post_event(OMX_EventError,OMX_ErrorSameState,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorSameState; | |
} | |
/* Requesting transition from Idle to WaitForResources */ | |
else if(eState == OMX_StateWaitForResources) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources\n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Idle to Pause */ | |
else if(eState == OMX_StatePause) | |
{ | |
/*To pause the Video core we need to start the driver*/ | |
if( dev_start() ) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Pause\n"); | |
omx_report_error (); | |
eRet = OMX_ErrorHardware; | |
} | |
else | |
{ | |
BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); | |
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n"); | |
bFlag = 0; | |
} | |
} | |
/* Requesting transition from Idle to Invalid */ | |
else if(eState == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid\n"); | |
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorInvalidState; | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled\n",eState); | |
eRet = OMX_ErrorBadParameter; | |
} | |
} | |
/******************************/ | |
/* Current State is Executing */ | |
/******************************/ | |
else if(m_state == OMX_StateExecuting) | |
{ | |
/* Requesting transition from Executing to Idle */ | |
if(eState == OMX_StateIdle) | |
{ | |
/* Since error is None , we will post an event | |
at the end of this function definition | |
*/ | |
DEBUG_PRINT_LOW("\n OMXCORE-SM: Executing --> Idle \n"); | |
//here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle | |
BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); | |
execute_omx_flush(OMX_ALL); | |
bFlag = 0; | |
} | |
/* Requesting transition from Executing to Paused */ | |
else if(eState == OMX_StatePause) | |
{ | |
if(dev_pause()) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in SCP on Exe --> Pause\n"); | |
post_event(OMX_EventError,OMX_ErrorHardware,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorHardware; | |
} | |
else | |
{ | |
BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); | |
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n"); | |
bFlag = 0; | |
} | |
} | |
/* Requesting transition from Executing to Loaded */ | |
else if(eState == OMX_StateLoaded) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Loaded \n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Executing to WaitForResources */ | |
else if(eState == OMX_StateWaitForResources) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> WaitForResources \n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Executing to Executing */ | |
else if(eState == OMX_StateExecuting) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Executing \n"); | |
post_event(OMX_EventError,OMX_ErrorSameState,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorSameState; | |
} | |
/* Requesting transition from Executing to Invalid */ | |
else if(eState == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Invalid \n"); | |
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorInvalidState; | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled\n",eState); | |
eRet = OMX_ErrorBadParameter; | |
} | |
} | |
/***************************/ | |
/* Current State is Pause */ | |
/***************************/ | |
else if(m_state == OMX_StatePause) | |
{ | |
/* Requesting transition from Pause to Executing */ | |
if(eState == OMX_StateExecuting) | |
{ | |
DEBUG_PRINT_LOW("\n Pause --> Executing \n"); | |
if( dev_resume() ) | |
{ | |
post_event(OMX_EventError,OMX_ErrorHardware,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorHardware; | |
} | |
else | |
{ | |
BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); | |
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n"); | |
bFlag = 0; | |
} | |
} | |
/* Requesting transition from Pause to Idle */ | |
else if(eState == OMX_StateIdle) | |
{ | |
/* Since error is None , we will post an event | |
at the end of this function definition */ | |
DEBUG_PRINT_LOW("\n Pause --> Idle \n"); | |
BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); | |
execute_omx_flush(OMX_ALL); | |
bFlag = 0; | |
} | |
/* Requesting transition from Pause to loaded */ | |
else if(eState == OMX_StateLoaded) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Pause --> loaded \n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Pause to WaitForResources */ | |
else if(eState == OMX_StateWaitForResources) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Pause --> WaitForResources \n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from Pause to Pause */ | |
else if(eState == OMX_StatePause) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Pause --> Pause \n"); | |
post_event(OMX_EventError,OMX_ErrorSameState,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorSameState; | |
} | |
/* Requesting transition from Pause to Invalid */ | |
else if(eState == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Pause --> Invalid \n"); | |
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorInvalidState; | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled\n",eState); | |
eRet = OMX_ErrorBadParameter; | |
} | |
} | |
/***************************/ | |
/* Current State is WaitForResources */ | |
/***************************/ | |
else if(m_state == OMX_StateWaitForResources) | |
{ | |
/* Requesting transition from WaitForResources to Loaded */ | |
if(eState == OMX_StateLoaded) | |
{ | |
/* Since error is None , we will post an event | |
at the end of this function definition */ | |
DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded\n"); | |
} | |
/* Requesting transition from WaitForResources to WaitForResources */ | |
else if(eState == OMX_StateWaitForResources) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources\n"); | |
post_event(OMX_EventError,OMX_ErrorSameState, | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorSameState; | |
} | |
/* Requesting transition from WaitForResources to Executing */ | |
else if(eState == OMX_StateExecuting) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing\n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from WaitForResources to Pause */ | |
else if(eState == OMX_StatePause) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause\n"); | |
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorIncorrectStateTransition; | |
} | |
/* Requesting transition from WaitForResources to Invalid */ | |
else if(eState == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid\n"); | |
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorInvalidState; | |
} | |
/* Requesting transition from WaitForResources to Loaded - | |
is NOT tested by Khronos TS */ | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)\n",m_state,eState); | |
eRet = OMX_ErrorBadParameter; | |
} | |
} | |
/********************************/ | |
/* Current State is Invalid */ | |
/*******************************/ | |
else if(m_state == OMX_StateInvalid) | |
{ | |
/* State Transition from Inavlid to any state */ | |
if(eState == (OMX_StateLoaded || OMX_StateWaitForResources | |
|| OMX_StateIdle || OMX_StateExecuting | |
|| OMX_StatePause || OMX_StateInvalid)) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded\n"); | |
post_event(OMX_EventError,OMX_ErrorInvalidState,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
eRet = OMX_ErrorInvalidState; | |
} | |
} | |
else if(cmd == OMX_CommandFlush) | |
{ | |
if(0 == param1 || OMX_ALL == param1) | |
{ | |
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); | |
} | |
if(1 == param1 || OMX_ALL == param1) | |
{ | |
//generate output flush event only. | |
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); | |
} | |
execute_omx_flush(param1); | |
bFlag = 0; | |
} | |
else if( cmd == OMX_CommandPortEnable) | |
{ | |
if(param1 == PORT_INDEX_IN || param1 == OMX_ALL) | |
{ | |
m_sInPortDef.bEnabled = OMX_TRUE; | |
if( (m_state == OMX_StateLoaded && | |
!BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) | |
|| allocate_input_done()) | |
{ | |
post_event(OMX_CommandPortEnable,PORT_INDEX_IN, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n"); | |
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); | |
// Skip the event notification | |
bFlag = 0; | |
} | |
} | |
if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL) | |
{ | |
m_sOutPortDef.bEnabled = OMX_TRUE; | |
if( (m_state == OMX_StateLoaded && | |
!BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) | |
|| (allocate_output_done())) | |
{ | |
post_event(OMX_CommandPortEnable,PORT_INDEX_OUT, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n"); | |
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); | |
// Skip the event notification | |
bFlag = 0; | |
} | |
} | |
} | |
else if(cmd == OMX_CommandPortDisable) | |
{ | |
if(param1 == PORT_INDEX_IN || param1 == OMX_ALL) | |
{ | |
m_sInPortDef.bEnabled = OMX_FALSE; | |
if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) | |
&& release_input_done()) | |
{ | |
post_event(OMX_CommandPortDisable,PORT_INDEX_IN, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
else | |
{ | |
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); | |
if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) | |
{ | |
execute_omx_flush(PORT_INDEX_IN); | |
} | |
// Skip the event notification | |
bFlag = 0; | |
} | |
} | |
if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL) | |
{ | |
m_sOutPortDef.bEnabled = OMX_FALSE; | |
if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) | |
&& release_output_done()) | |
{ | |
post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\ | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
else | |
{ | |
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); | |
if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) | |
{ | |
execute_omx_flush(PORT_INDEX_OUT); | |
} | |
// Skip the event notification | |
bFlag = 0; | |
} | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)\n",cmd); | |
eRet = OMX_ErrorNotImplemented; | |
} | |
if(eRet == OMX_ErrorNone && bFlag) | |
{ | |
post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); | |
} | |
sem_post(&m_cmd_lock); | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::ExecuteOmxFlush | |
DESCRIPTION | |
Executes the OMX flush. | |
PARAMETERS | |
flushtype - input flush(1)/output flush(0)/ both. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
bool omx_video::execute_omx_flush(OMX_U32 flushType) | |
{ | |
bool bRet = false; | |
DEBUG_PRINT_LOW("\n execute_omx_flush - %d\n", flushType); | |
if(flushType == 0 || flushType == OMX_ALL) | |
{ | |
input_flush_progress = true; | |
//flush input only | |
bRet = execute_input_flush(); | |
} | |
if(flushType == 1 || flushType == OMX_ALL) | |
{ | |
//flush output only | |
output_flush_progress = true; | |
bRet = execute_output_flush(); | |
} | |
return bRet; | |
} | |
/*========================================================================= | |
FUNCTION : execute_output_flush | |
DESCRIPTION | |
Executes the OMX flush at OUTPUT PORT. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
==========================================================================*/ | |
bool omx_video::execute_output_flush(void) | |
{ | |
unsigned p1 = 0; // Parameter - 1 | |
unsigned p2 = 0; // Parameter - 2 | |
unsigned ident = 0; | |
bool bRet = true; | |
/*Generate FBD for all Buffers in the FTBq*/ | |
DEBUG_PRINT_LOW("\n execute_output_flush\n"); | |
pthread_mutex_lock(&m_lock); | |
while(m_ftb_q.m_size) | |
{ | |
m_ftb_q.pop_entry(&p1,&p2,&ident); | |
if(ident == OMX_COMPONENT_GENERATE_FTB ) | |
{ | |
pending_output_buffers++; | |
fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); | |
} | |
else if(ident == OMX_COMPONENT_GENERATE_FBD) | |
{ | |
fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); | |
} | |
} | |
pthread_mutex_unlock(&m_lock); | |
/*Check if there are buffers with the Driver*/ | |
if(dev_flush(PORT_INDEX_OUT)) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: o/p dev_flush() Failed"); | |
return false; | |
} | |
return bRet; | |
} | |
/*========================================================================= | |
FUNCTION : execute_input_flush | |
DESCRIPTION | |
Executes the OMX flush at INPUT PORT. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
==========================================================================*/ | |
bool omx_video::execute_input_flush(void) | |
{ | |
unsigned p1 = 0; // Parameter - 1 | |
unsigned p2 = 0; // Parameter - 2 | |
unsigned ident = 0; | |
bool bRet = true; | |
/*Generate EBD for all Buffers in the ETBq*/ | |
DEBUG_PRINT_LOW("\n execute_input_flush\n"); | |
pthread_mutex_lock(&m_lock); | |
while(m_etb_q.m_size) | |
{ | |
m_etb_q.pop_entry(&p1,&p2,&ident); | |
if(ident == OMX_COMPONENT_GENERATE_ETB) | |
{ | |
pending_input_buffers++; | |
empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); | |
} | |
else if(ident == OMX_COMPONENT_GENERATE_EBD) | |
{ | |
empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); | |
} | |
} | |
pthread_mutex_unlock(&m_lock); | |
/*Check if there are buffers with the Driver*/ | |
if(dev_flush(PORT_INDEX_IN)) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: i/p dev_flush() Failed"); | |
return false; | |
} | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::SendCommandEvent | |
DESCRIPTION | |
Send the event to decoder pipe. This is needed to generate the callbacks | |
in decoder thread context. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
bool omx_video::post_event(unsigned int p1, | |
unsigned int p2, | |
unsigned int id) | |
{ | |
bool bRet = false; | |
pthread_mutex_lock(&m_lock); | |
if( id == OMX_COMPONENT_GENERATE_FTB || \ | |
(id == OMX_COMPONENT_GENERATE_FRAME_DONE)) | |
{ | |
m_ftb_q.insert_entry(p1,p2,id); | |
} | |
else if((id == OMX_COMPONENT_GENERATE_ETB) \ | |
|| (id == OMX_COMPONENT_GENERATE_EBD)) | |
{ | |
m_etb_q.insert_entry(p1,p2,id); | |
} | |
else | |
{ | |
m_cmd_q.insert_entry(p1,p2,id); | |
} | |
bRet = true; | |
DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this); | |
post_message(this, id); | |
pthread_mutex_unlock(&m_lock); | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::GetParameter | |
DESCRIPTION | |
OMX Get Parameter method implementation | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
Error None if successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_INDEXTYPE paramIndex, | |
OMX_INOUT OMX_PTR paramData) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
unsigned int height=0,width = 0; | |
DEBUG_PRINT_LOW("get_parameter: \n"); | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
if(paramData == NULL) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n"); | |
return OMX_ErrorBadParameter; | |
} | |
switch(paramIndex) | |
{ | |
case OMX_IndexParamPortDefinition: | |
{ | |
OMX_PARAM_PORTDEFINITIONTYPE *portDefn; | |
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n"); | |
if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) | |
{ | |
DEBUG_PRINT_LOW("\n i/p actual cnt = %d\n", m_sInPortDef.nBufferCountActual); | |
DEBUG_PRINT_LOW("\n i/p min cnt = %d\n", m_sInPortDef.nBufferCountMin); | |
memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef)); | |
} | |
else if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) | |
{ | |
DEBUG_PRINT_LOW("\n o/p actual cnt = %d\n", m_sOutPortDef.nBufferCountActual); | |
DEBUG_PRINT_LOW("\n o/p min cnt = %d\n", m_sOutPortDef.nBufferCountMin); | |
memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef)); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
break; | |
} | |
case OMX_IndexParamVideoInit: | |
{ | |
OMX_PORT_PARAM_TYPE *portParamType = | |
(OMX_PORT_PARAM_TYPE *) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n"); | |
memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam)); | |
break; | |
} | |
case OMX_IndexParamVideoPortFormat: | |
{ | |
OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = | |
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n"); | |
if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) | |
{ | |
memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat)); | |
} | |
else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) | |
{ | |
memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat)); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
break; | |
} | |
case OMX_IndexParamVideoBitrate: | |
{ | |
OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate\n"); | |
if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) | |
{ | |
memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate)); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
break; | |
} | |
case OMX_IndexParamVideoMpeg4: | |
{ | |
OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4\n"); | |
memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4)); | |
break; | |
} | |
case OMX_IndexParamVideoH263: | |
{ | |
OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263\n"); | |
memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263)); | |
break; | |
} | |
case OMX_IndexParamVideoAvc: | |
{ | |
OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc\n"); | |
memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC)); | |
break; | |
} | |
case OMX_IndexParamVideoProfileLevelQuerySupported: | |
{ | |
OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported\n"); | |
//TODO include all the profiles and corresponding levels | |
if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) | |
{ | |
static const OMX_U32 MPEG4Profile[][2] = | |
{ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level0}, | |
{ (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level0b}, | |
{ (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level1}, | |
{ (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level2}, | |
{ (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level3}}; | |
static const OMX_U32 nSupport = sizeof(MPEG4Profile) / (sizeof(OMX_U32) * 2); | |
if(pParam->nProfileIndex >= 0 && pParam->nProfileIndex < nSupport) | |
{ | |
pParam->eProfile = (OMX_VIDEO_MPEG4PROFILETYPE) MPEG4Profile[pParam->nProfileIndex][0]; | |
pParam->eLevel = (OMX_VIDEO_MPEG4LEVELTYPE) MPEG4Profile[pParam->nProfileIndex][1]; | |
} | |
else | |
{ | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) | |
{ | |
static const OMX_U32 H263Profile[][2] = | |
{ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level10}, | |
{ (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level20}, | |
{ (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level30}, | |
{ (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level45}, | |
{ (OMX_U32) OMX_VIDEO_H263ProfileISWV2, (OMX_U32) OMX_VIDEO_H263Level10}, | |
{ (OMX_U32) OMX_VIDEO_H263ProfileISWV2, (OMX_U32) OMX_VIDEO_H263Level45}}; | |
static const OMX_U32 nSupport = sizeof(H263Profile) / (sizeof(OMX_U32) * 2); | |
if(pParam->nProfileIndex >= 0 && pParam->nProfileIndex < nSupport) | |
{ | |
pParam->eProfile = (OMX_VIDEO_H263PROFILETYPE) H263Profile[pParam->nProfileIndex][0]; | |
pParam->eLevel = (OMX_VIDEO_H263LEVELTYPE) H263Profile[pParam->nProfileIndex][1]; | |
} | |
else | |
{ | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC) | |
{ | |
//TODO | |
} | |
break; | |
} | |
case OMX_IndexParamVideoProfileLevelCurrent: | |
{ | |
OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent\n"); | |
memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel)); | |
break; | |
} | |
/*Component should support this port definition*/ | |
case OMX_IndexParamAudioInit: | |
{ | |
OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n"); | |
memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio)); | |
break; | |
} | |
/*Component should support this port definition*/ | |
case OMX_IndexParamImageInit: | |
{ | |
OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n"); | |
memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img)); | |
break; | |
} | |
/*Component should support this port definition*/ | |
case OMX_IndexParamOtherInit: | |
{ | |
DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x\n", paramIndex); | |
eRet =OMX_ErrorUnsupportedIndex; | |
break; | |
} | |
case OMX_IndexParamStandardComponentRole: | |
{ | |
OMX_PARAM_COMPONENTROLETYPE *comp_role; | |
comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; | |
comp_role->nVersion.nVersion = OMX_SPEC_VERSION; | |
comp_role->nSize = sizeof(*comp_role); | |
DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",paramIndex); | |
if(NULL != comp_role->cRole) | |
{ | |
strncpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",paramIndex); | |
eRet =OMX_ErrorBadParameter; | |
} | |
break; | |
} | |
/* Added for parameter test */ | |
case OMX_IndexParamPriorityMgmt: | |
{ | |
OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n"); | |
memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt)); | |
break; | |
} | |
/* Added for parameter test */ | |
case OMX_IndexParamCompBufferSupplier: | |
{ | |
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n"); | |
if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) | |
{ | |
memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier)); | |
} | |
else if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT) | |
{ | |
memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier)); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
break; | |
} | |
case OMX_IndexParamVideoQuantization: | |
{ | |
OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization\n"); | |
memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization)); | |
break; | |
} | |
case OMX_QcomIndexPortDefn: | |
//TODO | |
break; | |
case OMX_COMPONENT_CAPABILITY_TYPE_INDEX: | |
{ | |
OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData); | |
DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX\n"); | |
pParam->iIsOMXComponentMultiThreaded = OMX_TRUE; | |
pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE; | |
pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; | |
pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; | |
pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE; | |
pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE; | |
pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE; | |
pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE; | |
m_use_input_pmem = OMX_TRUE; | |
DEBUG_PRINT_LOW("Supporting capability index in encoder node"); | |
break; | |
} | |
case OMX_IndexParamVideoSliceFMO: | |
{ | |
OMX_VIDEO_PARAM_AVCSLICEFMO *avc_slice_fmo = (OMX_VIDEO_PARAM_AVCSLICEFMO*)paramData; | |
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoSliceFMO\n"); | |
if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\ | |
OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
memcpy(avc_slice_fmo, &m_sAVCSliceFMO, sizeof(m_sAVCSliceFMO)); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: get_parameter: AVCSliceFMO queried non-AVC codec\n"); | |
eRet = OMX_ErrorBadParameter; | |
} | |
break; | |
} | |
default: | |
{ | |
DEBUG_PRINT_ERROR("ERROR: get_parameter: unknown param %08x\n", paramIndex); | |
eRet =OMX_ErrorUnsupportedIndex; | |
break; | |
} | |
} | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::GetConfig | |
DESCRIPTION | |
OMX Get Config Method implementation. | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
OMX Error None if successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_INDEXTYPE configIndex, | |
OMX_INOUT OMX_PTR configData) | |
{ | |
//////////////////////////////////////////////////////////////// | |
// Supported Config Index Type | |
// ============================================================= | |
// OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE | |
// OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE | |
// OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE | |
//////////////////////////////////////////////////////////////// | |
if(configData == NULL) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: param is null"); | |
return OMX_ErrorBadParameter; | |
} | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: can't be in invalid state"); | |
return OMX_ErrorIncorrectStateOperation; | |
} | |
//@todo need to validate params | |
switch(configIndex) | |
{ | |
case OMX_IndexConfigVideoBitrate: | |
{ | |
OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData); | |
memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate)); | |
break; | |
} | |
case OMX_IndexConfigVideoFramerate: | |
{ | |
OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData); | |
if(m_state != OMX_StateLoaded) | |
{ | |
// we only allow this at init time! | |
DEBUG_PRINT_ERROR("ERROR: frame rate can only be configured in loaded state"); | |
return OMX_ErrorIncorrectStateOperation; | |
} | |
memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate)); | |
break; | |
} | |
case OMX_IndexConfigCommonRotate: | |
{ | |
OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData); | |
if(m_state != OMX_StateLoaded) | |
{ | |
// we only allow this at init time! | |
DEBUG_PRINT_ERROR("ERROR: frame rate can only be configured in loaded state",0,0,0); | |
return OMX_ErrorIncorrectStateOperation; | |
} | |
memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation)); | |
break; | |
} | |
default: | |
DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); | |
return OMX_ErrorUnsupportedIndex; | |
} | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::GetExtensionIndex | |
DESCRIPTION | |
OMX GetExtensionIndex method implementaion. <TBD> | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
OMX Error None if everything successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_STRING paramName, | |
OMX_OUT OMX_INDEXTYPE* indexType) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: get_extension_index: Error, Not implemented\n"); | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
return OMX_ErrorNotImplemented; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::GetState | |
DESCRIPTION | |
Returns the state information back to the caller.<TBD> | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
Error None if everything is successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::get_state(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_OUT OMX_STATETYPE* state) | |
{ | |
*state = m_state; | |
DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state); | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::ComponentTunnelRequest | |
DESCRIPTION | |
OMX Component Tunnel Request method implementation. <TBD> | |
PARAMETERS | |
None. | |
RETURN VALUE | |
OMX Error None if everything successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_HANDLETYPE peerComponent, | |
OMX_IN OMX_U32 peerPort, | |
OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented\n"); | |
return OMX_ErrorNotImplemented; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::UseInputBuffer | |
DESCRIPTION | |
Helper function for Use buffer in the input pin | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::use_input_buffer( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN OMX_U32 bytes, | |
OMX_IN OMX_U8* buffer) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
unsigned i = 0; | |
unsigned char *buf_addr = NULL; | |
DEBUG_PRINT_HIGH("use_input_buffer: port = %d appData = %p bytes = %d buffer = %p",port,appData,bytes,buffer); | |
if(bytes != m_sInPortDef.nBufferSize) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: use_input_buffer: Size Mismatch!! " | |
"bytes[%d] != Port.nBufferSize[%d]", bytes, m_sInPortDef.nBufferSize); | |
return OMX_ErrorBadParameter; | |
} | |
if(!m_inp_mem_ptr) | |
{ | |
input_use_buffer = true; | |
m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ | |
calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual); | |
if(m_inp_mem_ptr == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); | |
if(m_pInput_pmem == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem"); | |
return OMX_ErrorInsufficientResources; | |
} | |
for(i=0; i< m_sInPortDef.nBufferCountActual; i++) | |
{ | |
m_pInput_pmem[i].fd = -1; | |
} | |
} | |
for(i=0; i< m_sInPortDef.nBufferCountActual; i++) | |
{ | |
if(BITMASK_ABSENT(&m_inp_bm_count,i)) | |
{ | |
break; | |
} | |
} | |
if(i < m_sInPortDef.nBufferCountActual) | |
{ | |
*bufferHdr = (m_inp_mem_ptr + i); | |
BITMASK_SET(&m_inp_bm_count,i); | |
(*bufferHdr)->pBuffer = (OMX_U8 *)buffer; | |
(*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); | |
(*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION; | |
(*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize; | |
(*bufferHdr)->pAppPrivate = appData; | |
(*bufferHdr)->nInputPortIndex = PORT_INDEX_IN; | |
if(!m_use_input_pmem) | |
{ | |
m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
if(m_pInput_pmem[i].fd == 0) | |
{ | |
m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
} | |
if(m_pInput_pmem[i] .fd < 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; | |
m_pInput_pmem[i].offset = 0; | |
m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, | |
MAP_SHARED,m_pInput_pmem[i].fd,0); | |
if(m_pInput_pmem[i].buffer == MAP_FAILED) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: mmap() Failed"); | |
return OMX_ErrorInsufficientResources; | |
} | |
} | |
else | |
{ | |
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>((*bufferHdr)->pAppPrivate); | |
DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset); | |
if(pParam) | |
{ | |
m_pInput_pmem[i].fd = pParam->pmem_fd; | |
m_pInput_pmem[i].offset = pParam->offset; | |
m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; | |
m_pInput_pmem[i].buffer = (unsigned char *)buffer; | |
DEBUG_PRINT_LOW("\n DBG:: pParam->pmem_fd = %u, pParam->offset = %u", | |
pParam->pmem_fd, pParam->offset); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case"); | |
return OMX_ErrorBadParameter; | |
} | |
} | |
DEBUG_PRINT_LOW("\n use_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p", | |
(*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer); | |
if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_use_buf() Failed for i/p buf"); | |
return OMX_ErrorInsufficientResources; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: All buffers are already used, invalid use_buf call for " | |
"index = %u", i); | |
eRet = OMX_ErrorInsufficientResources; | |
} | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::UseOutputBuffer | |
DESCRIPTION | |
Helper function for Use buffer in the input pin | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::use_output_buffer( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN OMX_U32 bytes, | |
OMX_IN OMX_U8* buffer) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header | |
unsigned i= 0; // Temporary counter | |
unsigned char *buf_addr = NULL; | |
DEBUG_PRINT_HIGH("\n Inside use_output_buffer()"); | |
if(bytes != m_sOutPortDef.nBufferSize) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: use_output_buffer: Size Mismatch!! " | |
"bytes[%d] != Port.nBufferSize[%d]", bytes, m_sOutPortDef.nBufferSize); | |
return OMX_ErrorBadParameter; | |
} | |
if(!m_out_mem_ptr) | |
{ | |
output_use_buffer = true; | |
int nBufHdrSize = 0; | |
DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_sOutPortDef.nBufferCountActual); | |
nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE); | |
/* | |
* Memory for output side involves the following: | |
* 1. Array of Buffer Headers | |
* 2. Bitmask array to hold the buffer allocation details | |
* In order to minimize the memory management entire allocation | |
* is done in one step. | |
*/ | |
//OMX Buffer header | |
m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); | |
if(m_out_mem_ptr == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_out_mem_ptr"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual); | |
if(m_pOutput_pmem == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_pmem"); | |
return OMX_ErrorInsufficientResources; | |
} | |
if(m_out_mem_ptr) | |
{ | |
bufHdr = m_out_mem_ptr; | |
DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr); | |
// Settting the entire storage nicely | |
for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++) | |
{ | |
bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); | |
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; | |
bufHdr->nAllocLen = bytes; | |
bufHdr->nFilledLen = 0; | |
bufHdr->pAppPrivate = appData; | |
bufHdr->nOutputPortIndex = PORT_INDEX_OUT; | |
bufHdr->pBuffer = NULL; | |
bufHdr++; | |
m_pOutput_pmem[i].fd = -1; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%x]\n",m_out_mem_ptr); | |
eRet = OMX_ErrorInsufficientResources; | |
} | |
} | |
for(i=0; i< m_sOutPortDef.nBufferCountActual; i++) | |
{ | |
if(BITMASK_ABSENT(&m_out_bm_count,i)) | |
{ | |
break; | |
} | |
} | |
if(eRet == OMX_ErrorNone) | |
{ | |
if(i < m_sOutPortDef.nBufferCountActual) | |
{ | |
*bufferHdr = (m_out_mem_ptr + i ); | |
(*bufferHdr)->pBuffer = (OMX_U8 *)buffer; | |
BITMASK_SET(&m_out_bm_count,i); | |
if(!m_use_output_pmem) | |
{ | |
m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
if(m_pOutput_pmem[i].fd == 0) | |
{ | |
m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
} | |
if(m_pOutput_pmem[i].fd < 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; | |
m_pOutput_pmem[i].offset = 0; | |
m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE, | |
MAP_SHARED,m_pOutput_pmem[i].fd,0); | |
if(m_pOutput_pmem[i].buffer == MAP_FAILED) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: mmap() Failed"); | |
return OMX_ErrorInsufficientResources; | |
} | |
} | |
else | |
{ | |
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*>((*bufferHdr)->pAppPrivate); | |
DEBUG_PRINT_LOW("Inside qcom_ext pParam:0x%x )", pParam); | |
if(pParam) | |
{ | |
DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset); | |
m_pOutput_pmem[i].fd = pParam->pmem_fd; | |
m_pOutput_pmem[i].offset = pParam->offset; | |
m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; | |
m_pOutput_pmem[i].buffer = (unsigned char *)buffer; | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case"); | |
return OMX_ErrorBadParameter; | |
} | |
buf_addr = (unsigned char *)buffer; | |
} | |
DEBUG_PRINT_LOW("\n use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p", | |
(*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer); | |
if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT) != true) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf"); | |
return OMX_ErrorInsufficientResources; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for " | |
"index = %u", i); | |
eRet = OMX_ErrorInsufficientResources; | |
} | |
} | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::UseBuffer | |
DESCRIPTION | |
OMX Use Buffer method implementation. | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
OMX Error None , if everything successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::use_buffer( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN OMX_U32 bytes, | |
OMX_IN OMX_U8* buffer) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
if(port == PORT_INDEX_IN) | |
{ | |
eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); | |
} | |
else if(port == PORT_INDEX_OUT) | |
{ | |
eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
if(eRet == OMX_ErrorNone) | |
{ | |
if(allocate_done()) | |
{ | |
if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) | |
{ | |
// Send the callback now | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); | |
post_event(OMX_CommandStateSet,OMX_StateIdle, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated) | |
{ | |
if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) | |
{ | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); | |
post_event(OMX_CommandPortEnable, | |
PORT_INDEX_IN, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
else if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) | |
{ | |
if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) | |
{ | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); | |
post_event(OMX_CommandPortEnable, | |
PORT_INDEX_OUT, | |
OMX_COMPONENT_GENERATE_EVENT); | |
m_event_port_settings_sent = false; | |
} | |
} | |
} | |
return eRet; | |
} | |
OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) | |
{ | |
unsigned int index = 0; | |
OMX_U8 *temp_buff ; | |
if(bufferHdr == NULL || m_inp_mem_ptr == NULL) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]", | |
bufferHdr, m_inp_mem_ptr); | |
return OMX_ErrorBadParameter; | |
} | |
index = bufferHdr - m_inp_mem_ptr; | |
if(index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) | |
{ | |
if(m_pInput_pmem[index].fd > 0 && input_use_buffer == false) | |
{ | |
DEBUG_PRINT_LOW("\n FreeBuffer:: i/p AllocateBuffer case"); | |
if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf"); | |
} | |
munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); | |
close (m_pInput_pmem[index].fd); | |
m_pInput_pmem[index].fd = -1; | |
} | |
else if(m_pInput_pmem[index].fd > 0 && (input_use_buffer == true && | |
m_use_input_pmem == OMX_FALSE)) | |
{ | |
DEBUG_PRINT_LOW("\n FreeBuffer:: i/p Heap UseBuffer case"); | |
if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf"); | |
} | |
munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); | |
close (m_pInput_pmem[index].fd); | |
m_pInput_pmem[index].fd = -1; | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case"); | |
} | |
} | |
return OMX_ErrorNone; | |
} | |
OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) | |
{ | |
unsigned int index = 0; | |
OMX_U8 *temp_buff ; | |
if(bufferHdr == NULL || m_out_mem_ptr == NULL) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]", | |
bufferHdr, m_out_mem_ptr); | |
return OMX_ErrorBadParameter; | |
} | |
index = bufferHdr - m_out_mem_ptr; | |
if(index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem) | |
{ | |
if(m_pOutput_pmem[index].fd > 0 && output_use_buffer == false ) | |
{ | |
DEBUG_PRINT_LOW("\n FreeBuffer:: o/p AllocateBuffer case"); | |
if(dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf"); | |
} | |
munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size); | |
close (m_pOutput_pmem[index].fd); | |
m_pOutput_pmem[index].fd = -1; | |
} | |
else if( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true | |
&& m_use_output_pmem == OMX_FALSE)) | |
{ | |
DEBUG_PRINT_LOW("\n FreeBuffer:: o/p Heap UseBuffer case"); | |
if(dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf"); | |
} | |
munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size); | |
close (m_pOutput_pmem[index].fd); | |
m_pOutput_pmem[index].fd = -1; | |
} | |
else | |
{ | |
DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case"); | |
} | |
} | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::AllocateInputBuffer | |
DESCRIPTION | |
Helper function for allocate buffer in the input pin | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::allocate_input_buffer( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN OMX_U32 bytes) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
unsigned i = 0; | |
DEBUG_PRINT_HIGH("\n allocate_input_buffer()::"); | |
if(bytes != m_sInPortDef.nBufferSize) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Buffer size mismatch error: bytes[%u] != nBufferSize[%u]\n", | |
bytes, m_sInPortDef.nBufferSize); | |
return OMX_ErrorBadParameter; | |
} | |
if(!m_inp_mem_ptr) | |
{ | |
m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ | |
calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual); | |
if(m_inp_mem_ptr == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); | |
if(m_pInput_pmem == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem"); | |
return OMX_ErrorInsufficientResources; | |
} | |
for(i=0; i< m_sInPortDef.nBufferCountActual; i++) | |
{ | |
m_pInput_pmem[i].fd = -1; | |
} | |
} | |
for(i=0; i< m_sInPortDef.nBufferCountActual; i++) | |
{ | |
if(BITMASK_ABSENT(&m_inp_bm_count,i)) | |
{ | |
break; | |
} | |
} | |
if(i < m_sInPortDef.nBufferCountActual) | |
{ | |
*bufferHdr = (m_inp_mem_ptr + i); | |
(*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); | |
(*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION; | |
(*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize; | |
(*bufferHdr)->pAppPrivate = appData; | |
(*bufferHdr)->nInputPortIndex = PORT_INDEX_IN; | |
m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
if(m_pInput_pmem[i].fd == 0) | |
{ | |
m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
} | |
if(m_pInput_pmem[i].fd < 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed\n"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; | |
m_pInput_pmem[i].offset = 0; | |
m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, | |
MAP_SHARED,m_pInput_pmem[i].fd,0); | |
if(m_pInput_pmem[i].buffer == MAP_FAILED) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: mmap FAILED\n"); | |
return OMX_ErrorInsufficientResources; | |
} | |
(*bufferHdr)->pBuffer = (OMX_U8 *)m_pInput_pmem[i].buffer; | |
BITMASK_SET(&m_inp_bm_count,i); | |
//here change the I/P param here from buf_adr to pmem | |
if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for i/p buf\n"); | |
return OMX_ErrorInsufficientResources; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: All i/p buffers are allocated, invalid allocate buf call" | |
"for index [%d]\n", i); | |
eRet = OMX_ErrorInsufficientResources; | |
} | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::AllocateOutputBuffer | |
DESCRIPTION | |
Helper fn for AllocateBuffer in the output pin | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
OMX Error None if everything went well. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::allocate_output_buffer( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN OMX_U32 bytes) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header | |
unsigned i= 0; // Temporary counter | |
DEBUG_PRINT_HIGH("\n allocate_output_buffer()::"); | |
if(!m_out_mem_ptr) | |
{ | |
int nBufHdrSize = 0; | |
DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_sOutPortDef.nBufferCountActual); | |
nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE); | |
/* | |
* Memory for output side involves the following: | |
* 1. Array of Buffer Headers | |
* 2. Bitmask array to hold the buffer allocation details | |
* In order to minimize the memory management entire allocation | |
* is done in one step. | |
*/ | |
m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); | |
m_pOutput_pmem = (struct pmem *) calloc(sizeof(struct pmem), m_sOutPortDef.nBufferCountActual); | |
if(m_out_mem_ptr && m_pOutput_pmem) | |
{ | |
bufHdr = m_out_mem_ptr; | |
for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++) | |
{ | |
bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); | |
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; | |
// Set the values when we determine the right HxW param | |
bufHdr->nAllocLen = bytes; | |
bufHdr->nFilledLen = 0; | |
bufHdr->pAppPrivate = appData; | |
bufHdr->nOutputPortIndex = PORT_INDEX_OUT; | |
bufHdr->pBuffer = NULL; | |
bufHdr++; | |
m_pOutput_pmem[i].fd = -1; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem"); | |
eRet = OMX_ErrorInsufficientResources; | |
} | |
} | |
DEBUG_PRINT_HIGH("\n actual cnt = %u", m_sOutPortDef.nBufferCountActual); | |
for(i=0; i< m_sOutPortDef.nBufferCountActual; i++) | |
{ | |
if(BITMASK_ABSENT(&m_out_bm_count,i)) | |
{ | |
DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i); | |
break; | |
} | |
} | |
if(eRet == OMX_ErrorNone) | |
{ | |
if(i < m_sOutPortDef.nBufferCountActual) | |
{ | |
m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
if(m_pOutput_pmem[i].fd == 0) | |
{ | |
m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR); | |
} | |
if(m_pOutput_pmem[i].fd < 0) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() failed"); | |
return OMX_ErrorInsufficientResources; | |
} | |
m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; | |
m_pOutput_pmem[i].offset = 0; | |
m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE, | |
MAP_SHARED,m_pOutput_pmem[i].fd,0); | |
if(m_pOutput_pmem[i].buffer == MAP_FAILED) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: MMAP_FAILED in o/p alloc buffer"); | |
return OMX_ErrorInsufficientResources; | |
} | |
*bufferHdr = (m_out_mem_ptr + i ); | |
(*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer; | |
BITMASK_SET(&m_out_bm_count,i); | |
if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for o/p buf"); | |
return OMX_ErrorInsufficientResources; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: All o/p buffers are allocated, invalid allocate buf call" | |
"for index [%d]\n", i); | |
} | |
} | |
return eRet; | |
} | |
// AllocateBuffer -- API Call | |
/* ====================================================================== | |
FUNCTION | |
omx_video::AllocateBuffer | |
DESCRIPTION | |
Returns zero if all the buffers released.. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN OMX_U32 bytes) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type | |
DEBUG_PRINT_LOW("\n Allocate buffer on port %d \n", (int)port); | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
// What if the client calls again. | |
if(port == PORT_INDEX_IN) | |
{ | |
eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); | |
} | |
else if(port == PORT_INDEX_OUT) | |
{ | |
eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); | |
if(eRet == OMX_ErrorNone) | |
{ | |
if(allocate_done()) | |
{ | |
if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) | |
{ | |
// Send the callback now | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); | |
post_event(OMX_CommandStateSet,OMX_StateIdle, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated) | |
{ | |
if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) | |
{ | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); | |
post_event(OMX_CommandPortEnable, | |
PORT_INDEX_IN, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) | |
{ | |
if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) | |
{ | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); | |
post_event(OMX_CommandPortEnable, | |
PORT_INDEX_OUT, | |
OMX_COMPONENT_GENERATE_EVENT); | |
m_event_port_settings_sent = false; | |
} | |
} | |
} | |
DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet); | |
return eRet; | |
} | |
// Free Buffer - API call | |
/* ====================================================================== | |
FUNCTION | |
omx_video::FreeBuffer | |
DESCRIPTION | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_BUFFERHEADERTYPE* buffer) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
unsigned int nPortIndex; | |
DEBUG_PRINT_LOW("In for decoder free_buffer \n"); | |
if(m_state == OMX_StateIdle && | |
(BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) | |
{ | |
DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n"); | |
} | |
else if((m_sInPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_IN)|| | |
(m_sOutPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_OUT)) | |
{ | |
DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port); | |
} | |
else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,ports need to be disabled\n"); | |
post_event(OMX_EventError, | |
OMX_ErrorPortUnpopulated, | |
OMX_COMPONENT_GENERATE_EVENT); | |
return eRet; | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,port lost Buffers\n"); | |
post_event(OMX_EventError, | |
OMX_ErrorPortUnpopulated, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
if(port == PORT_INDEX_IN) | |
{ | |
// check if the buffer is valid | |
nPortIndex = buffer - m_inp_mem_ptr; | |
DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d, actual cnt %d \n", | |
nPortIndex, m_sInPortDef.nBufferCountActual); | |
if(nPortIndex < m_sInPortDef.nBufferCountActual) | |
{ | |
// Clear the bit associated with it. | |
BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); | |
free_input_buffer (buffer); | |
m_sInPortDef.bPopulated = OMX_FALSE; | |
/*Free the Buffer Header*/ | |
if(release_input_done()) | |
{ | |
input_use_buffer = false; | |
if(m_inp_mem_ptr) | |
{ | |
DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr\n"); | |
free (m_inp_mem_ptr); | |
m_inp_mem_ptr = NULL; | |
} | |
if(m_pInput_pmem) | |
{ | |
DEBUG_PRINT_LOW("Freeing m_pInput_pmem\n"); | |
free(m_pInput_pmem); | |
m_pInput_pmem = NULL; | |
} | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid\n"); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) | |
&& release_input_done()) | |
{ | |
DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); | |
post_event(OMX_CommandPortDisable, | |
PORT_INDEX_IN, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
else if(port == PORT_INDEX_OUT) | |
{ | |
// check if the buffer is valid | |
nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr; | |
DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d, actual cnt %d \n", | |
nPortIndex, m_sOutPortDef.nBufferCountActual); | |
if(nPortIndex < m_sOutPortDef.nBufferCountActual) | |
{ | |
// Clear the bit associated with it. | |
BITMASK_CLEAR(&m_out_bm_count,nPortIndex); | |
m_sOutPortDef.bPopulated = OMX_FALSE; | |
free_output_buffer (buffer); | |
if(release_output_done()) | |
{ | |
output_use_buffer = false; | |
if(m_out_mem_ptr) | |
{ | |
DEBUG_PRINT_LOW("Freeing m_out_mem_ptr\n"); | |
free (m_out_mem_ptr); | |
m_out_mem_ptr = NULL; | |
} | |
if(m_pOutput_pmem) | |
{ | |
DEBUG_PRINT_LOW("Freeing m_pOutput_pmem\n"); | |
free(m_pOutput_pmem); | |
m_pOutput_pmem = NULL; | |
} | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid\n"); | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) | |
&& release_output_done() ) | |
{ | |
DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n"); | |
DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); | |
post_event(OMX_CommandPortDisable, | |
PORT_INDEX_OUT, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
else | |
{ | |
eRet = OMX_ErrorBadPortIndex; | |
} | |
if((eRet == OMX_ErrorNone) && | |
(BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) | |
{ | |
if(release_done()) | |
{ | |
if(dev_stop() != 0) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: dev_stop() FAILED\n"); | |
eRet = OMX_ErrorHardware; | |
} | |
// Send the callback now | |
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); | |
post_event(OMX_CommandStateSet, OMX_StateLoaded, | |
OMX_COMPONENT_GENERATE_EVENT); | |
} | |
} | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::EmptyThisBuffer | |
DESCRIPTION | |
This routine is used to push the encoded video frames to | |
the video decoder. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
OMX Error None if everything went successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_BUFFERHEADERTYPE* buffer) | |
{ | |
OMX_ERRORTYPE ret1 = OMX_ErrorNone; | |
unsigned int nBufferIndex ; | |
DEBUG_PRINT_LOW("\n ETB: buffer = %p, buffer->pBuffer[%p]\n", buffer, buffer->pBuffer); | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> buffer is null or buffer size is invalid"); | |
return OMX_ErrorBadParameter; | |
} | |
if(buffer->nVersion.nVersion != OMX_SPEC_VERSION) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> OMX Version Invalid"); | |
return OMX_ErrorVersionMismatch; | |
} | |
if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Bad port index to call empty_this_buffer"); | |
return OMX_ErrorBadPortIndex; | |
} | |
if(!m_sInPortDef.bEnabled) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Cannot call empty_this_buffer while I/P port is disabled"); | |
return OMX_ErrorIncorrectStateOperation; | |
} | |
nBufferIndex = buffer - m_inp_mem_ptr; | |
if(nBufferIndex > m_sInPortDef.nBufferCountActual ) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]\n", nBufferIndex); | |
return OMX_ErrorBadParameter; | |
} | |
m_etb_count++; | |
DEBUG_PRINT_LOW("\n DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp); | |
post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB); | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::empty_this_buffer_proxy | |
DESCRIPTION | |
This routine is used to push the encoded video frames to | |
the video decoder. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
OMX Error None if everything went successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_BUFFERHEADERTYPE* buffer) | |
{ | |
OMX_U8 *pmem_data_buf = NULL; | |
int push_cnt = 0; | |
unsigned nBufIndex = 0; | |
OMX_ERRORTYPE ret = OMX_ErrorNone; | |
DEBUG_PRINT_LOW("\n ETBProxy: buffer->pBuffer[%p]\n", buffer->pBuffer); | |
if(buffer == NULL) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid buffer[%p]\n", buffer); | |
return OMX_ErrorBadParameter; | |
} | |
nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); | |
if(nBufIndex >= m_sInPortDef.nBufferCountActual) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid bufindex = %u\n", nBufIndex); | |
return OMX_ErrorBadParameter; | |
} | |
pending_input_buffers++; | |
if(input_flush_progress == true) | |
{ | |
post_event ((unsigned int)buffer,0, | |
OMX_COMPONENT_GENERATE_EBD); | |
DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Input flush in progress"); | |
return OMX_ErrorNone; | |
} | |
if(input_use_buffer && !m_use_input_pmem) | |
{ | |
DEBUG_PRINT_LOW("\n Heap UseBuffer case, so memcpy the data"); | |
pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer; | |
memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset), | |
buffer->nFilledLen); | |
DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf"); | |
} | |
if(dev_empty_buf(buffer, pmem_data_buf) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: ETBProxy: dev_empty_buf failed"); | |
/*Generate an async error and move to invalid state*/ | |
pending_input_buffers--; | |
return OMX_ErrorBadParameter; | |
} | |
return ret; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::FillThisBuffer | |
DESCRIPTION | |
IL client uses this method to release the frame buffer | |
after displaying them. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_BUFFERHEADERTYPE* buffer) | |
{ | |
DEBUG_PRINT_LOW("\n FTB: buffer->pBuffer[%p]\n", buffer->pBuffer); | |
if(m_state == OMX_StateInvalid) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State\n"); | |
return OMX_ErrorInvalidState; | |
} | |
if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size\n"); | |
return OMX_ErrorBadParameter; | |
} | |
if(buffer->nVersion.nVersion != OMX_SPEC_VERSION) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid\n"); | |
return OMX_ErrorVersionMismatch; | |
} | |
if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index\n"); | |
return OMX_ErrorBadPortIndex; | |
} | |
if(!m_sOutPortDef.bEnabled) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled\n"); | |
return OMX_ErrorIncorrectStateOperation; | |
} | |
post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB); | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::fill_this_buffer_proxy | |
DESCRIPTION | |
IL client uses this method to release the frame buffer | |
after displaying them. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::fill_this_buffer_proxy( | |
OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) | |
{ | |
OMX_U8 *pmem_data_buf = NULL; | |
OMX_ERRORTYPE nRet = OMX_ErrorNone; | |
DEBUG_PRINT_LOW("\n FTBProxy: bufferAdd->pBuffer[%p]\n", bufferAdd->pBuffer); | |
if(bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= m_sOutPortDef.nBufferCountActual) ) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: FTBProxy: Invalid i/p params\n"); | |
return OMX_ErrorBadParameter; | |
} | |
pending_output_buffers++; | |
/*Return back the output buffer to client*/ | |
if( m_sOutPortDef.bEnabled != OMX_TRUE || output_flush_progress == true) | |
{ | |
DEBUG_PRINT_LOW("\n o/p port is Disabled or Flush in Progress"); | |
post_event ((unsigned int)bufferAdd,0, | |
OMX_COMPONENT_GENERATE_FBD); | |
return OMX_ErrorNone; | |
} | |
if(output_use_buffer && !m_use_output_pmem) | |
{ | |
DEBUG_PRINT_LOW("\n Heap UseBuffer case"); | |
pmem_data_buf = (OMX_U8 *)m_pOutput_pmem[bufferAdd - m_out_mem_ptr].buffer; | |
} | |
if(dev_fill_buf(bufferAdd, pmem_data_buf) != true) | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: dev_fill_buf() Failed"); | |
pending_output_buffers--; | |
return OMX_ErrorBadParameter; | |
} | |
return OMX_ErrorNone; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_video::SetCallbacks | |
DESCRIPTION | |
Set the callbacks. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
OMX Error None if everything successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_IN OMX_CALLBACKTYPE* callbacks, | |
OMX_IN OMX_PTR appData) | |
{ | |
m_pCallbacks = *callbacks; | |
DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_pCallbacks.EmptyBufferDone,\ | |
m_pCallbacks.EventHandler,m_pCallbacks.FillBufferDone); | |
m_app_data = appData; | |
return OMX_ErrorNotImplemented; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::UseEGLImage | |
DESCRIPTION | |
OMX Use EGL Image method implementation <TBD>. | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
Not Implemented error. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, | |
OMX_IN OMX_U32 port, | |
OMX_IN OMX_PTR appData, | |
OMX_IN void* eglImage) | |
{ | |
DEBUG_PRINT_ERROR("ERROR: use_EGL_image: Not Implemented \n"); | |
return OMX_ErrorNotImplemented; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::ComponentRoleEnum | |
DESCRIPTION | |
OMX Component Role Enum method implementation. | |
PARAMETERS | |
<TBD>. | |
RETURN VALUE | |
OMX Error None if everything is successful. | |
========================================================================== */ | |
OMX_ERRORTYPE omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, | |
OMX_OUT OMX_U8* role, | |
OMX_IN OMX_U32 index) | |
{ | |
OMX_ERRORTYPE eRet = OMX_ErrorNone; | |
if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE)) | |
{ | |
if((0 == index) && role) | |
{ | |
strncpy((char *)role, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE); | |
DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); | |
eRet = OMX_ErrorNoMore; | |
} | |
} | |
else | |
{ | |
DEBUG_PRINT_ERROR("\nERROR: Querying Role on Unknown Component\n"); | |
eRet = OMX_ErrorInvalidComponentName; | |
} | |
return eRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::AllocateDone | |
DESCRIPTION | |
Checks if entire buffer pool is allocated by IL Client or not. | |
Need this to move to IDLE state. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false. | |
========================================================================== */ | |
bool omx_video::allocate_done(void) | |
{ | |
bool bRet = false; | |
bool bRet_In = false; | |
bool bRet_Out = false; | |
bRet_In = allocate_input_done(); | |
bRet_Out = allocate_output_done(); | |
if(bRet_In && bRet_Out) | |
{ | |
bRet = true; | |
} | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::AllocateInputDone | |
DESCRIPTION | |
Checks if I/P buffer pool is allocated by IL Client or not. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false. | |
========================================================================== */ | |
bool omx_video::allocate_input_done(void) | |
{ | |
bool bRet = false; | |
unsigned i=0; | |
if(m_inp_mem_ptr == NULL) | |
{ | |
return bRet; | |
} | |
if(m_inp_mem_ptr ) | |
{ | |
for(;i<m_sInPortDef.nBufferCountActual;i++) | |
{ | |
if(BITMASK_ABSENT(&m_inp_bm_count,i)) | |
{ | |
break; | |
} | |
} | |
} | |
if(i==m_sInPortDef.nBufferCountActual) | |
{ | |
bRet = true; | |
} | |
if(i==m_sInPortDef.nBufferCountActual && m_sInPortDef.bEnabled) | |
{ | |
m_sInPortDef.bPopulated = OMX_TRUE; | |
} | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::AllocateOutputDone | |
DESCRIPTION | |
Checks if entire O/P buffer pool is allocated by IL Client or not. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false. | |
========================================================================== */ | |
bool omx_video::allocate_output_done(void) | |
{ | |
bool bRet = false; | |
unsigned j=0; | |
if(m_out_mem_ptr == NULL) | |
{ | |
return bRet; | |
} | |
if(m_out_mem_ptr ) | |
{ | |
for(;j<m_sOutPortDef.nBufferCountActual;j++) | |
{ | |
if(BITMASK_ABSENT(&m_out_bm_count,j)) | |
{ | |
break; | |
} | |
} | |
} | |
if(j==m_sOutPortDef.nBufferCountActual) | |
{ | |
bRet = true; | |
} | |
if(j==m_sOutPortDef.nBufferCountActual && m_sOutPortDef.bEnabled) | |
{ | |
m_sOutPortDef.bPopulated = OMX_TRUE; | |
} | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::ReleaseDone | |
DESCRIPTION | |
Checks if IL client has released all the buffers. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
bool omx_video::release_done(void) | |
{ | |
bool bRet = false; | |
DEBUG_PRINT_LOW("Inside release_done()\n"); | |
if(release_input_done()) | |
{ | |
if(release_output_done()) | |
{ | |
bRet = true; | |
} | |
} | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::ReleaseOutputDone | |
DESCRIPTION | |
Checks if IL client has released all the buffers. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
bool omx_video::release_output_done(void) | |
{ | |
bool bRet = false; | |
unsigned i=0,j=0; | |
DEBUG_PRINT_LOW("Inside release_output_done()\n"); | |
if(m_out_mem_ptr) | |
{ | |
for(;j<m_sOutPortDef.nBufferCountActual;j++) | |
{ | |
if(BITMASK_PRESENT(&m_out_bm_count,j)) | |
{ | |
break; | |
} | |
} | |
if(j==m_sOutPortDef.nBufferCountActual) | |
{ | |
bRet = true; | |
} | |
} | |
else | |
{ | |
bRet = true; | |
} | |
return bRet; | |
} | |
/* ====================================================================== | |
FUNCTION | |
omx_venc::ReleaseInputDone | |
DESCRIPTION | |
Checks if IL client has released all the buffers. | |
PARAMETERS | |
None. | |
RETURN VALUE | |
true/false | |
========================================================================== */ | |
bool omx_video::release_input_done(void) | |
{ | |
bool bRet = false; | |
unsigned i=0,j=0; | |
DEBUG_PRINT_LOW("Inside release_input_done()\n"); | |
if(m_inp_mem_ptr) | |
{ | |
for(;j<m_sInPortDef.nBufferCountActual;j++) | |
{ | |
if( BITMASK_PRESENT(&m_inp_bm_count,j)) | |
{ | |
break; | |
} | |
} | |
if(j==m_sInPortDef.nBufferCountActual) | |
{ | |
bRet = true; | |
} | |
} | |
else | |
{ | |
bRet = true; | |
} | |
return bRet; | |
} | |
OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp, | |
OMX_BUFFERHEADERTYPE * buffer) | |
{ | |
DEBUG_PRINT_LOW("\nfill_buffer_done: buffer->pBuffer[%p]\n", buffer->pBuffer); | |
if(buffer == NULL || ((buffer - m_out_mem_ptr) > m_sOutPortDef.nBufferCountActual)) | |
{ | |
return OMX_ErrorBadParameter; | |
} | |
pending_output_buffers--; | |
/* For use buffer we need to copy the data */ | |
if(m_pCallbacks.FillBufferDone) | |
{ | |
if(buffer->nFilledLen > 0) | |
{ | |
m_fbd_count++; | |
} | |
m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer); | |
} | |
else | |
{ | |
return OMX_ErrorBadParameter; | |
} | |
return OMX_ErrorNone; | |
} | |
OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE hComp, | |
OMX_BUFFERHEADERTYPE* buffer) | |
{ | |
DEBUG_PRINT_LOW("\nempty_buffer_done: buffer->pBuffer[%p]\n", buffer->pBuffer); | |
if(buffer == NULL || ((buffer - m_inp_mem_ptr) > m_sInPortDef.nBufferCountActual)) | |
{ | |
return OMX_ErrorBadParameter; | |
} | |
pending_input_buffers--; | |
if(m_pCallbacks.EmptyBufferDone) | |
{ | |
m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, buffer); | |
} | |
return OMX_ErrorNone; | |
} |