| /** |
| * @copyright |
| * |
| * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| * @file |
| * |
| * omx_swvdec.h |
| * |
| * @brief |
| * |
| * OMX software video decoder component header. |
| */ |
| |
| #ifndef _OMX_SWVDEC_H_ |
| #define _OMX_SWVDEC_H_ |
| |
| //#undef NDEBUG // uncomment to enable assertions |
| |
| #include <pthread.h> |
| #include <semaphore.h> |
| |
| #include <linux/msm_ion.h> |
| #if TARGET_ION_ABI_VERSION >= 2 |
| #include <ion/ion.h> |
| #include <linux/dma-buf.h> |
| #endif |
| #include <media/msm_media_info.h> |
| |
| #include "qc_omx_component.h" |
| |
| #include "omx_swvdec_utils.h" |
| |
| #include "swvdec_types.h" |
| |
| using namespace android; |
| |
| /// OMX SwVdec version date |
| #define OMX_SWVDEC_VERSION_DATE "2017-10-06T11:32:51+0530" |
| |
| #define OMX_SPEC_VERSION 0x00000101 ///< OMX specification version |
| |
| #define OMX_SWVDEC_NUM_INSTANCES 1 ///< number of OMX SwVdec instances |
| |
| #define OMX_SWVDEC_IP_BUFFER_COUNT_MIN 5 ///< OMX SwVdec minimum ip buffer count |
| |
| #define OMX_SWVDEC_MAX_FRAMES_PER_ETB 2 ///< maximum number of frames per ETB |
| |
| /// frame dimensions structure |
| typedef struct { |
| unsigned int width; ///< frame width |
| unsigned int height; ///< frame height |
| } FRAME_DIMENSIONS; |
| |
| /// frame attributes structure |
| typedef struct { |
| unsigned int stride; ///< frame stride |
| unsigned int scanlines; ///< frame scanlines |
| unsigned int size; ///< frame size |
| } FRAME_ATTRIBUTES; |
| |
| /// asynchronous thread structure |
| typedef struct { |
| sem_t sem_thread_created; ///< thread created semaphore |
| sem_t sem_event; ///< event semaphore |
| pthread_t handle; ///< thread handle |
| bool created; ///< thread created? |
| bool exit; ///< thread exit variable |
| } ASYNC_THREAD; |
| |
| /// @cond |
| |
| struct vdec_ion { |
| int dev_fd; |
| struct ion_allocation_data alloc_data; |
| int data_fd; |
| }; |
| |
| struct vdec_bufferpayload { |
| void *bufferaddr; |
| size_t buffer_len; |
| int pmem_fd; |
| size_t offset; |
| size_t mmaped_size; |
| }; |
| |
| typedef struct { |
| OMX_BUFFERHEADERTYPE buffer_header; |
| struct vdec_ion ion_info; |
| struct vdec_bufferpayload buffer_payload; |
| SWVDEC_BUFFER buffer_swvdec; |
| bool buffer_populated; |
| unsigned int split_count; |
| } OMX_SWVDEC_BUFFER_INFO; |
| |
| /// @endcond |
| |
| /// port structure |
| typedef struct { |
| OMX_PARAM_PORTDEFINITIONTYPE def; ///< definition |
| OMX_BOOL enabled; ///< enabled? |
| OMX_BOOL populated; ///< populated? |
| OMX_BOOL unpopulated; ///< unpopulated? |
| OMX_BOOL flush_inprogress; ///< flush inprogress? |
| unsigned int num_pending_buffers; ///< # of pending buffers |
| } OMX_SWVDEC_PORT; |
| |
| /// meta_buffer information structure |
| typedef struct { |
| int fd; ///< file descriptor |
| int ref_count; ///< reference count |
| } OMX_SWVDEC_META_BUFFER_INFO; |
| |
| #define DEFAULT_FRAME_WIDTH 1920 ///< default frame width |
| #define DEFAULT_FRAME_HEIGHT 1080 ///< default frame height |
| |
| #define MAX(x, y) (((x) > (y)) ? (x) : (y)) ///< maximum |
| #define MIN(x, y) (((x) < (y)) ? (x) : (y)) ///< minimum |
| #define ALIGN(x, y) (((x) + ((y) - 1)) & (~((y) - 1))) |
| ///< align 'x' to next highest multiple of 'y' |
| |
| /// macro to print 'command type' string |
| #define OMX_COMMANDTYPE_STRING(x) \ |
| ((x == OMX_CommandStateSet) ? "OMX_CommandStateSet" : \ |
| ((x == OMX_CommandFlush) ? "OMX_CommandFlush" : \ |
| ((x == OMX_CommandPortDisable) ? "OMX_CommandPortDisable" : \ |
| ((x == OMX_CommandPortEnable) ? "OMX_CommandPortEnable" : \ |
| "unknown")))) |
| |
| /// macro to print 'state type' string |
| #define OMX_STATETYPE_STRING(x) \ |
| ((x == OMX_StateInvalid) ? "OMX_StateInvalid" : \ |
| ((x == OMX_StateLoaded) ? "OMX_StateLoaded" : \ |
| ((x == OMX_StateIdle) ? "OMX_StateIdle" : \ |
| ((x == OMX_StateExecuting) ? "OMX_StateExecuting" : \ |
| ((x == OMX_StatePause) ? "OMX_StatePause" : \ |
| ((x == OMX_StateWaitForResources) ? "OMX_StateWaitForResources" : \ |
| "unknown")))))) |
| |
| enum { |
| OMX_CORE_PORT_INDEX_IP = 0, ///< input port index |
| OMX_CORE_PORT_INDEX_OP = 1 ///< output port index |
| }; |
| |
| extern "C" { |
| OMX_API void *get_omx_component_factory_fn(void); |
| }; |
| |
| /// OMX SwVdec component class; derived from QC OMX component base class |
| class omx_swvdec : public qc_omx_component |
| { |
| public: |
| |
| omx_swvdec(); |
| |
| virtual ~omx_swvdec(); |
| |
| // derived class versions of base class pure virtual functions |
| |
| OMX_ERRORTYPE component_init(OMX_STRING cmp_name); |
| OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE cmp_handle); |
| OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE cmp_handle, |
| OMX_STRING cmp_name, |
| OMX_VERSIONTYPE *p_cmp_version, |
| OMX_VERSIONTYPE *p_spec_version, |
| OMX_UUIDTYPE *p_cmp_UUID); |
| OMX_ERRORTYPE send_command(OMX_HANDLETYPE cmp_handle, |
| OMX_COMMANDTYPE cmd, |
| OMX_U32 param, |
| OMX_PTR p_cmd_data); |
| OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE param_index, |
| OMX_PTR p_param_data); |
| OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE param_index, |
| OMX_PTR p_param_data); |
| OMX_ERRORTYPE get_config(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE config_index, |
| OMX_PTR p_config_data); |
| OMX_ERRORTYPE set_config(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE config_index, |
| OMX_PTR p_config_data); |
| OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE cmp_handle, |
| OMX_STRING param_name, |
| OMX_INDEXTYPE *p_index_type); |
| OMX_ERRORTYPE get_state(OMX_HANDLETYPE cmp_handle, |
| OMX_STATETYPE *p_state); |
| OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE cmp_handle, |
| OMX_U32 port, |
| OMX_HANDLETYPE peer_component, |
| OMX_U32 peer_port, |
| OMX_TUNNELSETUPTYPE *p_tunnel_setup); |
| OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_U32 port, |
| OMX_PTR p_app_data, |
| OMX_U32 bytes, |
| OMX_U8 *p_buffer); |
| OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_U32 port, |
| OMX_PTR p_app_data, |
| OMX_U32 bytes); |
| OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_U32 port, |
| OMX_BUFFERHEADERTYPE *p_buffer); |
| OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr); |
| OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr); |
| OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE cmp_handle, |
| OMX_CALLBACKTYPE *p_callbacks, |
| OMX_PTR p_app_data); |
| OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_U32 port, |
| OMX_PTR p_app_data, |
| void *egl_image); |
| OMX_ERRORTYPE component_role_enum(OMX_HANDLETYPE cmp_handle, |
| OMX_U8 *p_role, |
| OMX_U32 index); |
| |
| // SwVdec callback functions |
| |
| static SWVDEC_STATUS swvdec_empty_buffer_done_callback( |
| SWVDEC_HANDLE swvdec_handle, |
| SWVDEC_BUFFER *p_buffer_ip, |
| void *p_client_handle); |
| static SWVDEC_STATUS swvdec_fill_buffer_done_callback( |
| SWVDEC_HANDLE swvdec_handle, |
| SWVDEC_BUFFER *p_buffer_op, |
| void *p_client_handle); |
| static SWVDEC_STATUS swvdec_event_handler_callback( |
| SWVDEC_HANDLE swvdec_handle, |
| SWVDEC_EVENT event, |
| void *p_data, |
| void *p_client_handle); |
| |
| private: |
| |
| OMX_STATETYPE m_state; ///< component state |
| |
| unsigned int m_status_flags; ///< status flags |
| |
| char m_cmp_name[OMX_MAX_STRINGNAME_SIZE]; ///< component name |
| char m_role_name[OMX_MAX_STRINGNAME_SIZE]; ///< component role name |
| |
| SWVDEC_CODEC m_swvdec_codec; ///< SwVdec codec type |
| SWVDEC_HANDLE m_swvdec_handle; ///< SwVdec handle |
| bool m_swvdec_created; ///< SwVdec created? |
| |
| OMX_VIDEO_CODINGTYPE m_omx_video_codingtype; ///< OMX video coding type |
| OMX_COLOR_FORMATTYPE m_omx_color_formattype; ///< OMX color format type |
| |
| FRAME_DIMENSIONS m_frame_dimensions; ///< frame dimensions |
| FRAME_ATTRIBUTES m_frame_attributes; ///< frame attributes |
| |
| FRAME_DIMENSIONS m_frame_dimensions_max; |
| ///< max frame dimensions for adaptive playback |
| |
| ASYNC_THREAD m_async_thread; ///< asynchronous thread |
| |
| omx_swvdec_queue m_queue_command; ///< command queue |
| omx_swvdec_queue m_queue_port_ip; ///< input port queue for ETBs & EBDs |
| omx_swvdec_queue m_queue_port_op; ///< output port queue for FTBs & FBDs |
| |
| OMX_SWVDEC_PORT m_port_ip; ///< input port |
| OMX_SWVDEC_PORT m_port_op; ///< output port |
| |
| OMX_CALLBACKTYPE m_callback; ///< IL client callback structure |
| OMX_PTR m_app_data; ///< IL client app data pointer |
| |
| OMX_PRIORITYMGMTTYPE m_prio_mgmt; ///< priority management |
| |
| bool m_sync_frame_decoding_mode; ///< sync frame decoding mode enabled? |
| bool m_android_native_buffers; ///< android native buffers enabled? |
| |
| bool m_meta_buffer_mode_disabled; ///< meta buffer mode disabled? |
| bool m_meta_buffer_mode; ///< meta buffer mode enabled? |
| bool m_adaptive_playback_mode; ///< adaptive playback mode enabled? |
| bool m_arbitrary_bytes_mode; ///< arbitrary bytes mode enabled? |
| |
| bool m_port_reconfig_inprogress; ///< port reconfiguration in progress? |
| |
| bool m_dimensions_update_inprogress; ///< dimensions update in progress? |
| |
| sem_t m_sem_cmd; ///< semaphore for command processing |
| |
| OMX_SWVDEC_BUFFER_INFO *m_buffer_array_ip; ///< input buffer info array |
| OMX_SWVDEC_BUFFER_INFO *m_buffer_array_op; ///< output buffer info array |
| |
| OMX_SWVDEC_META_BUFFER_INFO *m_meta_buffer_array; ///< metabuffer info array |
| pthread_mutex_t m_meta_buffer_array_mutex; |
| ///< mutex for metabuffer info array |
| |
| std::priority_queue <OMX_TICKS, |
| std::vector<OMX_TICKS>, |
| std::greater<OMX_TICKS> > m_queue_timestamp; |
| ///< timestamp priority queue |
| |
| omx_swvdec_diag m_diag; ///< diagnostics class variable |
| |
| OMX_ERRORTYPE set_frame_dimensions(unsigned int width, |
| unsigned int height); |
| OMX_ERRORTYPE set_frame_attributes(OMX_COLOR_FORMATTYPE color_format); |
| OMX_ERRORTYPE set_adaptive_playback(unsigned int max_width, |
| unsigned int max_height); |
| |
| OMX_ERRORTYPE get_video_port_format( |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format); |
| OMX_ERRORTYPE set_video_port_format( |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format); |
| |
| OMX_ERRORTYPE get_port_definition(OMX_PARAM_PORTDEFINITIONTYPE *p_port_def); |
| OMX_ERRORTYPE set_port_definition(OMX_PARAM_PORTDEFINITIONTYPE *p_port_def); |
| |
| OMX_ERRORTYPE get_supported_profilelevel( |
| OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel); |
| |
| OMX_ERRORTYPE describe_color_format(DescribeColorFormatParams *p_params); |
| |
| OMX_ERRORTYPE set_port_definition_qcom( |
| OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def); |
| |
| // functions to set SwVdec properties with OMX component properties |
| |
| OMX_ERRORTYPE set_frame_dimensions_swvdec(); |
| OMX_ERRORTYPE set_frame_attributes_swvdec(); |
| OMX_ERRORTYPE set_adaptive_playback_swvdec(); |
| OMX_ERRORTYPE set_thumbnail_mode_swvdec(); |
| |
| // functions to get SwVdec properties and set OMX component properties |
| |
| OMX_ERRORTYPE get_frame_dimensions_swvdec(); |
| OMX_ERRORTYPE get_frame_attributes_swvdec(); |
| OMX_ERRORTYPE get_buffer_requirements_swvdec(unsigned int port_index); |
| |
| // buffer allocation & de-allocation functions |
| OMX_ERRORTYPE buffer_allocate_ip(OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_PTR p_app_data, |
| OMX_U32 size); |
| OMX_ERRORTYPE buffer_allocate_op(OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_PTR p_app_data, |
| OMX_U32 size); |
| OMX_ERRORTYPE buffer_allocate_ip_info_array(); |
| OMX_ERRORTYPE buffer_allocate_op_info_array(); |
| OMX_ERRORTYPE buffer_use_op(OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_PTR p_app_data, |
| OMX_U32 size, |
| OMX_U8 *p_buffer); |
| OMX_ERRORTYPE buffer_deallocate_ip(OMX_BUFFERHEADERTYPE *p_buffer_hdr); |
| OMX_ERRORTYPE buffer_deallocate_op(OMX_BUFFERHEADERTYPE *p_buffer_hdr); |
| void buffer_deallocate_ip_info_array(); |
| void buffer_deallocate_op_info_array(); |
| |
| OMX_ERRORTYPE meta_buffer_array_allocate(); |
| void meta_buffer_array_deallocate(); |
| void meta_buffer_ref_add(unsigned int index, int fd); |
| void meta_buffer_ref_remove(unsigned int index); |
| |
| OMX_BOOL port_ip_populated(); |
| OMX_BOOL port_op_populated(); |
| |
| OMX_ERRORTYPE flush(unsigned int port_index); |
| |
| int ion_memory_alloc_map(struct vdec_ion *p_ion_info, OMX_U32 size, OMX_U32 alignment); |
| void ion_memory_free(struct vdec_ion *p_ion_buf_info); |
| void ion_flush_op(unsigned int index); |
| unsigned char *ion_map(int fd, int len); |
| OMX_ERRORTYPE ion_unmap(int fd, void *bufaddr, int len); |
| |
| // component callback functions |
| |
| void swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip); |
| void swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op); |
| void swvdec_event_handler(SWVDEC_EVENT event, void *p_data); |
| |
| OMX_ERRORTYPE retval_swvdec2omx(SWVDEC_STATUS retval_swvdec); |
| |
| // status bits for pending events |
| enum { |
| PENDING_STATE_LOADED_TO_IDLE, ///< loaded to idle state |
| PENDING_STATE_EXECUTING_TO_IDLE, ///< executing to idle state |
| PENDING_STATE_IDLE_TO_LOADED, ///< idle to loaded state |
| PENDING_PORT_ENABLE_IP, ///< enablement of ip port |
| PENDING_PORT_ENABLE_OP, ///< enablement of op port |
| PENDING_PORT_DISABLE_IP, ///< disablement of ip port |
| PENDING_PORT_DISABLE_OP, ///< disablement of op port |
| PENDING_PORT_FLUSH_IP, ///< flush of ip port |
| PENDING_PORT_FLUSH_OP ///< flush of op port |
| }; |
| |
| // events raised internally |
| enum { |
| OMX_SWVDEC_EVENT_CMD, ///< command event |
| OMX_SWVDEC_EVENT_CMD_ACK, ///< command acknowledgement |
| OMX_SWVDEC_EVENT_ERROR, ///< error event |
| OMX_SWVDEC_EVENT_ETB, ///< ETB event |
| OMX_SWVDEC_EVENT_EBD, ///< EBD event |
| OMX_SWVDEC_EVENT_FTB, ///< FTB event |
| OMX_SWVDEC_EVENT_FBD, ///< FBD event |
| OMX_SWVDEC_EVENT_EOS, ///< EOS event |
| OMX_SWVDEC_EVENT_FLUSH_PORT_IP, ///< flush ip port event |
| OMX_SWVDEC_EVENT_FLUSH_PORT_OP, ///< flush op port event |
| OMX_SWVDEC_EVENT_PORT_RECONFIG, ///< port reconfig event |
| OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED ///< dimensions updated event |
| }; |
| |
| OMX_ERRORTYPE async_thread_create(); |
| void async_thread_destroy(); |
| |
| static void async_thread(void *p_cmp); |
| |
| void async_post_event(unsigned long event_id, |
| unsigned long event_param1, |
| unsigned long event_param2); |
| |
| static void async_process_event(void *p_cmp); |
| |
| OMX_ERRORTYPE async_process_event_cmd(OMX_COMMANDTYPE cmd, OMX_U32 param); |
| OMX_ERRORTYPE async_process_event_cmd_ack(OMX_COMMANDTYPE cmd, |
| OMX_U32 param); |
| OMX_ERRORTYPE async_process_event_error(OMX_ERRORTYPE error_code); |
| OMX_ERRORTYPE async_process_event_cmd_state_set(bool *p_cmd_ack, |
| OMX_STATETYPE state_new); |
| OMX_ERRORTYPE async_process_event_cmd_flush(unsigned int port_index); |
| OMX_ERRORTYPE async_process_event_cmd_port_disable( |
| bool *p_cmd_ack, |
| unsigned int port_index); |
| OMX_ERRORTYPE async_process_event_cmd_port_enable(bool *p_cmd_ack, |
| unsigned int port_index); |
| OMX_ERRORTYPE async_process_event_etb(OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index); |
| OMX_ERRORTYPE async_process_event_ftb(OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index); |
| OMX_ERRORTYPE async_process_event_ebd(OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index); |
| OMX_ERRORTYPE async_process_event_fbd(OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index); |
| OMX_ERRORTYPE async_process_event_eos(); |
| OMX_ERRORTYPE async_process_event_flush_port_ip(); |
| OMX_ERRORTYPE async_process_event_flush_port_op(); |
| OMX_ERRORTYPE async_process_event_port_reconfig(); |
| OMX_ERRORTYPE async_process_event_dimensions_updated(); |
| }; |
| |
| #endif // #ifndef _OMX_SWVDEC_H_ |