diff options
Diffstat (limited to 'mm-video-v4l2/vidc/venc/src/omx_video_base.cpp')
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_base.cpp | 4983 |
1 files changed, 4983 insertions, 0 deletions
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp new file mode 100644 index 00000000..b0e14038 --- /dev/null +++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp @@ -0,0 +1,4983 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2013, Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file omx_video_base.cpp + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include <string.h> +#include "omx_video_base.h" +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/prctl.h> +#ifdef _ANDROID_ICS_ +#include <media/hardware/HardwareAPI.h> +#include <gralloc_priv.h> +#endif +#ifndef _ANDROID_ +#include <glib.h> +#define strlcpy g_strlcpy +#endif +#define H264_SUPPORTED_WIDTH (480) +#define H264_SUPPORTED_HEIGHT (368) + +#define MPEG4_SUPPORTED_WIDTH (480) +#define MPEG4_SUPPORTED_HEIGHT (368) + +#define VC1_SP_MP_START_CODE 0xC5000000 +#define VC1_SP_MP_START_CODE_MASK 0xFF000000 +#define VC1_AP_START_CODE 0x00000100 +#define VC1_AP_START_CODE_MASK 0xFFFFFF00 +#define VC1_STRUCT_C_PROFILE_MASK 0xF0 +#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 +#define VC1_SIMPLE_PROFILE 0 +#define VC1_MAIN_PROFILE 1 +#define VC1_ADVANCE_PROFILE 3 +#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 +#define VC1_SIMPLE_PROFILE_MED_LEVEL 2 +#define VC1_STRUCT_C_LEN 4 +#define VC1_STRUCT_C_POS 8 +#define VC1_STRUCT_A_POS 12 +#define VC1_STRUCT_B_POS 24 +#define VC1_SEQ_LAYER_SIZE 36 + +typedef struct OMXComponentCapabilityFlagsType +{ + ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS + OMX_BOOL iIsOMXComponentMultiThreaded; + OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc; + OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc; + OMX_BOOL iOMXComponentSupportsMovableInputBuffers; + OMX_BOOL iOMXComponentSupportsPartialFrames; + OMX_BOOL iOMXComponentUsesNALStartCodes; + OMX_BOOL iOMXComponentCanHandleIncompleteFrames; + OMX_BOOL iOMXComponentUsesFullAVCFrames; + +} OMXComponentCapabilityFlagsType; +#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347 +#ifdef OUTPUT_BUFFER_LOG +extern FILE *outputBufferFile1; +#endif + +void* message_thread(void *input) +{ + omx_video* omx = reinterpret_cast<omx_video*>(input); + unsigned char id; + int n; + + DEBUG_PRINT_LOW("omx_venc: message thread start\n"); + prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0); + while(1) + { + n = read(omx->m_pipe_in, &id, 1); + if(0 == n) + { + break; + } + + if(1 == n) + { + omx->process_event_cb(omx, id); + } +#ifdef QLE_BUILD + if(n < 0) break; +#else + if((n < 0) && (errno != EINTR)) break; +#endif + } + DEBUG_PRINT_LOW("omx_venc: message thread stop\n"); + return 0; +} + +void post_message(omx_video *omx, unsigned char id) +{ + DEBUG_PRINT_LOW("omx_venc: post_message %d\n", id); + write(omx->m_pipe_out, &id, 1); +} + +// omx_cmd_queue destructor +omx_video::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_video::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_video::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) +{ + bool ret = true; + if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } + else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full\n"); + } + return ret; +} + +// omx cmd queue pop +bool omx_video::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) +{ + bool ret = true; + if(m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + } + } + else + { + ret = false; + } + return ret; +} + +// Retrieve the first mesg type in the queue +unsigned omx_video::omx_cmd_queue::get_q_msg_type() +{ + return m_q[m_read].id; +} + + + +#ifdef _ANDROID_ +VideoHeap::VideoHeap(int fd, size_t size, void* base) +{ + // dup file descriptor, map once, use pmem + init(dup(fd), base, size, 0 , MEM_DEVICE); +} +#endif // _ANDROID_ + +/* ====================================================================== +FUNCTION + omx_venc::omx_venc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_video::omx_video(): + m_pInput_pmem(NULL), + m_pOutput_pmem(NULL), +#ifdef USE_ION + m_pInput_ion(NULL), + m_pOutput_ion(NULL), +#endif + m_error_propogated(false), + m_state(OMX_StateInvalid), + m_app_data(NULL), + m_use_input_pmem(OMX_FALSE), + m_use_output_pmem(OMX_FALSE), + m_inp_mem_ptr(NULL), + m_out_mem_ptr(NULL), + input_flush_progress (false), + output_flush_progress (false), + input_use_buffer (false), + output_use_buffer (false), + pending_input_buffers(0), + pending_output_buffers(0), + m_out_bm_count(0), + m_inp_bm_count(0), + m_flags(0), + m_etb_count(0), + m_fbd_count(0), + m_event_port_settings_sent(false), + m_input_msg_id(OMX_COMPONENT_GENERATE_ETB), + psource_frame(NULL), + pdest_frame(NULL), + c2d_opened(false) +{ + DEBUG_PRINT_HIGH("\n omx_video(): Inside Constructor()"); + memset(&m_cmp,0,sizeof(m_cmp)); + memset(&m_pCallbacks,0,sizeof(m_pCallbacks)); + async_thread_created = false; + msg_thread_created = false; + + 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"); + if (msg_thread_created) + pthread_join(msg_thread_id,NULL); + DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit\n"); + /*For V4L2 based drivers, pthread_join is done in device_close + * so no need to do it here*/ +#ifndef _MSM8974_ + if (async_thread_created) + pthread_join(async_thread_id,NULL); +#endif + pthread_mutex_destroy(&m_lock); + sem_destroy(&m_cmd_lock); + DEBUG_PRINT_HIGH("\n m_etb_count = %u, m_fbd_count = %u\n", m_etb_count, + m_fbd_count); + DEBUG_PRINT_HIGH("omx_video: Destructor exit\n"); + DEBUG_PRINT_HIGH("Exiting 7x30 OMX Video Encoder ...\n"); +} + +/* ====================================================================== +FUNCTION + omx_venc::OMXCntrlProcessMsgCb + +DESCRIPTION + IL Client callbacks are generated through this routine. The decoder + provides the thread context for this routine. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +void omx_video::process_event_cb(void *ctxt, unsigned char id) +{ + unsigned p1; // Parameter - 1 + unsigned p2; // Parameter - 2 + unsigned ident; + unsigned qsize=0; // qsize + omx_video *pThis = (omx_video *) ctxt; + + if(!pThis) + { + DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out\n"); + return; + } + + // Protect the shared queue data structure + do + { + /*Read the message id's from the queue*/ + + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size; + if(qsize) + { + pThis->m_cmd_q.pop_entry(&p1,&p2,&ident); + } + + if(qsize == 0) + { + qsize = pThis->m_ftb_q.m_size; + if(qsize) + { + pThis->m_ftb_q.pop_entry(&p1,&p2,&ident); + } + } + + if(qsize == 0) + { + qsize = pThis->m_etb_q.m_size; + if(qsize) + { + pThis->m_etb_q.pop_entry(&p1,&p2,&ident); + } + } + + pthread_mutex_unlock(&pThis->m_lock); + + /*process message if we have one*/ + if(qsize > 0) + { + id = ident; + switch(id) + { + case OMX_COMPONENT_GENERATE_EVENT: + if(pThis->m_pCallbacks.EventHandler) + { + switch(p1) + { + case OMX_CommandStateSet: + pThis->m_state = (OMX_STATETYPE) p2; + DEBUG_PRINT_LOW("Process -> state set to %d \n", pThis->m_state); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL); + break; + + case OMX_EventError: + DEBUG_PRINT_ERROR("\nERROR: OMX_EventError: p2 = %d\n", p2); + if(p2 == OMX_ErrorHardware) + { + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError,OMX_ErrorHardware,0,NULL); + } + else + { + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError, p2, NULL, NULL ); + + } + break; + + case OMX_CommandPortDisable: + DEBUG_PRINT_LOW("Process -> Port %d set to PORT_STATE_DISABLED" \ + "state \n", p2); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + case OMX_CommandPortEnable: + DEBUG_PRINT_LOW("Process ->Port %d set PORT_STATE_ENABLED state\n" \ + , p2); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + default: + DEBUG_PRINT_LOW("\n process_event_cb forwarding EventCmdComplete %d \n", p1); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks\n"); + } + break; + case OMX_COMPONENT_GENERATE_ETB_OPQ: + DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB_OPQ\n"); + if(pThis->empty_this_buffer_opaque((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n"); + pThis->omx_report_error (); + } + break; + case OMX_COMPONENT_GENERATE_ETB: + DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB\n"); + if(pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FTB: + if( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: FTBProxy() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_COMMAND: + pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ + (OMX_U32)p2,(OMX_PTR)NULL); + break; + + case OMX_COMPONENT_GENERATE_EBD: + if( pThis->empty_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FBD: + if( pThis->fill_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: + + pThis->input_flush_progress = false; + DEBUG_PRINT_HIGH("\nm_etb_count at i/p flush = %u", m_etb_count); + m_etb_count = 0; + if(pThis->m_pCallbacks.EventHandler) + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_INPUT_FLUSH_PENDING)) + { + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + PORT_INDEX_IN,NULL ); + } + else if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_IDLE_PENDING)) + { + if(!pThis->output_flush_progress) + { + DEBUG_PRINT_LOW("\n dev_stop called after input flush complete\n"); + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in i/p flush!\n"); + pThis->omx_report_error (); + } + } + } + } + + break; + + case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: + + pThis->output_flush_progress = false; + DEBUG_PRINT_HIGH("\nm_fbd_count at o/p flush = %u", m_fbd_count); + m_fbd_count = 0; + if(pThis->m_pCallbacks.EventHandler) + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) + { + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + PORT_INDEX_OUT,NULL ); + } + else if(BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("\n dev_stop called after Output flush complete\n"); + if(!pThis->input_flush_progress) + { + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in o/p flush!\n"); + pThis->omx_report_error (); + } + } + } + } + break; + + case OMX_COMPONENT_GENERATE_START_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE msg"); + + if(pThis->m_pCallbacks.EventHandler) + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success"); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Move to \ + executing"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting, NULL); + } + else if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_PAUSE_PENDING)) + { + if(dev_pause()) + { + DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in Start Done!\n"); + pThis->omx_report_error (); + } + } + else if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_LOADED_START_PENDING)) + { + if(dev_loaded_start_done()) + { + DEBUG_PRINT_LOW("successful loaded Start Done!"); + } + else + { + DEBUG_PRINT_ERROR("ERROR: failed in loaded Start Done!"); + pThis->omx_report_error (); + } + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_START_PENDING); + } + else + { + DEBUG_PRINT_LOW("\nERROR: unknown flags=%x\n",pThis->m_flags); + } + } + else + { + DEBUG_PRINT_LOW("\n Event Handler callback is NULL"); + } + break; + + case OMX_COMPONENT_GENERATE_PAUSE_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE msg"); + if(pThis->m_pCallbacks.EventHandler) + { + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) + { + //Send the callback now + pThis->complete_pending_buffer_done_cbs(); + DEBUG_PRINT_LOW("omx_video::process_event_cb() Sending PAUSE complete after all pending EBD/FBD\n"); + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); + pThis->m_state = OMX_StatePause; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StatePause, NULL); + } + } + + break; + + case OMX_COMPONENT_GENERATE_RESUME_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_RESUME_DONE msg"); + if(pThis->m_pCallbacks.EventHandler) + { + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting,NULL); + } + } + + break; + + case OMX_COMPONENT_GENERATE_STOP_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE msg"); + if(pThis->m_pCallbacks.EventHandler) + { + pThis->complete_pending_buffer_done_cbs(); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); + pThis->m_state = OMX_StateIdle; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateIdle,NULL); + } + else if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_LOADED_STOP_PENDING)) + { + if(dev_loaded_stop_done()) + { + DEBUG_PRINT_LOW("successful loaded Stop Done!"); + } + else + { + DEBUG_PRINT_ERROR("ERROR: failed in loaded Stop Done!"); + pThis->omx_report_error (); + } + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_STOP_PENDING); + } + else + { + DEBUG_PRINT_LOW("\nERROR: unknown flags=%x\n",pThis->m_flags); + } + } + + break; + + case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: + DEBUG_PRINT_ERROR("\nERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!\n"); + pThis->omx_report_error (); + break; +#ifndef _MSM8974_ + case OMX_COMPONENT_GENERATE_LTRUSE_FAILED: + DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_LTRUSE_FAILED!"); + if(pThis->m_pCallbacks.EventHandler) + { + DEBUG_PRINT_ERROR("Sending QOMX_ErrorLTRUseFailed, p2 = 0x%x", p2); + pThis->m_pCallbacks.EventHandler( + &pThis->m_cmp, pThis->m_app_data, + OMX_EventError, QOMX_ErrorLTRUseFailed, NULL, NULL); + } + break; +#endif + default: + DEBUG_PRINT_LOW("\n process_event_cb unknown msg id 0x%02x", id); + break; + } + } + + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\ + pThis->m_etb_q.m_size; + + pthread_mutex_unlock(&pThis->m_lock); + + } + while(qsize>0); + DEBUG_PRINT_LOW("\n exited the while loop\n"); + +} + + + + +/* ====================================================================== +FUNCTION + omx_venc::GetComponentVersion + +DESCRIPTION + Returns the component version. + +PARAMETERS + TBD. + +RETURN VALUE + OMX_ErrorNone. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_component_version +( +OMX_IN OMX_HANDLETYPE hComp, +OMX_OUT OMX_STRING componentName, +OMX_OUT OMX_VERSIONTYPE* componentVersion, +OMX_OUT OMX_VERSIONTYPE* specVersion, +OMX_OUT OMX_UUIDTYPE* componentUUID +) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + /* TBD -- Return the proper version */ + if (specVersion) + { + specVersion->nVersion = OMX_SPEC_VERSION; + } + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_venc::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if(cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) + { + if((param1 != PORT_INDEX_IN) && (param1 != PORT_INDEX_OUT) && (param1 != PORT_INDEX_BOTH)) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index\n"); + return OMX_ErrorBadPortIndex; + } + } + if(cmd == OMX_CommandMarkBuffer) + { + if(param1 != PORT_INDEX_IN) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index \n"); + return OMX_ErrorBadPortIndex; + } + if(!cmdData) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null"); + return OMX_ErrorBadParameter; + } + } + + post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + sem_wait(&m_cmd_lock); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_venc::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1; + + if(cmd == OMX_CommandStateSet) + { + /***************************/ + /* Current State is Loaded */ + /***************************/ + if(m_state == OMX_StateLoaded) + { + if(eState == OMX_StateIdle) + { + //if all buffers are allocated or all ports disabled + if(allocate_done() || + ( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE)) + { + DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle\n"); + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Loaded to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Loaded to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources\n"); + } + /* Requesting transition from Loaded to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled\n",\ + eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if(m_state == OMX_StateIdle) + { + if(eState == OMX_StateLoaded) + { + if(release_done()) + { + /* + Since error is None , we will post an event at the end + of this function definition + */ + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded\n"); + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed at Idle --> Loaded"); + eRet = OMX_ErrorHardware; + } + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Idle to Executing */ + else if(eState == OMX_StateExecuting) + { + if( dev_start() ) + { + DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Exe\n"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n"); + bFlag = 0; + } + + dev_start_done(); + } + /* Requesting transition from Idle to Idle */ + else if(eState == OMX_StateIdle) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Idle to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Idle to Pause */ + else if(eState == OMX_StatePause) + { + /*To pause the Video core we need to start the driver*/ + if( dev_start() ) + { + DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Pause\n"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause\n"); + bFlag = 0; + } + } + /* Requesting transition from Idle to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if(m_state == OMX_StateExecuting) + { + /* Requesting transition from Executing to Idle */ + if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition + */ + DEBUG_PRINT_LOW("\n OMXCORE-SM: Executing --> Idle \n"); + //here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + execute_omx_flush(OMX_ALL); + bFlag = 0; + } + /* Requesting transition from Executing to Paused */ + else if(eState == OMX_StatePause) + { + + if(dev_pause()) + { + DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in SCP on Exe --> Pause\n"); + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Executing-->Pause\n"); + bFlag = 0; + } + } + /* Requesting transition from Executing to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Executing \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Executing to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if(m_state == OMX_StatePause) + { + /* Requesting transition from Pause to Executing */ + if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_LOW("\n Pause --> Executing \n"); + if( dev_resume() ) + { + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Pause-->Executing\n"); + post_event (NULL, NULL, OMX_COMPONENT_GENERATE_RESUME_DONE); + bFlag = 0; + } + } + /* Requesting transition from Pause to Idle */ + else if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("\n Pause --> Idle \n"); + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + execute_omx_flush(OMX_ALL); + bFlag = 0; + } + /* Requesting transition from Pause to loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> Pause \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Pause to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is WaitForResources */ + /***************************/ + else if(m_state == OMX_StateWaitForResources) + { + /* Requesting transition from WaitForResources to Loaded */ + if(eState == OMX_StateLoaded) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded\n"); + } + /* Requesting transition from WaitForResources to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorSameState, + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from WaitForResources to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + /* Requesting transition from WaitForResources to Loaded - + is NOT tested by Khronos TS */ + + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)\n",m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /********************************/ + /* Current State is Invalid */ + /*******************************/ + else if(m_state == OMX_StateInvalid) + { + /* State Transition from Inavlid to any state */ + if(eState == (OMX_StateLoaded || OMX_StateWaitForResources + || OMX_StateIdle || OMX_StateExecuting + || OMX_StatePause || OMX_StateInvalid)) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorInvalidState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + } + else if(cmd == OMX_CommandFlush) + { + if(0 == param1 || OMX_ALL == param1) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); + } + if(1 == param1 || OMX_ALL == param1) + { + //generate output flush event only. + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + } + + execute_omx_flush(param1); + bFlag = 0; + } + else if( cmd == OMX_CommandPortEnable) + { + if(param1 == PORT_INDEX_IN || param1 == OMX_ALL) + { + m_sInPortDef.bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || allocate_input_done()) + { + post_event(OMX_CommandPortEnable,PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL) + { + m_sOutPortDef.bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (allocate_output_done())) + { + post_event(OMX_CommandPortEnable,PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + } + else if(cmd == OMX_CommandPortDisable) + { + if(param1 == PORT_INDEX_IN || param1 == OMX_ALL) + { + m_sInPortDef.bEnabled = OMX_FALSE; + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_input_done()) + { + post_event(OMX_CommandPortDisable,PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + execute_omx_flush(PORT_INDEX_IN); + } + + // Skip the event notification + bFlag = 0; + } + } + if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL) + { + m_sOutPortDef.bEnabled = OMX_FALSE; + + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_output_done()) + { + post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\ + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + execute_omx_flush(PORT_INDEX_OUT); + } + // Skip the event notification + bFlag = 0; + + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + if(eRet == OMX_ErrorNone && bFlag) + { + post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + sem_post(&m_cmd_lock); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_venc::ExecuteOmxFlush + +DESCRIPTION + Executes the OMX flush. + +PARAMETERS + flushtype - input flush(1)/output flush(0)/ both. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_video::execute_omx_flush(OMX_U32 flushType) +{ + bool bRet = false; + DEBUG_PRINT_LOW("\n execute_omx_flush - %d\n", flushType); +#ifdef _MSM8974_ + /* XXX: The driver/hardware does not support flushing of individual ports + * in all states. So we pretty much need to flush both ports internally, + * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it + * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set, + * we automatically omit sending the FLUSH done for the "opposite" port. */ + + input_flush_progress = true; + output_flush_progress = true; + bRet = execute_flush_all(); +#else + 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(); + } +#endif + return bRet; +} +/*========================================================================= +FUNCTION : execute_output_flush + +DESCRIPTION + Executes the OMX flush at OUTPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_video::execute_output_flush(void) +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate FBD for all Buffers in the FTBq*/ + DEBUG_PRINT_LOW("\n execute_output_flush\n"); + pthread_mutex_lock(&m_lock); + while(m_ftb_q.m_size) + { + m_ftb_q.pop_entry(&p1,&p2,&ident); + + if(ident == OMX_COMPONENT_GENERATE_FTB ) + { + pending_output_buffers++; + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_FBD) + { + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + + pthread_mutex_unlock(&m_lock); + /*Check if there are buffers with the Driver*/ + if(dev_flush(PORT_INDEX_OUT)) + { + DEBUG_PRINT_ERROR("\nERROR: o/p dev_flush() Failed"); + return false; + } + + return bRet; +} +/*========================================================================= +FUNCTION : execute_input_flush + +DESCRIPTION + Executes the OMX flush at INPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_video::execute_input_flush(void) +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate EBD for all Buffers in the ETBq*/ + DEBUG_PRINT_LOW("\n execute_input_flush\n"); + + pthread_mutex_lock(&m_lock); + while(m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_ETB) + { + pending_input_buffers++; + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_EBD) + { + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + else if(ident == OMX_COMPONENT_GENERATE_ETB_OPQ) + { + m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2); + } + } + if(mUseProxyColorFormat) { + if(psource_frame) { + m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame); + psource_frame = NULL; + } + while(m_opq_meta_q.m_size) { + unsigned p1,p2,id; + m_opq_meta_q.pop_entry(&p1,&p2,&id); + m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data, + (OMX_BUFFERHEADERTYPE *)p1); + } + if(pdest_frame){ + m_opq_pmem_q.insert_entry((unsigned int)pdest_frame,0,0); + pdest_frame = NULL; + } + } + pthread_mutex_unlock(&m_lock); + /*Check if there are buffers with the Driver*/ + if(dev_flush(PORT_INDEX_IN)) + { + DEBUG_PRINT_ERROR("\nERROR: i/p dev_flush() Failed"); + return false; + } + + return bRet; +} + + +/*========================================================================= +FUNCTION : execute_flush + +DESCRIPTION + Executes the OMX flush at INPUT & OUTPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +#ifdef _MSM8974_ +bool omx_video::execute_flush_all(void) +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + DEBUG_PRINT_LOW("\n execute_flush_all\n"); + + /*Generate EBD for all Buffers in the ETBq*/ + pthread_mutex_lock(&m_lock); + while(m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_ETB) + { + pending_input_buffers++; + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_EBD) + { + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + + /*Generate FBD for all Buffers in the FTBq*/ + DEBUG_PRINT_LOW("\n execute_output_flush\n"); + 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_BOTH)) + { + DEBUG_PRINT_ERROR("\nERROR: dev_flush() Failed"); + return false; + } + return bRet; +} + +#endif + +/* ====================================================================== +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_FBD) || + (id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH)) + { + m_ftb_q.insert_entry(p1,p2,id); + } + else if ((id == OMX_COMPONENT_GENERATE_ETB) || + (id == OMX_COMPONENT_GENERATE_EBD) || + (id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH)) + { + m_etb_q.insert_entry(p1,p2,id); + } + else + { + m_cmd_q.insert_entry(p1,p2,id); + } + + bRet = true; + DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this); + post_message(this, id); + pthread_mutex_unlock(&m_lock); + + return bRet; +} + +/* ====================================================================== +FUNCTION + omx_venc::GetParameter + +DESCRIPTION + OMX Get Parameter method implementation + +PARAMETERS + <TBD>. + +RETURN VALUE + Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int height=0,width = 0; + + DEBUG_PRINT_LOW("get_parameter: \n"); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n"); + return OMX_ErrorBadParameter; + } + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n"); + if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) + { + DEBUG_PRINT_LOW("m_sInPortDef: size = %d, min cnt = %d, actual cnt = %d", + m_sInPortDef.nBufferSize, m_sInPortDef.nBufferCountMin, + m_sInPortDef.nBufferCountActual); + memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef)); +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + { + portDefn->nBufferSize = sizeof(encoder_media_buffer_type); + } + if (mUseProxyColorFormat) { + portDefn->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque; + } +#endif + } + else if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + dev_get_buf_req (&m_sOutPortDef.nBufferCountMin, + &m_sOutPortDef.nBufferCountActual, + &m_sOutPortDef.nBufferSize, + m_sOutPortDef.nPortIndex); + DEBUG_PRINT_LOW("m_sOutPortDef: size = %d, min cnt = %d, actual cnt = %d", + m_sOutPortDef.nBufferSize, m_sOutPortDef.nBufferCountMin, + m_sOutPortDef.nBufferCountActual); + memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n"); + + memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam)); + break; + } + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n"); + + if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) + { + int index = portFmt->nIndex; + if(index > 1) + eRet = OMX_ErrorNoMore; + else { + memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat)); +#ifdef _ANDROID_ICS_ + if (index == 1) { + //we support two formats + //index 0 - YUV420SP + //index 1 - opaque which internally maps to YUV420SP. + //this can be extended in the future + portFmt->nIndex = index; //restore index set from client + portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque; + } +#endif + } + } + else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate\n"); + + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + + break; + } + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4\n"); + memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4)); + break; + } + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263\n"); + memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263)); + break; + } + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc\n"); + memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC)); + break; + } + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported\n"); + eRet = get_supported_profile_level(pParam); + if(eRet) + DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %lu, %lu", + pParam->eProfile, pParam->eLevel); + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent\n"); + memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel)); + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n"); + memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio)); + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n"); + memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img)); + break; + + } + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + comp_role->nVersion.nVersion = OMX_SPEC_VERSION; + comp_role->nSize = sizeof(*comp_role); + + DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",paramIndex); + if(NULL != comp_role->cRole) + { + strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",paramIndex); + eRet =OMX_ErrorBadParameter; + } + break; + } + /* Added for parameter test */ + case OMX_IndexParamPriorityMgmt: + { + + OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n"); + memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt)); + break; + } + /* Added for parameter test */ + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n"); + if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) + { + memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier)); + } + else if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT) + { + memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization\n"); + memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization)); + break; + } + + case OMX_QcomIndexParamVideoQPRange: + { + OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoQPRange\n"); + memcpy(qp_range, &m_sSessionQPRange, sizeof(m_sSessionQPRange)); + break; + } + + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData; + DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection\n"); + errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC; + errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync; + errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing; + break; + } + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData; + DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh\n"); + DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET\n"); + intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode; + intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs; + break; + } + case OMX_QcomIndexPortDefn: + //TODO + break; + case OMX_COMPONENT_CAPABILITY_TYPE_INDEX: + { + OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData); + DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX\n"); + pParam->iIsOMXComponentMultiThreaded = OMX_TRUE; + pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE; + pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; + pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; + pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE; + pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE; + pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE; + pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE; + m_use_input_pmem = OMX_TRUE; + DEBUG_PRINT_LOW("Supporting capability index in encoder node"); + break; + } +#if !defined(MAX_RES_720P) || defined(_MSM8974_) + case OMX_QcomIndexParamIndexExtraDataType: + { + DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType"); + QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData; + if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) + { + if (pParam->nPortIndex == PORT_INDEX_OUT) + { + pParam->bEnabled = + (OMX_BOOL)((m_sExtraData & VEN_EXTRADATA_SLICEINFO) ? 1 : 0); + DEBUG_PRINT_HIGH("Slice Info extradata %d", pParam->bEnabled); + } + else + { + DEBUG_PRINT_ERROR("get_parameter: slice information is " + "valid for output port only"); + eRet =OMX_ErrorUnsupportedIndex; + } + } +#ifndef _MSM8974_ + else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoLTRInfo) + { + if (pParam->nPortIndex == PORT_INDEX_OUT) + { + pParam->bEnabled = + (OMX_BOOL)((m_sExtraData & VEN_EXTRADATA_LTRINFO) ? 1 : 0); + DEBUG_PRINT_HIGH("LTR Info extradata %d", pParam->bEnabled); + } + else + { + DEBUG_PRINT_ERROR("get_parameter: LTR information is " + "valid for output port only"); + eRet = OMX_ErrorUnsupportedIndex; + } + } +#endif + else + { + DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)", + pParam->nIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + break; + } + case QOMX_IndexParamVideoLTRCountRangeSupported: + { + DEBUG_PRINT_HIGH("get_parameter: QOMX_IndexParamVideoLTRCountRangeSupported"); + QOMX_EXTNINDEX_RANGETYPE *pParam = (QOMX_EXTNINDEX_RANGETYPE *)paramData; + if (pParam->nPortIndex == PORT_INDEX_OUT) + { + OMX_U32 min = 0, max = 0, step_size = 0; + if (dev_get_capability_ltrcount(&min, &max, &step_size)) + { + pParam->nMin = min; + pParam->nMax = max; + pParam->nStepSize = step_size; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: get_capability_ltrcount failed"); + eRet = OMX_ErrorUndefined; + } + } + else + { + DEBUG_PRINT_ERROR("LTR count range is valid for output port only"); + eRet = OMX_ErrorUnsupportedIndex; + } + } + break; +#endif + case QOMX_IndexParamVideoSyntaxHdr: + { + DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr"); + QOMX_EXTNINDEX_PARAMTYPE* pParam = + reinterpret_cast<QOMX_EXTNINDEX_PARAMTYPE*>(paramData); + if (pParam->pData == NULL) + { + DEBUG_PRINT_ERROR("Error: Data buffer is NULL"); + eRet = OMX_ErrorBadParameter; + break; + } + if (get_syntaxhdr_enable == false) + { + DEBUG_PRINT_ERROR("ERROR: get_parameter: Get syntax header disabled"); + eRet = OMX_ErrorUnsupportedIndex; + break; + } + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_START_PENDING); + if(dev_loaded_start()) + { + DEBUG_PRINT_LOW("device start successful"); + } + else + { + DEBUG_PRINT_ERROR("device start failed"); + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_START_PENDING); + return OMX_ErrorHardware; + } + if(dev_get_seq_hdr(pParam->pData, + (unsigned)(pParam->nSize - sizeof(QOMX_EXTNINDEX_PARAMTYPE)), + (unsigned *)&pParam->nDataSize)) + { + DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %lu)", + pParam->nDataSize); + for (unsigned i = 0; i < pParam->nDataSize; i++) { + DEBUG_PRINT_LOW("Header[%d] = %x", i, *((char *)pParam->pData + i)); + } + } + else + { + DEBUG_PRINT_ERROR("Error returned from GetSyntaxHeader()"); + eRet = OMX_ErrorHardware; + } + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING); + if(dev_loaded_stop()) + { + DEBUG_PRINT_LOW("device stop successful"); + } + else + { + DEBUG_PRINT_ERROR("device stop failed"); + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING); + eRet = OMX_ErrorHardware; + } + break; + } + case OMX_IndexParamVideoSliceFMO: + default: + { + DEBUG_PRINT_LOW("ERROR: get_parameter: unknown param %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + + } + + return eRet; + +} +/* ====================================================================== +FUNCTION + omx_video::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + //////////////////////////////////////////////////////////////// + // Supported Config Index Type + // ============================================================= + // OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE + // OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE + // OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE + //////////////////////////////////////////////////////////////// + + if(configData == NULL) + { + DEBUG_PRINT_ERROR("ERROR: param is null"); + return OMX_ErrorBadParameter; + } + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: can't be in invalid state"); + return OMX_ErrorIncorrectStateOperation; + } + + //@todo need to validate params + switch(configIndex) + { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData); + memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate)); + break; + } + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData); + memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate)); + break; + } + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData); + memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation)); + break; + } + case QOMX_IndexConfigVideoIntraperiod: + { + DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod\n"); + QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData); + memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod)); + break; + } + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pParam = + reinterpret_cast<OMX_VIDEO_CONFIG_AVCINTRAPERIOD*>(configData); + DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoAVCIntraPeriod"); + memcpy(pParam, &m_sConfigAVCIDRPeriod, sizeof(m_sConfigAVCIDRPeriod)); + break; + } + 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) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } +#ifdef MAX_RES_1080P + if (!strncmp(paramName, "OMX.QCOM.index.param.SliceDeliveryMode", + sizeof("OMX.QCOM.index.param.SliceDeliveryMode") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode; + return OMX_ErrorNone; + } +#endif +#ifdef _ANDROID_ICS_ + if (!strncmp(paramName, "OMX.google.android.index.storeMetaDataInBuffers",sizeof("OMX.google.android.index.storeMetaDataInBuffers") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoEncodeMetaBufferMode; + return OMX_ErrorNone; + } +#endif + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_video::GetState + +DESCRIPTION + Returns the state information back to the caller.<TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_video::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + *state = m_state; + DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_video::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. <TBD> + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented\n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_video::UseInputBuffer + +DESCRIPTION + Helper function for Use buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_input_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + unsigned i = 0; + unsigned char *buf_addr = NULL; + + DEBUG_PRINT_HIGH("use_input_buffer: port = %lu appData = %p bytes = %lu buffer = %p",port,appData,bytes,buffer); + if(bytes != m_sInPortDef.nBufferSize) + { + DEBUG_PRINT_ERROR("\nERROR: use_input_buffer: Size Mismatch!! " + "bytes[%lu] != Port.nBufferSize[%lu]", bytes, m_sInPortDef.nBufferSize); + return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr) + { + input_use_buffer = true; + m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual); + if(m_inp_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr"); + return OMX_ErrorInsufficientResources; + } + + + m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); + if(m_pInput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem"); + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual); + if(m_pInput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + m_pInput_pmem[i].fd = -1; +#ifdef USE_ION + m_pInput_ion[i].ion_device_fd =-1; + m_pInput_ion[i].fd_ion_data.fd =-1; + m_pInput_ion[i].ion_alloc_data.handle=NULL; +#endif + } + + } + + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_inp_bm_count,i)) + { + break; + } + } + + if(i < m_sInPortDef.nBufferCountActual) + { + + *bufferHdr = (m_inp_mem_ptr + i); + BITMASK_SET(&m_inp_bm_count,i); + + (*bufferHdr)->pBuffer = (OMX_U8 *)buffer; + (*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); + (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION; + (*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize; + (*bufferHdr)->pAppPrivate = appData; + (*bufferHdr)->nInputPortIndex = PORT_INDEX_IN; + + if(!m_use_input_pmem) + { +#ifdef USE_ION +#ifdef _MSM8974_ + m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, + &m_pInput_ion[i].ion_alloc_data, + &m_pInput_ion[i].fd_ion_data,0); +#else + m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, + &m_pInput_ion[i].ion_alloc_data, + &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED); +#endif + if(m_pInput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd; +#else + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + if(m_pInput_pmem[i].fd == 0) + { + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pInput_pmem[i] .fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; + m_pInput_pmem[i].offset = 0; + m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pInput_pmem[i].fd,0); + + if(m_pInput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: mmap() Failed"); + close(m_pInput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + else + { + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>((*bufferHdr)->pAppPrivate); + DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset); + + if(pParam) + { + m_pInput_pmem[i].fd = pParam->pmem_fd; + m_pInput_pmem[i].offset = pParam->offset; + m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; + m_pInput_pmem[i].buffer = (unsigned char *)buffer; + DEBUG_PRINT_LOW("\n DBG:: pParam->pmem_fd = %u, pParam->offset = %u", + pParam->pmem_fd, pParam->offset); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case"); + return OMX_ErrorBadParameter; + } + } + + DEBUG_PRINT_LOW("\nuse_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p", + (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer); + if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_use_buf() Failed for i/p buf"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: All buffers are already used, invalid use_buf call for " + "index = %u", i); + eRet = OMX_ErrorInsufficientResources; + } + + return eRet; +} + + + +/* ====================================================================== +FUNCTION + omx_video::UseOutputBuffer + +DESCRIPTION + Helper function for Use buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter + unsigned char *buf_addr = NULL; +#ifdef _MSM8974_ + int align_size; +#endif + + DEBUG_PRINT_HIGH("\n Inside use_output_buffer()"); + if(bytes != m_sOutPortDef.nBufferSize) + { + DEBUG_PRINT_ERROR("\nERROR: use_output_buffer: Size Mismatch!! " + "bytes[%lu] != Port.nBufferSize[%lu]", bytes, m_sOutPortDef.nBufferSize); + return OMX_ErrorBadParameter; + } + + if(!m_out_mem_ptr) + { + output_use_buffer = true; + int nBufHdrSize = 0; + + DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_sOutPortDef.nBufferCountActual); + nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE); + /* + * Memory for output side involves the following: + * 1. Array of Buffer Headers + * 2. Bitmask array to hold the buffer allocation details + * In order to minimize the memory management entire allocation + * is done in one step. + */ + //OMX Buffer header + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + if(m_out_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_out_mem_ptr"); + return OMX_ErrorInsufficientResources; + } + + m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_pmem"); + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + if(m_out_mem_ptr) + { + bufHdr = m_out_mem_ptr; + DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr); + // Settting the entire storage nicely + for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = bytes; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = PORT_INDEX_OUT; + bufHdr->pBuffer = NULL; + bufHdr++; + m_pOutput_pmem[i].fd = -1; +#ifdef USE_ION + m_pOutput_ion[i].ion_device_fd =-1; + m_pOutput_ion[i].fd_ion_data.fd=-1; + m_pOutput_ion[i].ion_alloc_data.handle =NULL; +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%p]\n",m_out_mem_ptr); + eRet = OMX_ErrorInsufficientResources; + } + } + + for(i=0; i< m_sOutPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + break; + } + } + + if(eRet == OMX_ErrorNone) + { + if(i < m_sOutPortDef.nBufferCountActual) + { + *bufferHdr = (m_out_mem_ptr + i ); + (*bufferHdr)->pBuffer = (OMX_U8 *)buffer; + (*bufferHdr)->pAppPrivate = appData; + BITMASK_SET(&m_out_bm_count,i); + + if(!m_use_output_pmem) + { +#ifdef USE_ION +#ifdef _MSM8974_ + align_size = ((m_sOutPortDef.nBufferSize + 4095)/4096) * 4096; + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,0); +#else + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory( + m_sOutPortDef.nBufferSize, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED); +#endif + if(m_pOutput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd; +#else + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + + if(m_pOutput_pmem[i].fd == 0) + { + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pOutput_pmem[i].fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; + m_pOutput_pmem[i].offset = 0; +#ifdef _MSM8974_ + m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,align_size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pOutput_pmem[i].fd,0); +#else + 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); +#endif + if(m_pOutput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: mmap() Failed"); + close(m_pOutput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + else + { + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*>((*bufferHdr)->pAppPrivate); + DEBUG_PRINT_LOW("Inside qcom_ext pParam:0x%x )", pParam); + + if(pParam) + { + DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset); + m_pOutput_pmem[i].fd = pParam->pmem_fd; + m_pOutput_pmem[i].offset = pParam->offset; + m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; + m_pOutput_pmem[i].buffer = (unsigned char *)buffer; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case"); + return OMX_ErrorBadParameter; + } + buf_addr = (unsigned char *)buffer; + } + + DEBUG_PRINT_LOW("\n use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p", + (*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer); + if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) + { + DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for " + "index = %u", i); + eRet = OMX_ErrorInsufficientResources; + } + } + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_video::UseBuffer + +DESCRIPTION + OMX Use Buffer method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None , if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(port == PORT_INDEX_IN) + { + eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } + else if(port == PORT_INDEX_OUT) + { + eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if(eRet == OMX_ErrorNone) + { + if(allocate_done()) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + + } + else if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + m_event_port_settings_sent = false; + } + } + } + return eRet; +} + +OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + OMX_U8 *temp_buff ; + + if(bufferHdr == NULL || m_inp_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]", + bufferHdr, m_inp_mem_ptr); + return OMX_ErrorBadParameter; + } + + index = bufferHdr - ((!mUseProxyColorFormat)?m_inp_mem_ptr:meta_buffer_hdr); +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + { + if(index < m_sInPortDef.nBufferCountActual) + { + memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index])); + memset(&meta_buffers[index], 0, sizeof(meta_buffers[index])); + } + if(!mUseProxyColorFormat) + return OMX_ErrorNone; + else + c2d_conv.close(); + } +#endif + if(index < m_sInPortDef.nBufferCountActual && !mUseProxyColorFormat && + dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) + { + DEBUG_PRINT_LOW("\nERROR: dev_free_buf() Failed for i/p buf"); + } + + if(index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) + { + if(m_pInput_pmem[index].fd > 0 && input_use_buffer == false) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: i/p AllocateBuffer case"); + munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); + close (m_pInput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[index]); +#endif + m_pInput_pmem[index].fd = -1; + } + else if(m_pInput_pmem[index].fd > 0 && (input_use_buffer == true && + m_use_input_pmem == OMX_FALSE)) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: i/p Heap UseBuffer case"); + if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf"); + } + munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); + close (m_pInput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[index]); +#endif + m_pInput_pmem[index].fd = -1; + } + else + { + DEBUG_PRINT_ERROR("\n FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case"); + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + OMX_U8 *temp_buff ; + + if(bufferHdr == NULL || m_out_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]", + bufferHdr, m_out_mem_ptr); + return OMX_ErrorBadParameter; + } + index = bufferHdr - m_out_mem_ptr; + + if(index < m_sOutPortDef.nBufferCountActual && + dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) + { + DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf"); + } + + if(index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem) + { + if(m_pOutput_pmem[index].fd > 0 && output_use_buffer == false ) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: o/p AllocateBuffer case"); + munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size); + close (m_pOutput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[index]); +#endif + m_pOutput_pmem[index].fd = -1; + } + else if( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true + && m_use_output_pmem == OMX_FALSE)) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: o/p Heap UseBuffer case"); + if(dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) + { + DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf"); + } + munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size); + close (m_pOutput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[index]); +#endif + m_pOutput_pmem[index].fd = -1; + } + else + { + DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case"); + } + } + return OMX_ErrorNone; +} +#ifdef _ANDROID_ICS_ +OMX_ERRORTYPE omx_video::allocate_input_meta_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_PTR appData, + OMX_U32 bytes) +{ + unsigned index = 0; + if(!bufferHdr || bytes != sizeof(encoder_media_buffer_type)) + { + DEBUG_PRINT_ERROR("wrong params allocate_input_meta_buffer Hdr %p len %lu", + bufferHdr,bytes); + return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr && !mUseProxyColorFormat) + m_inp_mem_ptr = meta_buffer_hdr; + for(index = 0;((index < m_sInPortDef.nBufferCountActual) && + meta_buffer_hdr[index].pBuffer); index++); + if(index == m_sInPortDef.nBufferCountActual) + { + DEBUG_PRINT_ERROR("All buffers are allocated input_meta_buffer"); + return OMX_ErrorBadParameter; + } + if(mUseProxyColorFormat){ + if(opaque_buffer_hdr[index]){ + DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr"); + return OMX_ErrorBadParameter; + } + if(allocate_input_buffer(hComp,&opaque_buffer_hdr[index], + PORT_INDEX_IN,appData,m_sInPortDef.nBufferSize) != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr"); + return OMX_ErrorBadParameter; + } + } + BITMASK_SET(&m_inp_bm_count,index); + *bufferHdr = &meta_buffer_hdr[index]; + memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index])); + meta_buffer_hdr[index].nSize = sizeof(meta_buffer_hdr[index]); + meta_buffer_hdr[index].nAllocLen = bytes; + meta_buffer_hdr[index].nVersion.nVersion = OMX_SPEC_VERSION; + meta_buffer_hdr[index].nInputPortIndex = PORT_INDEX_IN; + meta_buffer_hdr[index].pBuffer = (OMX_U8*)&meta_buffers[index]; + meta_buffer_hdr[index].pAppPrivate = appData; + if(mUseProxyColorFormat) { + m_opq_pmem_q.insert_entry((unsigned int)opaque_buffer_hdr[index],0,0); + DEBUG_PRINT_HIGH("\n opaque_buffer_hdr insert %p", opaque_buffer_hdr[index]); + } + return OMX_ErrorNone; +} +#endif +/* ====================================================================== +FUNCTION + omx_venc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::allocate_input_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned i = 0; + + DEBUG_PRINT_HIGH("\n allocate_input_buffer()::"); + if(bytes != m_sInPortDef.nBufferSize) + { + DEBUG_PRINT_ERROR("\nERROR: Buffer size mismatch error: bytes[%lu] != nBufferSize[%lu]\n", + bytes, m_sInPortDef.nBufferSize); + return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr) + { + DEBUG_PRINT_HIGH("%s: size = %lu, actual cnt %lu", __FUNCTION__, + m_sInPortDef.nBufferSize, m_sInPortDef.nBufferCountActual); + m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual); + if(m_inp_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr"); + return OMX_ErrorInsufficientResources; + } + + m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); + + if(m_pInput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem"); + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual); + if(m_pInput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + m_pInput_pmem[i].fd = -1; +#ifdef USE_ION + m_pInput_ion[i].ion_device_fd =-1; + m_pInput_ion[i].fd_ion_data.fd =-1; + m_pInput_ion[i].ion_alloc_data.handle=NULL; +#endif + } + } + + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_inp_bm_count,i)) + { + break; + } + } + if(i < m_sInPortDef.nBufferCountActual) + { + + *bufferHdr = (m_inp_mem_ptr + i); + (*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); + (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION; + (*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize; + (*bufferHdr)->pAppPrivate = appData; + (*bufferHdr)->nInputPortIndex = PORT_INDEX_IN; + +#ifdef USE_ION +#ifdef _MSM8974_ + m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, + &m_pInput_ion[i].ion_alloc_data, + &m_pInput_ion[i].fd_ion_data,0); +#else + m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, + &m_pInput_ion[i].ion_alloc_data, + &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED); +#endif + if(m_pInput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + + m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd; +#else + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + + if(m_pInput_pmem[i].fd == 0) + { + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pInput_pmem[i].fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed\n"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; + m_pInput_pmem[i].offset = 0; + + m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pInput_pmem[i].fd,0); + if(m_pInput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: mmap FAILED= %d\n", errno); + close(m_pInput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + + (*bufferHdr)->pBuffer = (OMX_U8 *)m_pInput_pmem[i].buffer; + DEBUG_PRINT_LOW("\n Virtual address in allocate buffer is %p", m_pInput_pmem[i].buffer); + BITMASK_SET(&m_inp_bm_count,i); + //here change the I/P param here from buf_adr to pmem + if(!mUseProxyColorFormat && (dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true)) + { + DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for i/p buf\n"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: All i/p buffers are allocated, invalid allocate buf call" + "for index [%d]\n", i); + eRet = OMX_ErrorInsufficientResources; + } + + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_venc::AllocateOutputBuffer + +DESCRIPTION + Helper fn for AllocateBuffer in the output pin + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything went well. + +========================================================================== */ +OMX_ERRORTYPE omx_video::allocate_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter +#ifdef _MSM8974_ + int align_size; +#endif + DEBUG_PRINT_HIGH("\n allocate_output_buffer()for %lu bytes", bytes); + if(!m_out_mem_ptr) + { + int nBufHdrSize = 0; + DEBUG_PRINT_HIGH("%s: size = %lu, actual cnt %lu", __FUNCTION__, + m_sOutPortDef.nBufferSize, m_sOutPortDef.nBufferCountActual); + nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE); + + /* + * Memory for output side involves the following: + * 1. Array of Buffer Headers + * 2. Bitmask array to hold the buffer allocation details + * In order to minimize the memory management entire allocation + * is done in one step. + */ + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + +#ifdef USE_ION + m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pOutput_pmem = (struct pmem *) calloc(sizeof(struct pmem), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_pmem"); + return OMX_ErrorInsufficientResources; + } + if(m_out_mem_ptr && m_pOutput_pmem) + { + bufHdr = m_out_mem_ptr; + + for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + // Set the values when we determine the right HxW param + bufHdr->nAllocLen = bytes; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = PORT_INDEX_OUT; + bufHdr->pBuffer = NULL; + bufHdr++; + m_pOutput_pmem[i].fd = -1; +#ifdef USE_ION + m_pOutput_ion[i].ion_device_fd =-1; + m_pOutput_ion[i].fd_ion_data.fd=-1; + m_pOutput_ion[i].ion_alloc_data.handle =NULL; +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem"); + eRet = OMX_ErrorInsufficientResources; + } + } + + DEBUG_PRINT_HIGH("\n actual cnt = %lu", m_sOutPortDef.nBufferCountActual); + for(i=0; i< m_sOutPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i); + break; + } + } + if(eRet == OMX_ErrorNone) + { + if(i < m_sOutPortDef.nBufferCountActual) + { +#ifdef USE_ION +#ifdef _MSM8974_ + align_size = ((m_sOutPortDef.nBufferSize + 4095)/4096) * 4096; + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,0); +#else + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sOutPortDef.nBufferSize, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED); +#endif + if(m_pOutput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + + m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd; +#else + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + if(m_pOutput_pmem[i].fd == 0) + { + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pOutput_pmem[i].fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() failed"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; + m_pOutput_pmem[i].offset = 0; +#ifdef _MSM8974_ + m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,align_size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pOutput_pmem[i].fd,0); +#else + 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); +#endif + if(m_pOutput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: MMAP_FAILED in o/p alloc buffer"); + close (m_pOutput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + + *bufferHdr = (m_out_mem_ptr + i ); + (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer; + (*bufferHdr)->pAppPrivate = appData; + + BITMASK_SET(&m_out_bm_count,i); + + if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for o/p buf"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: All o/p buffers are allocated, invalid allocate buf call" + "for index [%d] actual: %lu\n", i, m_sOutPortDef.nBufferCountActual); + } + } + + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_video::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + DEBUG_PRINT_LOW("\n Allocate buffer of size = %d on port %d \n", bytes, (int)port); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + // What if the client calls again. + if(port == PORT_INDEX_IN) + { +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + eRet = allocate_input_meta_buffer(hComp,bufferHdr,appData,bytes); + else +#endif + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } + else if(port == PORT_INDEX_OUT) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); + if(eRet == OMX_ErrorNone) + { + if(allocate_done()) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + m_event_port_settings_sent = false; + } + } + } + DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet); + return eRet; +} + + +// Free Buffer - API call +/* ====================================================================== +FUNCTION + omx_video::FreeBuffer + +DESCRIPTION + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int nPortIndex; + + DEBUG_PRINT_LOW("In for encoder free_buffer \n"); + + if(m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n"); + } + else if((m_sInPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_IN)|| + (m_sOutPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_OUT)) + { + DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port); + } + else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,ports need to be disabled\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + return eRet; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,port lost Buffers\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + + if(port == PORT_INDEX_IN) + { + // check if the buffer is valid + nPortIndex = buffer - ((!mUseProxyColorFormat)?m_inp_mem_ptr:meta_buffer_hdr); + + DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d, actual cnt %d \n", + nPortIndex, m_sInPortDef.nBufferCountActual); + if(nPortIndex < m_sInPortDef.nBufferCountActual) + { + // Clear the bit associated with it. + BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); + free_input_buffer (buffer); + m_sInPortDef.bPopulated = OMX_FALSE; + + /*Free the Buffer Header*/ + if(release_input_done() +#ifdef _ANDROID_ICS_ + && !meta_mode_enable +#endif + ) + { + input_use_buffer = false; + if(m_inp_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr\n"); + free (m_inp_mem_ptr); + m_inp_mem_ptr = NULL; + } + if(m_pInput_pmem) + { + DEBUG_PRINT_LOW("Freeing m_pInput_pmem\n"); + free(m_pInput_pmem); + m_pInput_pmem = NULL; + } +#ifdef USE_ION + if(m_pInput_ion) + { + DEBUG_PRINT_LOW("Freeing m_pInput_ion\n"); + free(m_pInput_ion); + m_pInput_ion = NULL; + } +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_input_done()) + { + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_event(OMX_CommandPortDisable, + PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + } + else if(port == PORT_INDEX_OUT) + { + // check if the buffer is valid + nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr; + + DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d, actual cnt %d \n", + nPortIndex, m_sOutPortDef.nBufferCountActual); + if(nPortIndex < m_sOutPortDef.nBufferCountActual) + { + // Clear the bit associated with it. + BITMASK_CLEAR(&m_out_bm_count,nPortIndex); + m_sOutPortDef.bPopulated = OMX_FALSE; + free_output_buffer (buffer); + + if(release_output_done()) + { + output_use_buffer = false; + if(m_out_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing m_out_mem_ptr\n"); + free (m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + if(m_pOutput_pmem) + { + DEBUG_PRINT_LOW("Freeing m_pOutput_pmem\n"); + free(m_pOutput_pmem); + m_pOutput_pmem = NULL; + } +#ifdef USE_ION + if(m_pOutput_ion) + { + DEBUG_PRINT_LOW("Freeing m_pOutput_ion\n"); + free(m_pOutput_ion); + m_pOutput_ion = NULL; + } +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_output_done() ) + { + DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n"); + + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + post_event(OMX_CommandPortDisable, + PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + + } + } + else + { + eRet = OMX_ErrorBadPortIndex; + } + if((eRet == OMX_ErrorNone) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if(release_done()) + { + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("ERROR: dev_stop() FAILED\n"); + eRet = OMX_ErrorHardware; + } + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + post_event(OMX_CommandStateSet, OMX_StateLoaded, + OMX_COMPONENT_GENERATE_EVENT); + } else { + DEBUG_PRINT_ERROR("in free buffer, release not done, need to free more buffers input 0x%x output 0x%x", + m_out_bm_count, m_inp_bm_count); + } + } + + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_video::EmptyThisBuffer + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE ret1 = OMX_ErrorNone; + unsigned int nBufferIndex ; + + DEBUG_PRINT_LOW("\n ETB: buffer = %p, buffer->pBuffer[%p]\n", buffer, buffer->pBuffer); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) + { + DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> buffer is null or buffer size is invalid"); + return OMX_ErrorBadParameter; + } + + if(buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> OMX Version Invalid"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN) + { + DEBUG_PRINT_ERROR("\nERROR: Bad port index to call empty_this_buffer"); + return OMX_ErrorBadPortIndex; + } + if(!m_sInPortDef.bEnabled) + { + DEBUG_PRINT_ERROR("\nERROR: Cannot call empty_this_buffer while I/P port is disabled"); + return OMX_ErrorIncorrectStateOperation; + } + + nBufferIndex = buffer - ((!mUseProxyColorFormat)?m_inp_mem_ptr:meta_buffer_hdr); + + if(nBufferIndex > m_sInPortDef.nBufferCountActual ) + { + DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]\n", nBufferIndex); + return OMX_ErrorBadParameter; + } + + m_etb_count++; + DEBUG_PRINT_LOW("\n DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp); + post_event ((unsigned)hComp,(unsigned)buffer,m_input_msg_id); + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_video::empty_this_buffer_proxy + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_U8 *pmem_data_buf = NULL; + int push_cnt = 0; + unsigned nBufIndex = 0, nBufIndex_meta = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + encoder_media_buffer_type *media_buffer; + +#ifdef _MSM8974_ + int fd = 0; +#endif + 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); + nBufIndex_meta = buffer - meta_buffer_hdr; + media_buffer = (encoder_media_buffer_type *)meta_buffer_hdr[nBufIndex].pBuffer; + if(nBufIndex >= m_sInPortDef.nBufferCountActual && + nBufIndex_meta >= m_sInPortDef.nBufferCountActual) + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid bufindex = %u\n", nBufIndex); + return OMX_ErrorBadParameter; + } + pending_input_buffers++; + if(input_flush_progress == true) + { + post_event ((unsigned int)buffer,0, + OMX_COMPONENT_GENERATE_EBD); + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Input flush in progress"); + return OMX_ErrorNone; + } +#ifdef _MSM8974_ + if(!meta_mode_enable || + (media_buffer && media_buffer->buffer_type == kMetadataBufferTypeGrallocSource)) { + fd = m_pInput_pmem[nBufIndex].fd; + } +#endif +#ifdef _ANDROID_ICS_ + if(meta_mode_enable && !mUseProxyColorFormat) + { + bool met_error = false; + if(media_buffer) + { + if (media_buffer->buffer_type != kMetadataBufferTypeCameraSource && + media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) + met_error = true; + else { + if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource) + { + if(media_buffer->meta_handle == NULL) + met_error = true; + else if((media_buffer->meta_handle->numFds != 1 && + media_buffer->meta_handle->numInts != 2)) + met_error = true; + } + } + } else + met_error = true; + if(met_error) + { + DEBUG_PRINT_ERROR("\nERROR: Unkown source/metahandle in ETB call"); + post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorBadParameter; + } + struct pmem Input_pmem_info; + if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource) + { + Input_pmem_info.buffer = media_buffer; + Input_pmem_info.fd = media_buffer->meta_handle->data[0]; +#ifdef _MSM8974_ + fd = Input_pmem_info.fd; +#endif + Input_pmem_info.offset = media_buffer->meta_handle->data[1]; + Input_pmem_info.size = media_buffer->meta_handle->data[2]; + DEBUG_PRINT_LOW("ETB fd = %d, offset = %d, size = %d",Input_pmem_info.fd, + Input_pmem_info.offset, + Input_pmem_info.size); + } else { + private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle; + Input_pmem_info.buffer = media_buffer; + Input_pmem_info.fd = handle->fd; +#ifdef _MSM8974_ + fd = Input_pmem_info.fd; +#endif + Input_pmem_info.offset = 0; + Input_pmem_info.size = handle->size; + } + if(dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) { + DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf"); + post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorBadParameter; + } + } + else if(input_use_buffer && !m_use_input_pmem) +#else + if(input_use_buffer && !m_use_input_pmem) +#endif + { + DEBUG_PRINT_LOW("\n Heap UseBuffer case, so memcpy the data"); + pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer; + memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset), + buffer->nFilledLen); + DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf"); + } +#ifdef _MSM8974_ + if(dev_empty_buf(buffer, pmem_data_buf,nBufIndex,fd) != true) +#else + if(dev_empty_buf(buffer, pmem_data_buf,0,0) != true) +#endif + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: dev_empty_buf failed"); +#ifdef _ANDROID_ICS_ + omx_release_meta_buffer(buffer); +#endif + post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD); + /*Generate an async error and move to invalid state*/ + pending_input_buffers--; + return OMX_ErrorBadParameter; + } + return ret; +} + +/* ====================================================================== +FUNCTION + omx_video::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + DEBUG_PRINT_LOW("\n FTB: buffer->pBuffer[%p]\n", buffer->pBuffer); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size\n"); + return OMX_ErrorBadParameter; + } + + if(buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index\n"); + return OMX_ErrorBadPortIndex; + } + + if(!m_sOutPortDef.bEnabled) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled\n"); + return OMX_ErrorIncorrectStateOperation; + } + + post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_video::fill_this_buffer_proxy + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::fill_this_buffer_proxy( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) +{ + OMX_U8 *pmem_data_buf = NULL; + OMX_ERRORTYPE nRet = OMX_ErrorNone; + + DEBUG_PRINT_LOW("\n FTBProxy: bufferAdd->pBuffer[%p]\n", bufferAdd->pBuffer); + + if(bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= m_sOutPortDef.nBufferCountActual) ) + { + DEBUG_PRINT_ERROR("\nERROR: FTBProxy: Invalid i/p params\n"); + return OMX_ErrorBadParameter; + } + + pending_output_buffers++; + /*Return back the output buffer to client*/ + if( m_sOutPortDef.bEnabled != OMX_TRUE || output_flush_progress == true) + { + DEBUG_PRINT_LOW("\n o/p port is Disabled or Flush in Progress"); + post_event ((unsigned int)bufferAdd,0, + OMX_COMPONENT_GENERATE_FBD); + return OMX_ErrorNone; + } + + if(output_use_buffer && !m_use_output_pmem) + { + DEBUG_PRINT_LOW("\n Heap UseBuffer case"); + pmem_data_buf = (OMX_U8 *)m_pOutput_pmem[bufferAdd - m_out_mem_ptr].buffer; + } + + if(dev_fill_buf(bufferAdd, pmem_data_buf,(bufferAdd - m_out_mem_ptr),m_pOutput_pmem[bufferAdd - m_out_mem_ptr].fd) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_fill_buf() Failed"); + post_event ((unsigned int)bufferAdd,0,OMX_COMPONENT_GENERATE_FBD); + pending_output_buffers--; + return OMX_ErrorBadParameter; + } + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_video::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + + m_pCallbacks = *callbacks; + DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_pCallbacks.EmptyBufferDone,\ + m_pCallbacks.EventHandler,m_pCallbacks.FillBufferDone); + m_app_data = appData; + return OMX_ErrorNotImplemented; +} + + +/* ====================================================================== +FUNCTION + omx_venc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation <TBD>. + +PARAMETERS + <TBD>. + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + DEBUG_PRINT_ERROR("ERROR: use_EGL_image: Not Implemented \n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_venc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } +#ifdef _MSM8974_ + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } +#endif + 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) +{ +#ifdef _MSM8974_ + int index = buffer - m_out_mem_ptr; +#endif + DEBUG_PRINT_LOW("fill_buffer_done: buffer->pBuffer[%p], flags=0x%x size = %d", + buffer->pBuffer, buffer->nFlags,buffer->nFilledLen); + if(buffer == NULL || ((buffer - m_out_mem_ptr) > m_sOutPortDef.nBufferCountActual)) + { + return OMX_ErrorBadParameter; + } + + pending_output_buffers--; + + extra_data_handle.create_extra_data(buffer); +#ifndef _MSM8974_ + if(buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { + DEBUG_PRINT_LOW("parsing extradata"); + extra_data_handle.parse_extra_data(buffer); + } +#endif + /* For use buffer we need to copy the data */ + if(m_pCallbacks.FillBufferDone) + { + if(buffer->nFilledLen > 0) + { + m_fbd_count++; + +#ifdef OUTPUT_BUFFER_LOG + if(outputBufferFile1) + { + fwrite((const char *)buffer->pBuffer, buffer->nFilledLen, 1, outputBufferFile1); + } +#endif + } +#ifdef _MSM8974_ + if(buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { + if(!dev_handle_extradata((void *)buffer, index)) + DEBUG_PRINT_ERROR("Failed to parse extradata\n"); + } +#endif + m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer); + } + else + { + return OMX_ErrorBadParameter; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + int buffer_index = -1; + int buffer_index_meta = -1; + + buffer_index = (buffer - m_inp_mem_ptr); + buffer_index_meta = (buffer - meta_buffer_hdr); + DEBUG_PRINT_LOW("\n empty_buffer_done: buffer[%p]", buffer); + if(buffer == NULL || + ((buffer_index > m_sInPortDef.nBufferCountActual) && + (buffer_index_meta > m_sInPortDef.nBufferCountActual))) + { + DEBUG_PRINT_ERROR("\n ERROR in empty_buffer_done due to index buffer"); + return OMX_ErrorBadParameter; + } + + pending_input_buffers--; + + if(mUseProxyColorFormat && (buffer_index < m_sInPortDef.nBufferCountActual)) { + if(!pdest_frame) { + pdest_frame = buffer; + DEBUG_PRINT_LOW("\n empty_buffer_done pdest_frame address is %p",pdest_frame); + return push_input_buffer(hComp); + + } else { + DEBUG_PRINT_LOW("\n empty_buffer_done insert address is %p",buffer); + if (!m_opq_pmem_q.insert_entry((unsigned int)buffer, 0, 0)) { + DEBUG_PRINT_ERROR("\n empty_buffer_done: pmem queue is full"); + return OMX_ErrorBadParameter; + } + } + } else if(m_pCallbacks.EmptyBufferDone) { + m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, buffer); + } + return OMX_ErrorNone; +} + +void omx_video::complete_pending_buffer_done_cbs() +{ + unsigned p1; + unsigned p2; + unsigned ident; + omx_cmd_queue tmp_q, pending_bd_q; + pthread_mutex_lock(&m_lock); + // pop all pending GENERATE FDB from ftb queue + while (m_ftb_q.m_size) + { + m_ftb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_FBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to ftb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_ftb_q.insert_entry(p1,p2,ident); + } + // pop all pending GENERATE EDB from etb queue + while (m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_EBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to etb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_etb_q.insert_entry(p1,p2,ident); + } + pthread_mutex_unlock(&m_lock); + // process all pending buffer dones + while(pending_bd_q.m_size) + { + pending_bd_q.pop_entry(&p1,&p2,&ident); + switch(ident) + { + case OMX_COMPONENT_GENERATE_EBD: + if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); + omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FBD: + if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); + omx_report_error (); + } + break; + } + } +} + +#ifdef MAX_RES_720P +OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 1) { + if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d\n", + profileLevelType->eProfile,profileLevelType->eLevel); + return eRet; +} +#endif + +#ifdef MAX_RES_1080P +OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 1) { + if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) + { +#ifdef _MSM8974_ + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; + + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; + } + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } +#else + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } +#endif + } + else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %lu\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore\n"); + eRet = OMX_ErrorNoMore; + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %lu\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%lu, Level:%lu\n", + profileLevelType->eProfile,profileLevelType->eLevel); + return eRet; +} +#endif + +#ifdef USE_ION +int alloc_map_ion_memory(int size,struct ion_allocation_data *alloc_data, + struct ion_fd_data *fd_data,int flag) +{ + struct venc_ion buf_ion_info; + int ion_device_fd =-1,rc=0,ion_dev_flags = 0; + if (size <=0 || !alloc_data || !fd_data) { + DEBUG_PRINT_ERROR("\nInvalid input to alloc_map_ion_memory"); + return -EINVAL; + } + + ion_dev_flags = O_RDONLY; + ion_device_fd = open (MEM_DEVICE,ion_dev_flags); + if(ion_device_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ION Device open() Failed"); + return ion_device_fd; + } + alloc_data->len = size; + alloc_data->align = 4096; + alloc_data->flags = flag; +#ifdef MAX_RES_720P + alloc_data->len = (size + (alloc_data->align - 1)) & ~(alloc_data->align - 1); + alloc_data->heap_mask = ION_HEAP(MEM_HEAP_ID); +#else + alloc_data->heap_mask = (ION_HEAP(MEM_HEAP_ID) | + ION_HEAP(ION_IOMMU_HEAP_ID)); +#endif + rc = ioctl(ion_device_fd,ION_IOC_ALLOC,alloc_data); + if(rc || !alloc_data->handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + alloc_data->handle =NULL; + close(ion_device_fd); + ion_device_fd = -1; + return ion_device_fd; + } + fd_data->handle = alloc_data->handle; + rc = ioctl(ion_device_fd,ION_IOC_MAP,fd_data); + if(rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + buf_ion_info.ion_alloc_data = *alloc_data; + buf_ion_info.ion_device_fd = ion_device_fd; + buf_ion_info.fd_ion_data = *fd_data; + free_ion_memory(&buf_ion_info); + fd_data->fd =-1; + ion_device_fd =-1; + } + return ion_device_fd; +} + +void free_ion_memory(struct venc_ion *buf_ion_info) +{ + if (!buf_ion_info) { + DEBUG_PRINT_ERROR("\n Invalid input to free_ion_memory"); + return; + } + if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, + &buf_ion_info->ion_alloc_data.handle)) { + DEBUG_PRINT_ERROR("\n ION free failed "); + return; + } + close(buf_ion_info->ion_device_fd); + buf_ion_info->ion_alloc_data.handle = NULL; + buf_ion_info->ion_device_fd = -1; + buf_ion_info->fd_ion_data.fd = -1; +} +#endif + +#ifdef _ANDROID_ICS_ +void omx_video::omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer) +{ + if(buffer && meta_mode_enable) + { + encoder_media_buffer_type *media_ptr; + struct pmem Input_pmem; + unsigned int index_pmem = 0; + bool meta_error = false; + + index_pmem = (buffer - m_inp_mem_ptr); + if(mUseProxyColorFormat && + (index_pmem < m_sInPortDef.nBufferCountActual)) { + if(!dev_free_buf((&m_pInput_pmem[index_pmem]),PORT_INDEX_IN)){ + DEBUG_PRINT_ERROR("\n omx_release_meta_buffer dev free failed"); + } + } else { + media_ptr = (encoder_media_buffer_type *) buffer->pBuffer; + if(media_ptr && media_ptr->meta_handle) + { + if(media_ptr->buffer_type == kMetadataBufferTypeCameraSource && + media_ptr->meta_handle->numFds == 1 && + media_ptr->meta_handle->numInts == 2) { + Input_pmem.fd = media_ptr->meta_handle->data[0]; + Input_pmem.buffer = media_ptr; + Input_pmem.size = media_ptr->meta_handle->data[2]; + Input_pmem.offset = media_ptr->meta_handle->data[1]; + DEBUG_PRINT_LOW("EBD fd = %d, offset = %d, size = %d",Input_pmem.fd, + Input_pmem.offset, + Input_pmem.size); + } else if(media_ptr->buffer_type == kMetadataBufferTypeGrallocSource) { + private_handle_t *handle = (private_handle_t *)media_ptr->meta_handle; + Input_pmem.buffer = media_ptr; + Input_pmem.fd = handle->fd; + Input_pmem.offset = 0; + Input_pmem.size = handle->size; + } else { + meta_error = true; + DEBUG_PRINT_ERROR(" Meta Error set in EBD"); + } + if(!meta_error) + meta_error = !dev_free_buf(&Input_pmem,PORT_INDEX_IN); + if(meta_error) + { + DEBUG_PRINT_ERROR(" Warning dev_free_buf failed flush value is %d", + input_flush_progress); + } + } + } + } +} +#endif +omx_video::omx_c2d_conv::omx_c2d_conv() +{ + c2dcc = NULL; + mLibHandle = NULL; + mConvertOpen = NULL; + mConvertClose = NULL; + src_format = NV12_128m; + pthread_mutex_init(&c_lock, NULL); +} + +bool omx_video::omx_c2d_conv::init() { + bool status = true; + if(mLibHandle || mConvertOpen || mConvertClose) { + DEBUG_PRINT_ERROR("\n omx_c2d_conv::init called twice"); + status = false; + } + if(status) { + mLibHandle = dlopen("libc2dcolorconvert.so", RTLD_LAZY); + if(mLibHandle){ + mConvertOpen = (createC2DColorConverter_t *) + dlsym(mLibHandle,"createC2DColorConverter"); + mConvertClose = (destroyC2DColorConverter_t *) + dlsym(mLibHandle,"destroyC2DColorConverter"); + if(!mConvertOpen || !mConvertClose) + status = false; + } else + status = false; + } + if(!status && mLibHandle){ + dlclose(mLibHandle); + mLibHandle = NULL; + mConvertOpen = NULL; + mConvertClose = NULL; + } + return status; +} + +bool omx_video::omx_c2d_conv::convert(int src_fd, void *src_base, void *src_viraddr, + int dest_fd, void *dest_base, void *dest_viraddr) +{ + int result; + if(!src_viraddr || !dest_viraddr || !c2dcc || !src_base || !dest_base){ + DEBUG_PRINT_ERROR("\n Invalid arguments omx_c2d_conv::convert"); + return false; + } + pthread_mutex_lock(&c_lock); + result = c2dcc->convertC2D(src_fd, src_base, src_viraddr, + dest_fd, dest_base, dest_viraddr); + pthread_mutex_unlock(&c_lock); + DEBUG_PRINT_LOW("\n Color convert status %d",result); + return ((result < 0)?false:true); +} + +bool omx_video::omx_c2d_conv::open(unsigned int height,unsigned int width, + ColorConvertFormat src, ColorConvertFormat dest,unsigned int src_stride) +{ + bool status = false; + pthread_mutex_lock(&c_lock); + if(!c2dcc) { + c2dcc = mConvertOpen(width, height, width, height, + src,dest,0,src_stride); + if(c2dcc) { + src_format = src; + status = true; + } else + DEBUG_PRINT_ERROR("\n mConvertOpen failed"); + } + pthread_mutex_unlock(&c_lock); + return status; +} + +void omx_video::omx_c2d_conv::close() +{ + if(mLibHandle) { + pthread_mutex_lock(&c_lock); + if(mConvertClose && c2dcc) + mConvertClose(c2dcc); + pthread_mutex_unlock(&c_lock); + c2dcc = NULL; + } +} +omx_video::omx_c2d_conv::~omx_c2d_conv() +{ + DEBUG_PRINT_ERROR("\n Destroy C2D instance"); + if(mLibHandle) { + if(mConvertClose && c2dcc) { + pthread_mutex_lock(&c_lock); + mConvertClose(c2dcc); + pthread_mutex_unlock(&c_lock); + } + dlclose(mLibHandle); + } + c2dcc = NULL; + mLibHandle = NULL; + mConvertOpen = NULL; + mConvertClose = NULL; + pthread_mutex_destroy(&c_lock); +} + +int omx_video::omx_c2d_conv::get_src_format() +{ + int format = -1; + if(src_format == NV12_128m) { + format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; + } else if(src_format == RGBA8888) { + format = HAL_PIXEL_FORMAT_RGBA_8888; + } + return format; +} + +bool omx_video::omx_c2d_conv::get_buffer_size(int port,unsigned int &buf_size) +{ + int cret = 0; + bool ret = false; + C2DBuffReq bufferreq; + if(c2dcc){ + bufferreq.size = 0; + pthread_mutex_lock(&c_lock); + cret = c2dcc->getBuffReq(port,&bufferreq); + pthread_mutex_unlock(&c_lock); + DEBUG_PRINT_LOW("\n Status of getbuffer is %d", cret); + ret = (cret)?false:true; + buf_size = bufferreq.size; + } + return ret; +} + +OMX_ERRORTYPE omx_video::empty_this_buffer_opaque(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + unsigned nBufIndex = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + encoder_media_buffer_type *media_buffer; + DEBUG_PRINT_LOW("\n ETBProxyOpaque: buffer[%p]\n", buffer); + + if(buffer == NULL) { + DEBUG_PRINT_ERROR("\nERROR: ETBProxyA: Invalid buffer[%p]\n",buffer); + return OMX_ErrorBadParameter; + } + nBufIndex = buffer - meta_buffer_hdr; + if(nBufIndex >= m_sInPortDef.nBufferCountActual) { + DEBUG_PRINT_ERROR("\nERROR: ETBProxyA: Invalid bufindex = %u\n", + nBufIndex); + return OMX_ErrorBadParameter; + } + media_buffer = (encoder_media_buffer_type *)buffer->pBuffer; + private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle; + /*Enable following code once private handle color format is + updated correctly*/ + + if(c2d_opened && handle->format != c2d_conv.get_src_format()) { + c2d_conv.close(); + c2d_opened = false; + } + if (!c2d_opened) { + if (handle->format == HAL_PIXEL_FORMAT_RGBA_8888) { + DEBUG_PRINT_ERROR("\n open Color conv for RGBA888 W: %d, H: %d\n", + m_sInPortDef.format.video.nFrameWidth, + m_sInPortDef.format.video.nFrameHeight); + if(!c2d_conv.open(m_sInPortDef.format.video.nFrameHeight, + m_sInPortDef.format.video.nFrameWidth,RGBA8888,NV12_128m,handle->width)){ + m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); + DEBUG_PRINT_ERROR("\n Color conv open failed"); + return OMX_ErrorBadParameter; + } + c2d_opened = true; +#ifdef _MSM8974_ + if(!dev_set_format(handle->format)) + DEBUG_PRINT_ERROR("cannot set color format for RGBA8888\n"); +#endif + } else if(handle->format != HAL_PIXEL_FORMAT_NV12_ENCODEABLE) { + DEBUG_PRINT_ERROR("\n Incorrect color format"); + m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); + return OMX_ErrorBadParameter; + } + } + if(input_flush_progress == true) + { + m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); + DEBUG_PRINT_ERROR("\nERROR: ETBProxyA: Input flush in progress"); + return OMX_ErrorNone; + } + + if(!psource_frame) { + psource_frame = buffer; + ret = push_input_buffer(hComp); + } else { + if (!m_opq_meta_q.insert_entry((unsigned)buffer,0,0)) { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Queue is full"); + ret = OMX_ErrorBadParameter; + } + } + if(ret != OMX_ErrorNone) { + m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); + DEBUG_PRINT_LOW("\nERROR: ETBOpaque failed:"); + } + return ret; +} + +OMX_ERRORTYPE omx_video::queue_meta_buffer(OMX_HANDLETYPE hComp, + struct pmem &Input_pmem_info) { + + OMX_ERRORTYPE ret = OMX_ErrorNone; + unsigned address = 0,p2,id; + + DEBUG_PRINT_LOW("\n In queue Meta Buffer"); + if(!psource_frame || !pdest_frame) { + DEBUG_PRINT_ERROR("\n convert_queue_buffer invalid params"); + return OMX_ErrorBadParameter; + } + + if(dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) { + DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf"); + post_event ((unsigned int)psource_frame,0,OMX_COMPONENT_GENERATE_EBD); + ret = OMX_ErrorBadParameter; + } + + if(ret == OMX_ErrorNone) + ret = empty_this_buffer_proxy(hComp,psource_frame); + + if(ret == OMX_ErrorNone) { + psource_frame = NULL; + if(!psource_frame && m_opq_meta_q.m_size) { + m_opq_meta_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE* ) address; + } + } + return ret; +} + +OMX_ERRORTYPE omx_video::convert_queue_buffer(OMX_HANDLETYPE hComp, + struct pmem &Input_pmem_info,unsigned &index){ + + unsigned char *uva; + OMX_ERRORTYPE ret = OMX_ErrorNone; + unsigned address = 0,p2,id; + + DEBUG_PRINT_LOW("\n In Convert and queue Meta Buffer"); + if(!psource_frame || !pdest_frame) { + DEBUG_PRINT_ERROR("\n convert_queue_buffer invalid params"); + return OMX_ErrorBadParameter; + } + + if(!psource_frame->nFilledLen){ + pdest_frame->nOffset = 0; + pdest_frame->nFilledLen = 0; + pdest_frame->nTimeStamp = psource_frame->nTimeStamp; + pdest_frame->nFlags = psource_frame->nFlags; + DEBUG_PRINT_LOW("\n Buffer header %p Filled len size %d", + pdest_frame,pdest_frame->nFilledLen); + } else { + uva = (unsigned char *)mmap(NULL, Input_pmem_info.size, + PROT_READ|PROT_WRITE, + MAP_SHARED,Input_pmem_info.fd,0); + if(uva == MAP_FAILED) { + ret = OMX_ErrorBadParameter; + } else { + if(!c2d_conv.convert(Input_pmem_info.fd, uva, uva, + m_pInput_pmem[index].fd, pdest_frame->pBuffer, pdest_frame->pBuffer)) { + DEBUG_PRINT_ERROR("\n Color Conversion failed"); + ret = OMX_ErrorBadParameter; + } else { + unsigned int buf_size = 0; + if (!c2d_conv.get_buffer_size(C2D_OUTPUT,buf_size)) + ret = OMX_ErrorBadParameter; + else { + pdest_frame->nOffset = 0; + pdest_frame->nFilledLen = buf_size; + pdest_frame->nTimeStamp = psource_frame->nTimeStamp; + pdest_frame->nFlags = psource_frame->nFlags; + DEBUG_PRINT_LOW("\n Buffer header %p Filled len size %d", + pdest_frame,pdest_frame->nFilledLen); + } + } + munmap(uva,Input_pmem_info.size); + } + } + if(dev_use_buf(&m_pInput_pmem[index],PORT_INDEX_IN,0) != true) { + DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf"); + post_event ((unsigned int)pdest_frame,0,OMX_COMPONENT_GENERATE_EBD); + ret = OMX_ErrorBadParameter; + } + if(ret == OMX_ErrorNone) + ret = empty_this_buffer_proxy(hComp,pdest_frame); + if(ret == OMX_ErrorNone) { + m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, psource_frame); + psource_frame = NULL; + pdest_frame = NULL; + if(!psource_frame && m_opq_meta_q.m_size) { + m_opq_meta_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE* ) address; + } + if(!pdest_frame && m_opq_pmem_q.m_size) { + m_opq_pmem_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE* ) address; + DEBUG_PRINT_LOW("\n pdest_frame pop address is %p",pdest_frame); + } + } + return ret; +} + +OMX_ERRORTYPE omx_video::push_input_buffer(OMX_HANDLETYPE hComp) +{ + unsigned address = 0,p2,id, index = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if(!psource_frame && m_opq_meta_q.m_size) { + m_opq_meta_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE* ) address; + } + if(!pdest_frame && m_opq_pmem_q.m_size) { + m_opq_pmem_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE* ) address; + } + while(psource_frame != NULL && pdest_frame != NULL && + ret == OMX_ErrorNone) { + struct pmem Input_pmem_info; + encoder_media_buffer_type *media_buffer; + index = pdest_frame - m_inp_mem_ptr; + if(index >= m_sInPortDef.nBufferCountActual){ + DEBUG_PRINT_ERROR("\n Output buffer index is wrong %d act count %d", + index,m_sInPortDef.nBufferCountActual); + return OMX_ErrorBadParameter; + } + media_buffer = (encoder_media_buffer_type *)psource_frame->pBuffer; + /*Will enable to verify camcorder in current TIPS can be removed*/ + if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource) { + Input_pmem_info.buffer = media_buffer; + Input_pmem_info.fd = media_buffer->meta_handle->data[0]; + Input_pmem_info.offset = media_buffer->meta_handle->data[1]; + Input_pmem_info.size = media_buffer->meta_handle->data[2]; + DEBUG_PRINT_LOW("ETB fd = %d, offset = %d, size = %d",Input_pmem_info.fd, + Input_pmem_info.offset, + Input_pmem_info.size); + ret = queue_meta_buffer(hComp,Input_pmem_info); + } else { + private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle; + Input_pmem_info.buffer = media_buffer; + Input_pmem_info.fd = handle->fd; + Input_pmem_info.offset = 0; + Input_pmem_info.size = handle->size; + if(handle->format == HAL_PIXEL_FORMAT_RGBA_8888) + ret = convert_queue_buffer(hComp,Input_pmem_info,index); + else if(handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE) + ret = queue_meta_buffer(hComp,Input_pmem_info); + else + ret = OMX_ErrorBadParameter; + } + } + return ret; +} |