| /*-------------------------------------------------------------------------- |
| Copyright (c) 2010-2017, 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 |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| #define __STDC_FORMAT_MACROS //enables the format specifiers in inttypes.h |
| #include <inttypes.h> |
| #include <string.h> |
| #include "omx_video_base.h" |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <sys/prctl.h> |
| #ifdef _ANDROID_ICS_ |
| #include <media/hardware/HardwareAPI.h> |
| #include <gralloc_priv.h> |
| #endif |
| #ifndef _ANDROID_ |
| #include <glib.h> |
| #define strlcpy g_strlcpy |
| #endif |
| #define H264_SUPPORTED_WIDTH (480) |
| #define H264_SUPPORTED_HEIGHT (368) |
| |
| #define MPEG4_SUPPORTED_WIDTH (480) |
| #define MPEG4_SUPPORTED_HEIGHT (368) |
| |
| #define VC1_SP_MP_START_CODE 0xC5000000 |
| #define VC1_SP_MP_START_CODE_MASK 0xFF000000 |
| #define VC1_AP_START_CODE 0x00000100 |
| #define VC1_AP_START_CODE_MASK 0xFFFFFF00 |
| #define VC1_STRUCT_C_PROFILE_MASK 0xF0 |
| #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 |
| #define VC1_SIMPLE_PROFILE 0 |
| #define VC1_MAIN_PROFILE 1 |
| #define VC1_ADVANCE_PROFILE 3 |
| #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 |
| #define VC1_SIMPLE_PROFILE_MED_LEVEL 2 |
| #define VC1_STRUCT_C_LEN 4 |
| #define VC1_STRUCT_C_POS 8 |
| #define VC1_STRUCT_A_POS 12 |
| #define VC1_STRUCT_B_POS 24 |
| #define VC1_SEQ_LAYER_SIZE 36 |
| |
| #define SZ_4K 0x1000 |
| #define SZ_1M 0x100000 |
| |
| #ifndef ION_FLAG_CP_BITSTREAM |
| #define ION_FLAG_CP_BITSTREAM 0 |
| #endif |
| |
| #ifndef ION_FLAG_CP_PIXEL |
| #define ION_FLAG_CP_PIXEL 0 |
| #endif |
| |
| #undef MEM_HEAP_ID |
| |
| #ifdef MASTER_SIDE_CP |
| |
| #define MEM_HEAP_ID ION_SECURE_HEAP_ID |
| #define SECURE_ALIGN SZ_4K |
| #define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL) |
| #define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM) |
| |
| #else //SLAVE_SIDE_CP |
| |
| #define MEM_HEAP_ID ION_CP_MM_HEAP_ID |
| #define SECURE_ALIGN SZ_1M |
| #define SECURE_FLAGS_INPUT_BUFFER ION_SECURE |
| #define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE |
| |
| #endif |
| |
| typedef struct OMXComponentCapabilityFlagsType { |
| ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS |
| OMX_U32 nSize; |
| OMX_VERSIONTYPE nVersion; |
| OMX_BOOL iIsOMXComponentMultiThreaded; |
| OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc; |
| OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc; |
| OMX_BOOL iOMXComponentSupportsMovableInputBuffers; |
| OMX_BOOL iOMXComponentSupportsPartialFrames; |
| OMX_BOOL iOMXComponentUsesNALStartCodes; |
| OMX_BOOL iOMXComponentCanHandleIncompleteFrames; |
| OMX_BOOL iOMXComponentUsesFullAVCFrames; |
| |
| } OMXComponentCapabilityFlagsType; |
| #define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347 |
| |
| void* message_thread(void *input) |
| { |
| omx_video* omx = reinterpret_cast<omx_video*>(input); |
| unsigned char id; |
| int n; |
| |
| fd_set readFds; |
| int res = 0; |
| struct timeval tv; |
| |
| DEBUG_PRINT_HIGH("omx_venc: message thread start"); |
| prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0); |
| while (!omx->msg_thread_stop) { |
| |
| tv.tv_sec = 2; |
| tv.tv_usec = 0; |
| |
| FD_ZERO(&readFds); |
| FD_SET(omx->m_pipe_in, &readFds); |
| |
| res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv); |
| if (res < 0) { |
| DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno)); |
| continue; |
| } else if (res == 0 /*timeout*/ || omx->msg_thread_stop) { |
| continue; |
| } |
| |
| 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)) { |
| DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno); |
| break; |
| } |
| #endif |
| } |
| DEBUG_PRINT_HIGH("omx_venc: message thread stop"); |
| return 0; |
| } |
| |
| void post_message(omx_video *omx, unsigned char id) |
| { |
| DEBUG_PRINT_LOW("omx_venc: post_message %d", id); |
| int ret_value; |
| ret_value = write(omx->m_pipe_out, &id, 1); |
| if (ret_value <= 0) { |
| DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno)); |
| } else { |
| DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value); |
| } |
| } |
| |
| // 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 long p1, unsigned long p2, unsigned long id) |
| { |
| bool ret = true; |
| if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) { |
| m_q[m_write].id = id; |
| m_q[m_write].param1 = p1; |
| m_q[m_write].param2 = p2; |
| m_write++; |
| m_size ++; |
| if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) { |
| m_write = 0; |
| } |
| } else { |
| ret = false; |
| DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full"); |
| } |
| return ret; |
| } |
| |
| // omx cmd queue pop |
| bool omx_video::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *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(): |
| c2d_opened(false), |
| psource_frame(NULL), |
| pdest_frame(NULL), |
| secure_session(false), |
| mEmptyEosBuffer(NULL), |
| m_pipe_in(-1), |
| m_pipe_out(-1), |
| 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_sExtraData(0), |
| m_input_msg_id(OMX_COMPONENT_GENERATE_ETB), |
| 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), |
| hw_overload(false), |
| m_graphicBufferSize(0) |
| { |
| DEBUG_PRINT_HIGH("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; |
| msg_thread_stop = false; |
| |
| mUsesColorConversion = false; |
| pthread_mutex_init(&m_lock, NULL); |
| sem_init(&m_cmd_lock,0,0); |
| DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr); |
| |
| pthread_mutex_init(&m_buf_lock, NULL); |
| } |
| |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_venc::~omx_venc |
| |
| DESCRIPTION |
| Destructor |
| |
| PARAMETERS |
| None |
| |
| RETURN VALUE |
| None. |
| ========================================================================== */ |
| omx_video::~omx_video() |
| { |
| DEBUG_PRINT_HIGH("~omx_video(): Inside Destructor()"); |
| if (msg_thread_created) { |
| msg_thread_stop = true; |
| post_message(this, OMX_COMPONENT_CLOSE_MSG); |
| DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit"); |
| pthread_join(msg_thread_id,NULL); |
| } |
| close(m_pipe_in); |
| close(m_pipe_out); |
| m_pipe_in = -1; |
| m_pipe_out = -1; |
| DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit"); |
| /*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("m_etb_count = %" PRIu64 ", m_fbd_count = %" PRIu64, m_etb_count, |
| m_fbd_count); |
| |
| pthread_mutex_destroy(&m_buf_lock); |
| DEBUG_PRINT_HIGH("omx_video: Destructor exit"); |
| DEBUG_PRINT_HIGH("Exiting OMX Video Encoder ..."); |
| } |
| |
| /* ====================================================================== |
| 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 long p1; // Parameter - 1 |
| unsigned long p2; // Parameter - 2 |
| unsigned long ident; |
| unsigned qsize=0; // qsize |
| omx_video *pThis = (omx_video *) ctxt; |
| |
| if (!pThis) { |
| DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out"); |
| 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", 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("ERROR: OMX_EventError: p2 = %lu", p2); |
| if (p2 == (unsigned)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, 0, 0); |
| |
| } |
| break; |
| |
| case OMX_CommandPortDisable: |
| DEBUG_PRINT_LOW("Process -> Port %lu set to PORT_STATE_DISABLED" \ |
| "state", 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 %lu set PORT_STATE_ENABLED state" \ |
| , p2); |
| pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ |
| OMX_EventCmdComplete, p1, p2, NULL ); |
| break; |
| |
| default: |
| DEBUG_PRINT_LOW("process_event_cb forwarding EventCmdComplete %lu", 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"); |
| } |
| break; |
| case OMX_COMPONENT_GENERATE_ETB_OPQ: |
| DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB_OPQ"); |
| if (pThis->empty_this_buffer_opaque((OMX_HANDLETYPE)p1,\ |
| (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy() failed!"); |
| pThis->omx_report_error (); |
| } |
| break; |
| case OMX_COMPONENT_GENERATE_ETB: { |
| OMX_ERRORTYPE iret; |
| DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB"); |
| iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2); |
| if (iret == OMX_ErrorInsufficientResources) { |
| DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload"); |
| pThis->omx_report_hw_overload (); |
| } else if (iret != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure"); |
| pThis->omx_report_error (); |
| } |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_FTB: |
| if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ |
| (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("ERROR: FTBProxy() failed!"); |
| 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("ERROR: empty_buffer_done() failed!"); |
| 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("ERROR: fill_buffer_done() failed!"); |
| pThis->omx_report_error (); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: |
| |
| pThis->input_flush_progress = false; |
| DEBUG_PRINT_HIGH("m_etb_count at i/p flush = %" PRIu64, 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("dev_stop called after input flush complete"); |
| if (dev_stop() != 0) { |
| DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in i/p flush!"); |
| pThis->omx_report_error (); |
| } |
| } |
| } |
| } |
| |
| break; |
| |
| case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: |
| |
| pThis->output_flush_progress = false; |
| DEBUG_PRINT_HIGH("m_fbd_count at o/p flush = %" PRIu64, 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("dev_stop called after Output flush complete"); |
| if (!pThis->input_flush_progress) { |
| if (dev_stop() != 0) { |
| DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in o/p flush!"); |
| pThis->omx_report_error (); |
| } |
| } |
| } |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_START_DONE: |
| DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE msg"); |
| |
| if (pThis->m_pCallbacks.EventHandler) { |
| DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success"); |
| if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) { |
| DEBUG_PRINT_LOW("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("ERROR: dev_pause() failed in Start Done!"); |
| 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("ERROR: unknown flags=%" PRIx64, pThis->m_flags); |
| } |
| } else { |
| DEBUG_PRINT_LOW("Event Handler callback is NULL"); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_PAUSE_DONE: |
| DEBUG_PRINT_LOW("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"); |
| 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("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("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("ERROR: unknown flags=%" PRIx64, pThis->m_flags); |
| } |
| } |
| |
| break; |
| |
| case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: |
| DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!"); |
| 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 |
| case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING: |
| DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING"); |
| pThis->omx_report_unsupported_setting(); |
| break; |
| |
| case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD: |
| DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD"); |
| pThis->omx_report_hw_overload(); |
| break; |
| |
| default: |
| DEBUG_PRINT_LOW("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("exited the while loop"); |
| |
| } |
| |
| |
| |
| |
| /* ====================================================================== |
| 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 |
| ) |
| { |
| (void)hComp; |
| (void)componentName; |
| (void)componentVersion; |
| (void)componentUUID; |
| if (m_state == OMX_StateInvalid) { |
| DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State"); |
| 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 |
| ) |
| { |
| (void)hComp; |
| if (m_state == OMX_StateInvalid) { |
| DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State"); |
| return OMX_ErrorInvalidState; |
| } |
| |
| if (cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) { |
| if ((param1 != (OMX_U32)PORT_INDEX_IN) && (param1 != (OMX_U32)PORT_INDEX_OUT) && (param1 != (OMX_U32)PORT_INDEX_BOTH)) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index"); |
| return OMX_ErrorBadPortIndex; |
| } |
| } |
| if (cmd == OMX_CommandMarkBuffer) { |
| if (param1 != PORT_INDEX_IN) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index"); |
| return OMX_ErrorBadPortIndex; |
| } |
| if (!cmdData) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null"); |
| return OMX_ErrorBadParameter; |
| } |
| } |
| |
| post_event((unsigned long)cmd,(unsigned long)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 |
| ) |
| { |
| (void)hComp; |
| (void)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"); |
| } else { |
| DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending"); |
| 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"); |
| 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"); |
| } |
| /* Requesting transition from Loaded to Executing */ |
| else if (eState == OMX_StateExecuting) { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing"); |
| 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"); |
| 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"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled",\ |
| 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"); |
| if (dev_stop() != 0) { |
| DEBUG_PRINT_ERROR("ERROR: dev_stop() failed at Idle --> Loaded"); |
| eRet = OMX_ErrorHardware; |
| } |
| } else { |
| DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending"); |
| 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("ERROR: dev_start() failed in SCP on Idle --> Exe"); |
| omx_report_error (); |
| eRet = OMX_ErrorHardware; |
| } else { |
| BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); |
| DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing"); |
| bFlag = 0; |
| } |
| |
| dev_start_done(); |
| } |
| /* Requesting transition from Idle to Idle */ |
| else if (eState == OMX_StateIdle) { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle"); |
| 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"); |
| 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("ERROR: dev_start() failed in SCP on Idle --> Pause"); |
| omx_report_error (); |
| eRet = OMX_ErrorHardware; |
| } else { |
| BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); |
| DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause"); |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Idle to Invalid */ |
| else if (eState == OMX_StateInvalid) { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled",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("OMXCORE-SM: Executing --> Idle"); |
| //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("ERROR: dev_pause() failed in SCP on Exe --> Pause"); |
| 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"); |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Executing to Loaded */ |
| else if (eState == OMX_StateLoaded) { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Loaded"); |
| 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("ERROR: OMXCORE-SM: Executing --> WaitForResources"); |
| 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("ERROR: OMXCORE-SM: Executing --> Executing"); |
| 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("ERROR: OMXCORE-SM: Executing --> Invalid"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled",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("Pause --> Executing"); |
| 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"); |
| post_event (0, 0, 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("Pause --> Idle"); |
| 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("ERROR: Pause --> loaded"); |
| 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("ERROR: Pause --> WaitForResources"); |
| 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("ERROR: Pause --> Pause"); |
| 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("ERROR: Pause --> Invalid"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled",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"); |
| } |
| /* Requesting transition from WaitForResources to WaitForResources */ |
| else if (eState == OMX_StateWaitForResources) { |
| DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources"); |
| 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"); |
| 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"); |
| 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"); |
| 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)",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"); |
| 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"); |
| 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"); |
| 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)",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("execute_omx_flush - %u", (unsigned int)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 long p1 = 0; // Parameter - 1 |
| unsigned long p2 = 0; // Parameter - 2 |
| unsigned long ident = 0; |
| bool bRet = true; |
| |
| /*Generate FBD for all Buffers in the FTBq*/ |
| DEBUG_PRINT_LOW("execute_output_flush"); |
| 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("ERROR: 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 long p1 = 0; // Parameter - 1 |
| unsigned long p2 = 0; // Parameter - 2 |
| unsigned long ident = 0; |
| bool bRet = true; |
| |
| /*Generate EBD for all Buffers in the ETBq*/ |
| DEBUG_PRINT_LOW("execute_input_flush"); |
| |
| 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 long 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 long)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("ERROR: 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 long p1 = 0; // Parameter - 1 |
| unsigned long p2 = 0; // Parameter - 2 |
| unsigned long ident = 0; |
| bool bRet = true; |
| |
| DEBUG_PRINT_LOW("execute_flush_all"); |
| |
| /*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); |
| } 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 long 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 long)pdest_frame,0,0); |
| pdest_frame = NULL; |
| } |
| } |
| |
| /*Generate FBD for all Buffers in the FTBq*/ |
| DEBUG_PRINT_LOW("execute_output_flush"); |
| 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("ERROR: 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 long p1, |
| unsigned long p2, |
| unsigned long 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("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) |
| { |
| (void)hComp; |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| unsigned int height=0,width = 0; |
| |
| DEBUG_PRINT_LOW("get_parameter:"); |
| if (m_state == OMX_StateInvalid) { |
| DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State"); |
| return OMX_ErrorInvalidState; |
| } |
| if (paramData == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData"); |
| return OMX_ErrorBadParameter; |
| } |
| switch ((int)paramIndex) { |
| case OMX_IndexParamPortDefinition: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE); |
| OMX_PARAM_PORTDEFINITIONTYPE *portDefn; |
| portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; |
| |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition"); |
| if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) { |
| dev_get_buf_req (&m_sInPortDef.nBufferCountMin, |
| &m_sInPortDef.nBufferCountActual, |
| &m_sInPortDef.nBufferSize, |
| m_sInPortDef.nPortIndex); |
| DEBUG_PRINT_LOW("m_sInPortDef: size = %u, min cnt = %u, actual cnt = %u", |
| (unsigned int)m_sInPortDef.nBufferSize, (unsigned int)m_sInPortDef.nBufferCountMin, |
| (unsigned int)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) { |
| if (m_state != OMX_StateExecuting) { |
| dev_get_buf_req (&m_sOutPortDef.nBufferCountMin, |
| &m_sOutPortDef.nBufferCountActual, |
| &m_sOutPortDef.nBufferSize, |
| m_sOutPortDef.nPortIndex); |
| } |
| DEBUG_PRINT_LOW("m_sOutPortDef: size = %u, min cnt = %u, actual cnt = %u", |
| (unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)m_sOutPortDef.nBufferCountMin, |
| (unsigned int)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: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); |
| OMX_PORT_PARAM_TYPE *portParamType = |
| (OMX_PORT_PARAM_TYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit"); |
| |
| memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam)); |
| break; |
| } |
| case OMX_IndexParamVideoPortFormat: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE); |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = |
| (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat"); |
| |
| if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) { |
| unsigned index = portFmt->nIndex; |
| |
| #ifdef _UBWC_ |
| //we support following formats |
| //index 0 - Compressed (UBWC) Venus flavour of YUV420SP |
| //index 1 - Venus flavour of YUV420SP |
| //index 2 - Compressed (UBWC) Venus flavour of RGBA8888 |
| //index 3 - Venus flavour of RGBA8888 |
| //index 4 - opaque which internally maps to YUV420SP. |
| //index 5 - vannilla YUV420SP |
| //this can be extended in the future |
| int supportedFormats[] = { |
| [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed, |
| [1] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m, |
| [2] = QOMX_COLOR_Format32bitRGBA8888Compressed, |
| [3] = QOMX_COLOR_Format32bitRGBA8888, |
| [4] = QOMX_COLOR_FormatAndroidOpaque, |
| [5] = OMX_COLOR_FormatYUV420SemiPlanar, |
| }; |
| #else |
| //we support two formats |
| //index 0 - Venus flavour of YUV420SP |
| //index 1 - opaque which internally maps to YUV420SP. |
| //index 2 - vannilla YUV420SP |
| //this can be extended in the future |
| int supportedFormats[] = { |
| [0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m, |
| [1] = QOMX_COLOR_FormatAndroidOpaque, |
| [2] = OMX_COLOR_FormatYUV420SemiPlanar, |
| }; |
| #endif |
| if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1)) |
| eRet = OMX_ErrorNoMore; |
| else { |
| memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat)); |
| portFmt->nIndex = index; //restore index set from client |
| portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)supportedFormats[index]; |
| } |
| } 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: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_BITRATETYPE); |
| OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate"); |
| |
| 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: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_MPEG4TYPE); |
| OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4"); |
| memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4)); |
| break; |
| } |
| case OMX_IndexParamVideoH263: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_H263TYPE); |
| OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263"); |
| memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263)); |
| break; |
| } |
| case OMX_IndexParamVideoAvc: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_AVCTYPE); |
| OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc"); |
| memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC)); |
| break; |
| } |
| case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_VP8TYPE); |
| OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoVp8"); |
| memcpy(pParam, &m_sParamVP8, sizeof(m_sParamVP8)); |
| break; |
| } |
| case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_HEVCTYPE); |
| OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoHevc"); |
| memcpy(pParam, &m_sParamHEVC, sizeof(m_sParamHEVC)); |
| break; |
| } |
| case OMX_IndexParamVideoProfileLevelQuerySupported: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); |
| OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported"); |
| eRet = get_supported_profile_level(pParam); |
| if (eRet && eRet != OMX_ErrorNoMore) |
| DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %u, %u", |
| (unsigned int)pParam->eProfile, (unsigned int)pParam->eLevel); |
| break; |
| } |
| case OMX_IndexParamVideoProfileLevelCurrent: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); |
| OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent"); |
| memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel)); |
| break; |
| } |
| /*Component should support this port definition*/ |
| case OMX_IndexParamAudioInit: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); |
| OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit"); |
| memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio)); |
| break; |
| } |
| /*Component should support this port definition*/ |
| case OMX_IndexParamImageInit: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE); |
| OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit"); |
| 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", paramIndex); |
| eRet =OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| case OMX_IndexParamStandardComponentRole: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE); |
| 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",paramIndex); |
| strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); |
| break; |
| } |
| /* Added for parameter test */ |
| case OMX_IndexParamPriorityMgmt: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE); |
| OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt"); |
| memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt)); |
| break; |
| } |
| /* Added for parameter test */ |
| case OMX_IndexParamCompBufferSupplier: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE); |
| OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier"); |
| 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: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE); |
| OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization"); |
| memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization)); |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoQPRange: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_QPRANGETYPE); |
| OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoQPRange"); |
| memcpy(qp_range, &m_sSessionQPRange, sizeof(m_sSessionQPRange)); |
| break; |
| } |
| |
| case OMX_IndexParamVideoErrorCorrection: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE); |
| OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData; |
| DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection"); |
| errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC; |
| errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync; |
| errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing; |
| break; |
| } |
| case OMX_IndexParamVideoIntraRefresh: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_INTRAREFRESHTYPE); |
| OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData; |
| DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh"); |
| DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET"); |
| intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode; |
| intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs; |
| break; |
| } |
| case OMX_QcomIndexPortDefn: |
| //TODO |
| break; |
| case OMX_COMPONENT_CAPABILITY_TYPE_INDEX: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMXComponentCapabilityFlagsType); |
| OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData); |
| DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX"); |
| 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: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE); |
| 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 & VENC_EXTRADATA_SLICEINFO); |
| DEBUG_PRINT_HIGH("Slice Info extradata %d", pParam->bEnabled); |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: slice information is " |
| "valid for output port only"); |
| eRet = OMX_ErrorUnsupportedIndex; |
| } |
| } else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderMBInfo) { |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| pParam->bEnabled = |
| (OMX_BOOL)(m_sExtraData & VENC_EXTRADATA_MBINFO); |
| DEBUG_PRINT_HIGH("MB Info extradata %d", pParam->bEnabled); |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: MB information is " |
| "valid for output port only"); |
| eRet = OMX_ErrorUnsupportedIndex; |
| } |
| } else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataFrameDimension) { |
| if (pParam->nPortIndex == PORT_INDEX_IN) { |
| pParam->bEnabled = |
| (OMX_BOOL)((m_sExtraData & VENC_EXTRADATA_FRAMEDIMENSION) ? 1 : 0); |
| DEBUG_PRINT_HIGH("Frame dimension extradata %d", pParam->bEnabled); |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: frame dimension is " |
| "valid for input 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); |
| 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: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_RANGETYPE); |
| 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; |
| case OMX_QcomIndexParamVideoLTRCount: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoLTRCount"); |
| OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE *pParam = |
| reinterpret_cast<OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*>(paramData); |
| memcpy(pParam, &m_sParamLTRCount, sizeof(m_sParamLTRCount)); |
| break; |
| } |
| #endif |
| case QOMX_IndexParamVideoSyntaxHdr: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE); |
| 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 *)(void *)&pParam->nDataSize)) { |
| DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %u)", |
| (unsigned int)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_QcomIndexHierarchicalStructure: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_HIERARCHICALLAYERS); |
| QOMX_VIDEO_HIERARCHICALLAYERS* hierp = (QOMX_VIDEO_HIERARCHICALLAYERS*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexHierarchicalStructure"); |
| memcpy(hierp, &m_sHierLayers, sizeof(m_sHierLayers)); |
| break; |
| } |
| case OMX_QcomIndexParamMBIStatisticsMode: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QOMX_VIDEO_MBI_STATISTICS); |
| OMX_QOMX_VIDEO_MBI_STATISTICS* mbi_mode = (OMX_QOMX_VIDEO_MBI_STATISTICS*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamMBIStatisticsMode"); |
| memcpy(mbi_mode, &m_sMBIStatistics, sizeof(m_sMBIStatistics)); |
| break; |
| } |
| case OMX_QcomIndexParamPerfLevel: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PERF_LEVEL); |
| OMX_U32 perflevel; |
| OMX_QCOM_VIDEO_PARAM_PERF_LEVEL *pParam = |
| reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PERF_LEVEL*>(paramData); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamPerfLevel"); |
| if (!dev_get_performance_level(&perflevel)) { |
| DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d", |
| pParam->ePerfLevel); |
| } else { |
| pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel; |
| } |
| break; |
| } |
| case OMX_QcomIndexParamH264VUITimingInfo: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO); |
| OMX_U32 enabled; |
| OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam = |
| reinterpret_cast<OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO*>(paramData); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamH264VUITimingInfo"); |
| if (!dev_get_vui_timing_info(&enabled)) { |
| DEBUG_PRINT_ERROR("Invalid entry returned from get_vui_Timing_info %d", |
| pParam->bEnable); |
| } else { |
| pParam->bEnable = (OMX_BOOL)enabled; |
| } |
| break; |
| } |
| case OMX_QTIIndexParamVQZIPSEIType: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE); |
| OMX_U32 enabled; |
| OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam = |
| reinterpret_cast<OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE*>(paramData); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVQZIPSEIType"); |
| if (!dev_get_vqzip_sei_info(&enabled)) { |
| DEBUG_PRINT_ERROR("Invalid entry returned from get_vqzip_sei_type %d", |
| pParam->bEnable); |
| } else { |
| pParam->bEnable = (OMX_BOOL)enabled; |
| } |
| break; |
| } |
| case OMX_QcomIndexParamPeakBitrate: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE); |
| OMX_U32 peakbitrate; |
| OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *pParam = |
| reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE*>(paramData); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamPeakBitrate"); |
| if (!dev_get_peak_bitrate(&peakbitrate)) { |
| DEBUG_PRINT_ERROR("Invalid entry returned from get_peak_bitrate %u", |
| (unsigned int)pParam->nPeakBitrate); |
| } else { |
| pParam->nPeakBitrate = peakbitrate; |
| } |
| break; |
| } |
| case QOMX_IndexParamVideoInitialQp: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP); |
| QOMX_EXTNINDEX_VIDEO_INITIALQP* initqp = |
| reinterpret_cast<QOMX_EXTNINDEX_VIDEO_INITIALQP *>(paramData); |
| memcpy(initqp, &m_sParamInitqp, sizeof(m_sParamInitqp)); |
| break; |
| } |
| case OMX_QcomIndexParamBatchSize: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_U32TYPE); |
| OMX_PARAM_U32TYPE* batch = |
| reinterpret_cast<OMX_PARAM_U32TYPE *>(paramData); |
| |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamBatchSize"); |
| if (!dev_get_batch_size(&batch->nU32)) { |
| DEBUG_PRINT_ERROR("Invalid entry returned from dev_get_batch_size %u", |
| (unsigned int)batch->nSize); |
| eRet = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| batch->nPortIndex = PORT_INDEX_IN; |
| break; |
| } |
| case OMX_QcomIndexParamSequenceHeaderWithIDR: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, PrependSPSPPSToIDRFramesParams); |
| PrependSPSPPSToIDRFramesParams * pParam = |
| reinterpret_cast<PrependSPSPPSToIDRFramesParams *>(paramData); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamSequenceHeaderWithIDR"); |
| memcpy(pParam, &m_sPrependSPSPPS, sizeof(m_sPrependSPSPPS)); |
| break; |
| } |
| case OMX_QcomIndexParamVencAspectRatio: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_VENC_SAR); |
| QOMX_EXTNINDEX_VIDEO_VENC_SAR * pParam = |
| reinterpret_cast<QOMX_EXTNINDEX_VIDEO_VENC_SAR *>(paramData); |
| memcpy(pParam, &m_sSar, sizeof(m_sSar)); |
| break; |
| } |
| case OMX_IndexParamAndroidVideoTemporalLayering: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE); |
| OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pLayerInfo = |
| reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE*>(paramData); |
| if (!dev_get_temporal_layer_caps(&m_sParamTemporalLayers.nLayerCountMax, |
| &m_sParamTemporalLayers.nBLayerCountMax)) { |
| DEBUG_PRINT_ERROR("Failed to get temporal layer capabilities"); |
| eRet = OMX_ErrorHardware; |
| } |
| memcpy(pLayerInfo, &m_sParamTemporalLayers, sizeof(m_sParamTemporalLayers)); |
| break; |
| } |
| case OMX_IndexParamVideoSliceFMO: |
| default: |
| { |
| DEBUG_PRINT_LOW("ERROR: get_parameter: unknown param %08x", 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) |
| { |
| (void)hComp; |
| //////////////////////////////////////////////////////////////// |
| // 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 ((int)configIndex) { |
| case OMX_IndexConfigVideoBitrate: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_BITRATETYPE); |
| OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData); |
| memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate)); |
| break; |
| } |
| case OMX_IndexConfigVideoFramerate: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_FRAMERATETYPE); |
| OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData); |
| memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate)); |
| break; |
| } |
| case OMX_IndexConfigCommonRotate: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ROTATIONTYPE); |
| 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"); |
| VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_INTRAPERIODTYPE); |
| QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData); |
| memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod)); |
| break; |
| } |
| case OMX_IndexConfigVideoAVCIntraPeriod: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_AVCINTRAPERIOD); |
| 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; |
| } |
| case OMX_IndexConfigCommonDeinterlace: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_DEINTERLACE); |
| OMX_VIDEO_CONFIG_DEINTERLACE *pParam = |
| reinterpret_cast<OMX_VIDEO_CONFIG_DEINTERLACE*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_IndexConfigCommonDeinterlace"); |
| memcpy(pParam, &m_sConfigDeinterlace, sizeof(m_sConfigDeinterlace)); |
| break; |
| } |
| case OMX_IndexConfigVideoVp8ReferenceFrame: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_VP8REFERENCEFRAMETYPE); |
| OMX_VIDEO_VP8REFERENCEFRAMETYPE* pParam = |
| reinterpret_cast<OMX_VIDEO_VP8REFERENCEFRAMETYPE*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoVp8ReferenceFrame"); |
| memcpy(pParam, &m_sConfigVp8ReferenceFrame, sizeof(m_sConfigVp8ReferenceFrame)); |
| break; |
| } |
| case OMX_QcomIndexConfigPerfLevel: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL); |
| OMX_U32 perflevel; |
| OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *pParam = |
| reinterpret_cast<OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigPerfLevel"); |
| if (!dev_get_performance_level(&perflevel)) { |
| DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d", |
| pParam->ePerfLevel); |
| } else { |
| pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel; |
| } |
| break; |
| } |
| case OMX_QcomIndexConfigNumHierPLayers: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS); |
| QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS* pParam = |
| reinterpret_cast<QOMX_EXTNINDEX_VIDEO_HIER_P_LAYERS*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigNumHierPLayers"); |
| memcpy(pParam, &m_sHPlayers, sizeof(m_sHPlayers)); |
| break; |
| } |
| case OMX_QcomIndexConfigQp: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_SKYPE_VIDEO_CONFIG_QP); |
| OMX_SKYPE_VIDEO_CONFIG_QP* pParam = |
| reinterpret_cast<OMX_SKYPE_VIDEO_CONFIG_QP*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigQp"); |
| memcpy(pParam, &m_sConfigQP, sizeof(m_sConfigQP)); |
| break; |
| } |
| case OMX_QcomIndexConfigBaseLayerId: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID); |
| OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID* pParam = |
| reinterpret_cast<OMX_SKYPE_VIDEO_CONFIG_BASELAYERPID*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigBaseLayerId"); |
| memcpy(pParam, &m_sBaseLayerID, sizeof(m_sBaseLayerID)); |
| break; |
| } |
| case OMX_IndexConfigAndroidIntraRefresh: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE); |
| OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE* pParam = |
| reinterpret_cast<OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidIntraRefresh"); |
| memcpy(pParam, &m_sConfigIntraRefresh, sizeof(m_sConfigIntraRefresh)); |
| break; |
| } |
| case OMX_IndexParamAndroidVideoTemporalLayering: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE); |
| OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *layerConfig = |
| (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)configData; |
| DEBUG_PRINT_LOW("get_config: OMX_IndexConfigAndroidVideoTemporalLayering"); |
| memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers)); |
| break; |
| } |
| case OMX_QTIIndexConfigDescribeColorAspects: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams); |
| DescribeColorAspectsParams* pParam = |
| reinterpret_cast<DescribeColorAspectsParams*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_QTIIndexConfigDescribeColorAspects"); |
| if (pParam->bRequestingDataSpace) { |
| DEBUG_PRINT_ERROR("Does not handle dataspace request"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| if (pParam->bDataSpaceChanged == OMX_TRUE) { |
| |
| print_debug_color_aspects(&(pParam->sAspects), "get_config (dataspace changed) Client says"); |
| // If the dataspace says RGB, recommend 601-limited; |
| // since that is the destination colorspace that C2D or Venus will convert to. |
| if (pParam->nPixelFormat == HAL_PIXEL_FORMAT_RGBA_8888) { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: Recommend 601-limited for RGBA8888"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; |
| pParam->sAspects.mRange = ColorAspects::RangeLimited; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; |
| } else { |
| // For IMPLEMENTATION_DEFINED (or anything else), stick to client's defaults. |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: use client-default for format=%x", |
| pParam->nPixelFormat); |
| } |
| print_debug_color_aspects(&(pParam->sAspects), "get_config (dataspace changed) recommended"); |
| } else { |
| memcpy(pParam, &m_sConfigColorAspects, sizeof(m_sConfigColorAspects)); |
| print_debug_color_aspects(&(pParam->sAspects), "get_config"); |
| } |
| break; |
| } |
| case OMX_IndexConfigAndroidVendorExtension: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); |
| |
| OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext = |
| reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData); |
| VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext); |
| return get_vendor_extension_config(ext); |
| } |
| |
| default: |
| DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); |
| return OMX_ErrorUnsupportedIndex; |
| } |
| return OMX_ErrorNone; |
| |
| } |
| |
| #define extn_equals(param, extn) (!strcmp(param, extn)) |
| |
| /* ====================================================================== |
| 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) |
| { |
| (void)hComp; |
| if (m_state == OMX_StateInvalid) { |
| DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State"); |
| return OMX_ErrorInvalidState; |
| } |
| #ifdef MAX_RES_1080P |
| if (extn_equals(paramName, "OMX.QCOM.index.param.SliceDeliveryMode")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode; |
| return OMX_ErrorNone; |
| } |
| #endif |
| #ifdef _ANDROID_ICS_ |
| if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode; |
| return OMX_ErrorNone; |
| } |
| #endif |
| if (extn_equals(paramName, "OMX.google.android.index.prependSPSPPSToIDRFrames")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamSequenceHeaderWithIDR; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.param.video.HierStructure")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexHierarchicalStructure; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.param.video.LTRCount")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoLTRCount; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.param.video.LTRPeriod")) { |
| *indexType = (OMX_INDEXTYPE)QOMX_IndexConfigVideoLTRPeriod; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.config.video.LTRUse")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoLTRUse; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.config.video.LTRMark")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoLTRMark; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.config.video.hierplayers")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigNumHierPLayers; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.param.video.baselayerid")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigBaseLayerId; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.config.video.qp")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigQp; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.param.video.sar")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVencAspectRatio; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.QCOM.index.param.video.InputBatch")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamBatchSize; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_ENABLE_ROIINFO)) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_ROIINFO)) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoRoiInfo; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects; |
| return OMX_ErrorNone; |
| } |
| 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) |
| { |
| (void)hComp; |
| *state = m_state; |
| DEBUG_PRINT_LOW("get_state: Returning the state %d",*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) |
| { |
| (void) hComp, (void) port, (void) peerComponent, (void) peerPort, (void) tunnelSetup; |
| DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented"); |
| 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) |
| { |
| (void) hComp; |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| |
| unsigned i = 0; |
| unsigned char *buf_addr = NULL; |
| |
| DEBUG_PRINT_HIGH("use_input_buffer: port = %u appData = %p bytes = %u buffer = %p",(unsigned int)port,appData,(unsigned int)bytes,buffer); |
| if (bytes < m_sInPortDef.nBufferSize) { |
| DEBUG_PRINT_ERROR("ERROR: use_input_buffer: Size Mismatch!! " |
| "bytes[%u] < Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)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("ERROR: calloc() Failed for m_inp_mem_ptr"); |
| return OMX_ErrorInsufficientResources; |
| } |
| DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr); |
| |
| |
| m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); |
| if (m_pInput_pmem == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: 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("ERROR: 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 = 0; |
| #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, |
| secure_session ? SECURE_FLAGS_INPUT_BUFFER : 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("ERROR: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("ERROR: /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 = NULL; |
| if(!secure_session) { |
| 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("ERROR: mmap() Failed"); |
| m_pInput_pmem[i].buffer = NULL; |
| 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:%lu,offset:0x%x)", pParam->pmem_fd, (unsigned)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("DBG:: pParam->pmem_fd = %u, pParam->offset = %u", |
| (unsigned int)pParam->pmem_fd, (unsigned int)pParam->offset); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case"); |
| return OMX_ErrorBadParameter; |
| } |
| } |
| |
| DEBUG_PRINT_LOW("use_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p", |
| (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer); |
| if ( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true) { |
| DEBUG_PRINT_ERROR("ERROR: dev_use_buf() Failed for i/p buf"); |
| return OMX_ErrorInsufficientResources; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: 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) |
| { |
| (void)hComp, (void)port; |
| 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("Inside use_output_buffer()"); |
| if (bytes < m_sOutPortDef.nBufferSize) { |
| DEBUG_PRINT_ERROR("ERROR: use_output_buffer: Size Mismatch!! " |
| "bytes[%u] < Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sOutPortDef.nBufferSize); |
| return OMX_ErrorBadParameter; |
| } |
| |
| auto_lock l(m_buf_lock); |
| if (!m_out_mem_ptr) { |
| output_use_buffer = true; |
| int nBufHdrSize = 0; |
| |
| DEBUG_PRINT_LOW("Allocating First Output Buffer(%u)",(unsigned int)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("ERROR: 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("ERROR: 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("ERROR: 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",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 = 0; |
| #endif |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%p]",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; |
| |
| if (!m_use_output_pmem) { |
| #ifdef USE_ION |
| #ifdef _MSM8974_ |
| align_size = (m_sOutPortDef.nBufferSize + (SZ_4K - 1)) & ~(SZ_4K - 1); |
| 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, |
| secure_session ? SECURE_FLAGS_OUTPUT_BUFFER : 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("ERROR: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("ERROR: /dev/pmem_adsp open() Failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| #endif |
| m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; |
| m_pOutput_pmem[i].offset = 0; |
| |
| m_pOutput_pmem[i].buffer = NULL; |
| if(!secure_session) { |
| #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("ERROR: mmap() Failed"); |
| m_pOutput_pmem[i].buffer = NULL; |
| 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: %p", pParam); |
| |
| if (pParam) { |
| DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (int)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("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; |
| } |
| |
| BITMASK_SET(&m_out_bm_count,i); |
| } 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"); |
| 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",(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 - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr); |
| #ifdef _ANDROID_ICS_ |
| if (meta_mode_enable) { |
| if (index < m_sInPortDef.nBufferCountActual) { |
| memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index])); |
| memset(&meta_buffers[index], 0, sizeof(meta_buffers[index])); |
| } |
| if (!mUseProxyColorFormat) |
| return OMX_ErrorNone; |
| else { |
| c2d_conv.close(); |
| opaque_buffer_hdr[index] = NULL; |
| } |
| } |
| #endif |
| if (index < m_sInPortDef.nBufferCountActual && !mUseProxyColorFormat && |
| dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) { |
| DEBUG_PRINT_LOW("ERROR: dev_free_buf() Failed for i/p buf"); |
| } |
| |
| if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) { |
| auto_lock l(m_lock); |
| |
| if (mUseProxyColorFormat) { |
| if (m_opq_pmem_q.m_size) { |
| unsigned long addr, p1, id; |
| m_opq_pmem_q.pop_entry(&addr, &p1, &id); |
| DEBUG_PRINT_LOW("Removed entry in m_opq_pmem_q: address %lu", addr); |
| } |
| } |
| |
| if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) { |
| DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case"); |
| if(!secure_session) { |
| munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); |
| } else { |
| free(m_pInput_pmem[index].buffer); |
| } |
| m_pInput_pmem[index].buffer = NULL; |
| 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("FreeBuffer:: i/p Heap UseBuffer case"); |
| if (dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) { |
| DEBUG_PRINT_ERROR("ERROR: dev_free_buf() Failed for i/p buf"); |
| } |
| if(!secure_session) { |
| munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); |
| m_pInput_pmem[index].buffer = NULL; |
| } |
| 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("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("FreeBuffer:: o/p AllocateBuffer case"); |
| if(!secure_session) { |
| munmap (m_pOutput_pmem[index].buffer, |
| m_pOutput_pmem[index].size); |
| } else { |
| char *data = (char*) m_pOutput_pmem[index].buffer; |
| native_handle_t *handle = NULL; |
| memcpy(&handle, data + sizeof(OMX_U32), sizeof(native_handle_t*)); |
| native_handle_delete(handle); |
| free(m_pOutput_pmem[index].buffer); |
| } |
| 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("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"); |
| } |
| if(!secure_session) { |
| munmap (m_pOutput_pmem[index].buffer, |
| m_pOutput_pmem[index].size); |
| } |
| close (m_pOutput_pmem[index].fd); |
| #ifdef USE_ION |
| free_ion_memory(&m_pOutput_ion[index]); |
| #endif |
| m_pOutput_pmem[index].fd = -1; |
| } else { |
| DEBUG_PRINT_LOW("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 %u", |
| bufferHdr, (unsigned int)bytes); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (!m_inp_mem_ptr && !mUseProxyColorFormat) { |
| m_inp_mem_ptr = meta_buffer_hdr; |
| DEBUG_PRINT_LOW("use meta_buffer_hdr (%p) as m_inp_mem_ptr = %p", |
| meta_buffer_hdr, m_inp_mem_ptr); |
| } |
| 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 = sizeof(meta_buffers[index]); |
| 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 long)opaque_buffer_hdr[index],0,0); |
| DEBUG_PRINT_HIGH("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) |
| { |
| (void)hComp, (void)port; |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| unsigned i = 0; |
| |
| DEBUG_PRINT_HIGH("allocate_input_buffer()::"); |
| if (bytes < m_sInPortDef.nBufferSize) { |
| DEBUG_PRINT_ERROR("ERROR: Buffer size mismatch error: bytes[%u] < nBufferSize[%u]", |
| (unsigned int)bytes, (unsigned int)m_sInPortDef.nBufferSize); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (!m_inp_mem_ptr) { |
| DEBUG_PRINT_HIGH("%s: size = %u, actual cnt %u", __FUNCTION__, |
| (unsigned int)m_sInPortDef.nBufferSize, (unsigned int)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("ERROR: calloc() Failed for m_inp_mem_ptr"); |
| return OMX_ErrorInsufficientResources; |
| } |
| |
| DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr); |
| m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); |
| |
| if (m_pInput_pmem == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: 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("ERROR: 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 = 0; |
| #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; |
| // make fd available to app layer, help with testing |
| (*bufferHdr)->pInputPortPrivate = (OMX_PTR)&m_pInput_pmem[i]; |
| |
| #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, |
| secure_session ? SECURE_FLAGS_INPUT_BUFFER : 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("ERROR: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("ERROR: /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 = NULL; |
| if(!secure_session) { |
| 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("ERROR: mmap FAILED= %d", errno); |
| m_pInput_pmem[i].buffer = NULL; |
| close(m_pInput_pmem[i].fd); |
| #ifdef USE_ION |
| free_ion_memory(&m_pInput_ion[i]); |
| #endif |
| return OMX_ErrorInsufficientResources; |
| } |
| } else { |
| //This should only be used for passing reference to source type and |
| //secure handle fd struct native_handle_t* |
| m_pInput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*)); |
| if (m_pInput_pmem[i].buffer == NULL) { |
| DEBUG_PRINT_ERROR("%s: failed to allocate native-handle", __func__); |
| return OMX_ErrorInsufficientResources; |
| } |
| } |
| |
| (*bufferHdr)->pBuffer = (OMX_U8 *)m_pInput_pmem[i].buffer; |
| DEBUG_PRINT_LOW("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("ERROR: dev_use_buf FAILED for i/p buf"); |
| return OMX_ErrorInsufficientResources; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: All i/p buffers are allocated, invalid allocate buf call" |
| "for index [%d]", 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) |
| { |
| (void)hComp, (void)port; |
| 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("allocate_output_buffer()for %u bytes", (unsigned int)bytes); |
| if (!m_out_mem_ptr) { |
| int nBufHdrSize = 0; |
| DEBUG_PRINT_HIGH("%s: size = %u, actual cnt %u", __FUNCTION__, |
| (unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)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("ERROR: 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("ERROR: 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 = m_sOutPortDef.nBufferSize; |
| bufHdr->nFilledLen = 0; |
| bufHdr->pAppPrivate = appData; |
| bufHdr->nOutputPortIndex = PORT_INDEX_OUT; |
| // make fd available to app layer, help with testing |
| bufHdr->pOutputPortPrivate = (OMX_PTR)&m_pOutput_pmem[i]; |
| 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 = 0; |
| #endif |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| } |
| |
| DEBUG_PRINT_HIGH("actual cnt = %u", (unsigned int)m_sOutPortDef.nBufferCountActual); |
| for (i=0; i< m_sOutPortDef.nBufferCountActual; i++) { |
| if (BITMASK_ABSENT(&m_out_bm_count,i)) { |
| DEBUG_PRINT_LOW("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, |
| secure_session ? SECURE_FLAGS_OUTPUT_BUFFER : ION_FLAG_CACHED); |
| #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("ERROR: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("ERROR: /dev/pmem_adsp open() failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| #endif |
| m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; |
| m_pOutput_pmem[i].offset = 0; |
| |
| m_pOutput_pmem[i].buffer = NULL; |
| if(!secure_session) { |
| #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("ERROR: MMAP_FAILED in o/p alloc buffer"); |
| m_pOutput_pmem[i].buffer = NULL; |
| close (m_pOutput_pmem[i].fd); |
| #ifdef USE_ION |
| free_ion_memory(&m_pOutput_ion[i]); |
| #endif |
| return OMX_ErrorInsufficientResources; |
| } |
| } |
| else { |
| //This should only be used for passing reference to source type and |
| //secure handle fd struct native_handle_t* |
| m_pOutput_pmem[i].buffer = malloc(sizeof(OMX_U32) + sizeof(native_handle_t*)); |
| if (m_pOutput_pmem[i].buffer == NULL) { |
| DEBUG_PRINT_ERROR("%s: failed to allocate native-handle", __func__); |
| return OMX_ErrorInsufficientResources; |
| } |
| native_handle_t *handle = native_handle_create(1, 0); |
| handle->data[0] = m_pOutput_pmem[i].fd; |
| char *data = (char*) m_pOutput_pmem[i].buffer; |
| OMX_U32 type = 1; |
| memcpy(data, &type, sizeof(OMX_U32)); |
| memcpy(data + sizeof(OMX_U32), &handle, sizeof(native_handle_t*)); |
| } |
| |
| *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("ERROR: dev_use_buf FAILED for o/p buf"); |
| return OMX_ErrorInsufficientResources; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: All o/p buffers are allocated, invalid allocate buf call" |
| "for index [%d] actual: %u", i, (unsigned int)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("Allocate buffer of size = %u on port %d", (unsigned int)bytes, (int)port); |
| if (m_state == OMX_StateInvalid) { |
| DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State"); |
| 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",(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",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) |
| { |
| (void)hComp; |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| unsigned int nPortIndex; |
| |
| DEBUG_PRINT_LOW("In for encoder free_buffer"); |
| |
| if (m_state == OMX_StateIdle && |
| (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) { |
| DEBUG_PRINT_LOW(" free buffer while Component in Loading pending"); |
| } 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 %u disabled", (unsigned int)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"); |
| 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"); |
| post_event(OMX_EventError, |
| OMX_ErrorPortUnpopulated, |
| OMX_COMPONENT_GENERATE_EVENT); |
| } |
| |
| if (port == PORT_INDEX_IN) { |
| // check if the buffer is valid |
| nPortIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr); |
| |
| DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %u, actual cnt %u", |
| nPortIndex, (unsigned int)m_sInPortDef.nBufferCountActual); |
| if (nPortIndex < m_sInPortDef.nBufferCountActual && |
| BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) { |
| // Clear the bit associated with it. |
| BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); |
| free_input_buffer (buffer); |
| m_sInPortDef.bPopulated = OMX_FALSE; |
| |
| /*Free the Buffer Header*/ |
| if (release_input_done()) { |
| input_use_buffer = false; |
| // "m_inp_mem_ptr" may point to "meta_buffer_hdr" in some modes, |
| // in which case, it was not explicitly allocated |
| if (m_inp_mem_ptr && m_inp_mem_ptr != meta_buffer_hdr) { |
| DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr"); |
| free (m_inp_mem_ptr); |
| } |
| m_inp_mem_ptr = NULL; |
| if (m_pInput_pmem) { |
| DEBUG_PRINT_LOW("Freeing m_pInput_pmem"); |
| free(m_pInput_pmem); |
| m_pInput_pmem = NULL; |
| } |
| #ifdef USE_ION |
| if (m_pInput_ion) { |
| DEBUG_PRINT_LOW("Freeing m_pInput_ion"); |
| free(m_pInput_ion); |
| m_pInput_ion = NULL; |
| } |
| #endif |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid"); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| |
| if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) |
| && release_input_done()) { |
| DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); |
| 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 %u, actual cnt %u", |
| nPortIndex, (unsigned int)m_sOutPortDef.nBufferCountActual); |
| if (nPortIndex < m_sOutPortDef.nBufferCountActual && |
| BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) { |
| auto_lock l(m_buf_lock); |
| // 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"); |
| free (m_out_mem_ptr); |
| m_out_mem_ptr = NULL; |
| } |
| if (m_pOutput_pmem) { |
| DEBUG_PRINT_LOW("Freeing m_pOutput_pmem"); |
| free(m_pOutput_pmem); |
| m_pOutput_pmem = NULL; |
| } |
| #ifdef USE_ION |
| if (m_pOutput_ion) { |
| DEBUG_PRINT_LOW("Freeing m_pOutput_ion"); |
| free(m_pOutput_ion); |
| m_pOutput_ion = NULL; |
| } |
| #endif |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid"); |
| 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"); |
| |
| DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); |
| 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"); |
| 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_HIGH("in free buffer, release not done, need to free more buffers input %" PRIx64" output %" PRIx64, |
| 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 ; |
| |
| dev_set_extradata_cookie((void *)buffer); |
| DEBUG_PRINT_LOW("ETB: buffer = %p, buffer->pBuffer[%p]", buffer, buffer->pBuffer); |
| if (m_state != OMX_StateExecuting && |
| m_state != OMX_StatePause && |
| m_state != OMX_StateIdle) { |
| DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State"); |
| return OMX_ErrorInvalidState; |
| } |
| |
| if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> buffer is null or buffer size is invalid"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> OMX Version Invalid"); |
| return OMX_ErrorVersionMismatch; |
| } |
| |
| if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN) { |
| DEBUG_PRINT_ERROR("ERROR: Bad port index to call empty_this_buffer"); |
| return OMX_ErrorBadPortIndex; |
| } |
| if (!m_sInPortDef.bEnabled) { |
| DEBUG_PRINT_ERROR("ERROR: Cannot call empty_this_buffer while I/P port is disabled"); |
| return OMX_ErrorIncorrectStateOperation; |
| } |
| |
| nBufferIndex = buffer - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr); |
| |
| if (nBufferIndex > m_sInPortDef.nBufferCountActual ) { |
| DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]", nBufferIndex); |
| return OMX_ErrorBadParameter; |
| } |
| |
| m_etb_count++; |
| DEBUG_PRINT_LOW("DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp); |
| post_event ((unsigned long)hComp,(unsigned long)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) |
| { |
| (void)hComp; |
| OMX_U8 *pmem_data_buf = NULL; |
| int push_cnt = 0; |
| unsigned nBufIndex = 0; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| encoder_media_buffer_type *media_buffer = NULL; |
| |
| #ifdef _MSM8974_ |
| int fd = 0; |
| #endif |
| DEBUG_PRINT_LOW("ETBProxy: buffer->pBuffer[%p]", buffer->pBuffer); |
| if (buffer == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid buffer[%p]", buffer); |
| return OMX_ErrorBadParameter; |
| } |
| |
| // Buffer sanity checks |
| if (meta_mode_enable && !mUsesColorConversion) { |
| //For color-conversion case, we have an internal buffer and not a meta buffer |
| bool met_error = false; |
| nBufIndex = buffer - meta_buffer_hdr; |
| if (nBufIndex >= m_sInPortDef.nBufferCountActual) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid meta-bufIndex = %u", nBufIndex); |
| return OMX_ErrorBadParameter; |
| } |
| media_buffer = (encoder_media_buffer_type *)meta_buffer_hdr[nBufIndex].pBuffer; |
| if (media_buffer) { |
| if (media_buffer->buffer_type != kMetadataBufferTypeCameraSource && |
| media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) { |
| met_error = true; |
| } else { |
| if (media_buffer->buffer_type == kMetadataBufferTypeCameraSource) { |
| if (media_buffer->meta_handle == NULL) |
| met_error = true; |
| else { |
| int nFds = media_buffer->meta_handle->numFds, |
| nInt = media_buffer->meta_handle->numInts; |
| met_error = ((nFds == 1 && nInt >= 2) /*normal*/ || |
| (nFds < 16 && nInt >= nFds*3) /*batch*/) ? false : true; |
| if (met_error) { |
| DEBUG_PRINT_ERROR("Unbalanced fds in handle: fds=%d ints=%d", |
| nFds, nInt); |
| } |
| } |
| } |
| } |
| } else |
| met_error = true; |
| if (met_error) { |
| DEBUG_PRINT_ERROR("ERROR: Unkown source/metahandle in ETB call"); |
| post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD); |
| return OMX_ErrorBadParameter; |
| } |
| } else { |
| nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); |
| if (nBufIndex >= m_sInPortDef.nBufferCountActual) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid bufIndex = %u", nBufIndex); |
| return OMX_ErrorBadParameter; |
| } |
| } |
| |
| pending_input_buffers++; |
| if (input_flush_progress == true) { |
| post_event ((unsigned long)buffer,0, |
| OMX_COMPONENT_GENERATE_EBD); |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy: Input flush in progress"); |
| return OMX_ErrorNone; |
| } |
| #ifdef _MSM8974_ |
| if (!meta_mode_enable) { |
| fd = m_pInput_pmem[nBufIndex].fd; |
| } |
| #endif |
| #ifdef _ANDROID_ICS_ |
| if (meta_mode_enable && !mUsesColorConversion) { |
| // Camera or Gralloc-source meta-buffers queued with encodeable color-format |
| struct pmem Input_pmem_info; |
| if (!media_buffer) { |
| DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__); |
| return OMX_ErrorBadParameter; |
| } |
| 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 (meta-Camera) 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; |
| DEBUG_PRINT_LOW("ETB (meta-gralloc) fd = %d, offset = %d, size = %d", |
| Input_pmem_info.fd, Input_pmem_info.offset, |
| Input_pmem_info.size); |
| } |
| if (dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,nBufIndex) != true) { |
| DEBUG_PRINT_ERROR("ERROR: in dev_use_buf"); |
| post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD); |
| return OMX_ErrorBadParameter; |
| } |
| } else if (input_use_buffer && !m_use_input_pmem && m_pInput_pmem[nBufIndex].buffer) |
| #else |
| if (input_use_buffer && !m_use_input_pmem && m_pInput_pmem[nBufIndex].buffer) |
| #endif |
| { |
| DEBUG_PRINT_LOW("Heap UseBuffer case, so memcpy the data"); |
| |
| auto_lock l(m_lock); |
| pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer; |
| if (pmem_data_buf) { |
| memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset), |
| buffer->nFilledLen); |
| } |
| DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf"); |
| } else if (mUseProxyColorFormat) { |
| // Gralloc-source buffers with color-conversion |
| fd = m_pInput_pmem[nBufIndex].fd; |
| DEBUG_PRINT_LOW("ETB (color-converted) fd = %d, size = %u", |
| fd, (unsigned int)buffer->nFilledLen); |
| } else if (m_sInPortDef.format.video.eColorFormat == |
| OMX_COLOR_FormatYUV420SemiPlanar) { |
| //For the case where YUV420SP buffers are qeueued to component |
| //by sources other than camera (Apps via MediaCodec), conversion |
| //to vendor flavoured NV12 color format is required. |
| if (!dev_color_align(buffer, m_sInPortDef.format.video.nFrameWidth, |
| m_sInPortDef.format.video.nFrameHeight)) { |
| DEBUG_PRINT_ERROR("Failed to adjust buffer color"); |
| post_event((unsigned long)buffer, 0, OMX_COMPONENT_GENERATE_EBD); |
| return OMX_ErrorUndefined; |
| } |
| } |
| if (m_sExtraData && !dev_handle_input_extradata((void *)buffer, fd)) { |
| DEBUG_PRINT_ERROR("Failed to parse input extradata\n"); |
| #ifdef _ANDROID_ICS_ |
| omx_release_meta_buffer(buffer); |
| #endif |
| post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD); |
| /*Generate an async error and move to invalid state*/ |
| pending_input_buffers--; |
| return OMX_ErrorBadParameter; |
| } |
| #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("ERROR: ETBProxy: dev_empty_buf failed"); |
| #ifdef _ANDROID_ICS_ |
| omx_release_meta_buffer(buffer); |
| #endif |
| post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD); |
| /*Generate an async error and move to invalid state*/ |
| pending_input_buffers--; |
| if (hw_overload) { |
| return OMX_ErrorInsufficientResources; |
| } |
| 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("FTB: buffer->pBuffer[%p]", buffer->pBuffer); |
| if (m_state != OMX_StateExecuting && |
| m_state != OMX_StatePause && |
| m_state != OMX_StateIdle) { |
| DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State"); |
| return OMX_ErrorInvalidState; |
| } |
| |
| if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid"); |
| return OMX_ErrorVersionMismatch; |
| } |
| |
| if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index"); |
| return OMX_ErrorBadPortIndex; |
| } |
| |
| if (!m_sOutPortDef.bEnabled) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled"); |
| return OMX_ErrorIncorrectStateOperation; |
| } |
| |
| post_event((unsigned long) hComp, (unsigned long)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) |
| { |
| (void)hComp; |
| OMX_U8 *pmem_data_buf = NULL; |
| OMX_ERRORTYPE nRet = OMX_ErrorNone; |
| |
| DEBUG_PRINT_LOW("FTBProxy: bufferAdd->pBuffer[%p]", bufferAdd->pBuffer); |
| |
| if (bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= (int)m_sOutPortDef.nBufferCountActual) ) { |
| DEBUG_PRINT_ERROR("ERROR: FTBProxy: Invalid i/p params"); |
| 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("o/p port is Disabled or Flush in Progress"); |
| post_event ((unsigned long)bufferAdd,0, |
| OMX_COMPONENT_GENERATE_FBD); |
| return OMX_ErrorNone; |
| } |
| |
| if (output_use_buffer && !m_use_output_pmem) { |
| DEBUG_PRINT_LOW("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("ERROR: dev_fill_buf() Failed"); |
| post_event ((unsigned long)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) |
| { |
| (void)hComp; |
| m_pCallbacks = *callbacks; |
| DEBUG_PRINT_LOW("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) |
| { |
| (void)hComp, (void)bufferHdr, (void)port, (void)appData, (void)eglImage; |
| DEBUG_PRINT_ERROR("ERROR: use_EGL_image: Not Implemented"); |
| 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) |
| { |
| (void)hComp; |
| 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",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",role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| 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",role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| 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",role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| 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",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",role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| 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",role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| 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",role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| #endif |
| else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { |
| if ((0 == index) && role) { |
| strlcpy((char *)role, "video_encoder.hevc", OMX_MAX_STRINGNAME_SIZE); |
| DEBUG_PRINT_LOW("component_role_enum: role %s", role); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: No more roles"); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| else { |
| DEBUG_PRINT_ERROR("ERROR: Querying Role on Unknown Component"); |
| 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()"); |
| 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()"); |
| 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()"); |
| 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 = %u", |
| buffer->pBuffer, (unsigned)buffer->nFlags, (unsigned int)buffer->nFilledLen); |
| if (buffer == NULL || ((buffer - m_out_mem_ptr) > (int)m_sOutPortDef.nBufferCountActual)) { |
| return OMX_ErrorBadParameter; |
| } |
| |
| pending_output_buffers--; |
| |
| if(!secure_session) { |
| 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++; |
| |
| if (dev_get_output_log_flag()) { |
| dev_output_log_buffers((const char*)buffer->pBuffer, buffer->nFilledLen); |
| } |
| } |
| if (buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { |
| if (!dev_handle_output_extradata((void *)buffer)) |
| DEBUG_PRINT_ERROR("Failed to parse output extradata"); |
| |
| dev_extradata_log_buffers((char *)(((unsigned long)buffer->pBuffer + buffer->nOffset + |
| buffer->nFilledLen + 3) & (~3))); |
| } |
| 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; |
| |
| buffer_index = buffer - ((mUseProxyColorFormat && !mUsesColorConversion) ? meta_buffer_hdr : m_inp_mem_ptr); |
| DEBUG_PRINT_LOW("empty_buffer_done: buffer[%p]", buffer); |
| if (buffer == NULL || |
| ((buffer_index > (int)m_sInPortDef.nBufferCountActual))) { |
| DEBUG_PRINT_ERROR("ERROR in empty_buffer_done due to index buffer"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| pending_input_buffers--; |
| |
| if (mUseProxyColorFormat && |
| (buffer_index >= 0 && (buffer_index < (int)m_sInPortDef.nBufferCountActual))) { |
| if (!pdest_frame && !input_flush_progress && mUsesColorConversion) { |
| pdest_frame = buffer; |
| DEBUG_PRINT_LOW("empty_buffer_done pdest_frame address is %p",pdest_frame); |
| return push_input_buffer(hComp); |
| } |
| //check if empty-EOS-buffer is being returned, treat this same as the |
| //color-conversion case as we queued a color-conversion buffer to encoder |
| bool handleEmptyEosBuffer = (mEmptyEosBuffer == buffer); |
| if (mUsesColorConversion || handleEmptyEosBuffer) { |
| if (handleEmptyEosBuffer) { |
| mEmptyEosBuffer = NULL; |
| } |
| // return color-conversion buffer back to the pool |
| DEBUG_PRINT_LOW("empty_buffer_done insert address is %p",buffer); |
| if (!m_opq_pmem_q.insert_entry((unsigned long)buffer, 0, 0)) { |
| DEBUG_PRINT_ERROR("empty_buffer_done: pmem queue is full"); |
| return OMX_ErrorBadParameter; |
| } |
| } else { |
| // We are not dealing with color-conversion, Buffer being returned |
| // here is client's buffer, return it back to client |
| if (m_pCallbacks.EmptyBufferDone && buffer) { |
| m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer); |
| DEBUG_PRINT_LOW("empty_buffer_done: Returning client buf %p", buffer); |
| } |
| } |
| } 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 long p1; |
| unsigned long p2; |
| unsigned long 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("ERROR: empty_buffer_done() failed!"); |
| omx_report_error (); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_FBD: |
| if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) { |
| DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!"); |
| 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", |
| (int)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", (int)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", (int)profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %d", (int)profileLevelType->nPortIndex); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d", |
| (int)profileLevelType->eProfile, (int)profileLevelType->eLevel); |
| return eRet; |
| } |
| #endif |
| |
| #ifdef MAX_RES_1080P |
| OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| if (!profileLevelType) |
| return OMX_ErrorBadParameter; |
| |
| if (profileLevelType->nPortIndex == 1) { |
| if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) { |
| #if defined _MSM8974_ && !defined _MSM8226_ |
| if (profileLevelType->nProfileIndex == 0) { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; |
| } else if (profileLevelType->nProfileIndex == 1) { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; |
| } else if (profileLevelType->nProfileIndex == 2) { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; |
| } else if (profileLevelType->nProfileIndex == 3) { |
| profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; |
| } else if (profileLevelType->nProfileIndex == 4) { |
| profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; |
| } else { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", |
| (unsigned int)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; |
| #ifdef _MSM8226_ |
| } else if (profileLevelType->nProfileIndex == 3) { |
| profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; |
| #endif |
| } else { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d", |
| (int)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 %u", (unsigned int)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 %u", (unsigned int)profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) { |
| if (profileLevelType->nProfileIndex == 0) { |
| profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_VP8Level_Version0; |
| } else if (profileLevelType->nProfileIndex == 1) { |
| profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_VP8Level_Version1; |
| } else { |
| DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", |
| (unsigned int)profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingHEVC) { |
| if (profileLevelType->nProfileIndex == 0) { |
| profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel52; |
| } else if (profileLevelType->nProfileIndex == 1) { |
| profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10; |
| profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel52; |
| } else { |
| DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", |
| (unsigned int)profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore"); |
| eRet = OMX_ErrorNoMore; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u", |
| (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel); |
| return eRet; |
| } |
| #endif |
| |
| #ifdef USE_ION |
| int omx_video::alloc_map_ion_memory(int size, |
| struct ion_allocation_data *alloc_data, |
| struct ion_fd_data *fd_data,int flag) |
| { |
| struct venc_ion buf_ion_info; |
| int ion_device_fd =-1,rc=0,ion_dev_flags = 0; |
| if (size <=0 || !alloc_data || !fd_data) { |
| DEBUG_PRINT_ERROR("Invalid 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("ERROR: ION Device open() Failed"); |
| return ion_device_fd; |
| } |
| |
| if(secure_session) { |
| alloc_data->len = (size + (SECURE_ALIGN - 1)) & ~(SECURE_ALIGN - 1); |
| alloc_data->align = SECURE_ALIGN; |
| alloc_data->flags = flag; |
| alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID); |
| if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) { |
| alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); |
| } |
| DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %u align %u flags %x", |
| (unsigned int)alloc_data->len, (unsigned int)alloc_data->align, |
| alloc_data->flags); |
| } else { |
| alloc_data->len = (size + (SZ_4K - 1)) & ~(SZ_4K - 1); |
| alloc_data->align = SZ_4K; |
| alloc_data->flags = (flag & ION_FLAG_CACHED ? ION_FLAG_CACHED : 0); |
| #ifdef MAX_RES_720P |
| alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID); |
| #else |
| alloc_data->heap_id_mask = (ION_HEAP(MEM_HEAP_ID) | |
| ION_HEAP(ION_IOMMU_HEAP_ID)); |
| #endif |
| DEBUG_PRINT_HIGH("ION ALLOC unsec buf: size %u align %u flags %x", |
| (unsigned int)alloc_data->len, (unsigned int)alloc_data->align, |
| alloc_data->flags); |
| } |
| |
| rc = ioctl(ion_device_fd,ION_IOC_ALLOC,alloc_data); |
| if (rc || !alloc_data->handle) { |
| DEBUG_PRINT_ERROR("ION ALLOC memory failed 0x%x", rc); |
| alloc_data->handle = 0; |
| 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("ION MAP failed "); |
| buf_ion_info.ion_alloc_data = *alloc_data; |
| buf_ion_info.ion_device_fd = ion_device_fd; |
| buf_ion_info.fd_ion_data = *fd_data; |
| free_ion_memory(&buf_ion_info); |
| fd_data->fd =-1; |
| ion_device_fd =-1; |
| } |
| return ion_device_fd; |
| } |
| |
| void omx_video::free_ion_memory(struct venc_ion *buf_ion_info) |
| { |
| if (!buf_ion_info) { |
| DEBUG_PRINT_ERROR("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("ION free failed "); |
| return; |
| } |
| close(buf_ion_info->ion_device_fd); |
| buf_ion_info->ion_alloc_data.handle = 0; |
| 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 (mUsesColorConversion && |
| (index_pmem < m_sInPortDef.nBufferCountActual)) { |
| if (!dev_free_buf((&m_pInput_pmem[index_pmem]),PORT_INDEX_IN)) { |
| DEBUG_PRINT_ERROR("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("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("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("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("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_HIGH("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("Status of getbuffer is %d", cret); |
| ret = (cret)?false:true; |
| buf_size = bufferreq.size; |
| } |
| return ret; |
| } |
| |
| bool omx_video::is_conv_needed(int hal_fmt, int hal_flags) |
| { |
| bool bRet = hal_fmt == HAL_PIXEL_FORMAT_RGBA_8888 && |
| !(hal_flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED); |
| #ifdef _HW_RGBA |
| bRet = false; |
| #endif |
| DEBUG_PRINT_LOW("RGBA conversion %s", bRet ? "Needed":"Not-Needed"); |
| return bRet; |
| } |
| |
| void omx_video::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) { |
| DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d", |
| prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs); |
| } |
| |
| 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; |
| private_handle_t *handle = NULL; |
| DEBUG_PRINT_LOW("ETBProxyOpaque: buffer[%p]", buffer); |
| |
| if (buffer == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid buffer[%p]",buffer); |
| return OMX_ErrorBadParameter; |
| } |
| nBufIndex = buffer - meta_buffer_hdr; |
| if (nBufIndex >= m_sInPortDef.nBufferCountActual) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid bufindex = %u", |
| nBufIndex); |
| return OMX_ErrorBadParameter; |
| } |
| media_buffer = (encoder_media_buffer_type *)buffer->pBuffer; |
| if ((!media_buffer || !media_buffer->meta_handle) && |
| !(buffer->nFlags & OMX_BUFFERFLAG_EOS)) { |
| DEBUG_PRINT_ERROR("Incorrect Buffer queued media buffer = %p", |
| media_buffer); |
| m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer); |
| return OMX_ErrorBadParameter; |
| } else if (media_buffer) { |
| handle = (private_handle_t *)media_buffer->meta_handle; |
| } |
| |
| if (media_buffer && media_buffer->buffer_type == |
| kMetadataBufferTypeCameraSource) { |
| return empty_this_buffer_proxy(hComp, buffer); |
| } |
| |
| /*Enable following code once private handle color format is |
| updated correctly*/ |
| |
| if (buffer->nFilledLen > 0 && handle) { |
| if (c2d_opened && handle->format != c2d_conv.get_src_format()) { |
| c2d_conv.close(); |
| c2d_opened = false; |
| } |
| |
| if (!c2d_opened) { |
| mUsesColorConversion = is_conv_needed(handle->format, handle->flags); |
| if (mUsesColorConversion) { |
| DEBUG_PRINT_INFO("open Color conv forW: %u, H: %u", |
| (unsigned int)m_sInPortDef.format.video.nFrameWidth, |
| (unsigned int)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("Color conv open failed"); |
| return OMX_ErrorBadParameter; |
| } |
| c2d_opened = true; |
| #ifdef _MSM8974_ |
| if (!dev_set_format(NV12_128m)) |
| DEBUG_PRINT_ERROR("cannot set color format"); |
| #endif |
| } |
| } |
| } |
| if (input_flush_progress == true) { |
| m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); |
| DEBUG_PRINT_ERROR("ERROR: 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 long)buffer,0,0)) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy: Queue is full"); |
| m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); |
| ret = OMX_ErrorBadParameter; |
| } |
| } |
| return ret; |
| } |
| |
| OMX_ERRORTYPE omx_video::queue_meta_buffer(OMX_HANDLETYPE hComp, |
| struct pmem &Input_pmem_info) |
| { |
| |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| unsigned long address = 0,p2,id; |
| |
| DEBUG_PRINT_LOW("In queue Meta Buffer"); |
| if (!psource_frame || !pdest_frame) { |
| DEBUG_PRINT_ERROR("convert_queue_buffer invalid params"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (psource_frame->nFilledLen > 0) { |
| if (dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) { |
| DEBUG_PRINT_ERROR("ERROR: in dev_use_buf"); |
| post_event ((unsigned long)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; |
| } |
| } else { |
| // there has been an error and source frame has been scheduled for an EBD |
| psource_frame = NULL; |
| } |
| return ret; |
| } |
| |
| OMX_ERRORTYPE omx_video::convert_queue_buffer(OMX_HANDLETYPE hComp, |
| struct pmem &Input_pmem_info,unsigned long &index) |
| { |
| |
| unsigned char *uva; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| unsigned long address = 0,p2,id; |
| |
| DEBUG_PRINT_LOW("In Convert and queue Meta Buffer"); |
| if (!psource_frame || !pdest_frame) { |
| DEBUG_PRINT_ERROR("convert_queue_buffer invalid params"); |
| return OMX_ErrorBadParameter; |
| } |
| if (secure_session) { |
| DEBUG_PRINT_ERROR("cannot convert buffer during secure session"); |
| return OMX_ErrorInvalidState; |
| } |
| |
| if (!psource_frame->nFilledLen) { |
| if(psource_frame->nFlags & OMX_BUFFERFLAG_EOS) { |
| pdest_frame->nFilledLen = psource_frame->nFilledLen; |
| pdest_frame->nTimeStamp = psource_frame->nTimeStamp; |
| pdest_frame->nFlags = psource_frame->nFlags; |
| DEBUG_PRINT_HIGH("Skipping color conversion for empty EOS Buffer " |
| "header=%p filled-len=%u", pdest_frame, (unsigned int)pdest_frame->nFilledLen); |
| } else { |
| pdest_frame->nOffset = 0; |
| pdest_frame->nFilledLen = 0; |
| pdest_frame->nTimeStamp = psource_frame->nTimeStamp; |
| pdest_frame->nFlags = psource_frame->nFlags; |
| DEBUG_PRINT_LOW("Buffer header %p Filled len size %u", |
| pdest_frame, (unsigned int)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("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("Buffer header %p Filled len size %u", |
| pdest_frame, (unsigned int)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("ERROR: in dev_use_buf"); |
| post_event ((unsigned long)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("pdest_frame pop address is %p",pdest_frame); |
| } |
| } else { |
| // there has been an error and source frame has been scheduled for an EBD |
| psource_frame = NULL; |
| } |
| return ret; |
| } |
| |
| OMX_ERRORTYPE omx_video::push_input_buffer(OMX_HANDLETYPE hComp) |
| { |
| unsigned long address = 0,p2,id, index = 0; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| |
| DEBUG_PRINT_LOW("In push input buffer"); |
| 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("Output buffer index is wrong %u act count %u", |
| (unsigned int)index, (unsigned int)m_sInPortDef.nBufferCountActual); |
| return OMX_ErrorBadParameter; |
| } |
| |
| //Meta-Buffer with empty filled-length can contain garbage handle |
| //Some clients queue such buffers to signal EOS. Handle this case |
| // separately by queueing an intermediate color-conversion buffer |
| // and propagate the EOS. |
| if (psource_frame->nFilledLen == 0 && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) { |
| return push_empty_eos_buffer(hComp, psource_frame); |
| } |
| 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; |
| m_graphicBufferSize = handle->size; |
| if (is_conv_needed(handle->format, handle->flags)) |
| ret = convert_queue_buffer(hComp,Input_pmem_info,index); |
| else if (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE || |
| handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m || |
| handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed || |
| handle->format == HAL_PIXEL_FORMAT_RGBA_8888 || |
| handle->format == QOMX_COLOR_Format32bitRGBA8888Compressed) |
| ret = queue_meta_buffer(hComp,Input_pmem_info); |
| else |
| ret = OMX_ErrorBadParameter; |
| } |
| } |
| return ret; |
| } |
| |
| OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp, |
| OMX_BUFFERHEADERTYPE* buffer) { |
| OMX_BUFFERHEADERTYPE* opqBuf = NULL; |
| OMX_ERRORTYPE retVal = OMX_ErrorNone; |
| unsigned index = 0; |
| |
| DEBUG_PRINT_LOW("In push empty eos buffer"); |
| do { |
| if (mUsesColorConversion) { |
| if (pdest_frame) { |
| //[1] use a checked out conversion buffer, if one is available |
| opqBuf = pdest_frame; |
| pdest_frame = NULL; |
| } else if (m_opq_pmem_q.m_size) { |
| //[2] else pop out one from the queue, if available |
| unsigned long address = 0, p2, id; |
| m_opq_pmem_q.pop_entry(&address,&p2,&id); |
| opqBuf = (OMX_BUFFERHEADERTYPE* ) address; |
| } |
| index = opqBuf - m_inp_mem_ptr; |
| } else { |
| opqBuf = (OMX_BUFFERHEADERTYPE* ) buffer; |
| index = opqBuf - meta_buffer_hdr; |
| } |
| |
| if (!opqBuf || index >= m_sInPortDef.nBufferCountActual) { |
| DEBUG_PRINT_ERROR("push_empty_eos_buffer: Could not find a " |
| "color-conversion buffer to queue ! defer until available"); |
| //[3] else, returning back will defer calling this function again |
| //until a conversion buffer is returned by the encoder and also |
| //hold on to the client's buffer |
| return OMX_ErrorNone; |
| } |
| struct pmem Input_pmem_info; |
| Input_pmem_info.buffer = opqBuf; |
| Input_pmem_info.fd = m_pInput_pmem[index].fd; |
| Input_pmem_info.offset = 0; |
| Input_pmem_info.size = m_pInput_pmem[index].size; |
| |
| if (dev_use_buf(&Input_pmem_info, PORT_INDEX_IN, 0) != true) { |
| DEBUG_PRINT_ERROR("ERROR: in dev_use_buf for empty eos buffer"); |
| retVal = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| //Queue with null pBuffer, as pBuffer in client's hdr can be junk |
| //Clone the color-conversion buffer to avoid overwriting original buffer |
| OMX_BUFFERHEADERTYPE emptyEosBufHdr; |
| memcpy(&emptyEosBufHdr, opqBuf, sizeof(OMX_BUFFERHEADERTYPE)); |
| emptyEosBufHdr.nFilledLen = 0; |
| emptyEosBufHdr.nTimeStamp = buffer->nTimeStamp; |
| emptyEosBufHdr.nFlags = buffer->nFlags; |
| emptyEosBufHdr.pBuffer = NULL; |
| if (!mUsesColorConversion && !mUseProxyColorFormat) |
| emptyEosBufHdr.nAllocLen = m_sInPortDef.nBufferSize; |
| else if (mUseProxyColorFormat) |
| emptyEosBufHdr.nAllocLen = m_graphicBufferSize > 0 ? m_graphicBufferSize : m_sInPortDef.nBufferSize; |
| if (dev_empty_buf(&emptyEosBufHdr, 0, index, m_pInput_pmem[index].fd) != true) { |
| DEBUG_PRINT_ERROR("ERROR: in dev_empty_buf for empty eos buffer"); |
| dev_free_buf(&Input_pmem_info, PORT_INDEX_IN); |
| retVal = OMX_ErrorBadParameter; |
| break; |
| } |
| mEmptyEosBuffer = opqBuf; |
| } while(false); |
| |
| //return client's buffer regardless since intermediate color-conversion |
| //buffer is sent to the the encoder |
| m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer); |
| --pending_input_buffers; |
| return retVal; |
| } |
| |
| // no code beyond this ! |
| |
| // inline import of vendor extensions implementation |
| #include "omx_video_extensions.hpp" |