| /*-------------------------------------------------------------------------- |
| Copyright (c) 2010-2019, 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 <qdMetaData.h> |
| #include "omx_video_base.h" |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <sys/prctl.h> |
| #include <sys/ioctl.h> |
| #ifdef _ANDROID_ICS_ |
| #include <media/hardware/HardwareAPI.h> |
| #include <gralloc_priv.h> |
| #endif |
| #ifdef _USE_GLIB_ |
| #include <glib.h> |
| #define strlcpy g_strlcpy |
| #endif |
| #define H264_SUPPORTED_WIDTH (480) |
| #define H264_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 |
| #undef ALIGN |
| #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1)) |
| |
| #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 SLAVE_SIDE_CP |
| #define MEM_HEAP_ID ION_CP_MM_HEAP_ID |
| #define SECURE_ALIGN SZ_1M |
| #define SECURE_FLAGS_INPUT_BUFFER ION_FLAG_SECURE |
| #define SECURE_FLAGS_OUTPUT_BUFFER ION_FLAG_SECURE |
| #else //MASTER_SIDE_CP |
| #define MEM_HEAP_ID ION_SECURE_HEAP_ID |
| #define SECURE_ALIGN SZ_4K |
| #define SECURE_FLAGS_INPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_PIXEL) |
| #define SECURE_FLAGS_OUTPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_BITSTREAM) |
| #endif |
| |
| // Gralloc flag to indicate UBWC |
| #define GRALLOC1_CONSUMER_USAGE_UBWC_FLAG GRALLOC1_CONSUMER_USAGE_PRIVATE_0 |
| |
| 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_enc(void *input) |
| { |
| omx_video* omx = reinterpret_cast<omx_video*>(input); |
| int ret; |
| |
| DEBUG_PRINT_HIGH("omx_venc: message thread start"); |
| prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0); |
| while (!omx->msg_thread_stop) { |
| ret = omx->signal.wait(2 * 1000000000); |
| if (ret == ETIMEDOUT || omx->msg_thread_stop) { |
| continue; |
| } else if (ret) { |
| DEBUG_PRINT_ERROR("omx_venc: message_thread_enc wait on condition failed, exiting"); |
| break; |
| } |
| omx->process_event_cb(omx); |
| } |
| 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); |
| omx->signal.signal(); |
| } |
| |
| // 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; |
| } |
| |
| |
| /* ====================================================================== |
| 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), |
| #ifdef _UBWC_ |
| m_ubwc_supported(true), |
| #else |
| m_ubwc_supported(false), |
| #endif |
| mUsesColorConversion(false), |
| mC2dSrcFmt(NO_COLOR_FORMAT), |
| mC2dDestFmt(NO_COLOR_FORMAT), |
| mC2DFrameHeight(0), |
| mC2DFrameWidth(0), |
| 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_sParamConsumerUsage(0), |
| m_input_msg_id(OMX_COMPONENT_GENERATE_ETB), |
| m_inp_mem_ptr(NULL), |
| m_out_mem_ptr(NULL), |
| m_client_output_extradata_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), |
| allocate_native_handle(false), |
| m_out_bm_count(0), |
| m_client_out_bm_count(0), |
| m_client_in_bm_count(0), |
| m_inp_bm_count(0), |
| m_out_extradata_bm_count(0), |
| m_flags(0), |
| m_etb_count(0), |
| m_fbd_count(0), |
| m_event_port_settings_sent(false), |
| hw_overload(false), |
| m_graphicbuffer_size(0), |
| m_buffer_freed(0), |
| profile_mode(false), |
| profile_frame_count(0), |
| profile_start_time(0), |
| profile_last_time(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; |
| |
| OMX_INIT_STRUCT(&m_blurInfo, OMX_QTI_VIDEO_CONFIG_BLURINFO); |
| m_blurInfo.nPortIndex == (OMX_U32)PORT_INDEX_IN; |
| |
| mMapPixelFormat2Converter.insert({ |
| {HAL_PIXEL_FORMAT_RGBA_8888, RGBA8888}, |
| {HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC, NV12_UBWC}, |
| {HAL_PIXEL_FORMAT_NV12_HEIF, NV12_512}, |
| }); |
| |
| pthread_mutex_init(&m_lock, NULL); |
| pthread_mutex_init(&m_TimeStampInfo.m_lock, NULL); |
| m_TimeStampInfo.deferred_inbufq.m_size=0; |
| m_TimeStampInfo.deferred_inbufq.m_read = m_TimeStampInfo.deferred_inbufq.m_write = 0; |
| sem_init(&m_cmd_lock,0,0); |
| DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr); |
| |
| memset(m_platform, 0, sizeof(m_platform)); |
| #ifdef _ANDROID_ |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| property_get("ro.board.platform", property_value, "0"); |
| strlcpy(m_platform, property_value, sizeof(m_platform)); |
| property_get("vendor.vidc.enc.profile.in", property_value, "0"); |
| profile_mode = !!atoi(property_value); |
| #endif |
| |
| 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()"); |
| /*For V4L2 based drivers, pthread_join is done in device_close |
| * so no need to do it here*/ |
| pthread_mutex_destroy(&m_lock); |
| pthread_mutex_destroy(&m_TimeStampInfo.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); |
| if (profile_mode && (profile_start_time < profile_last_time)) { |
| DEBUG_PRINT_HIGH("Input frame rate = %f", |
| ((profile_frame_count - 1) * 1e6) / (profile_last_time - profile_start_time)); |
| } |
| 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 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) { |
| switch (ident) { |
| 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); |
| if (pThis->m_state == OMX_StateLoaded) { |
| m_buffer_freed = false; |
| } |
| 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; |
| 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", (unsigned int)ident); |
| 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) || |
| (eState == OMX_StateWaitForResources) || |
| (eState == OMX_StateIdle) || |
| (eState == OMX_StateExecuting) || |
| (eState == OMX_StatePause) || |
| (eState == 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); |
| /* 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(); |
| 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++; |
| VIDC_TRACE_INT_LOW("FTB-pending", 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++; |
| VIDC_TRACE_INT_LOW("ETB-pending", 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); |
| } |
| } |
| while (m_TimeStampInfo.deferred_inbufq.m_size) { |
| m_TimeStampInfo.deferred_inbufq.pop_entry(&p1,&p2,&ident); |
| m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p1); |
| } |
| 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 |
| ==========================================================================*/ |
| 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++; |
| VIDC_TRACE_INT_LOW("ETB-pending", 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); |
| } |
| } |
| |
| while (m_TimeStampInfo.deferred_inbufq.m_size) { |
| m_TimeStampInfo.deferred_inbufq.pop_entry(&p1,&p2,&ident); |
| m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p1); |
| } |
| |
| 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++; |
| VIDC_TRACE_INT_LOW("FTB-pending", 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; |
| } |
| |
| /* ====================================================================== |
| 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; |
| } |
| |
| bool omx_video::reject_param_for_TME_mode(int index) { |
| int allowed_params[] = { |
| OMX_IndexParamPortDefinition, |
| OMX_IndexParamVideoPortFormat, |
| OMX_IndexParamVideoInit, |
| OMX_IndexParamAudioInit, |
| OMX_IndexParamImageInit, |
| OMX_IndexParamOtherInit, |
| OMX_IndexParamStandardComponentRole, |
| OMX_IndexParamPriorityMgmt, |
| OMX_IndexParamCompBufferSupplier, |
| OMX_GoogleAndroidIndexAllocateNativeHandle, |
| OMX_QcomIndexPortDefn, |
| OMX_QcomIndexParamVideoMetaBufferMode, |
| OMX_QTIIndexParamLowLatencyMode, |
| OMX_IndexParamVideoTme, |
| OMX_IndexParamVideoProfileLevelQuerySupported, |
| OMX_IndexParamConsumerUsageBits |
| }; |
| |
| if (m_sOutPortFormat.eCompressionFormat != (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingTME) { |
| return false; |
| } |
| |
| for (unsigned i = 0; i < (sizeof(allowed_params) / sizeof(int)); i++) { |
| if (index == allowed_params[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| bool omx_video::reject_config_for_TME_mode(int index) { |
| int allowed_configs[] = { |
| OMX_IndexConfigVideoFramerate, |
| OMX_IndexConfigPriority, |
| OMX_IndexConfigOperatingRate, |
| OMX_IndexConfigTimePosition, |
| OMX_QcomIndexConfigPerfLevel, |
| OMX_QTIIndexConfigDescribeColorAspects, |
| OMX_IndexConfigAndroidVendorExtension |
| }; |
| |
| if (m_sOutPortFormat.eCompressionFormat != (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingTME) { |
| return false; |
| } |
| |
| for (unsigned i = 0; i < (sizeof(allowed_configs) / sizeof(int)); i++) { |
| if (index == allowed_configs[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /* ====================================================================== |
| 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; |
| |
| 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; |
| } |
| |
| if (reject_param_for_TME_mode(paramIndex)) { |
| DEBUG_PRINT_ERROR("ERROR: Set Parameter 0x%x rejected in TME mode", (int)paramIndex); |
| return OMX_ErrorNone; |
| } |
| |
| 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: port %d", portDefn->nPortIndex); |
| if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) { |
| dev_get_buf_req (&m_sInPortDef.nBufferCountMin, |
| &m_sInPortDef.nBufferCountActual, |
| &m_sInPortDef.nBufferSize, |
| m_sInPortDef.nPortIndex); |
| |
| memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef)); |
| #ifdef _ANDROID_ICS_ |
| if (meta_mode_enable) { |
| // request size of largest metadata (happens to be NativeHandleSource) since |
| // we do not know the exact metadata-type yet |
| portDefn->nBufferSize = sizeof(LEGACY_CAM_METADATA_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); |
| dev_get_dimensions(m_sOutPortDef.nPortIndex, |
| &m_sOutPortDef.format.video.nFrameWidth, |
| &m_sOutPortDef.format.video.nFrameHeight); |
| } |
| |
| memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef)); |
| // Tiling in HW expects output port def to be aligned to tile size |
| // At the same time, FWK needs original WxH for various purposes |
| // Sending input WxH as output port def WxH to FWK |
| if (m_sOutPortDef.format.video.eCompressionFormat == |
| OMX_VIDEO_CodingImageHEIC) { |
| portDefn->format.video.nFrameWidth = |
| m_sInPortDef.format.video.nFrameWidth; |
| portDefn->format.video.nFrameHeight = |
| m_sInPortDef.format.video.nFrameHeight; |
| } |
| |
| if (secure_session || allocate_native_handle) { |
| portDefn->nBufferSize = |
| sizeof(native_handle_t) + (sizeof(int) * (1/*numFds*/ + 3/*numInts*/)); |
| } |
| } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_EXTRADATA_OUT) { |
| portDefn->nBufferSize = m_client_out_extradata_info.getSize(); |
| portDefn->nBufferCountMin= m_sOutPortDef.nBufferCountMin; |
| portDefn->nBufferCountActual = m_client_out_extradata_info.getBufferCount(); |
| portDefn->eDir = OMX_DirOutput; |
| DEBUG_PRINT_LOW("extradata port: size = %u, min cnt = %u, actual cnt = %u", |
| (unsigned int)portDefn->nBufferSize, (unsigned int)portDefn->nBufferCountMin, |
| (unsigned int)portDefn->nBufferCountActual); |
| } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_EXTRADATA_IN) { |
| portDefn->nBufferSize = m_client_in_extradata_info.getSize(); |
| portDefn->nBufferCountMin= m_sInPortDef.nBufferCountMin; |
| portDefn->nBufferCountActual = m_client_in_extradata_info.getBufferCount(); |
| portDefn->eDir = OMX_DirInput; |
| DEBUG_PRINT_LOW("extradata port: size = %u, min cnt = %u, actual cnt = %u", |
| (unsigned int)portDefn->nBufferSize, (unsigned int)portDefn->nBufferCountMin, |
| (unsigned int)portDefn->nBufferCountActual); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| |
| DEBUG_PRINT_HIGH("get_parameter: OMX_IndexParamPortDefinition: port %d, wxh %dx%d, min %d, actual %d, size %d, colorformat %#x, compression format %#x", |
| portDefn->nPortIndex, portDefn->format.video.nFrameWidth, |
| portDefn->format.video.nFrameHeight, portDefn->nBufferCountMin, |
| portDefn->nBufferCountActual, portDefn->nBufferSize, |
| portDefn->format.video.eColorFormat, portDefn->format.video.eCompressionFormat); |
| |
| 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; |
| OMX_U32 colorFormat = OMX_COLOR_FormatUnused; |
| if(dev_get_supported_color_format(index, &colorFormat)) { |
| memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat)); |
| portFmt->nIndex = index; //restore index set from client |
| portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; |
| } else { |
| eRet = OMX_ErrorNoMore; |
| } |
| } 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_INDEXTYPE)OMX_IndexParamVideoTme: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_PARAM_TMETYPE); |
| QOMX_VIDEO_PARAM_TMETYPE* pParam = (QOMX_VIDEO_PARAM_TMETYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoTme"); |
| memcpy(pParam, &m_sParamTME, sizeof(m_sParamTME)); |
| break; |
| } |
| case OMX_IndexParamVideoAndroidImageGrid: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE); |
| OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE* pParam = |
| (OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAndroidImageGrid"); |
| m_sParamAndroidImageGrid.bEnabled = OMX_TRUE; |
| m_sParamAndroidImageGrid.nTileWidth = DEFAULT_TILE_DIMENSION; |
| m_sParamAndroidImageGrid.nTileHeight = DEFAULT_TILE_DIMENSION; |
| m_sParamAndroidImageGrid.nGridRows = |
| m_sInPortDef.format.video.nFrameHeight > 0 ? |
| ((m_sInPortDef.format.video.nFrameHeight - 1) / DEFAULT_TILE_DIMENSION + 1) : |
| DEFAULT_TILE_ROWS; |
| m_sParamAndroidImageGrid.nGridCols = |
| m_sInPortDef.format.video.nFrameWidth > 0 ? |
| ((m_sInPortDef.format.video.nFrameWidth - 1) / DEFAULT_TILE_DIMENSION + 1) : |
| DEFAULT_TILE_COLS; |
| memcpy(pParam, &m_sParamAndroidImageGrid, sizeof(m_sParamAndroidImageGrid)); |
| 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 = dev_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; |
| } |
| case OMX_QcomIndexConfigH264EntropyCodingCabac: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_H264ENTROPYCODINGTYPE); |
| QOMX_VIDEO_H264ENTROPYCODINGTYPE * pParam = (QOMX_VIDEO_H264ENTROPYCODINGTYPE*)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexConfigH264EntropyCodingCabac"); |
| memcpy(pParam, &m_sParamEntropy, sizeof(m_sParamEntropy)); |
| 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 QOMX_IndexParamVideoInitialQp: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP); |
| QOMX_EXTNINDEX_VIDEO_INITIALQP *initial_qp = (QOMX_EXTNINDEX_VIDEO_INITIALQP*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoInitialQp"); |
| initial_qp->nQpI = m_sSessionQuantization.nQpI; |
| initial_qp->nQpP = m_sSessionQuantization.nQpP; |
| initial_qp->nQpB = m_sSessionQuantization.nQpB; |
| initial_qp->bEnableInitQp = m_QPSet; |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoIPBQPRange: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE); |
| OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_IPB_QPRANGETYPE*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoIPBQPRange"); |
| 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; |
| } |
| 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; |
| } |
| } else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoLTRInfo) { |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| pParam->bEnabled = |
| (OMX_BOOL)(m_sExtraData & VENC_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; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)", |
| pParam->nPortIndex); |
| eRet = OMX_ErrorUnsupportedIndex; |
| } |
| break; |
| } |
| case OMX_QTIIndexParamVideoClientExtradata: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE); |
| DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata"); |
| QOMX_EXTRADATA_ENABLE *pParam = |
| (QOMX_EXTRADATA_ENABLE *)paramData; |
| if (pParam->nPortIndex == PORT_INDEX_EXTRADATA_OUT) { |
| OMX_U32 output_extradata_mask = VENC_EXTRADATA_SLICEINFO | VENC_EXTRADATA_LTRINFO | |
| VENC_EXTRADATA_MBINFO; |
| pParam->bEnable = (m_sExtraData & output_extradata_mask) ? OMX_TRUE : OMX_FALSE; |
| eRet = OMX_ErrorNone; |
| } else if (pParam->nPortIndex == PORT_INDEX_EXTRADATA_IN) { |
| OMX_U32 input_extradata_mask = VENC_EXTRADATA_ROI; |
| pParam->bEnable = (m_sExtraData & input_extradata_mask) ? OMX_TRUE : OMX_FALSE; |
| eRet = OMX_ErrorNone; |
| } else { |
| DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)", |
| pParam->nPortIndex); |
| 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; |
| } |
| 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_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 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, &m_sParamTemporalLayers.eSupportedPatterns)) { |
| DEBUG_PRINT_ERROR("Failed to get temporal layer capabilities"); |
| eRet = OMX_ErrorHardware; |
| } |
| memcpy(pLayerInfo, &m_sParamTemporalLayers, sizeof(m_sParamTemporalLayers)); |
| break; |
| } |
| case OMX_QcomIndexParamVideoDownScalar: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR); |
| QOMX_INDEXDOWNSCALAR *pDownScalarParam = |
| reinterpret_cast<QOMX_INDEXDOWNSCALAR *>(paramData); |
| memcpy(pDownScalarParam, &m_sParamDownScalar, sizeof(m_sParamDownScalar)); |
| break; |
| } |
| case OMX_IndexParamVideoAndroidVp8Encoder: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE); |
| OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pVp8Params = |
| reinterpret_cast<OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE*>(paramData); |
| memcpy(pVp8Params,&m_sParamVP8Encoder,sizeof(m_sParamVP8Encoder)); |
| break; |
| } |
| case OMX_IndexParamConsumerUsageBits: |
| { |
| /* Consumer usage bits |
| * -------------------------------------------------------------------- |
| * GRALLOC_USAGE_PRIVATE_ | GRALLOC_USAGE_PRIVATE_ | Color | |
| * ALLOC_UBWC | ALLOC_10BITS | Format | |
| * (bit 28) | (bit30) | | |
| * -------------------------------------------------------------------- |
| * 0 | 0 | NV12 | |
| * 0 | 1 | P010 | |
| * 1 | 0 | UBWC_NV12 | |
| * 1 | 1 | BPP10_UBWC | |
| * -------------------------------------------------------------------- |
| */ |
| |
| if (paramData == NULL) { return OMX_ErrorBadParameter; } |
| |
| OMX_U32 *consumerUsage = (OMX_U32 *)paramData; |
| m_sParamConsumerUsage = 0; |
| dev_get_consumer_usage(&m_sParamConsumerUsage); |
| memcpy(consumerUsage, &m_sParamConsumerUsage, sizeof(m_sParamConsumerUsage)); |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamConsumerUsageBits %x", |
| m_sParamConsumerUsage); |
| break; |
| } |
| case OMX_QTIIndexParamVideoEnableBlur: |
| { |
| VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_CONFIG_BLURINFO); |
| OMX_QTI_VIDEO_CONFIG_BLURINFO *pBlurInfo = |
| reinterpret_cast<OMX_QTI_VIDEO_CONFIG_BLURINFO *>(paramData); |
| memcpy(pBlurInfo, &m_blurInfo, sizeof(OMX_QTI_VIDEO_CONFIG_BLURINFO)); |
| 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; |
| } |
| |
| if (reject_config_for_TME_mode(configIndex)) { |
| DEBUG_PRINT_ERROR("ERROR: config 0x%x rejected in TME mode", configIndex); |
| return OMX_ErrorNone; |
| } |
| |
| //@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 OMX_IndexConfigCommonMirror: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_MIRRORTYPE); |
| OMX_CONFIG_MIRRORTYPE* pParam = reinterpret_cast<OMX_CONFIG_MIRRORTYPE*>(configData); |
| memcpy(pParam, &m_sConfigFrameMirror, sizeof(m_sConfigFrameMirror)); |
| break; |
| } |
| case QOMX_IndexConfigVideoIntraperiod: |
| { |
| DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod nPframes : %d nBframes : %d", |
| m_sIntraperiod.nPFrames, m_sIntraperiod.nBFrames); |
| 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_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_IndexConfigOperatingRate: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_PARAM_U32TYPE); |
| OMX_PARAM_U32TYPE* pParam = |
| reinterpret_cast<OMX_PARAM_U32TYPE*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_IndexConfigOperatingRate"); |
| pParam->nU32 = m_nOperatingRate; |
| break; |
| } |
| case OMX_QTIIndexConfigVideoBlurResolution: |
| { |
| VALIDATE_OMX_PARAM_DATA(configData, OMX_QTI_VIDEO_CONFIG_BLURINFO); |
| OMX_QTI_VIDEO_CONFIG_BLURINFO* pParam = |
| reinterpret_cast<OMX_QTI_VIDEO_CONFIG_BLURINFO*>(configData); |
| DEBUG_PRINT_LOW("get_config: OMX_QTIIndexConfigVideoBlurResolution"); |
| memcpy(pParam, &m_blurInfo, sizeof(OMX_QTI_VIDEO_CONFIG_BLURINFO)); |
| 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_LOW("Does not handle dataspace request. Please ignore this Unsupported Setting (0x80001019)."); |
| 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 for RGBA8888"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; |
| // keep client-default setting for range |
| // pParam->sAspects.mRange = ColorAspects::RangeLimited; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; |
| } else { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): dataspace=0x%x", pParam->nDataSpace); |
| if (pParam->nDataSpace == HAL_DATASPACE_JFIF || pParam->nDataSpace == HAL_DATASPACE_V0_JFIF) { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_JFIF"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; |
| pParam->sAspects.mRange = ColorAspects::RangeFull; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; |
| } else if (pParam->nDataSpace == HAL_DATASPACE_BT601_525 || pParam->nDataSpace == HAL_DATASPACE_V0_BT601_525) { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT601_525"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525; |
| pParam->sAspects.mRange = ColorAspects::RangeLimited; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; |
| } else if (pParam->nDataSpace == HAL_DATASPACE_BT601_625 || pParam->nDataSpace == HAL_DATASPACE_V0_BT601_625) { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT601_625"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; |
| pParam->sAspects.mRange = ColorAspects::RangeLimited; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; |
| } else if (pParam->nDataSpace == HAL_DATASPACE_BT709 || pParam->nDataSpace == HAL_DATASPACE_V0_BT709) { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT709"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT709_5; |
| pParam->sAspects.mRange = ColorAspects::RangeLimited; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5; |
| } else if (pParam->nDataSpace == HAL_DATASPACE_BT2020) { |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_BT2020"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; |
| pParam->sAspects.mRange = ColorAspects::RangeFull; |
| pParam->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; |
| } else if (pParam->nDataSpace == (HAL_DATASPACE_STANDARD_BT2020|HAL_DATASPACE_TRANSFER_HLG|HAL_DATASPACE_RANGE_LIMITED)) { |
| //For SONY HDR |
| DEBUG_PRINT_INFO("get_config (dataspace changed): ColorSpace: for HAL_DATASPACE_STANDARD_BT2020|HAL_DATASPACE_TRANSFER_HLG|HAL_DATASPACE_RANGE_LIMITED"); |
| pParam->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; |
| pParam->sAspects.mRange = ColorAspects::RangeLimited; |
| pParam->sAspects.mTransfer = ColorAspects::TransferHLG; |
| pParam->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; |
| } 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_IndexConfigAndroidVideoTemporalLayering: |
| { |
| 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_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; |
| } |
| if (extn_equals(paramName, "OMX.QCOM.index.param.SliceDeliveryMode")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode; |
| return OMX_ErrorNone; |
| } |
| #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")) { |
| 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_CONFIG_VIDEO_SETTIMEDATA)) { |
| *indexType = (OMX_INDEXTYPE)OMX_IndexConfigTimePosition; |
| 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_QTI_INDEX_CONFIG_VIDEO_BLURINFO)) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoBlurResolution; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) { |
| *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_TME)) { |
| *indexType = (OMX_INDEXTYPE)OMX_IndexParamVideoTme; |
| return OMX_ErrorNone; |
| } |
| |
| if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_NATIVE_RECORDER)) { |
| *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamNativeRecorder; |
| 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].data_fd =-1; |
| m_pInput_ion[i].dev_fd =-1; |
| #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); |
| BITMASK_SET(&m_client_in_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 |
| bool status = alloc_map_ion_memory(m_sInPortDef.nBufferSize, |
| &m_pInput_ion[i], |
| secure_session ? SECURE_FLAGS_INPUT_BUFFER : 0); |
| if (status == false) { |
| DEBUG_PRINT_ERROR("ERROR:ION device open() Failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| m_pInput_pmem[i].fd = m_pInput_ion[i].data_fd; |
| #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 *)ion_map(m_pInput_pmem[i].fd, |
| m_pInput_pmem[i].size); |
| |
| if (m_pInput_pmem[i].buffer == MAP_FAILED) { |
| DEBUG_PRINT_ERROR("ERROR: mmap() Failed"); |
| m_pInput_pmem[i].buffer = NULL; |
| #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(PORT_INDEX_IN) != 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; |
| int align_size; |
| |
| 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; |
| } |
| |
| 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].data_fd =-1; |
| m_pOutput_ion[i].dev_fd =-1; |
| #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 |
| align_size = (m_sOutPortDef.nBufferSize + (SZ_4K - 1)) & ~(SZ_4K - 1); |
| bool status = alloc_map_ion_memory(align_size, |
| &m_pOutput_ion[i], |
| secure_session ? SECURE_FLAGS_OUTPUT_BUFFER : 0); |
| if (status == false) { |
| DEBUG_PRINT_ERROR("ERROR:ION device open() Failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| m_pOutput_pmem[i].fd = m_pOutput_ion[i].data_fd; |
| #endif |
| m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; |
| m_pOutput_pmem[i].offset = 0; |
| |
| m_pOutput_pmem[i].buffer = NULL; |
| if(!secure_session) { |
| m_pOutput_pmem[i].buffer = (unsigned char *)ion_map(m_pOutput_pmem[i].fd, |
| align_size); |
| if (m_pOutput_pmem[i].buffer == MAP_FAILED) { |
| DEBUG_PRINT_ERROR("ERROR: mmap() Failed"); |
| m_pOutput_pmem[i].buffer = NULL; |
| #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(PORT_INDEX_OUT) != true) { |
| DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf"); |
| return OMX_ErrorInsufficientResources; |
| } |
| |
| BITMASK_SET(&m_out_bm_count,i); |
| BITMASK_SET(&m_client_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; |
| } |
| |
| auto_lock l(m_buf_lock); |
| 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 if (port == PORT_INDEX_EXTRADATA_OUT) { |
| eRet = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer); |
| } else if (port == PORT_INDEX_EXTRADATA_IN) { |
| eRet = use_client_input_extradata_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::allocate_client_output_extradata_headers() { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| OMX_BUFFERHEADERTYPE *bufHdr = NULL; |
| int i = 0; |
| |
| if (!m_client_output_extradata_mem_ptr) { |
| int nBufferCount = 0; |
| |
| nBufferCount = m_client_out_extradata_info.getBufferCount(); |
| DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount); |
| |
| m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE)); |
| |
| if (m_client_output_extradata_mem_ptr) { |
| bufHdr = m_client_output_extradata_mem_ptr; |
| for (i=0; i < nBufferCount; i++) { |
| bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); |
| bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; |
| // Set the values when we determine the right HxW param |
| bufHdr->nAllocLen = 0; |
| bufHdr->nFilledLen = 0; |
| bufHdr->pAppPrivate = NULL; |
| bufHdr->nOutputPortIndex = PORT_INDEX_EXTRADATA_OUT; |
| bufHdr->pBuffer = NULL; |
| bufHdr->pOutputPortPrivate = NULL; |
| bufHdr++; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\ |
| m_client_output_extradata_mem_ptr); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| } |
| return eRet; |
| } |
| |
| OMX_ERRORTYPE omx_video::allocate_client_input_extradata_headers() { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| OMX_BUFFERHEADERTYPE *bufHdr = NULL; |
| int i = 0; |
| |
| if (!m_client_input_extradata_mem_ptr) { |
| int nBufferCount = 0; |
| |
| nBufferCount = m_client_in_extradata_info.getBufferCount(); |
| DEBUG_PRINT_HIGH("allocate_client_input_extradata_headers buffer_count - %d", nBufferCount); |
| |
| m_client_input_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE)); |
| |
| if (m_client_input_extradata_mem_ptr) { |
| bufHdr = m_client_input_extradata_mem_ptr; |
| for (i=0; i < nBufferCount; i++) { |
| bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); |
| bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; |
| // Set the values when we determine the right HxW param |
| bufHdr->nAllocLen = 0; |
| bufHdr->nFilledLen = 0; |
| bufHdr->pAppPrivate = NULL; |
| bufHdr->nInputPortIndex = PORT_INDEX_EXTRADATA_IN; |
| bufHdr->pBuffer = NULL; |
| bufHdr->pOutputPortPrivate = NULL; |
| bufHdr++; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\ |
| m_client_input_extradata_mem_ptr); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| } |
| return eRet; |
| } |
| |
| OMX_ERRORTYPE omx_video::use_client_output_extradata_buffer( |
| OMX_IN OMX_HANDLETYPE hComp, |
| OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, |
| OMX_IN OMX_U32 port, |
| OMX_IN OMX_PTR appData, |
| OMX_IN OMX_U32 bytes, |
| OMX_IN OMX_U8* buffer) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| unsigned i = 0; // Temporary counter |
| unsigned buffer_count = m_client_out_extradata_info.getBufferCount();; |
| OMX_U32 buffer_size = m_client_out_extradata_info.getSize(); |
| (void) hComp; |
| |
| if (port != PORT_INDEX_EXTRADATA_OUT || |
| !m_sExtraData || bytes != buffer_size|| bufferHdr == NULL) { |
| DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d," |
| "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port, |
| PORT_INDEX_EXTRADATA_OUT, m_sExtraData, bytes, buffer_size, bufferHdr); |
| eRet = OMX_ErrorBadParameter; |
| return eRet; |
| } |
| |
| if (!m_client_output_extradata_mem_ptr) { |
| eRet = allocate_client_output_extradata_headers(); |
| } |
| |
| if (eRet == OMX_ErrorNone) { |
| for (i = 0; i < buffer_count; i++) { |
| if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) { |
| break; |
| } |
| } |
| } |
| |
| if (i >= buffer_count) { |
| DEBUG_PRINT_ERROR("invalid buffer index"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| |
| if (eRet == OMX_ErrorNone) { |
| BITMASK_SET(&m_out_extradata_bm_count,i); |
| *bufferHdr = (m_client_output_extradata_mem_ptr + i ); |
| (*bufferHdr)->pAppPrivate = appData; |
| (*bufferHdr)->pBuffer = buffer; |
| (*bufferHdr)->nAllocLen = bytes; |
| } |
| |
| return eRet; |
| } |
| |
| OMX_ERRORTYPE omx_video::use_client_input_extradata_buffer( |
| OMX_IN OMX_HANDLETYPE hComp, |
| OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, |
| OMX_IN OMX_U32 port, |
| OMX_IN OMX_PTR appData, |
| OMX_IN OMX_U32 bytes, |
| OMX_IN OMX_U8* buffer) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| unsigned i = 0; // Temporary counter |
| unsigned buffer_count = m_client_in_extradata_info.getBufferCount(); |
| OMX_U32 buffer_size = m_client_in_extradata_info.getSize(); |
| (void) hComp; |
| |
| if (port != PORT_INDEX_EXTRADATA_IN || |
| !m_sExtraData || bytes != buffer_size|| bufferHdr == NULL) { |
| DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d," |
| "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port, |
| PORT_INDEX_EXTRADATA_IN, m_sExtraData, bytes, buffer_size, bufferHdr); |
| eRet = OMX_ErrorBadParameter; |
| return eRet; |
| } |
| |
| if (!m_client_input_extradata_mem_ptr) { |
| eRet = allocate_client_input_extradata_headers(); |
| } |
| |
| if (eRet == OMX_ErrorNone) { |
| for (i = 0; i < buffer_count; i++) { |
| if (BITMASK_ABSENT(&m_in_extradata_bm_count,i)) { |
| break; |
| } |
| } |
| } |
| |
| if (i >= buffer_count) { |
| DEBUG_PRINT_ERROR("invalid buffer index"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| |
| if (eRet == OMX_ErrorNone) { |
| BITMASK_SET(&m_in_extradata_bm_count,i); |
| *bufferHdr = (m_client_input_extradata_mem_ptr + i ); |
| (*bufferHdr)->pAppPrivate = appData; |
| (*bufferHdr)->pBuffer = buffer; |
| (*bufferHdr)->nAllocLen = bytes; |
| } |
| |
| 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 { |
| 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) { |
| |
| 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) { |
| ion_unmap(m_pInput_ion[index].data_fd, |
| m_pInput_pmem[index].buffer, |
| m_pInput_pmem[index].size); |
| } else { |
| free(m_pInput_pmem[index].buffer); |
| } |
| m_pInput_pmem[index].buffer = NULL; |
| #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) { |
| ion_unmap(m_pInput_ion[index].data_fd, |
| m_pInput_pmem[index].buffer, |
| m_pInput_pmem[index].size); |
| m_pInput_pmem[index].buffer = NULL; |
| } |
| #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) { |
| ion_unmap(m_pOutput_pmem[index].fd, |
| m_pOutput_pmem[index].buffer, |
| m_pOutput_pmem[index].size); |
| } else if (m_pOutput_pmem[index].buffer) { |
| native_handle_t *handle; |
| if (allocate_native_handle) { |
| handle = (native_handle_t *)m_pOutput_pmem[index].buffer; |
| } else { |
| handle = ((output_metabuffer *)m_pOutput_pmem[index].buffer)->nh; |
| free(m_pOutput_pmem[index].buffer); |
| } |
| native_handle_close(handle); |
| native_handle_delete(handle); |
| } |
| #ifdef USE_ION |
| free_ion_memory(&m_pOutput_ion[index]); |
| #endif |
| |
| m_pOutput_pmem[index].buffer = NULL; |
| 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) { |
| ion_unmap(m_pOutput_pmem[index].fd, |
| m_pOutput_pmem[index].buffer, |
| m_pOutput_pmem[index].size); |
| } |
| #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; |
| // In meta-mode alloc-length is not known conclusively |
| // Allow allocation for atleast gralloc metadata handles |
| // and check for size in ETB |
| if (!bufferHdr || bytes < sizeof(VideoGrallocMetadata)) { |
| 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 && |
| BITMASK_PRESENT(&m_inp_bm_count, index)); index++); |
| |
| if (index == m_sInPortDef.nBufferCountActual) { |
| DEBUG_PRINT_ERROR("All buffers are allocated input_meta_buffer"); |
| return OMX_ErrorBadParameter; |
| } |
| if (mUseProxyColorFormat) { |
| if (opaque_buffer_hdr[index]) { |
| DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr"); |
| return OMX_ErrorBadParameter; |
| } |
| if (allocate_input_buffer(hComp,&opaque_buffer_hdr[index], |
| PORT_INDEX_IN,appData,m_sInPortDef.nBufferSize) != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("All buffers are allocated opaque_buffer_hdr"); |
| return OMX_ErrorBadParameter; |
| } |
| } |
| BITMASK_SET(&m_inp_bm_count,index); |
| *bufferHdr = &meta_buffer_hdr[index]; |
| memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index])); |
| meta_buffer_hdr[index].nSize = sizeof(meta_buffer_hdr[index]); |
| meta_buffer_hdr[index].nAllocLen = bytes; |
| meta_buffer_hdr[index].nVersion.nVersion = OMX_SPEC_VERSION; |
| meta_buffer_hdr[index].nInputPortIndex = PORT_INDEX_IN; |
| meta_buffer_hdr[index].pBuffer = (OMX_U8*)&meta_buffers[index]; |
| meta_buffer_hdr[index].pAppPrivate = appData; |
| if (mUseProxyColorFormat) { |
| m_opq_pmem_q.insert_entry((unsigned 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].data_fd = -1; |
| m_pInput_ion[i].dev_fd = -1; |
| #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 |
| // No use case where caching encoder makes sense |
| bool status = alloc_map_ion_memory(m_sInPortDef.nBufferSize, |
| &m_pInput_ion[i], |
| secure_session ? SECURE_FLAGS_INPUT_BUFFER : 0); |
| if (status == false) { |
| DEBUG_PRINT_ERROR("ERROR:ION device open() Failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| m_pInput_pmem[i].fd = m_pInput_ion[i].data_fd; |
| #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 *)ion_map(m_pInput_pmem[i].fd, |
| m_pInput_pmem[i].size); |
| if (m_pInput_pmem[i].buffer == MAP_FAILED) { |
| DEBUG_PRINT_ERROR("ERROR: mmap FAILED= %d", errno); |
| m_pInput_pmem[i].buffer = NULL; |
| #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)->nAllocLen = sizeof(OMX_U32) + sizeof(native_handle_t*); |
| } |
| |
| (*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(PORT_INDEX_IN) != 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 |
| int align_size; |
| |
| 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 = bytes; |
| 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].data_fd = -1; |
| m_pOutput_ion[i].dev_fd = -1; |
| #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 |
| align_size = ALIGN(m_sOutPortDef.nBufferSize, 4096); |
| // Output buffers are cached so that muxer writing is faster |
| bool status = alloc_map_ion_memory(align_size, |
| &m_pOutput_ion[i], |
| secure_session ? SECURE_FLAGS_OUTPUT_BUFFER : ION_FLAG_CACHED); |
| if (status == false) { |
| DEBUG_PRINT_ERROR("ERROR:ION device open() Failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| |
| m_pOutput_pmem[i].fd = m_pOutput_ion[i].data_fd; |
| #endif |
| m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; |
| m_pOutput_pmem[i].offset = 0; |
| |
| m_pOutput_pmem[i].buffer = NULL; |
| *bufferHdr = (m_out_mem_ptr + i ); |
| |
| if(!secure_session) { |
| m_pOutput_pmem[i].buffer = (unsigned char *)ion_map(m_pOutput_pmem[i].fd, |
| align_size); |
| 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; |
| #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* |
| if (allocate_native_handle) { |
| native_handle_t *nh = native_handle_create(1 /*numFds*/, 3 /*numInts*/); |
| if (!nh) { |
| DEBUG_PRINT_ERROR("Native handle create failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| nh->data[0] = m_pOutput_pmem[i].fd; |
| nh->data[1] = 0; |
| nh->data[2] = 0; |
| nh->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096); |
| m_pOutput_pmem[i].buffer = (OMX_U8 *)nh; |
| } else { |
| native_handle_t *handle = native_handle_create(1, 3); //fd, offset, size, alloc length |
| if (!handle) { |
| DEBUG_PRINT_ERROR("ERROR: native handle creation failed"); |
| return OMX_ErrorInsufficientResources; |
| } |
| m_pOutput_pmem[i].buffer = malloc(sizeof(output_metabuffer)); |
| if (m_pOutput_pmem[i].buffer == NULL) { |
| DEBUG_PRINT_ERROR("%s: Failed to allocate meta buffer", __func__); |
| native_handle_close(handle); |
| native_handle_delete(handle); |
| return OMX_ErrorInsufficientResources; |
| } |
| (*bufferHdr)->nAllocLen = sizeof(output_metabuffer); |
| handle->data[0] = m_pOutput_pmem[i].fd; |
| handle->data[1] = 0; |
| handle->data[2] = 0; |
| handle->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096); |
| output_metabuffer *buffer = (output_metabuffer*) m_pOutput_pmem[i].buffer; |
| buffer->type = 1; |
| buffer->nh = handle; |
| } |
| } |
| |
| (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer; |
| (*bufferHdr)->pAppPrivate = appData; |
| |
| BITMASK_SET(&m_out_bm_count,i); |
| |
| if (dev_use_buf(PORT_INDEX_OUT) != true) { |
| DEBUG_PRINT_ERROR("ERROR: dev_use_buf FAILED for o/p buf"); |
| return OMX_ErrorInsufficientResources; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: All o/p buffers 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; |
| } |
| auto_lock l(m_buf_lock); |
| // 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"); |
| auto_lock l(m_buf_lock); |
| if (port == PORT_INDEX_OUT) { //client called freebuffer, clearing client buffer bitmask right away to avoid use after free |
| nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr; |
| if(BITMASK_PRESENT(&m_client_out_bm_count, nPortIndex)) |
| BITMASK_CLEAR(&m_client_out_bm_count,nPortIndex); |
| } else if (port == PORT_INDEX_IN) { |
| nPortIndex = buffer - (meta_mode_enable?meta_buffer_hdr:m_inp_mem_ptr); |
| if(BITMASK_PRESENT(&m_client_in_bm_count, nPortIndex)) |
| BITMASK_CLEAR(&m_client_in_bm_count,nPortIndex); |
| } |
| 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"); |
| m_buffer_freed = true; |
| 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"); |
| m_buffer_freed = true; |
| 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)) { |
| // 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 if (port == PORT_INDEX_EXTRADATA_OUT) { |
| nPortIndex = buffer - m_client_output_extradata_mem_ptr; |
| DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex); |
| |
| BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex); |
| |
| if (release_output_extradata_done()) { |
| free_output_extradata_buffer_header(); |
| } |
| } else if (port == PORT_INDEX_EXTRADATA_IN) { |
| nPortIndex = buffer - m_client_input_extradata_mem_ptr; |
| DEBUG_PRINT_LOW("free_buffer on extradata input port - Port idx %d", nPortIndex); |
| |
| BITMASK_CLEAR(&m_in_extradata_bm_count,nPortIndex); |
| |
| if (release_input_extradata_done()) { |
| free_input_extradata_buffer_header(); |
| } |
| } 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 output %" PRIx64" input %" PRIx64, |
| m_out_bm_count, m_inp_bm_count); |
| } |
| } |
| if (eRet != OMX_ErrorNone) { |
| m_buffer_freed = true; |
| } |
| |
| return eRet; |
| } |
| |
| void omx_video::free_output_extradata_buffer_header() { |
| m_sExtraData = false; |
| if (m_client_output_extradata_mem_ptr) { |
| DEBUG_PRINT_LOW("Free extradata pmem Pointer area"); |
| free(m_client_output_extradata_mem_ptr); |
| m_client_output_extradata_mem_ptr = NULL; |
| } |
| } |
| |
| void omx_video::free_input_extradata_buffer_header() { |
| m_sExtraData = false; |
| if (m_client_input_extradata_mem_ptr) { |
| DEBUG_PRINT_LOW("Free extradata pmem Pointer area"); |
| free(m_client_input_extradata_mem_ptr); |
| m_client_input_extradata_mem_ptr = NULL; |
| } |
| } |
| |
| /* ====================================================================== |
| 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) |
| { |
| if(buffer != NULL && buffer->nInputPortIndex == PORT_INDEX_EXTRADATA_IN) { |
| if(!dev_handle_client_input_extradata(buffer)) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::etb--> handling client extradata failed"); |
| return OMX_ErrorMax; |
| } |
| return OMX_ErrorNone; |
| } |
| OMX_ERRORTYPE ret1 = OMX_ErrorNone; |
| unsigned int nBufferIndex ; |
| |
| 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; |
| } |
| |
| DEBUG_PRINT_LOW("ETB: buffer = %p, buffer->pBuffer[%p]", buffer, buffer->pBuffer); |
| 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++; |
| m_etb_timestamp = buffer->nTimeStamp; |
| 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; |
| } |
| |
| bool omx_video::profile_etb() { |
| if (profile_mode) { |
| struct timeval act_time = {0, 0}; |
| gettimeofday(&act_time, NULL); |
| if (profile_start_time == 0) { |
| profile_start_time = (act_time.tv_usec + act_time.tv_sec * 1e6); |
| } else { |
| profile_last_time = (act_time.tv_usec + act_time.tv_sec * 1e6); |
| } |
| profile_frame_count++; |
| return true; |
| } |
| return false; |
| } |
| |
| /* ====================================================================== |
| 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) |
| { |
| VIDC_TRACE_NAME_HIGH("ETB"); |
| (void)hComp; |
| OMX_U8 *pmem_data_buf = NULL; |
| int push_cnt = 0; |
| unsigned nBufIndex = 0; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| LEGACY_CAM_METADATA_TYPE *media_buffer = NULL; |
| |
| int fd = 0; |
| |
| DEBUG_PRINT_LOW("ETBProxy: buffer->pBuffer[%p]", buffer->pBuffer); |
| if (buffer == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxy: Invalid buffer[%p]", buffer); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (profile_etb()) { |
| m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); |
| return OMX_ErrorNone; |
| } |
| |
| // 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 = (LEGACY_CAM_METADATA_TYPE *)meta_buffer_hdr[nBufIndex].pBuffer; |
| if (!media_buffer) { |
| DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__); |
| return OMX_ErrorBadParameter; |
| } |
| if ((media_buffer->buffer_type == LEGACY_CAM_SOURCE) |
| && buffer->nAllocLen != sizeof(LEGACY_CAM_METADATA_TYPE)) { |
| DEBUG_PRINT_ERROR("Invalid metadata size expected(%u) v/s recieved(%zu)", |
| buffer->nAllocLen, sizeof(LEGACY_CAM_METADATA_TYPE)); |
| met_error = true; |
| } else if (media_buffer) { |
| if (media_buffer->buffer_type != LEGACY_CAM_SOURCE && |
| media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) { |
| DEBUG_PRINT_ERROR("Buffer type is neither LEGACY_CAM_SOURCE nor gralloc source"); |
| met_error = true; |
| } else { |
| if (media_buffer->buffer_type == LEGACY_CAM_SOURCE) { |
| if (media_buffer->meta_handle == NULL) { |
| DEBUG_PRINT_ERROR("Buffer type is LEGACY_CAM_SOURCE but handle is null"); |
| met_error = true; |
| } |
| else { |
| // TBD: revisit this check ! |
| 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; |
| DEBUG_PRINT_ERROR("Unrecognized camera source type"); |
| } |
| 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; |
| } |
| } |
| |
| if (buffer->nFilledLen == 0 && (buffer->nFlags & OMX_BUFFERFLAG_EOS)) { |
| DEBUG_PRINT_LOW("Zero length EOS buffer"); |
| handle_empty_eos_buffer(); |
| post_event ((unsigned long)buffer,0, |
| OMX_COMPONENT_GENERATE_EBD); |
| return OMX_ErrorNone; |
| } |
| |
| pending_input_buffers++; |
| VIDC_TRACE_INT_LOW("ETB-pending", 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; |
| } |
| if (!meta_mode_enable) { |
| fd = m_pInput_pmem[nBufIndex].fd; |
| } |
| #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 == LEGACY_CAM_SOURCE) { |
| Input_pmem_info.buffer = media_buffer; |
| Input_pmem_info.fd = MetaBufferUtil::getFdAt(media_buffer->meta_handle, 0); |
| fd = Input_pmem_info.fd; |
| |
| int offset = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_OFFSET); |
| int size = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_SIZE); |
| if (offset < 0 || size < 0) { |
| DEBUG_PRINT_ERROR("meta-buffer is invalid!"); |
| return OMX_ErrorBadParameter; |
| } |
| Input_pmem_info.offset = offset; |
| Input_pmem_info.size = size; |
| DEBUG_PRINT_HIGH("ETB (meta-Camera) fd = %d, offset = %d, size = %d", |
| Input_pmem_info.fd, Input_pmem_info.offset, |
| Input_pmem_info.size); |
| } else { |
| VideoGrallocMetadata *media_buffer = (VideoGrallocMetadata *)meta_buffer_hdr[nBufIndex].pBuffer; |
| private_handle_t *handle = (private_handle_t *)media_buffer->pHandle; |
| Input_pmem_info.buffer = media_buffer; |
| Input_pmem_info.fd = handle->fd; |
| fd = Input_pmem_info.fd; |
| 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 input buffer dimensions is different from what is configured, |
| // reject the buffer |
| if (ALIGN((int)m_sInPortDef.format.video.nFrameWidth,32) != ALIGN(handle->unaligned_width,32) || |
| ALIGN((int)m_sInPortDef.format.video.nFrameHeight,32) != ALIGN(handle->unaligned_height,32)) { |
| ALOGE("Graphic buf size(%dx%d) does not match configured size(%ux%u)", |
| handle->unaligned_width, handle->unaligned_height, |
| m_sInPortDef.format.video.nFrameWidth, m_sInPortDef.format.video.nFrameHeight); |
| post_event ((unsigned long)buffer, 0, OMX_COMPONENT_GENERATE_EBD); |
| return OMX_ErrorNone; |
| } |
| } |
| if (dev_use_buf(PORT_INDEX_IN) != 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_buf_lock); |
| pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer; |
| if (pmem_data_buf && BITMASK_PRESENT(&m_client_in_bm_count, nBufIndex)) { |
| 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 (dev_empty_buf(buffer, pmem_data_buf,nBufIndex,fd) != true) |
| { |
| 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--; |
| VIDC_TRACE_INT_LOW("ETB-pending", 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) |
| { |
| if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| 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->nOutputPortIndex == PORT_INDEX_EXTRADATA_OUT) { |
| DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->invalid port in header"); |
| 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) |
| { |
| VIDC_TRACE_NAME_HIGH("FTB"); |
| (void)hComp; |
| OMX_U8 *pmem_data_buf = NULL; |
| OMX_ERRORTYPE nRet = OMX_ErrorNone; |
| auto_lock l(m_buf_lock); |
| if (m_buffer_freed == true) { |
| DEBUG_PRINT_ERROR("ERROR: FTBProxy: Invalid call. Called after freebuffer"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (bufferAdd != NULL) { |
| 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++; |
| VIDC_TRACE_INT_LOW("FTB-pending", 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--; |
| VIDC_TRACE_INT_LOW("FTB-pending", 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; |
| |
| if (!callbacks) |
| return OMX_ErrorBadParameter; |
| |
| 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_ErrorNone; |
| } |
| |
| |
| /* ====================================================================== |
| 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.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.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; |
| } |
| } 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; |
| } |
| } else if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc", OMX_MAX_STRINGNAME_SIZE) || |
| !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.hevc.cq", OMX_MAX_STRINGNAME_SIZE) || |
| !strncmp((char*)m_nkind, "OMX.qcom.video.encoder.heic", 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 if (!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.tme", OMX_MAX_STRINGNAME_SIZE)) { |
| if ((0 == index) && role) { |
| strlcpy((char *)role, "video_encoder.tme", 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; |
| bool bRet_Out_Extra = false; |
| bool bRet_In_Extra = false; |
| |
| bRet_In = allocate_input_done(); |
| bRet_Out = allocate_output_done(); |
| bRet_In_Extra = allocate_input_extradata_done(); |
| bRet_Out_Extra = allocate_output_extradata_done(); |
| |
| if (bRet_In && bRet_Out && bRet_Out_Extra && bRet_In_Extra) { |
| 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; |
| } |
| |
| bool omx_video::allocate_output_extradata_done(void) { |
| bool bRet = false; |
| unsigned j=0; |
| unsigned nBufferCount = 0; |
| |
| nBufferCount = m_client_out_extradata_info.getBufferCount(); |
| |
| if (!m_client_out_extradata_info.is_client_extradata_enabled()) { |
| return true; |
| } |
| |
| if (m_client_output_extradata_mem_ptr) { |
| for (; j < nBufferCount; j++) { |
| if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) { |
| break; |
| } |
| } |
| |
| if (j == nBufferCount) { |
| bRet = true; |
| DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers"); |
| } |
| } |
| |
| return bRet; |
| } |
| |
| bool omx_video::allocate_input_extradata_done(void) { |
| bool bRet = false; |
| unsigned j=0; |
| unsigned nBufferCount = 0; |
| |
| nBufferCount = m_client_in_extradata_info.getBufferCount(); |
| |
| if (!m_client_in_extradata_info.is_client_extradata_enabled()) { |
| return true; |
| } |
| |
| if (m_client_input_extradata_mem_ptr) { |
| for (; j < nBufferCount; j++) { |
| if (BITMASK_ABSENT(&m_in_extradata_bm_count,j)) { |
| break; |
| } |
| } |
| |
| if (j == nBufferCount) { |
| bRet = true; |
| DEBUG_PRINT_HIGH("Allocate done for all extradata i/p buffers"); |
| } |
| } |
| |
| 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()) { |
| if (release_output_extradata_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; |
| } |
| |
| bool omx_video::release_output_extradata_done(void) { |
| bool bRet = false; |
| unsigned i=0,j=0, buffer_count=0; |
| |
| buffer_count = m_client_out_extradata_info.getBufferCount(); |
| DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d", |
| m_client_output_extradata_mem_ptr, buffer_count); |
| |
| if (m_client_output_extradata_mem_ptr) { |
| for (; j<buffer_count; j++) { |
| if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) { |
| break; |
| } |
| } |
| if (j == buffer_count) { |
| bRet = true; |
| } |
| } else { |
| bRet = true; |
| } |
| return bRet; |
| } |
| |
| bool omx_video::release_input_extradata_done(void) { |
| bool bRet = false; |
| unsigned i=0,j=0, buffer_count=0; |
| |
| buffer_count = m_client_in_extradata_info.getBufferCount(); |
| DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d", |
| m_client_input_extradata_mem_ptr, buffer_count); |
| |
| if (m_client_input_extradata_mem_ptr) { |
| for (; j<buffer_count; j++) { |
| if ( BITMASK_PRESENT(&m_in_extradata_bm_count,j)) { |
| break; |
| } |
| } |
| if (j == buffer_count) { |
| bRet = true; |
| } |
| } else { |
| bRet = true; |
| } |
| return bRet; |
| } |
| |
| OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp, |
| OMX_BUFFERHEADERTYPE * buffer) |
| { |
| VIDC_TRACE_NAME_HIGH("FBD"); |
| int index = buffer - m_out_mem_ptr; |
| |
| 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--; |
| VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers); |
| VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000); |
| VIDC_TRACE_INT_LOW("FBD-size", buffer->nFilledLen); |
| |
| if (secure_session && m_pCallbacks.FillBufferDone) { |
| if (buffer->nFilledLen > 0) |
| m_fbd_count++; |
| m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer); |
| return OMX_ErrorNone; |
| } |
| |
| /* 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()) { |
| do_cache_operations(m_pOutput_ion[index].data_fd); |
| dev_output_log_buffers((const char*)buffer->pBuffer + buffer->nOffset, buffer->nFilledLen, |
| buffer->nTimeStamp); |
| do_cache_operations(m_pOutput_ion[index].data_fd); |
| |
| } |
| } |
| if (buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { |
| if (!dev_handle_output_extradata((void *)buffer, index)) |
| DEBUG_PRINT_ERROR("Failed to parse output extradata"); |
| |
| dev_extradata_log_buffers((char *)(((unsigned long)buffer->pBuffer + buffer->nOffset + |
| buffer->nFilledLen + 3) & (~3)), false); |
| } |
| 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) |
| { |
| VIDC_TRACE_NAME_HIGH("EBD"); |
| 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--; |
| VIDC_TRACE_INT_LOW("ETB-pending", 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); |
| } |
| if (mUsesColorConversion) { |
| // 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; |
| } |
| } |
| } |
| |
| void omx_video::do_cache_operations(int fd) |
| { |
| #ifdef USE_ION |
| struct dma_buf_sync buf_sync; |
| |
| if (fd < 0) |
| return; |
| |
| struct dma_buf_sync dma_buf_sync_data[2]; |
| dma_buf_sync_data[0].flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW; |
| dma_buf_sync_data[1].flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW; |
| |
| for(unsigned int i=0; i<2; i++) { |
| int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &dma_buf_sync_data[i]); |
| if (rc < 0) { |
| DEBUG_PRINT_ERROR("Failed DMA_BUF_IOCTL_SYNC %s fd : %d", i==0?"start":"end", fd); |
| return; |
| } |
| } |
| #else |
| (void)fd; |
| return; |
| #endif |
| } |
| |
| char *omx_video::ion_map(int fd, int len) |
| { |
| char *bufaddr = (char*)mmap(NULL, len, PROT_READ|PROT_WRITE, |
| MAP_SHARED, fd, 0); |
| #ifdef USE_ION |
| if (bufaddr != MAP_FAILED) { |
| do_cache_operations(fd); |
| } |
| #endif |
| return bufaddr; |
| } |
| |
| OMX_ERRORTYPE omx_video::ion_unmap(int fd, void *bufaddr, int len) |
| { |
| #ifdef USE_ION |
| do_cache_operations(fd); |
| #else |
| (void)fd; |
| #endif |
| if (-1 == munmap(bufaddr, len)) { |
| DEBUG_PRINT_ERROR("munmap failed."); |
| return OMX_ErrorInsufficientResources; |
| } |
| return OMX_ErrorNone; |
| } |
| |
| #ifdef USE_ION |
| bool omx_video::alloc_map_ion_memory(int size, venc_ion *ion_info, int flag) |
| { |
| struct venc_ion buf_ion_info; |
| int rc=0; |
| |
| if (size <=0 || !ion_info) { |
| DEBUG_PRINT_ERROR("Invalid input to alloc_map_ion_memory"); |
| return false; |
| } |
| |
| ion_info->data_fd = -1; |
| ion_info->dev_fd = ion_open(); |
| if (ion_info->dev_fd <= 0) { |
| DEBUG_PRINT_ERROR("ERROR: ION Device open() Failed"); |
| return false; |
| } |
| |
| if(secure_session) { |
| ion_info->alloc_data.len = (size + (SECURE_ALIGN - 1)) & ~(SECURE_ALIGN - 1); |
| ion_info->alloc_data.flags = flag; |
| ion_info->alloc_data.heap_id_mask = ION_HEAP(MEM_HEAP_ID); |
| if (ion_info->alloc_data.flags & ION_FLAG_CP_BITSTREAM) { |
| ion_info->alloc_data.heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); |
| } |
| DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %u flags %x", |
| (unsigned int)ion_info->alloc_data.len, |
| ion_info->alloc_data.flags); |
| } else { |
| ion_info->alloc_data.len = (size + (SZ_4K - 1)) & ~(SZ_4K - 1); |
| ion_info->alloc_data.flags = (flag & ION_FLAG_CACHED); |
| |
| /* If color format is Vanilla NV12, we will need to use caching for optimal |
| color alignment performance. |
| */ |
| |
| if (m_sInPortDef.format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) |
| { |
| DEBUG_PRINT_HIGH("Enabling cacheing for this buffer"); |
| ion_info->alloc_data.flags = ION_FLAG_CACHED; |
| } |
| ion_info->alloc_data.heap_id_mask = (ION_HEAP(MEM_HEAP_ID) | |
| ION_HEAP(ION_SYSTEM_HEAP_ID)); |
| DEBUG_PRINT_HIGH("ION ALLOC unsec buf: size %u flags %x", |
| (unsigned int)ion_info->alloc_data.len, |
| ion_info->alloc_data.flags); |
| } |
| #ifdef HYPERVISOR |
| ion_info->alloc_data.flags &= (~ION_FLAG_CACHED); |
| #endif |
| |
| rc = ion_alloc_fd(ion_info->dev_fd, ion_info->alloc_data.len, 0, |
| ion_info->alloc_data.heap_id_mask, |
| ion_info->alloc_data.flags, &ion_info->data_fd); |
| if (rc || ion_info->data_fd < 0) { |
| DEBUG_PRINT_ERROR("ION ALLOC memory failed 0x%x", rc); |
| ion_close(ion_info->dev_fd); |
| ion_info->data_fd = -1; |
| ion_info->dev_fd = -1; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| 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 (buf_ion_info->data_fd >= 0) { |
| close(buf_ion_info->data_fd); |
| buf_ion_info->data_fd = -1; |
| } |
| if (buf_ion_info->dev_fd >= 0) { |
| ion_close(buf_ion_info->dev_fd); |
| buf_ion_info->dev_fd = -1; |
| } |
| } |
| #endif |
| |
| #ifdef _ANDROID_ICS_ |
| void omx_video::omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer) |
| { |
| if (buffer && meta_mode_enable) { |
| LEGACY_CAM_METADATA_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 = (LEGACY_CAM_METADATA_TYPE *) buffer->pBuffer; |
| if (media_ptr && media_ptr->meta_handle) { |
| if (media_ptr->buffer_type == LEGACY_CAM_SOURCE) { |
| Input_pmem.buffer = media_ptr; |
| Input_pmem.fd = MetaBufferUtil::getFdAt(media_ptr->meta_handle, 0); |
| int size = MetaBufferUtil::getIntAt(media_ptr->meta_handle, 0, MetaBufferUtil::INT_SIZE); |
| int offset = MetaBufferUtil::getIntAt(media_ptr->meta_handle, 0, MetaBufferUtil::INT_OFFSET); |
| if (Input_pmem.fd < 0 || size < 0 || offset < 0) { |
| DEBUG_PRINT_ERROR("Invalid meta buffer"); |
| meta_error = true; |
| } |
| Input_pmem.size = size; |
| Input_pmem.offset = offset; |
| 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) { |
| VideoGrallocMetadata *media_ptr = (VideoGrallocMetadata *)buffer->pBuffer; |
| private_handle_t *handle = (private_handle_t *)media_ptr->pHandle; |
| Input_pmem.buffer = media_ptr; |
| Input_pmem.fd = handle->fd; |
| Input_pmem.offset = 0; |
| Input_pmem.size = handle->size; |
| } else { |
| meta_error = true; |
| } |
| if (!meta_error) |
| meta_error = !dev_free_buf(&Input_pmem,PORT_INDEX_IN); |
| if (meta_error) { |
| DEBUG_PRINT_HIGH("In batchmode or dev_free_buf failed, flush %d", |
| input_flush_progress); |
| } |
| } |
| } |
| } |
| } |
| #endif |
| |
| bool is_ubwc_interlaced(private_handle_t *handle) { |
| int interlace_flag = 0; |
| |
| if (getMetaData(const_cast<private_handle_t *>(handle), |
| GET_PP_PARAM_INTERLACED, &interlace_flag)) { |
| interlace_flag = 0; |
| } |
| return (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC) && |
| !!interlace_flag; |
| } |
| |
| bool omx_video::is_conv_needed(private_handle_t *handle) |
| { |
| bool bRet = false; |
| bool interlaced = is_ubwc_interlaced(handle); |
| |
| if (!strncmp(m_platform, "msm8996", 7)) { |
| bRet = handle->format == HAL_PIXEL_FORMAT_RGBA_8888 && |
| !(handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED || |
| handle->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI); |
| } else { |
| bRet = handle->format == HAL_PIXEL_FORMAT_RGBA_8888; |
| } |
| |
| #ifdef _HW_RGBA |
| bRet = false; |
| #endif |
| bRet |= interlaced; |
| DEBUG_PRINT_LOW("RGBA conversion %s. Format %d Flag %d interlace_flag = %d", |
| bRet ? "Needed":"Not-Needed", handle->format, |
| handle->flags, interlaced); |
| 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) |
| { |
| VIDC_TRACE_NAME_LOW("ETB-Opaque"); |
| unsigned nBufIndex = 0; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| VideoGrallocMetadata *media_buffer; // This method primarily assumes gralloc-metadata |
| 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; |
| } |
| |
| if (profile_etb()) { |
| m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); |
| return OMX_ErrorNone; |
| } |
| |
| if (!dev_buffer_ready_to_queue(buffer)) { |
| DEBUG_PRINT_HIGH("Info: ETBProxyA: buffer[%p] is deffered", buffer); |
| return OMX_ErrorNone; |
| } |
| |
| nBufIndex = buffer - meta_buffer_hdr; |
| if (nBufIndex >= m_sInPortDef.nBufferCountActual) { |
| DEBUG_PRINT_ERROR("ERROR: ETBProxyA: Invalid bufindex = %u", |
| nBufIndex); |
| return OMX_ErrorBadParameter; |
| } |
| |
| media_buffer = (VideoGrallocMetadata *)buffer->pBuffer; |
| if (!media_buffer) { |
| DEBUG_PRINT_ERROR("%s: invalid media_buffer",__FUNCTION__); |
| return OMX_ErrorBadParameter; |
| } |
| if ((media_buffer->eType == LEGACY_CAM_SOURCE) |
| && buffer->nAllocLen != sizeof(LEGACY_CAM_METADATA_TYPE)) { |
| DEBUG_PRINT_ERROR("Invalid metadata size expected(%u) v/s recieved(%zu)", |
| buffer->nAllocLen, sizeof(LEGACY_CAM_METADATA_TYPE)); |
| return OMX_ErrorBadParameter; |
| } |
| |
| if (media_buffer && media_buffer->eType == LEGACY_CAM_SOURCE) { |
| return empty_this_buffer_proxy(hComp, buffer); |
| } |
| |
| if ((!media_buffer || !media_buffer->pHandle || media_buffer->eType != kMetadataBufferTypeGrallocSource) && |
| !(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->pHandle; |
| } |
| |
| /*Enable following code once private handle color format is |
| updated correctly*/ |
| |
| if (buffer->nFilledLen > 0 && handle && !is_streamon_done((OMX_U32) PORT_INDEX_OUT)) { |
| |
| ColorConvertFormat c2dSrcFmt = RGBA8888; |
| ColorConvertFormat c2dDestFmt = m_ubwc_supported ? NV12_UBWC : NV12_128m; |
| |
| ColorMapping::const_iterator found = |
| mMapPixelFormat2Converter.find(handle->format); |
| |
| if (found != mMapPixelFormat2Converter.end() && is_conv_needed(handle)) { |
| c2dSrcFmt = (ColorConvertFormat)found->second; |
| c2dcc.setConversionNeeded(true); |
| } else { |
| DEBUG_PRINT_HIGH("Couldn't find color mapping for (%x).", handle->format); |
| c2dcc.setConversionNeeded(false); |
| } |
| |
| mUsesColorConversion = is_conv_needed(handle); |
| bool interlaced = is_ubwc_interlaced(handle); |
| int full_range_flag = m_sConfigColorAspects.sAspects.mRange == ColorAspects::RangeFull ? |
| private_handle_t::PRIV_FLAGS_ITU_R_601_FR : 0; |
| |
| if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingImageHEIC) |
| c2dDestFmt = NV12_512; |
| |
| if (c2dcc.getConversionNeeded() && |
| c2dcc.isPropChanged(m_sInPortDef.format.video.nFrameWidth, |
| interlaced ? ((m_sInPortDef.format.video.nFrameHeight + 1) / 2) : |
| m_sInPortDef.format.video.nFrameHeight, |
| m_sInPortDef.format.video.nFrameWidth, |
| m_sInPortDef.format.video.nFrameHeight, |
| c2dSrcFmt, c2dDestFmt, |
| handle->flags, handle->width)) { |
| DEBUG_PRINT_HIGH("C2D setResolution (0x%X -> 0x%x) HxW (%dx%d) Stride (%d)", |
| c2dSrcFmt, c2dDestFmt, |
| m_sInPortDef.format.video.nFrameHeight, |
| m_sInPortDef.format.video.nFrameWidth, |
| handle->width); |
| if (!c2dcc.setResolution(m_sInPortDef.format.video.nFrameWidth, |
| interlaced ? ((m_sInPortDef.format.video.nFrameHeight + 1) / 2) : |
| m_sInPortDef.format.video.nFrameHeight, |
| m_sInPortDef.format.video.nFrameWidth, |
| m_sInPortDef.format.video.nFrameHeight, |
| c2dSrcFmt, c2dDestFmt, |
| handle->flags | full_range_flag, handle->width)) { |
| m_pCallbacks.EmptyBufferDone(hComp,m_app_data,buffer); |
| DEBUG_PRINT_ERROR("SetResolution failed"); |
| return OMX_ErrorBadParameter; |
| } |
| |
| mC2dSrcFmt = c2dSrcFmt; |
| mC2DFrameHeight = m_sInPortDef.format.video.nFrameHeight; |
| mC2DFrameWidth = m_sInPortDef.format.video.nFrameWidth; |
| |
| if (mC2dDestFmt != c2dDestFmt && !dev_set_format(c2dDestFmt)) { |
| DEBUG_PRINT_ERROR("cannot set color format"); |
| return OMX_ErrorBadParameter; |
| } |
| mC2dDestFmt = c2dDestFmt; |
| } |
| |
| dev_get_buf_req (&m_sInPortDef.nBufferCountMin, |
| &m_sInPortDef.nBufferCountActual, |
| &m_sInPortDef.nBufferSize, |
| m_sInPortDef.nPortIndex); |
| } |
| |
| 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) |
| { |
| |
| 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(PORT_INDEX_IN) != 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 if (c2dcc.getConversionNeeded()) { |
| uva = (unsigned char *)ion_map(Input_pmem_info.fd,Input_pmem_info.size); |
| if (uva == MAP_FAILED) { |
| ret = OMX_ErrorBadParameter; |
| } else { |
| DEBUG_PRINT_HIGH("Start Color Conversion..."); |
| if (!c2dcc.convertC2D(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; |
| buf_size = c2dcc.getBuffSize(C2D_OUTPUT); |
| 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); |
| } |
| ion_unmap(Input_pmem_info.fd, uva,Input_pmem_info.size); |
| } |
| } |
| if (dev_use_buf(PORT_INDEX_IN) != 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; |
| LEGACY_CAM_METADATA_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; |
| } |
| |
| if (psource_frame->nFilledLen == 0 && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) { |
| return handle_empty_eos_buffer(); |
| } |
| media_buffer = (LEGACY_CAM_METADATA_TYPE *)psource_frame->pBuffer; |
| /*Will enable to verify camcorder in current TIPS can be removed*/ |
| if (media_buffer->buffer_type == LEGACY_CAM_SOURCE) { |
| Input_pmem_info.buffer = media_buffer; |
| Input_pmem_info.fd = MetaBufferUtil::getFdAt(media_buffer->meta_handle, 0); |
| Input_pmem_info.offset = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_OFFSET); |
| Input_pmem_info.size = MetaBufferUtil::getIntAt(media_buffer->meta_handle, 0, MetaBufferUtil::INT_SIZE); |
| m_graphicbuffer_size = Input_pmem_info.size; |
| 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); |
| } else { |
| VideoGrallocMetadata *media_buffer = (VideoGrallocMetadata *)psource_frame->pBuffer; |
| private_handle_t *handle = (private_handle_t *)media_buffer->pHandle; |
| bool is_venus_supported_format = (handle->format == HAL_PIXEL_FORMAT_NV12_ENCODEABLE || |
| handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m || |
| handle->format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed || |
| handle->format == QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus || |
| handle->format == QOMX_COLOR_Format32bitRGBA8888Compressed || |
| handle->format == HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC || |
| handle->format == HAL_PIXEL_FORMAT_NV21_ZSL || |
| handle->format == QOMX_COLOR_FormatYVU420SemiPlanar || |
| handle->format == HAL_PIXEL_FORMAT_NV12_HEIF); |
| |
| Input_pmem_info.buffer = media_buffer; |
| Input_pmem_info.fd = handle->fd; |
| Input_pmem_info.offset = 0; |
| Input_pmem_info.size = handle->size; |
| m_graphicbuffer_size = Input_pmem_info.size; |
| if (is_conv_needed(handle)) |
| ret = convert_queue_buffer(hComp,Input_pmem_info,index); |
| else if (is_venus_supported_format) |
| ret = queue_meta_buffer(hComp); |
| else |
| ret = OMX_ErrorBadParameter; |
| } |
| } |
| return ret; |
| } |
| |
| OMX_ERRORTYPE omx_video::handle_empty_eos_buffer(void) |
| { |
| if(!dev_handle_empty_eos_buffer()) |
| return OMX_ErrorHardware; |
| else |
| return OMX_ErrorNone; |
| } |
| |
| // no code beyond this ! |
| |
| // inline import of vendor extensions implementation |
| #include "omx_video_extensions.hpp" |