summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2015-11-21 17:55:54 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2015-11-21 17:55:54 -0800
commit418b5fab13b31e10cc954db33b68ddef5b6d0fbb (patch)
treedede256eb0a757e5b3e4b27baf8090e606328bcb
parent6e5aa04372146c3a2ab04fdf19b7b18a3f12a4c6 (diff)
parente592d0a7da065572dafca837edbd2c656852935b (diff)
downloadandroid_hardware_qcom_media-418b5fab13b31e10cc954db33b68ddef5b6d0fbb.tar.gz
android_hardware_qcom_media-418b5fab13b31e10cc954db33b68ddef5b6d0fbb.tar.bz2
android_hardware_qcom_media-418b5fab13b31e10cc954db33b68ddef5b6d0fbb.zip
Merge "mm-video: swvdec: Add SwVdec OMX component."
-rw-r--r--mm-video-v4l2/vidc/vdec/Android.mk26
-rw-r--r--mm-video-v4l2/vidc/vdec/inc/omx_swvdec.h459
-rw-r--r--mm-video-v4l2/vidc/vdec/inc/omx_swvdec_utils.h179
-rw-r--r--mm-video-v4l2/vidc/vdec/src/omx_swvdec.cpp5835
-rw-r--r--mm-video-v4l2/vidc/vdec/src/omx_swvdec_utils.cpp461
5 files changed, 6960 insertions, 0 deletions
diff --git a/mm-video-v4l2/vidc/vdec/Android.mk b/mm-video-v4l2/vidc/vdec/Android.mk
index 0d27319f..f741e88c 100644
--- a/mm-video-v4l2/vidc/vdec/Android.mk
+++ b/mm-video-v4l2/vidc/vdec/Android.mk
@@ -31,6 +31,7 @@ TARGETS_THAT_HAVE_VENUS_HEVC := apq8084 msm8994 msm8996
TARGETS_THAT_NEED_HEVC_LIB := msm8974 msm8610 msm8226 msm8916
TARGETS_THAT_NEED_SW_HEVC := msm8974 msm8226 msm8916
TARGETS_THAT_SUPPORT_UBWC := msm8996
+TARGETS_THAT_NEED_SW_VDEC := msm8937
ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_USE_HEVC_ADSP_HEAP)),true)
libmm-vdec-def += -D_HEVC_USE_ADSP_HEAP_
@@ -74,6 +75,7 @@ libmm-vdec-inc += $(TOP)/frameworks/native/include/media/hardware
libmm-vdec-inc += $(TOP)/hardware/qcom/media/libc2dcolorconvert
libmm-vdec-inc += $(TOP)/frameworks/av/include/media/stagefright
libmm-vdec-inc += $(TARGET_OUT_HEADERS)/mm-video/SwVdec
+libmm-vdec-inc += $(TARGET_OUT_HEADERS)/mm-video/swvdec
libmm-vdec-inc += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
ifeq ($(PLATFORM_SDK_VERSION), 18) #JB_MR2
@@ -162,7 +164,31 @@ LOCAL_SRC_FILES += src/hevc_utils.cpp
LOCAL_STATIC_LIBRARIES := libOmxVidcCommon
include $(BUILD_SHARED_LIBRARY)
+endif
+endif
+
+# ---------------------------------------------------------------------------------
+# Make the Shared library (libOmxSwVdec)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+ifneq "$(wildcard $(QCPATH) )" ""
+ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_NEED_SW_VDEC)),true)
+
+LOCAL_MODULE := libOmxSwVdec
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := $(libmm-vdec-def)
+LOCAL_C_INCLUDES += $(libmm-vdec-inc)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(libmm-vdec-add-dep)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_SHARED_LIBRARIES += libswvdec
+
+LOCAL_SRC_FILES := src/omx_swvdec.cpp
+LOCAL_SRC_FILES += src/omx_swvdec_utils.cpp
+
+include $(BUILD_SHARED_LIBRARY)
endif
endif
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_swvdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_swvdec.h
new file mode 100644
index 00000000..78aae672
--- /dev/null
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_swvdec.h
@@ -0,0 +1,459 @@
+/**
+ * @copyright
+ *
+ * Copyright (c) 2015, 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_
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <linux/msm_ion.h>
+#include <linux/msm_vidc_dec.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 "2015-11-09T18:33:31+0530"
+
+#define OMX_SPEC_VERSION 0x00000101 ///< OMX specification version
+
+#define OMX_SWVDEC_NUM_INSTANCES 1 ///< number of OMX SwVdec instances
+
+// @todo Make this macro default and store in a variable?
+#define OMX_SWVDEC_IP_BUFFER_COUNT 5 ///< OMX SwVdec input buffer count
+
+/// frame rate structure
+typedef struct {
+ unsigned int fps_numerator; ///< fps numerator
+ unsigned int fps_denominator; ///< fps denominator
+} FRAME_RATE;
+
+#define DEFAULT_FPS_NUMERATOR 30 ///< default fps numerator
+#define DEFAULT_FPS_DENOMINATOR 1 ///< default fps denominator
+
+/// 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 ion_fd_device;
+ struct ion_fd_data ion_fd_data;
+ struct ion_allocation_data ion_alloc_data;
+};
+
+typedef struct {
+ OMX_BUFFERHEADERTYPE buffer_header;
+ struct vdec_ion ion_info;
+ struct vdec_bufferpayload buffer_payload;
+ SWVDEC_BUFFER buffer_swvdec;
+ bool buffer_populated;
+} 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 {
+ unsigned int fd; ///< file descriptor
+ unsigned int dup_fd; ///< duplicate file descriptor
+ unsigned int offset; ///< offset
+ unsigned int ref_count; ///< reference count
+} OMX_SWVDEC_META_BUFFER_INFO;
+
+#define DEFAULT_FRAME_WIDTH 1920 ///< default frame width
+#define DEFAULT_FRAME_HEIGHT 1088 ///< default frame height
+
+#define DEFAULT_ALIGNMENT_STRIDE 128 ///< default stride alignment
+#define DEFAULT_ALIGNMENT_SCANLINES_Y 32 ///< default Y scanlines alignment
+#define DEFAULT_ALIGNMENT_SCANLINES_UV 16 ///< default UV scanlines alignment
+#define DEFAULT_ALIGNMENT_SIZE 4096 ///< default size alignment
+
+#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_RATE m_frame_rate; ///< frame rate
+ FRAME_DIMENSIONS m_frame_dimensions; ///< frame dimensions
+ FRAME_ATTRIBUTES m_frame_attributes; ///< frame attributes
+
+ 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; ///< meta buffer mode enabled?
+
+ bool m_port_reconfig_inprogress; ///< port reconfiguration 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
+
+ omx_swvdec_ts_list m_ts_list; ///< timestamp list
+
+ omx_swvdec_diag m_diag; ///< diagnostics class variable
+
+ OMX_ERRORTYPE set_frame_dimensions(unsigned int width,
+ unsigned int height);
+ OMX_ERRORTYPE set_frame_attributes(unsigned int alignment_stride,
+ unsigned int alignment_scanlines_y,
+ unsigned int alignment_scanlines_uv,
+ unsigned int alignment_size);
+
+ 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();
+
+ // 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,
+ unsigned int fd,
+ unsigned int offset);
+ void meta_buffer_ref_remove(unsigned int fd, unsigned int offset);
+
+ OMX_BOOL port_ip_populated();
+ OMX_BOOL port_op_populated();
+
+ OMX_ERRORTYPE flush(unsigned int port_index);
+
+ int ion_memory_alloc_map(struct ion_allocation_data *p_alloc_data,
+ struct ion_fd_data *p_fd_data,
+ OMX_U32 size,
+ OMX_U32 alignment);
+ void ion_memory_free(struct vdec_ion *p_ion_buf_info);
+
+ // 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_ERRORTYPE async_thread_create();
+ void async_thread_destroy();
+
+ static void async_thread(void *p_cmp);
+
+ bool 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();
+};
+
+#endif // #ifndef _OMX_SWVDEC_H_
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_swvdec_utils.h b/mm-video-v4l2/vidc/vdec/inc/omx_swvdec_utils.h
new file mode 100644
index 00000000..acc8cc95
--- /dev/null
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_swvdec_utils.h
@@ -0,0 +1,179 @@
+/**
+ * @copyright
+ *
+ * Copyright (c) 2015, 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_utils.h
+ *
+ * @brief
+ *
+ * OMX software video decoder utility functions header.
+ */
+
+#ifndef _OMX_SWVDEC_UTILS_H_
+#define _OMX_SWVDEC_UTILS_H_
+
+#include <pthread.h>
+
+#include <cutils/log.h>
+
+extern unsigned int g_omx_swvdec_logmask;
+ ///< global OMX SwVdec logmask variable extern declaration
+
+void omx_swvdec_log_init();
+
+#define OMX_SWVDEC_LOGMASK_LOW 4 ///< 100: logmask for low priority logs
+#define OMX_SWVDEC_LOGMASK_HIGH 2 ///< 010: logmask for high priority logs
+#define OMX_SWVDEC_LOGMASK_ERROR 1 ///< 001: logmask for error priority logs
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "OMX_SWVDEC" ///< OMX SwVdec log tag
+
+/// low priority log message
+#define OMX_SWVDEC_LOG_LOW(string, ...) \
+ do { \
+ if (g_omx_swvdec_logmask & OMX_SWVDEC_LOGMASK_LOW) \
+ ALOGD("--- %s(): " string, __FUNCTION__, ##__VA_ARGS__); \
+ } while (0)
+
+/// high priority log message
+#define OMX_SWVDEC_LOG_HIGH(string, ...) \
+ do { \
+ if (g_omx_swvdec_logmask & OMX_SWVDEC_LOGMASK_HIGH) \
+ ALOGI("--- %s(): " string, __FUNCTION__, ##__VA_ARGS__); \
+ } while (0)
+
+/// error priority log message
+#define OMX_SWVDEC_LOG_ERROR(string, ...) \
+ do { \
+ if (g_omx_swvdec_logmask & OMX_SWVDEC_LOGMASK_ERROR) \
+ ALOGE("!!! %s(): " string, __FUNCTION__, ##__VA_ARGS__); \
+ } while (0)
+
+/// high priority log message for OMX SwVdec API calls
+#define OMX_SWVDEC_LOG_API(string, ...) \
+ do { \
+ if (g_omx_swvdec_logmask & OMX_SWVDEC_LOGMASK_HIGH) \
+ ALOGI(">>> %s(): " string, __FUNCTION__, ##__VA_ARGS__); \
+ } while (0)
+
+/// high priority log message for OMX SwVdec callbacks
+#define OMX_SWVDEC_LOG_CALLBACK(string, ...) \
+ do { \
+ if (g_omx_swvdec_logmask & OMX_SWVDEC_LOGMASK_HIGH) \
+ ALOGI("<<< %s(): " string, __FUNCTION__, ##__VA_ARGS__); \
+ } while (0)
+
+#define OMX_SWVDEC_QUEUE_ELEMENTS 100 ///< number of elements in queue
+
+/// OMX SwVdec event information structure
+typedef struct {
+ unsigned long event_id; ///< event ID
+ unsigned long event_param1; ///< event parameter 1
+ unsigned long event_param2; ///< event parameter 2
+} OMX_SWVDEC_EVENT_INFO;
+
+/// OMX SwVdec queue class
+class omx_swvdec_queue
+{
+public:
+ omx_swvdec_queue();
+ ~omx_swvdec_queue();
+
+ bool push(OMX_SWVDEC_EVENT_INFO *p_event_info);
+ bool pop(OMX_SWVDEC_EVENT_INFO *p_event_info);
+
+private:
+ OMX_SWVDEC_EVENT_INFO m_queue[OMX_SWVDEC_QUEUE_ELEMENTS];
+ ///< event queue
+ unsigned int m_count_total; ///< count of total elements
+ unsigned int m_count_filled; ///< count of filled elements
+ unsigned int m_index_write; ///< queue index for writing
+ unsigned int m_index_read; ///< queue index for reading
+ pthread_mutex_t m_mutex; ///< mutex for queue access
+};
+
+#define OMX_SWVDEC_TS_LIST_ELEMENTS 100
+ ///< number of elements in timestamp list
+
+/// OMX SwVdec timestamp element structure.
+typedef struct {
+ bool filled; ///< element filled?
+ long long timestamp; ///< timestamp
+} OMX_SWVDEC_TS_ELEMENT;
+
+/// OMX SwVdec timestamp list class
+class omx_swvdec_ts_list
+{
+public:
+ omx_swvdec_ts_list();
+ ~omx_swvdec_ts_list();
+
+ void reset();
+ bool push(long long timestamp);
+ bool pop(long long *p_timestamp);
+
+private:
+ OMX_SWVDEC_TS_ELEMENT m_list[OMX_SWVDEC_TS_LIST_ELEMENTS];
+ ///< list of timestamp elements
+ int m_count_filled; ///< count of filled elements
+ pthread_mutex_t m_mutex; ///< mutex for list access
+};
+
+#define DIAG_FILENAME_IP "/data/misc/media/input.bin" ///< input filename
+#define DIAG_FILENAME_OP "/data/misc/media/output.yuv" ///< output filename
+
+/// OMX SwVdec diagnostics class
+class omx_swvdec_diag
+{
+public:
+ omx_swvdec_diag();
+ ~omx_swvdec_diag();
+
+ void dump_ip(unsigned char *p_buffer, unsigned int filled_length);
+ void dump_op(unsigned char *p_buffer,
+ unsigned int width,
+ unsigned int height,
+ unsigned int stride,
+ unsigned int scanlines);
+
+private:
+ unsigned int m_dump_ip; ///< dump input bitstream
+ unsigned int m_dump_op; ///< dump output YUV
+
+ char *m_filename_ip; ///< input filename string
+ char *m_filename_op; ///< output filename string
+
+ FILE *m_file_ip; ///< input file handle
+ FILE *m_file_op; ///< output file handle
+};
+
+#endif // #ifndef _OMX_SWVDEC_UTILS_H_
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_swvdec.cpp b/mm-video-v4l2/vidc/vdec/src/omx_swvdec.cpp
new file mode 100644
index 00000000..54c1df66
--- /dev/null
+++ b/mm-video-v4l2/vidc/vdec/src/omx_swvdec.cpp
@@ -0,0 +1,5835 @@
+/**
+ * @copyright
+ *
+ * Copyright (c) 2015, 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.cpp
+ *
+ * @brief
+ *
+ * OMX software video decoder component source.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <media/hardware/HardwareAPI.h>
+#include <gralloc_priv.h>
+
+#include "OMX_QCOMExtns.h"
+
+#include "omx_swvdec.h"
+
+#include "swvdec_api.h"
+
+/**
+ * ----------------
+ * PUBLIC FUNCTIONS
+ * ----------------
+ */
+
+/**
+ * @brief Create & return component class instance.
+ *
+ * @retval Pointer to new component class instance.
+ */
+void *get_omx_component_factory_fn(void)
+{
+ return new omx_swvdec;
+}
+
+/**
+ * @brief Component constructor.
+ */
+omx_swvdec::omx_swvdec():
+ m_state(OMX_StateInvalid),
+ m_status_flags(0),
+ m_swvdec_codec(SWVDEC_CODEC_INVALID),
+ m_swvdec_handle(NULL),
+ m_swvdec_created(false),
+ m_omx_video_codingtype(OMX_VIDEO_CodingUnused),
+ m_omx_color_formattype(OMX_COLOR_FormatUnused),
+ m_sync_frame_decoding_mode(false),
+ m_android_native_buffers(false),
+ m_meta_buffer_mode(false),
+ m_port_reconfig_inprogress(false),
+ m_buffer_array_ip(NULL),
+ m_buffer_array_op(NULL),
+ m_meta_buffer_array(NULL)
+{
+ // memset all member variables that are composite structures
+ memset(&m_cmp, 0, sizeof(m_cmp)); // part of base class
+ memset(&m_cmp_name[0], 0, sizeof(m_cmp_name));
+ memset(&m_role_name[0], 0, sizeof(m_role_name));
+ memset(&m_frame_rate, 0, sizeof(m_frame_rate));
+ memset(&m_frame_dimensions, 0, sizeof(m_frame_dimensions));
+ memset(&m_frame_attributes, 0, sizeof(m_frame_attributes));
+ memset(&m_async_thread, 0, sizeof(m_async_thread));
+ memset(&m_port_ip, 0, sizeof(m_port_ip));
+ memset(&m_port_op, 0, sizeof(m_port_op));
+ memset(&m_callback, 0, sizeof(m_callback));
+ memset(&m_app_data, 0, sizeof(m_app_data));
+ memset(&m_prio_mgmt, 0, sizeof(m_prio_mgmt));
+ memset(&m_sem_cmd, 0, sizeof(m_sem_cmd));
+ memset(&m_meta_buffer_array_mutex, 0, sizeof(m_meta_buffer_array_mutex));
+
+ // null-terminate component name & role name strings
+ m_cmp_name[0] = '\0';
+ m_role_name[0] = '\0';
+
+ // ports are enabled & unpopulated by default
+ m_port_ip.enabled = OMX_TRUE;
+ m_port_op.enabled = OMX_TRUE;
+ m_port_ip.unpopulated = OMX_TRUE;
+ m_port_op.unpopulated = OMX_TRUE;
+}
+
+/**
+ * @brief Component destructor.
+ */
+omx_swvdec::~omx_swvdec()
+{
+}
+
+/**
+ * @brief Initialize component.
+ *
+ * @param[in] cmp_name: Component name string.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::component_init(OMX_STRING cmp_name)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_LOG_API("'%s', version date: %s",
+ cmp_name,
+ OMX_SWVDEC_VERSION_DATE);
+
+ omx_swvdec_log_init();
+
+ if (m_state != OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
+ OMX_STATETYPE_STRING(m_state));
+ retval = OMX_ErrorIncorrectStateOperation;
+ goto component_init_exit;
+ }
+
+ // set up codec type variables based on component name string
+
+ if (!strncmp(cmp_name,
+ "OMX.qti.video.decoder.mpeg4sw",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ OMX_SWVDEC_LOG_LOW("'video_decoder.mpeg4'");
+
+ strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE);
+ strlcpy(m_role_name, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
+
+ m_swvdec_codec = SWVDEC_CODEC_MPEG4;
+ m_omx_video_codingtype = OMX_VIDEO_CodingMPEG4;
+ }
+ else if (!strncmp(cmp_name,
+ "OMX.qti.video.decoder.h263sw",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ OMX_SWVDEC_LOG_LOW("video_decoder.h263");
+
+ strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE);
+ strlcpy(m_role_name, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
+
+ m_swvdec_codec = SWVDEC_CODEC_H263;
+ m_omx_video_codingtype = OMX_VIDEO_CodingH263;
+ }
+ else if (((!strncmp(cmp_name,
+ "OMX.qti.video.decoder.divxsw",
+ OMX_MAX_STRINGNAME_SIZE))) ||
+ ((!strncmp(cmp_name,
+ "OMX.qti.video.decoder.divx4sw",
+ OMX_MAX_STRINGNAME_SIZE))))
+ {
+ OMX_SWVDEC_LOG_LOW("video_decoder.divx");
+
+ strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE);
+ strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
+
+ m_swvdec_codec = SWVDEC_CODEC_MPEG4;
+ m_omx_video_codingtype = ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name);
+ retval = OMX_ErrorInvalidComponentName;
+ goto component_init_exit;
+ }
+
+ m_omx_color_formattype =
+ (OMX_COLOR_FORMATTYPE) OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
+
+ m_frame_rate.fps_numerator = DEFAULT_FPS_NUMERATOR;
+ m_frame_rate.fps_denominator = DEFAULT_FPS_DENOMINATOR;
+
+ {
+ SWVDEC_CALLBACK callback;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ // initialize SwVdec core library
+
+ callback.pfn_empty_buffer_done = swvdec_empty_buffer_done_callback;
+ callback.pfn_fill_buffer_done = swvdec_fill_buffer_done_callback;
+ callback.pfn_event_notification = swvdec_event_handler_callback;
+ callback.p_client = this;
+
+ if ((retval_swvdec = swvdec_init(&m_swvdec_handle,
+ m_swvdec_codec,
+ &callback)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ goto component_init_exit;
+ }
+
+ m_swvdec_created = true;
+
+ // set frame dimensions for OMX component & SwVdec core
+ if ((retval = set_frame_dimensions(DEFAULT_FRAME_WIDTH,
+ DEFAULT_FRAME_HEIGHT)) !=
+ OMX_ErrorNone)
+ {
+ goto component_init_exit;
+ }
+
+ // set frame attributes for OMX component & SwVdec core
+ if ((retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
+ DEFAULT_ALIGNMENT_SCANLINES_Y,
+ DEFAULT_ALIGNMENT_SCANLINES_UV,
+ DEFAULT_ALIGNMENT_SIZE)) !=
+ OMX_ErrorNone)
+ {
+ goto component_init_exit;
+ }
+ }
+
+ // get SwVdec buffer requirements for input port; set m_port_ip
+ if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
+ OMX_ErrorNone)
+ {
+ goto component_init_exit;
+ }
+
+ // get SwVdec buffer requirements for output port; set m_port_op
+ if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
+ OMX_ErrorNone)
+ {
+ goto component_init_exit;
+ }
+
+ // create callback thread's mutex & condition variable
+ if ((retval = async_thread_create()) != OMX_ErrorNone)
+ {
+ goto component_init_exit;
+ }
+
+ // create semaphore for command processing
+ if (sem_init(&m_sem_cmd, 0, 0))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to create command processing semaphore");
+ retval = OMX_ErrorInsufficientResources;
+ goto component_init_exit;
+ }
+
+ // create mutex for meta buffer info array
+ if (pthread_mutex_init(&m_meta_buffer_array_mutex, NULL))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to create meta buffer info array mutex");
+ retval = OMX_ErrorInsufficientResources;
+ goto component_init_exit;
+ }
+
+ // move to 'loaded' state
+ OMX_SWVDEC_LOG_HIGH("OMX_StateInvalid -> OMX_StateLoaded");
+ m_state = OMX_StateLoaded;
+
+component_init_exit:
+ return retval;
+}
+
+/**
+ * @brief De-initialize component.
+ *
+ * @param[in] cmp_handle: Component handle.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::component_deinit(OMX_HANDLETYPE cmp_handle)
+{
+ OMX_SWVDEC_LOG_API("");
+
+ if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ }
+
+ pthread_mutex_destroy(&m_meta_buffer_array_mutex);
+
+ sem_destroy(&m_sem_cmd);
+
+ async_thread_destroy();
+
+ if (m_swvdec_created)
+ {
+ swvdec_deinit(m_swvdec_handle);
+ m_swvdec_handle = NULL;
+ }
+
+ OMX_SWVDEC_LOG_HIGH("all done, goodbye!");
+
+ return OMX_ErrorNone;
+}
+
+/**
+ * @brief Get component version.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] cmp_name: Component name string.
+ * @param[in,out] p_cmp_version: Pointer to component version variable.
+ * @param[in,out] p_spec_version: Pointer to OMX spec version variable.
+ * @param[in,out] p_cmp_UUID: Pointer to component UUID variable.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::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 retval = OMX_ErrorNone;
+
+ (void) p_cmp_UUID;
+
+ OMX_SWVDEC_LOG_API("");
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (strncmp(cmp_name, m_cmp_name, sizeof(m_cmp_name)))
+ {
+ OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name);
+ retval = OMX_ErrorInvalidComponentName;
+ }
+ else if (p_cmp_version == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_cmp_version = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_spec_version == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_spec_version = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ p_spec_version->nVersion = OMX_SPEC_VERSION;
+ }
+
+get_component_version_exit:
+ return retval;
+}
+
+/**
+ * @brief Send command to component.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] cmd: Command.
+ * @param[in] param: Command parameter.
+ * @param[in] p_cmd_data: Pointer to command data.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::send_command(OMX_HANDLETYPE cmp_handle,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param,
+ OMX_PTR p_cmd_data)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ (void) p_cmd_data; // prevent warning for unused function argument
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ goto send_command_exit;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ goto send_command_exit;
+ }
+
+ switch (cmd)
+ {
+
+ case OMX_CommandStateSet:
+ {
+ OMX_SWVDEC_LOG_API("%s, %s",
+ OMX_COMMANDTYPE_STRING(cmd),
+ OMX_STATETYPE_STRING((OMX_STATETYPE) param));
+ break;
+ }
+
+ case OMX_CommandFlush:
+ case OMX_CommandPortDisable:
+ case OMX_CommandPortEnable:
+ {
+ OMX_SWVDEC_LOG_API("%s, port index %d",
+ OMX_COMMANDTYPE_STRING(cmd),
+ param);
+
+ if ((param != OMX_CORE_PORT_INDEX_IP) &&
+ (param != OMX_CORE_PORT_INDEX_OP) &&
+ (param != OMX_ALL))
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", param);
+ retval = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_API("cmd %d, param %d", cmd, param);
+
+ OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", cmd);
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch (cmd)
+
+ if (retval == OMX_ErrorNone)
+ {
+ if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ }
+
+ if (retval != OMX_ErrorNone)
+ {
+ // command not processed; return error code via event handler callback
+ async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
+ }
+ else
+ {
+ // post command event
+ async_post_event(OMX_SWVDEC_EVENT_CMD, cmd, param);
+
+ // wait on command semaphore
+ sem_wait(&m_sem_cmd);
+ }
+
+send_command_exit:
+ return retval;
+}
+
+/**
+ * @brief Get a parameter from component.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] param_index: Parameter index.
+ * @param[in,out] p_param_data: Pointer to parameter data.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_parameter(OMX_HANDLETYPE cmp_handle,
+ OMX_INDEXTYPE param_index,
+ OMX_PTR p_param_data)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_param_data == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_param_data = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+
+ if (retval != OMX_ErrorNone)
+ {
+ goto get_parameter_exit;
+ }
+
+ switch (param_index)
+ {
+
+ case OMX_IndexParamAudioInit:
+ {
+ OMX_PORT_PARAM_TYPE *p_port_param =
+ (OMX_PORT_PARAM_TYPE *) p_param_data;
+
+ p_port_param->nPorts = 0;
+ p_port_param->nStartPortNumber = 0;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamAudioInit: "
+ "%d port(s), start port %d",
+ p_port_param->nPorts,
+ p_port_param->nStartPortNumber);
+ break;
+ }
+
+ case OMX_IndexParamImageInit:
+ {
+ OMX_PORT_PARAM_TYPE *p_port_param =
+ (OMX_PORT_PARAM_TYPE *) p_param_data;
+
+ p_port_param->nPorts = 0;
+ p_port_param->nStartPortNumber = 0;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamImageInit: "
+ "%d port(s), start port %d",
+ p_port_param->nPorts,
+ p_port_param->nStartPortNumber);
+ break;
+ }
+
+ case OMX_IndexParamVideoInit:
+ {
+ OMX_PORT_PARAM_TYPE *p_port_param =
+ (OMX_PORT_PARAM_TYPE *) p_param_data;
+
+ p_port_param->nPorts = 2;
+ p_port_param->nStartPortNumber = 0;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoInit: "
+ "%d port(s), start port %d",
+ p_port_param->nPorts,
+ p_port_param->nStartPortNumber);
+ break;
+ }
+
+ case OMX_IndexParamOtherInit:
+ {
+ OMX_PORT_PARAM_TYPE *p_port_param =
+ (OMX_PORT_PARAM_TYPE *) p_param_data;
+
+ p_port_param->nPorts = 0;
+ p_port_param->nStartPortNumber = 0;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamOtherInit: "
+ "%d port(s), start port %d",
+ p_port_param->nPorts,
+ p_port_param->nStartPortNumber);
+ break;
+ }
+
+ case OMX_IndexConfigPriorityMgmt:
+ {
+ OMX_PRIORITYMGMTTYPE *p_prio_mgmt =
+ (OMX_PRIORITYMGMTTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt");
+
+ memcpy(p_prio_mgmt, &m_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE));
+ break;
+ }
+
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *p_cmp_role =
+ (OMX_PARAM_COMPONENTROLETYPE *) p_param_data;
+
+ strlcpy((char *) p_cmp_role->cRole,
+ m_role_name,
+ OMX_MAX_STRINGNAME_SIZE);
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole: %s",
+ p_cmp_role->cRole);
+ break;
+ }
+
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *p_port_def =
+ (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d",
+ p_port_def->nPortIndex);
+
+ retval = get_port_definition(p_port_def);
+ break;
+ }
+
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier =
+ (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier, port index %d",
+ p_buffer_supplier->nPortIndex);
+
+ if ((p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_IP) ||
+ (p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_OP))
+ {
+ p_buffer_supplier->eBufferSupplier = OMX_BufferSupplyUnspecified;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_buffer_supplier->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, "
+ "port index %d, index %d",
+ p_port_format->nPortIndex,
+ p_port_format->nIndex);
+
+ retval = get_video_port_format(p_port_format);
+ break;
+ }
+
+ case OMX_IndexParamVideoMpeg2:
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2: unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoMpeg4:
+ {
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4: unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc: unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoH263:
+ {
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263: unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoProfileLevelQuerySupported, "
+ "port index %d, profile index %d",
+ p_profilelevel->nPortIndex,
+ p_profilelevel->nProfileIndex);
+
+ retval = get_supported_profilelevel(p_profilelevel);
+ break;
+ }
+
+ default:
+ {
+ /**
+ * Vendor-specific extension indices checked here since they are not
+ * part of the OMX_INDEXTYPE enumerated type.
+ */
+
+ switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
+ {
+
+ case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage:
+ {
+ GetAndroidNativeBufferUsageParams *p_buffer_usage =
+ (GetAndroidNativeBufferUsageParams *) p_param_data;
+
+ OMX_SWVDEC_LOG_API(
+ "OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage, "
+ "port index %d", p_buffer_usage->nPortIndex);
+
+ if (p_buffer_usage->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ p_buffer_usage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_buffer_usage->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+
+ case OMX_QcomIndexFlexibleYUVDescription:
+ {
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexFlexibleYUVDescription");
+
+ retval = describe_color_format((DescribeColorFormatParams *)
+ p_param_data);
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid");
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
+
+ } // default case
+
+ } // switch (param_index)
+
+get_parameter_exit:
+ return retval;
+}
+
+/**
+ * @brief Set a parameter to component.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] param_index: Parameter index.
+ * @param[in] p_param_data: Pointer to parameter data.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_parameter(OMX_HANDLETYPE cmp_handle,
+ OMX_INDEXTYPE param_index,
+ OMX_PTR p_param_data)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_param_data == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_param_data = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if ((m_state != OMX_StateLoaded) &&
+ (m_port_reconfig_inprogress == false))
+ {
+ OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
+ OMX_STATETYPE_STRING(m_state));
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+
+ if (retval != OMX_ErrorNone)
+ {
+ goto set_parameter_exit;
+ }
+
+ switch (param_index)
+ {
+
+ case OMX_IndexParamPriorityMgmt:
+ {
+ OMX_PRIORITYMGMTTYPE *p_prio_mgmt =
+ (OMX_PRIORITYMGMTTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt: "
+ "group ID %d, group priority %d",
+ p_prio_mgmt->nGroupID,
+ p_prio_mgmt->nGroupPriority);
+
+ if (m_state != OMX_StateLoaded)
+ {
+ OMX_SWVDEC_LOG_ERROR("'%d' state invalid; "
+ "should be in loaded state",
+ m_state);
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ memcpy(&m_prio_mgmt, p_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE));
+ }
+
+ break;
+ }
+
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *p_cmp_role =
+ (OMX_PARAM_COMPONENTROLETYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole '%s'",
+ p_cmp_role->cRole);
+
+ if (m_state != OMX_StateLoaded)
+ {
+ OMX_SWVDEC_LOG_ERROR("'%d' state invalid; "
+ "should be in loaded state",
+ m_state);
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ if (strncmp((char *) p_cmp_role->cRole,
+ m_role_name,
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ OMX_SWVDEC_LOG_ERROR("'%s': invalid component role name",
+ p_cmp_role->cRole);
+ retval = OMX_ErrorBadParameter;
+ }
+ }
+
+ break;
+ }
+
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *p_port_def =
+ (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d",
+ p_port_def->nPortIndex);
+
+ if ((m_state != OMX_StateLoaded) &&
+ (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
+ (m_port_ip.enabled == OMX_TRUE) &&
+ (m_port_ip.populated == OMX_TRUE)) ||
+ ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
+ (m_port_op.enabled == OMX_TRUE) &&
+ (m_port_op.populated == OMX_TRUE))))
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_IndexParamPortDefinition "
+ "disallowed in state %s "
+ "while port %d is enabled & populated",
+ OMX_STATETYPE_STRING(m_state),
+ p_port_def->nPortIndex);
+
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ retval = set_port_definition(p_port_def);
+ }
+
+ break;
+ }
+
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier =
+ (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier: "
+ "port index %d, buffer supplier %d",
+ p_buffer_supplier->nPortIndex,
+ (int) p_buffer_supplier->eBufferSupplier);
+
+ if ((p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_IP) &&
+ (p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_OP))
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_buffer_supplier->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, port index %d",
+ p_port_format->nPortIndex);
+
+ if ((m_state != OMX_StateLoaded) &&
+ (((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
+ (m_port_ip.enabled == OMX_TRUE) &&
+ (m_port_ip.populated == OMX_TRUE)) ||
+ ((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
+ (m_port_op.enabled == OMX_TRUE) &&
+ (m_port_op.populated == OMX_TRUE))))
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoPortFormat "
+ "disallowed in state %s "
+ "while port %d is enabled & populated",
+ OMX_STATETYPE_STRING(m_state),
+ p_port_format->nPortIndex);
+
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ retval = set_video_port_format(p_port_format);
+ }
+
+ break;
+ }
+
+ case OMX_IndexParamVideoMpeg2:
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2 unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoMpeg4:
+ {
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4 unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_IndexParamVideoH263:
+ {
+ OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263 unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ default:
+ {
+ /**
+ * Vendor-specific extension indices checked here since they are not
+ * part of the OMX_INDEXTYPE enumerated type.
+ */
+
+ switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
+ {
+
+ case OMX_QcomIndexPortDefn:
+ {
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def =
+ (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexPortDefn, port index %d",
+ p_port_def->nPortIndex);
+
+ if ((m_state != OMX_StateLoaded) &&
+ (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) &&
+ (m_port_ip.enabled == OMX_TRUE) &&
+ (m_port_ip.populated == OMX_TRUE)) ||
+ ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) &&
+ (m_port_op.enabled == OMX_TRUE) &&
+ (m_port_op.populated == OMX_TRUE))))
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexPortDefn "
+ "disallowed in state %s "
+ "while port %d is enabled & populated",
+ OMX_STATETYPE_STRING(m_state),
+ p_port_def->nPortIndex);
+
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ retval = set_port_definition_qcom(p_port_def);
+ }
+
+ break;
+ }
+
+ case OMX_QcomIndexParamVideoDivx:
+ {
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoDivx");
+ OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexParamVideoDivx unsupported");
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_QcomIndexParamVideoSyncFrameDecodingMode:
+ {
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoSyncFrameDecodingMode");
+ m_sync_frame_decoding_mode = true;
+ break;
+ }
+
+ case OMX_QcomIndexParamVideoDecoderPictureOrder:
+ {
+ QOMX_VIDEO_DECODER_PICTURE_ORDER *p_picture_order =
+ (QOMX_VIDEO_DECODER_PICTURE_ORDER *) p_param_data;
+
+ switch (p_picture_order->eOutputPictureOrder)
+ {
+
+ case QOMX_VIDEO_DISPLAY_ORDER:
+ {
+ OMX_SWVDEC_LOG_API(
+ "OMX_QcomIndexParamVideoDecoderPictureOrder, "
+ "QOMX_VIDEO_DISPLAY_ORDER");
+ break;
+ }
+
+ case QOMX_VIDEO_DECODE_ORDER:
+ {
+ OMX_SWVDEC_LOG_ERROR(
+ "OMX_QcomIndexParamVideoDecoderPictureOrder, "
+ "QOMX_VIDEO_DECODE_ORDER; unsupported");
+
+ retval = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR(
+ "OMX_QcomIndexParamVideoDecoderPictureOrder, %d; invalid");
+
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ }
+ break;
+ }
+
+ case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers:
+ {
+ OMX_SWVDEC_LOG_API(
+ "OMX_GoogleAndroidIndexEnableAndroidNativeBuffers, %s",
+ (((EnableAndroidNativeBuffersParams *) p_param_data)->enable ?
+ "enable" :
+ "disable"));
+
+ m_android_native_buffers =
+ (bool) (((EnableAndroidNativeBuffersParams *)
+ p_param_data)->enable);
+
+ break;
+ }
+
+ case OMX_GoogleAndroidIndexUseAndroidNativeBuffer:
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_GoogleAndroidIndexUseAndroidNativeBuffer "
+ "unsupported");
+
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ case OMX_QcomIndexParamEnableTimeStampReorder:
+ {
+ OMX_SWVDEC_LOG_API(
+ "OMX_QcomIndexParamEnableTimeStampReorder, %s",
+ (((QOMX_INDEXTIMESTAMPREORDER *) p_param_data)->bEnable ?
+ "enable" :
+ "disable"));
+
+ break;
+ }
+
+ case OMX_QcomIndexParamVideoMetaBufferMode:
+ {
+ StoreMetaDataInBuffersParams *p_meta_data =
+ (StoreMetaDataInBuffersParams *) p_param_data;
+
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoMetaBufferMode, "
+ "port index %d, %s",
+ p_meta_data->nPortIndex,
+ (p_meta_data->bStoreMetaData ?
+ "enabled" :
+ "disabled"));
+
+ if (p_meta_data->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ m_meta_buffer_mode = (bool) p_meta_data->bStoreMetaData;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_meta_data->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid");
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index)
+
+ break;
+ } // default case
+
+ } // switch (param_index)
+
+set_parameter_exit:
+ return retval;
+}
+
+/**
+ * @brief Get a configuration from component.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] config_index: Configuration index.
+ * @param[in] p_config_data: Pointer to configuration data.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_config(OMX_HANDLETYPE cmp_handle,
+ OMX_INDEXTYPE config_index,
+ OMX_PTR p_config_data)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ goto get_config_exit;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ goto get_config_exit;
+ }
+ else if (p_config_data == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_config_data = NULL");
+ retval = OMX_ErrorBadParameter;
+ goto get_config_exit;
+ }
+
+ switch (config_index)
+ {
+
+ case OMX_IndexConfigCommonOutputCrop:
+ {
+ OMX_CONFIG_RECTTYPE *p_recttype = (OMX_CONFIG_RECTTYPE *) p_config_data;
+
+ OMX_SWVDEC_LOG_API("OMX_IndexConfigCommonOutputCrop, port index %d",
+ p_recttype->nPortIndex);
+
+ if (p_recttype->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ p_recttype->nLeft = 0;
+ p_recttype->nTop = 0;
+ p_recttype->nWidth = m_frame_dimensions.width;
+ p_recttype->nHeight = m_frame_dimensions.height;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_recttype->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index)
+ {
+
+ case OMX_QcomIndexConfigInterlaced:
+ {
+ OMX_QCOM_CONFIG_INTERLACETYPE *p_config_interlacetype =
+ (OMX_QCOM_CONFIG_INTERLACETYPE *) p_config_data;
+
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexConfigInterlaced, "
+ "port index %d, index %d",
+ p_config_interlacetype->nPortIndex,
+ p_config_interlacetype->nIndex);
+
+ if (p_config_interlacetype->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ if (p_config_interlacetype->nIndex == 0)
+ {
+ p_config_interlacetype->eInterlaceType =
+ OMX_QCOM_InterlaceFrameProgressive;
+ }
+ else if (p_config_interlacetype->nIndex == 1)
+ {
+ p_config_interlacetype->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
+ }
+ else if (p_config_interlacetype->nIndex == 2)
+ {
+ p_config_interlacetype->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("index '%d' unsupported; "
+ "no more interlaced types",
+ p_config_interlacetype->nIndex);
+ retval = OMX_ErrorNoMore;
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_config_interlacetype->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+
+ case OMX_QcomIndexQueryNumberOfVideoDecInstance:
+ {
+ QOMX_VIDEO_QUERY_DECODER_INSTANCES *p_decoder_instances =
+ (QOMX_VIDEO_QUERY_DECODER_INSTANCES *) p_config_data;
+
+ OMX_SWVDEC_LOG_API("OMX_QcomIndexQueryNumberOfVideoDecInstance");
+
+ p_decoder_instances->nNumOfInstances = OMX_SWVDEC_NUM_INSTANCES;
+ break;
+ }
+
+ case OMX_QcomIndexConfigVideoFramePackingArrangement:
+ {
+ OMX_SWVDEC_LOG_API(
+ "OMX_QcomIndexConfigVideoFramePackingArrangement");
+
+ OMX_SWVDEC_LOG_ERROR(
+ "OMX_QcomIndexConfigVideoFramePackingArrangement unsupported");
+
+ retval = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("config index '%d' invalid", config_index);
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index)
+
+ break;
+ }
+
+ } // switch (config_index)
+
+get_config_exit:
+ return retval;
+}
+
+/**
+ * @brief Set a configuration to component.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_config(OMX_HANDLETYPE cmp_handle,
+ OMX_INDEXTYPE config_index,
+ OMX_PTR p_config_data)
+{
+ (void) cmp_handle;
+ (void) config_index;
+ (void) p_config_data;
+
+ OMX_SWVDEC_LOG_ERROR("not implemented");
+
+ return OMX_ErrorNotImplemented;
+}
+
+/**
+ * @brief Translate a vendor-specific extension string to a standard index type.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] param_name: Parameter name (extension string).
+ * @param[in,out] p_index_type: Pointer to extension string's index type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_extension_index(OMX_HANDLETYPE cmp_handle,
+ OMX_STRING param_name,
+ OMX_INDEXTYPE *p_index_type)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_index_type == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_index_type = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+
+ if (retval != OMX_ErrorNone)
+ goto get_extension_index_exit;
+
+ OMX_SWVDEC_LOG_API("'%s'", param_name);
+
+ if (!strncmp(param_name,
+ "OMX.QCOM.index.param.video.SyncFrameDecodingMode",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type =
+ (OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyncFrameDecodingMode;
+ }
+ else if (!strncmp(param_name,
+ "OMX.QCOM.index.param.IndexExtraData",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamIndexExtraDataType;
+ }
+ else if (!strncmp(param_name,
+ "OMX.google.android.index.enableAndroidNativeBuffers",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type =
+ (OMX_INDEXTYPE) OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
+ }
+ else if (!strncmp(param_name,
+ "OMX.google.android.index.useAndroidNativeBuffer2",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type =
+ (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
+ }
+ else if (!strncmp(param_name,
+ "OMX.google.android.index.useAndroidNativeBuffer",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type =
+ (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
+ }
+ else if (!strncmp(param_name,
+ "OMX.google.android.index.getAndroidNativeBufferUsage",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type =
+ (OMX_INDEXTYPE) OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
+ }
+ else if (!strncmp(param_name,
+ "OMX.google.android.index.storeMetaDataInBuffers",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamVideoMetaBufferMode;
+ }
+ else if (!strncmp(param_name,
+ "OMX.google.android.index.describeColorFormat",
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexFlexibleYUVDescription;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("'%s': not implemented", param_name);
+ retval = OMX_ErrorNotImplemented;
+ }
+
+get_extension_index_exit:
+ return retval;
+}
+
+/**
+ * @brief Get component state.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in,out] p_state: Pointer to state variable.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_state(OMX_HANDLETYPE cmp_handle,
+ OMX_STATETYPE *p_state)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_API("%s", OMX_STATETYPE_STRING(m_state));
+ *p_state = m_state;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Component tunnel request.
+ *
+ * @retval OMX_ErrorNotImplemented
+ */
+OMX_ERRORTYPE omx_swvdec::component_tunnel_request(
+ OMX_HANDLETYPE cmp_handle,
+ OMX_U32 port,
+ OMX_HANDLETYPE peer_component,
+ OMX_U32 peer_port,
+ OMX_TUNNELSETUPTYPE *p_tunnel_setup)
+{
+ (void) cmp_handle;
+ (void) port;
+ (void) peer_component;
+ (void) peer_port;
+ (void) p_tunnel_setup;
+
+ OMX_SWVDEC_LOG_API("");
+
+ OMX_SWVDEC_LOG_ERROR("not implemented");
+
+ return OMX_ErrorNotImplemented;
+}
+
+/**
+ * @brief Use buffer.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
+ * structure.
+ * @param[in] port: Port index.
+ * @param[in] p_app_data: Pointer to IL client app data.
+ * @param[in] bytes: Size of buffer to be allocated in bytes.
+ * @param[in] p_buffer: Pointer to buffer to be used.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::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 retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (pp_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer);
+
+ if (port == OMX_CORE_PORT_INDEX_OP)
+ {
+ retval = buffer_use_op(pp_buffer_hdr, p_app_data, bytes, p_buffer);
+
+ if (retval == OMX_ErrorNone)
+ {
+ SWVDEC_STATUS retval_swvdec;
+
+ if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) &&
+ (m_port_ip.populated == OMX_TRUE) &&
+ (m_port_op.populated == OMX_TRUE))
+ {
+ // start SwVdec
+ if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ goto use_buffer_exit;
+ }
+
+ m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandStateSet,
+ OMX_StateIdle);
+ }
+
+ if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) &&
+ (m_port_op.populated == OMX_TRUE))
+ {
+ if (m_port_reconfig_inprogress)
+ {
+ // start SwVdec
+ if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+
+ m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandPortEnable,
+ OMX_CORE_PORT_INDEX_OP);
+ }
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port);
+ retval = OMX_ErrorBadPortIndex;
+ }
+ }
+
+use_buffer_exit:
+ return retval;
+}
+
+/**
+ * @brief Allocate new buffer & associated header.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
+ * structure.
+ * @param[in] port: Port index.
+ * @param[in] p_app_data: Pointer to IL client app data.
+ * @param[in] bytes: Size of buffer to be allocated in bytes.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::allocate_buffer(OMX_HANDLETYPE cmp_handle,
+ OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
+ OMX_U32 port,
+ OMX_PTR p_app_data,
+ OMX_U32 bytes)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (pp_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_API("port index %d, %d bytes", port, bytes);
+
+ if (port == OMX_CORE_PORT_INDEX_IP)
+ {
+ retval = buffer_allocate_ip(pp_buffer_hdr,
+ p_app_data,
+ bytes);
+ }
+ else if (port == OMX_CORE_PORT_INDEX_OP)
+ {
+ if (m_meta_buffer_mode == true)
+ {
+ OMX_SWVDEC_LOG_ERROR("'meta buffer mode' enabled");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (m_android_native_buffers == true)
+ {
+ OMX_SWVDEC_LOG_ERROR("'android native buffers' enabled");
+ retval = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ retval = buffer_allocate_op(pp_buffer_hdr,
+ p_app_data,
+ bytes);
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index %d invalid", port);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ if (retval == OMX_ErrorNone)
+ {
+ SWVDEC_STATUS retval_swvdec;
+
+ if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) &&
+ (m_port_ip.populated == OMX_TRUE) &&
+ (m_port_op.populated == OMX_TRUE))
+ {
+ // start SwVdec
+ if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ goto allocate_buffer_exit;
+ }
+
+ m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandStateSet,
+ OMX_StateIdle);
+ }
+
+ if ((m_status_flags & (1 << PENDING_PORT_ENABLE_IP)) &&
+ (m_port_ip.populated == OMX_TRUE))
+ {
+ m_status_flags &= ~(1 << PENDING_PORT_ENABLE_IP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandPortEnable,
+ OMX_CORE_PORT_INDEX_IP);
+ }
+
+ if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) &&
+ (m_port_op.populated == OMX_TRUE))
+ {
+ if (m_port_reconfig_inprogress)
+ {
+ // start SwVdec
+ if ((retval_swvdec = swvdec_start(m_swvdec_handle)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+
+ m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandPortEnable,
+ OMX_CORE_PORT_INDEX_OP);
+ }
+ }
+ }
+
+allocate_buffer_exit:
+ return retval;
+}
+
+/**
+ * @brief Release buffer & associated header.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] port: Port index.
+ * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::free_buffer(OMX_HANDLETYPE cmp_handle,
+ OMX_U32 port,
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if ((port != OMX_CORE_PORT_INDEX_IP) &&
+ (port != OMX_CORE_PORT_INDEX_OP))
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port);
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else if (m_state != OMX_StateIdle)
+ {
+ if (m_state != OMX_StateExecuting)
+ {
+ OMX_SWVDEC_LOG_ERROR("disallowed in state %s",
+ OMX_STATETYPE_STRING(m_state));
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ if (((port == OMX_CORE_PORT_INDEX_IP) && m_port_ip.enabled) ||
+ ((port == OMX_CORE_PORT_INDEX_OP) && m_port_op.enabled))
+ {
+ OMX_SWVDEC_LOG_ERROR("port index %d not disabled", port);
+ retval = OMX_ErrorBadPortIndex;
+ }
+ }
+ }
+
+ if (retval == OMX_ErrorNone)
+ {
+ OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer_hdr);
+
+ if (port == OMX_CORE_PORT_INDEX_IP)
+ {
+ retval = buffer_deallocate_ip(p_buffer_hdr);
+ }
+ else
+ {
+ retval = buffer_deallocate_op(p_buffer_hdr);
+ }
+ }
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_status_flags & (1 << PENDING_STATE_IDLE_TO_LOADED)))
+ {
+ if ((m_port_ip.unpopulated == OMX_TRUE) &&
+ (m_port_op.unpopulated == OMX_TRUE))
+ {
+ SWVDEC_STATUS retval_swvdec;
+
+ // stop SwVdec
+ if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
+ SWVDEC_STATUS_SUCCESS)
+ {
+ m_status_flags &= ~(1 << PENDING_STATE_IDLE_TO_LOADED);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandStateSet,
+ OMX_StateLoaded);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+ }
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_status_flags & (1 << PENDING_PORT_DISABLE_IP)) &&
+ m_port_ip.unpopulated)
+ {
+ m_status_flags &= ~(1 << PENDING_PORT_DISABLE_IP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandPortDisable,
+ OMX_CORE_PORT_INDEX_IP);
+ }
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_status_flags & (1 << PENDING_PORT_DISABLE_OP)) &&
+ m_port_op.unpopulated)
+ {
+ if (m_port_reconfig_inprogress)
+ {
+ SWVDEC_STATUS retval_swvdec;
+
+ if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+
+ m_status_flags &= ~(1 << PENDING_PORT_DISABLE_OP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandPortDisable,
+ OMX_CORE_PORT_INDEX_OP);
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Send a buffer to component's input port to be emptied.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::empty_this_buffer(OMX_HANDLETYPE cmp_handle,
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_buffer_hdr->pBuffer == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_buffer_hdr->pInputPortPrivate == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pInputPortPrivate = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (m_port_ip.enabled == OMX_FALSE)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip port disabled");
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else if (p_buffer_hdr->nInputPortIndex != OMX_CORE_PORT_INDEX_IP)
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_buffer_hdr->nInputPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ if (retval != OMX_ErrorNone)
+ {
+ goto empty_this_buffer_exit;
+ }
+
+ for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
+ {
+ if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
+ {
+ OMX_SWVDEC_LOG_LOW("ip buffer %p has index %d",
+ p_buffer_hdr->pBuffer,
+ ii);
+ break;
+ }
+ }
+
+ if (ii == m_port_ip.def.nBufferCountActual)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip buffer %p not found",
+ p_buffer_hdr->pBuffer);
+ retval = OMX_ErrorBadParameter;
+ goto empty_this_buffer_exit;
+ }
+
+ if (m_sync_frame_decoding_mode &&
+ ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
+ {
+ p_buffer_hdr->nFlags |= OMX_BUFFERFLAG_EOS;
+ }
+
+ OMX_SWVDEC_LOG_API("%p: buffer %p, flags 0x%08x, filled length %d, "
+ "timestamp %lld",
+ p_buffer_hdr,
+ p_buffer_hdr->pBuffer,
+ p_buffer_hdr->nFlags,
+ p_buffer_hdr->nFilledLen,
+ p_buffer_hdr->nTimeStamp);
+
+ async_post_event(OMX_SWVDEC_EVENT_ETB,
+ (unsigned long) p_buffer_hdr,
+ (unsigned long) ii);
+
+empty_this_buffer_exit:
+ return retval;
+}
+
+/**
+ * @brief Send a buffer to component's output port to be filled.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] p_buffer_hdr: Pointer to buffer's buffer header.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::fill_this_buffer(OMX_HANDLETYPE cmp_handle,
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ SWVDEC_BUFFER *p_buffer_swvdec;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_buffer_hdr->pBuffer == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_buffer_hdr->pOutputPortPrivate == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pOutputPortPrivate = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (m_port_op.enabled == OMX_FALSE)
+ {
+ OMX_SWVDEC_LOG_ERROR("op port disabled");
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else if (p_buffer_hdr->nOutputPortIndex != OMX_CORE_PORT_INDEX_OP)
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_buffer_hdr->nOutputPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ if (retval != OMX_ErrorNone)
+ {
+ goto fill_this_buffer_exit;
+ }
+
+ OMX_SWVDEC_LOG_API("%p", p_buffer_hdr);
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
+ {
+ OMX_SWVDEC_LOG_LOW("op buffer %p has index %d",
+ p_buffer_hdr->pBuffer,
+ ii);
+ break;
+ }
+ }
+
+ if (ii == m_port_op.def.nBufferCountActual)
+ {
+ OMX_SWVDEC_LOG_ERROR("op buffer %p not found",
+ p_buffer_hdr->pBuffer);
+ retval = OMX_ErrorBadParameter;
+ goto fill_this_buffer_exit;
+ }
+
+ p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec;
+
+ if (m_meta_buffer_mode)
+ {
+ struct VideoDecoderOutputMetaData *p_meta_data;
+
+ private_handle_t *p_private_handle;
+
+ struct vdec_bufferpayload *p_buffer_payload;
+
+ p_meta_data =
+ (struct VideoDecoderOutputMetaData *) p_buffer_hdr->pBuffer;
+
+ p_private_handle = (private_handle_t *) (p_meta_data->pHandle);
+
+ p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
+
+ if (p_private_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR(
+ "p_buffer_hdr->pBuffer->pHandle = NULL");
+
+ retval = OMX_ErrorBadParameter;
+ goto fill_this_buffer_exit;
+ }
+
+ pthread_mutex_lock(&m_meta_buffer_array_mutex);
+
+ if (m_meta_buffer_array[ii].ref_count == 0)
+ {
+ unsigned char *bufferaddr;
+
+ bufferaddr = (unsigned char *) mmap(NULL,
+ m_port_op.def.nBufferSize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ p_private_handle->fd,
+ 0);
+
+ if (bufferaddr == MAP_FAILED)
+ {
+ OMX_SWVDEC_LOG_ERROR("mmap() failed for "
+ "fd %d of size %d",
+ p_private_handle->fd,
+ m_port_op.def.nBufferSize);
+
+ retval = OMX_ErrorInsufficientResources;
+ goto fill_this_buffer_exit;
+ }
+
+ p_buffer_payload->bufferaddr = bufferaddr;
+ p_buffer_payload->pmem_fd = p_private_handle->fd;
+ p_buffer_payload->buffer_len = m_port_op.def.nBufferSize;
+ p_buffer_payload->mmaped_size = m_port_op.def.nBufferSize;
+
+ p_buffer_swvdec->p_buffer = bufferaddr;
+ p_buffer_swvdec->size = m_port_op.def.nBufferSize;
+ p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
+ }
+
+ pthread_mutex_unlock(&m_meta_buffer_array_mutex);
+
+ meta_buffer_ref_add(ii,
+ p_buffer_payload->pmem_fd,
+ p_buffer_payload->offset);
+ }
+
+ OMX_SWVDEC_LOG_LOW("%p: buffer %p",
+ p_buffer_hdr,
+ p_buffer_swvdec->p_buffer);
+
+ async_post_event(OMX_SWVDEC_EVENT_FTB,
+ (unsigned long) p_buffer_hdr,
+ (unsigned long) ii);
+
+fill_this_buffer_exit:
+ return retval;
+}
+
+/**
+ * @brief Set component's callback structure.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in] p_callbacks: Pointer to callback structure.
+ * @param[in] p_app_data: Pointer to IL client app data.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_callbacks(OMX_HANDLETYPE cmp_handle,
+ OMX_CALLBACKTYPE *p_callbacks,
+ OMX_PTR p_app_data)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_LOG_API("");
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (p_callbacks->EventHandler == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_callbacks->EventHandler = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_callbacks->EmptyBufferDone == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_callbacks->EmptyBufferDone = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else if (p_callbacks->FillBufferDone == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_callbacks->FillBufferDone = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ m_callback = *p_callbacks;
+ m_app_data = p_app_data;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Use EGL image.
+ *
+ * @retval OMX_ErrorNotImplemented
+ */
+OMX_ERRORTYPE omx_swvdec::use_EGL_image(OMX_HANDLETYPE cmp_handle,
+ OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
+ OMX_U32 port,
+ OMX_PTR p_app_data,
+ void *egl_image)
+{
+ (void) cmp_handle;
+ (void) pp_buffer_hdr;
+ (void) port;
+ (void) p_app_data;
+ (void) egl_image;
+
+ OMX_SWVDEC_LOG_API("");
+
+ OMX_SWVDEC_LOG_ERROR("not implemented");
+
+ return OMX_ErrorNotImplemented;
+}
+
+/**
+ * @brief Enumerate component role.
+ *
+ * @param[in] cmp_handle: Component handle.
+ * @param[in,out] p_role: Pointer to component role string.
+ * @param[in] index: Role index being queried.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::component_role_enum(OMX_HANDLETYPE cmp_handle,
+ OMX_U8 *p_role,
+ OMX_U32 index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in invalid state");
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (cmp_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL");
+ retval = OMX_ErrorInvalidComponent;
+ }
+ else if (index > 0)
+ {
+ OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more roles", index);
+ retval = OMX_ErrorNoMore;
+ }
+ else
+ {
+ memcpy(p_role, m_role_name, OMX_MAX_STRINGNAME_SIZE);
+ OMX_SWVDEC_LOG_API("index '%d': '%s'", index, p_role);
+ }
+
+ return retval;
+}
+
+/**
+ * -------------------------
+ * SwVdec callback functions
+ * -------------------------
+ */
+
+/**
+ * @brief SwVdec empty buffer done callback.
+ *
+ * @param[in] swvdec_handle: SwVdec handle.
+ * @param[in] p_buffer_ip: Pointer to input buffer structure.
+ * @param[in] p_client_handle: Pointer to SwVdec's client handle.
+ *
+ * @retval SWVDEC_STATUS_SUCCESS
+ * @retval SWVDEC_STATUS_NULL_POINTER
+ * @retval SWVDEC_STATUS_INVALID_PARAMETERS
+ */
+SWVDEC_STATUS omx_swvdec::swvdec_empty_buffer_done_callback(
+ SWVDEC_HANDLE swvdec_handle,
+ SWVDEC_BUFFER *p_buffer_ip,
+ void *p_client_handle)
+{
+ SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
+
+ if (p_buffer_ip == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_ip = NULL");
+ retval = SWVDEC_STATUS_NULL_POINTER;
+ }
+ else if (p_client_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
+ retval = SWVDEC_STATUS_NULL_POINTER;
+ }
+ else
+ {
+ omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
+
+ if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
+ {
+ OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
+ retval = SWVDEC_STATUS_INVALID_PARAMETERS;
+ }
+ else
+ {
+ p_omx_swvdec->swvdec_empty_buffer_done(p_buffer_ip);
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief SwVdec fill buffer done callback.
+ *
+ * @param[in] swvdec_handle: SwVdec handle.
+ * @param[in] p_buffer_op: Pointer to output buffer structure.
+ * @param[in] p_client_handle: Pointer to SwVdec's client handle.
+ *
+ * @retval SWVDEC_STATUS_SUCCESS
+ * @retval SWVDEC_STATUS_NULL_POINTER
+ * @retval SWVDEC_STATUS_INVALID_PARAMETERS
+ */
+SWVDEC_STATUS omx_swvdec::swvdec_fill_buffer_done_callback(
+ SWVDEC_HANDLE swvdec_handle,
+ SWVDEC_BUFFER *p_buffer_op,
+ void *p_client_handle)
+{
+ SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
+
+ if (p_buffer_op == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_op = NULL");
+ retval = SWVDEC_STATUS_NULL_POINTER;
+ }
+ else if (p_client_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
+ retval = SWVDEC_STATUS_NULL_POINTER;
+ }
+ else
+ {
+ omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
+
+ if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
+ {
+ OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
+ retval = SWVDEC_STATUS_INVALID_PARAMETERS;
+ }
+ else
+ {
+ p_omx_swvdec->swvdec_fill_buffer_done(p_buffer_op);
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief SwVdec event handler callback.
+ *
+ * @param[in] swvdec_handle: SwVdec handle.
+ * @param[in] event: Event.
+ * @param[in] p_data: Pointer to event-specific data.
+ * @param[in] p_client_handle: Pointer to SwVdec's client handle.
+ *
+ * @retval SWVDEC_STATUS_SUCCESS
+ * @retval SWVDEC_STATUS_NULL_POINTER
+ * @retval SWVDEC_STATUS_INVALID_PARAMETERS
+ */
+SWVDEC_STATUS omx_swvdec::swvdec_event_handler_callback(
+ SWVDEC_HANDLE swvdec_handle,
+ SWVDEC_EVENT event,
+ void *p_data,
+ void *p_client_handle)
+{
+ SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS;
+
+ if ((event == SWVDEC_EVENT_RELEASE_REFERENCE) && (p_data == NULL))
+ {
+ OMX_SWVDEC_LOG_ERROR("p_data = NULL");
+ retval = SWVDEC_STATUS_NULL_POINTER;
+ }
+ else if (p_client_handle == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL");
+ retval = SWVDEC_STATUS_NULL_POINTER;
+ }
+ else
+ {
+ omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle;
+
+ if (swvdec_handle != p_omx_swvdec->m_swvdec_handle)
+ {
+ OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle");
+ retval = SWVDEC_STATUS_INVALID_PARAMETERS;
+ }
+ else
+ {
+ p_omx_swvdec->swvdec_event_handler(event, p_data);
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * -----------------
+ * PRIVATE FUNCTIONS
+ * -----------------
+ */
+
+/**
+ * @brief Set frame dimensions for OMX component & SwVdec core.
+ *
+ * @param[in] width: Frame width.
+ * @param[in] height: Frame height.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_frame_dimensions(unsigned int width,
+ unsigned int height)
+{
+ OMX_ERRORTYPE retval;
+
+ m_frame_dimensions.width = width;
+ m_frame_dimensions.height = height;
+
+ OMX_SWVDEC_LOG_HIGH("%d x %d",
+ m_frame_dimensions.width,
+ m_frame_dimensions.height);
+
+ retval = set_frame_dimensions_swvdec();
+
+ return retval;
+}
+
+/**
+ * @brief Set frame attributes for OMX component & SwVdec core, based on
+ * frame dimensions & alignment factors.
+ *
+ * @param[in] alignment_stride: Frame stride alignment factor.
+ * @param[in] alignment_scanlines_y: Frame luma scanlines alignment factor.
+ * @param[in] alignment_scanlines_uv: Frame chroma scanlines alignment factor.
+ * @param[in] alignment_size: Frame size alignment factor.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_frame_attributes(
+ unsigned int alignment_stride,
+ unsigned int alignment_scanlines_y,
+ unsigned int alignment_scanlines_uv,
+ unsigned int alignment_size)
+{
+ OMX_ERRORTYPE retval;
+
+ unsigned int width = m_frame_dimensions.width;
+ unsigned int height = m_frame_dimensions.height;
+
+ unsigned int scanlines_uv;
+
+ unsigned int plane_size_y;
+ unsigned int plane_size_uv;
+
+ m_frame_attributes.stride = ALIGN(width, alignment_stride);
+ m_frame_attributes.scanlines = ALIGN(height, alignment_scanlines_y);
+
+ scanlines_uv = ALIGN(height / 2, alignment_scanlines_uv);
+
+ plane_size_y = m_frame_attributes.stride * m_frame_attributes.scanlines;
+ plane_size_uv = m_frame_attributes.stride * scanlines_uv;
+
+ m_frame_attributes.size =
+ ALIGN(plane_size_y + plane_size_uv, alignment_size);
+
+ OMX_SWVDEC_LOG_HIGH("stride %d, scanlines %d, size %d",
+ m_frame_attributes.stride,
+ m_frame_attributes.scanlines,
+ m_frame_attributes.size);
+
+ retval = set_frame_attributes_swvdec();
+
+ return retval;
+}
+
+/**
+ * @brief Get video port format for input or output port.
+ *
+ * @param[in,out] p_port_format: Pointer to video port format type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_video_port_format(
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
+ {
+ if (p_port_format->nIndex == 0)
+ {
+ p_port_format->eColorFormat = OMX_COLOR_FormatUnused;
+ p_port_format->eCompressionFormat = m_omx_video_codingtype;
+
+ OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
+ "compression format 0x%08x",
+ p_port_format->eColorFormat,
+ p_port_format->eCompressionFormat);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; "
+ "no more compression formats",
+ p_port_format->nIndex);
+ retval = OMX_ErrorNoMore;
+ }
+ }
+ else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ if (p_port_format->nIndex == 0)
+ {
+ p_port_format->eColorFormat =
+ OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m;
+ p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+ OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
+ "compression format 0x%08x",
+ p_port_format->eColorFormat,
+ p_port_format->eCompressionFormat);
+ }
+ else if (p_port_format->nIndex == 1)
+ {
+ p_port_format->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+ OMX_SWVDEC_LOG_HIGH("color format 0x%08x, "
+ "compression format 0x%08x",
+ p_port_format->eColorFormat,
+ p_port_format->eCompressionFormat);
+ }
+ // Here, add additional supported color formats as necessary.
+ else
+ {
+ OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more color formats",
+ p_port_format->nIndex);
+ retval = OMX_ErrorNoMore;
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_port_format->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Set video port format for input or output port.
+ *
+ * @param[in] p_port_format: Pointer to video port format type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_video_port_format(
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP)
+ {
+ // do nothing
+ OMX_SWVDEC_LOG_HIGH("OMX_IndexParamVideoPortFormat, port index 0; "
+ "doing nothing");
+ }
+ else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ /**
+ * If color format specified by IL client is different from default,
+ * set alignment factors for new color format and call
+ * set_frame_attributes().
+ */
+ switch (p_port_format->eColorFormat)
+ {
+
+ case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m:
+ {
+ // do nothing; this is the default color format
+ OMX_SWVDEC_LOG_HIGH(
+ "'0x%08x': OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m",
+ p_port_format->eColorFormat);
+ break;
+ }
+
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ {
+ OMX_SWVDEC_LOG_HIGH("'0x%08x': OMX_COLOR_FormatYUV420SemiPlanar",
+ p_port_format->eColorFormat);
+
+ retval = set_frame_attributes(16, // stride alignment
+ 1, // Y scanlines alignment
+ 1, // UV scanlines alignment
+ 4096); // size alignment
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid or unsupported",
+ p_port_format->eColorFormat);
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_port_format->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+set_video_port_format_exit:
+ return retval;
+}
+
+/**
+ * @brief Get port definition for input or output port.
+ *
+ * @param[in,out] p_port_def: Pointer to port definition type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_port_definition(
+ OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ p_port_def->eDomain = OMX_PortDomainVideo;
+
+ if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
+ {
+ if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) !=
+ OMX_ErrorNone)
+ {
+ goto get_port_definition_exit;
+ }
+
+ p_port_def->eDir = OMX_DirInput;
+ p_port_def->nBufferCountActual = m_port_ip.def.nBufferCountActual;
+ p_port_def->nBufferCountMin = m_port_ip.def.nBufferCountMin;
+ p_port_def->nBufferSize = m_port_ip.def.nBufferSize;
+ p_port_def->bEnabled = m_port_ip.enabled;
+ p_port_def->bPopulated = m_port_ip.populated;
+
+ OMX_SWVDEC_LOG_HIGH("port index %d: "
+ "count actual %d, count min %d, size %d",
+ p_port_def->nPortIndex,
+ p_port_def->nBufferCountActual,
+ p_port_def->nBufferCountMin,
+ p_port_def->nBufferSize);
+
+ // frame dimensions & attributes don't apply to input port
+
+ p_port_def->format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ p_port_def->format.video.eCompressionFormat = m_omx_video_codingtype;
+ }
+ else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ unsigned int frame_width = m_frame_dimensions.width;
+ unsigned int frame_height = m_frame_dimensions.height;
+
+ if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone)
+ {
+ goto get_port_definition_exit;
+ }
+
+ p_port_def->format.video.nFrameWidth = m_frame_dimensions.width;
+ p_port_def->format.video.nFrameHeight = m_frame_dimensions.height;
+
+ // if frame dimensions have changed, update frame attributes
+ if ((frame_width != m_frame_dimensions.width) ||
+ (frame_height != m_frame_dimensions.height))
+ {
+ if ((retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
+ DEFAULT_ALIGNMENT_SCANLINES_Y,
+ DEFAULT_ALIGNMENT_SCANLINES_UV,
+ DEFAULT_ALIGNMENT_SIZE)) !=
+ OMX_ErrorNone)
+ {
+ goto get_port_definition_exit;
+ }
+ }
+
+ if ((retval = get_frame_attributes_swvdec()) != OMX_ErrorNone)
+ {
+ goto get_port_definition_exit;
+ }
+
+ p_port_def->format.video.nStride = m_frame_attributes.stride;
+ p_port_def->format.video.nSliceHeight = m_frame_attributes.scanlines;
+
+ OMX_SWVDEC_LOG_HIGH("port index %d: "
+ "%d x %d, stride %d, sliceheight %d",
+ p_port_def->nPortIndex,
+ p_port_def->format.video.nFrameWidth,
+ p_port_def->format.video.nFrameHeight,
+ p_port_def->format.video.nStride,
+ p_port_def->format.video.nSliceHeight);
+
+ /**
+ * Query to SwVdec core for buffer requirements is not allowed in
+ * executing state since it will overwrite the component's buffer
+ * requirements updated via the most recent set_parameter().
+ *
+ * Buffer requirements communicated to component via set_parameter() are
+ * not propagated to SwVdec core.
+ *
+ * The only execption is if port reconfiguration is in progress, in
+ * which case the query to SwVdec core is required since buffer
+ * requirements can change based on new dimensions.
+ */
+ if ((m_state != OMX_StateExecuting) || m_port_reconfig_inprogress)
+ {
+ if ((retval =
+ get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) !=
+ OMX_ErrorNone)
+ {
+ goto get_port_definition_exit;
+ }
+ }
+
+ p_port_def->eDir = OMX_DirOutput;
+ p_port_def->nBufferCountActual = m_port_op.def.nBufferCountActual;
+ p_port_def->nBufferCountMin = m_port_op.def.nBufferCountMin;
+ p_port_def->nBufferSize = m_port_op.def.nBufferSize;
+ p_port_def->bEnabled = m_port_op.enabled;
+ p_port_def->bPopulated = m_port_op.populated;
+
+ OMX_SWVDEC_LOG_HIGH("port index %d: "
+ "count actual %d, count min %d, size %d",
+ p_port_def->nPortIndex,
+ p_port_def->nBufferCountActual,
+ p_port_def->nBufferCountMin,
+ p_port_def->nBufferSize);
+
+ p_port_def->format.video.eColorFormat = m_omx_color_formattype;
+ p_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+get_port_definition_exit:
+ return retval;
+}
+
+/**
+ * @brief Set port definition for input or output port.
+ *
+ * @param[in] p_port_def: Pointer to port definition type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_port_definition(
+ OMX_PARAM_PORTDEFINITIONTYPE *p_port_def)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_LOG_HIGH("port index %d: "
+ "count actual %d, count min %d, size %d",
+ p_port_def->nPortIndex,
+ p_port_def->nBufferCountActual,
+ p_port_def->nBufferCountMin,
+ p_port_def->nBufferSize);
+
+ if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
+ {
+ m_port_ip.def.nBufferCountActual = p_port_def->nBufferCountActual;
+ m_port_ip.def.nBufferCountMin = p_port_def->nBufferCountMin;
+ m_port_ip.def.nBufferSize = p_port_def->nBufferSize;
+ }
+ else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ OMX_SWVDEC_LOG_HIGH("port index %d: %d x %d",
+ p_port_def->nPortIndex,
+ p_port_def->format.video.nFrameWidth,
+ p_port_def->format.video.nFrameHeight);
+
+ m_port_op.def.nBufferCountActual = p_port_def->nBufferCountActual;
+ m_port_op.def.nBufferCountMin = p_port_def->nBufferCountMin;
+ m_port_op.def.nBufferSize = p_port_def->nBufferSize;
+
+ retval = set_frame_dimensions(p_port_def->format.video.nFrameWidth,
+ p_port_def->format.video.nFrameHeight);
+ if (retval != OMX_ErrorNone)
+ goto set_port_definition_exit;
+
+ m_frame_attributes.stride = p_port_def->format.video.nStride;
+ m_frame_attributes.scanlines = p_port_def->format.video.nSliceHeight;
+ m_frame_attributes.size = p_port_def->nBufferSize;
+
+ retval = set_frame_attributes(DEFAULT_ALIGNMENT_STRIDE,
+ DEFAULT_ALIGNMENT_SCANLINES_Y,
+ DEFAULT_ALIGNMENT_SCANLINES_UV,
+ DEFAULT_ALIGNMENT_SIZE);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+set_port_definition_exit:
+ return retval;
+}
+
+/**
+ * @brief Get supported profile & level.
+ *
+ * The supported profiles & levels are not queried from SwVdec core, but
+ * hard-coded. This should ideally be replaced with a query to SwVdec core.
+ *
+ * @param[in,out] p_profilelevel: Pointer to video profile & level type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_supported_profilelevel(
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (p_profilelevel == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_profilelevel = NULL");
+ retval = OMX_ErrorBadParameter;
+ goto get_supported_profilelevel_exit;
+ }
+
+ if (p_profilelevel->nPortIndex != OMX_CORE_PORT_INDEX_IP)
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_profilelevel->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ goto get_supported_profilelevel_exit;
+ }
+
+ if (m_omx_video_codingtype == OMX_VIDEO_CodingH263)
+ {
+ if (p_profilelevel->nProfileIndex == 0)
+ {
+ p_profilelevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
+ p_profilelevel->eLevel = OMX_VIDEO_H263Level70;
+ OMX_SWVDEC_LOG_HIGH("H.263 baseline profile, level 70");
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
+ "no more profiles",
+ p_profilelevel->nProfileIndex);
+ retval = OMX_ErrorNoMore;
+ }
+ }
+ else if ((m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4) ||
+ (m_omx_video_codingtype ==
+ ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)))
+ {
+ if (p_profilelevel->nProfileIndex == 0)
+ {
+ p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5;
+ OMX_SWVDEC_LOG_HIGH("MPEG-4 simple profile, level 5");
+ }
+ else if (p_profilelevel->nProfileIndex == 1)
+ {
+ p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5;
+ OMX_SWVDEC_LOG_HIGH("MPEG-4 advanced simple profile, level 5");
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; "
+ "no more profiles",
+ p_profilelevel->nProfileIndex);
+ retval = OMX_ErrorNoMore;
+ }
+ }
+ else
+ {
+ assert(0);
+ retval = OMX_ErrorUndefined;
+ }
+
+get_supported_profilelevel_exit:
+ return retval;
+}
+
+/**
+ * @brief Describe color format.
+ *
+ * @param[in,out] p_params: Pointer to 'DescribeColorFormatParams' structure.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::describe_color_format(
+ DescribeColorFormatParams *p_params)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (p_params == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_params = NULL");
+ retval = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ MediaImage *p_img = &p_params->sMediaImage;
+
+ switch (p_params->eColorFormat)
+ {
+
+ case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
+ {
+ size_t stride, scanlines;
+
+ p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
+ p_img->mNumPlanes = 3;
+
+ p_img->mWidth = p_params->nFrameWidth;
+ p_img->mHeight = p_params->nFrameHeight;
+
+ stride = ALIGN(p_img->mWidth, DEFAULT_ALIGNMENT_STRIDE);
+ scanlines = ALIGN(p_img->mHeight, DEFAULT_ALIGNMENT_SCANLINES_Y);
+
+ p_img->mBitDepth = 8;
+
+ // plane 0 (Y)
+ p_img->mPlane[MediaImage::Y].mOffset = 0;
+ p_img->mPlane[MediaImage::Y].mColInc = 1;
+ p_img->mPlane[MediaImage::Y].mRowInc = stride;
+ p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
+ p_img->mPlane[MediaImage::Y].mVertSubsampling = 1;
+
+ // plane 1 (U)
+ p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines;
+ p_img->mPlane[MediaImage::Y].mColInc = 2;
+ p_img->mPlane[MediaImage::Y].mRowInc = stride;
+ p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
+ p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
+
+ // plane 2 (V)
+ p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines + 1;
+ p_img->mPlane[MediaImage::Y].mColInc = 2;
+ p_img->mPlane[MediaImage::Y].mRowInc = stride;
+ p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
+ p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
+
+ break;
+ }
+
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ {
+ size_t stride, scanlines;
+
+ p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
+ p_img->mNumPlanes = 3;
+
+ p_img->mWidth = p_params->nFrameWidth;
+ p_img->mHeight = p_params->nFrameHeight;
+
+ stride = ALIGN(p_img->mWidth, 16);
+ scanlines = ALIGN(p_img->mHeight, 1);
+
+ p_img->mBitDepth = 8;
+
+ // plane 0 (Y)
+ p_img->mPlane[MediaImage::Y].mOffset = 0;
+ p_img->mPlane[MediaImage::Y].mColInc = 1;
+ p_img->mPlane[MediaImage::Y].mRowInc = stride;
+ p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
+ p_img->mPlane[MediaImage::Y].mVertSubsampling = 1;
+
+ // plane 1 (U)
+ p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines;
+ p_img->mPlane[MediaImage::Y].mColInc = 2;
+ p_img->mPlane[MediaImage::Y].mRowInc = stride;
+ p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
+ p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
+
+ // plane 2 (V)
+ p_img->mPlane[MediaImage::Y].mOffset = stride * scanlines + 1;
+ p_img->mPlane[MediaImage::Y].mColInc = 2;
+ p_img->mPlane[MediaImage::Y].mRowInc = stride;
+ p_img->mPlane[MediaImage::Y].mHorizSubsampling = 2;
+ p_img->mPlane[MediaImage::Y].mVertSubsampling = 2;
+
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid/unsupported",
+ p_params->eColorFormat);
+
+ p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
+
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch (p_params->eColorFormat)
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Set QTI vendor-specific port definition for input or output port.
+ *
+ * @param[in] p_port_def: Pointer to QTI vendor-specific port definition type.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_port_definition_qcom(
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP)
+ {
+ switch (p_port_def->nFramePackingFormat)
+ {
+
+ case OMX_QCOM_FramePacking_Arbitrary:
+ {
+ OMX_SWVDEC_LOG_ERROR("OMX_QCOM_FramePacking_Arbitrary unsupported");
+ retval = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+
+ case OMX_QCOM_FramePacking_OnlyOneCompleteFrame:
+ {
+ OMX_SWVDEC_LOG_HIGH(
+ "OMX_QCOM_FramePacking_OnlyOneCompleteFrame");
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR(
+ "frame packing format '%d' unsupported");
+ retval = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+
+ }
+ }
+ else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP)
+ {
+ OMX_SWVDEC_LOG_HIGH("nMemRegion %d, nCacheAttr %d",
+ p_port_def->nMemRegion,
+ p_port_def->nCacheAttr);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid",
+ p_port_def->nPortIndex);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Set SwVdec frame dimensions based on OMX component frame dimensions.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_frame_dimensions_swvdec()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ SWVDEC_PROPERTY property;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
+
+ property.info.frame_dimensions.width = m_frame_dimensions.width;
+ property.info.frame_dimensions.height = m_frame_dimensions.height;
+
+ if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Set SwVdec frame attributes based on OMX component frame attributes.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::set_frame_attributes_swvdec()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ SWVDEC_FRAME_ATTRIBUTES *p_frame_attributes;
+
+ SWVDEC_PROPERTY property;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ p_frame_attributes = &property.info.frame_attributes;
+
+ property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
+
+ p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12;
+
+ p_frame_attributes->semiplanar.stride = m_frame_attributes.stride;
+ p_frame_attributes->semiplanar.offset_uv = (m_frame_attributes.stride *
+ m_frame_attributes.scanlines);
+
+ p_frame_attributes->size = m_frame_attributes.size;
+
+ if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Get SwVdec frame dimensions and set OMX component frame dimensions.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_frame_dimensions_swvdec()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ SWVDEC_PROPERTY property;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS;
+
+ if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ else
+ {
+ m_frame_dimensions.width = property.info.frame_dimensions.width;
+ m_frame_dimensions.height = property.info.frame_dimensions.height;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Get SwVdec frame attributes and set OMX component frame attributes.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_frame_attributes_swvdec()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ SWVDEC_PROPERTY property;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES;
+
+ if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ else
+ {
+ m_frame_attributes.stride =
+ property.info.frame_attributes.semiplanar.stride;
+
+ m_frame_attributes.scanlines =
+ (property.info.frame_attributes.semiplanar.offset_uv /
+ property.info.frame_attributes.semiplanar.stride);
+
+ m_frame_attributes.size = property.info.frame_attributes.size;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Get SwVdec buffer requirements; set input or output port definitions.
+ *
+ * @param[in] port_index: Port index.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::get_buffer_requirements_swvdec(
+ unsigned int port_index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ SWVDEC_PROPERTY property;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ SWVDEC_BUFFER_REQ *p_buffer_req;
+
+ if (port_index == OMX_CORE_PORT_INDEX_IP)
+ {
+ property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_IP;
+
+ p_buffer_req = &property.info.buffer_req_ip;
+
+ if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ goto get_buffer_requirements_swvdec_exit;
+ }
+
+ m_port_ip.def.nBufferSize = p_buffer_req->size;
+ m_port_ip.def.nBufferCountMin = p_buffer_req->mincount;
+ m_port_ip.def.nBufferCountActual = MAX(p_buffer_req->mincount,
+ OMX_SWVDEC_IP_BUFFER_COUNT);
+ m_port_ip.def.nBufferAlignment = p_buffer_req->alignment;
+
+ OMX_SWVDEC_LOG_HIGH("ip port: %d bytes x %d, %d-byte aligned",
+ m_port_ip.def.nBufferSize,
+ m_port_ip.def.nBufferCountActual,
+ m_port_ip.def.nBufferAlignment);
+ }
+ else if (port_index == OMX_CORE_PORT_INDEX_OP)
+ {
+ property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_OP;
+
+ p_buffer_req = &property.info.buffer_req_op;
+
+ if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ goto get_buffer_requirements_swvdec_exit;
+ }
+
+ if (m_sync_frame_decoding_mode)
+ {
+ // only 1 output buffer for sync frame decoding mode
+ p_buffer_req->mincount = 1;
+ }
+
+ m_port_op.def.nBufferSize = p_buffer_req->size;
+ m_port_op.def.nBufferCountMin = p_buffer_req->mincount;
+ m_port_op.def.nBufferCountActual = p_buffer_req->mincount;
+ m_port_op.def.nBufferAlignment = p_buffer_req->alignment;
+
+ OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned",
+ m_port_op.def.nBufferSize,
+ m_port_op.def.nBufferCountActual,
+ m_port_op.def.nBufferAlignment);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index);
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+get_buffer_requirements_swvdec_exit:
+ return retval;
+}
+
+/**
+ * @brief Allocate input buffer, and input buffer info array if ncessary.
+ *
+ * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
+ * structure.
+ * @param[in] p_app_data: Pointer to IL client app data.
+ * @param[in] size: Size of buffer to be allocated in bytes.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip(
+ OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
+ OMX_PTR p_app_data,
+ OMX_U32 size)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ if (size != m_port_ip.def.nBufferSize)
+ {
+ OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
+ "configured size (%d bytes)",
+ size,
+ m_port_ip.def.nBufferSize);
+ retval = OMX_ErrorBadParameter;
+ goto buffer_allocate_ip_exit;
+ }
+
+ if (m_buffer_array_ip == NULL)
+ {
+ // input buffer info array not allocated; allocate here
+
+ OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
+ m_port_ip.def.nBufferCountActual,
+ (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
+
+ if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone)
+ {
+ goto buffer_allocate_ip_exit;
+ }
+ }
+
+ for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_ip[ii].buffer_populated == false)
+ {
+ OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
+ break;
+ }
+ }
+
+ if (ii < m_port_ip.def.nBufferCountActual)
+ {
+ int pmem_fd = -1;
+
+ unsigned char *bufferaddr;
+
+ OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated",
+ ii,
+ size);
+
+ m_buffer_array_ip[ii].ion_info.ion_fd_device =
+ ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info.ion_alloc_data,
+ &m_buffer_array_ip[ii].ion_info.ion_fd_data,
+ size,
+ m_port_ip.def.nBufferAlignment);
+
+ if (m_buffer_array_ip[ii].ion_info.ion_fd_device < 0)
+ {
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_ip_exit;
+ }
+
+ pmem_fd = m_buffer_array_ip[ii].ion_info.ion_fd_data.fd;
+
+ bufferaddr = (unsigned char *) mmap(NULL,
+ size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ pmem_fd,
+ 0);
+
+ if (bufferaddr == MAP_FAILED)
+ {
+ OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
+ pmem_fd,
+ size);
+ close(pmem_fd);
+ ion_memory_free(&m_buffer_array_ip[ii].ion_info);
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_ip_exit;
+ }
+
+ *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
+
+ m_buffer_array_ip[ii].buffer_payload.bufferaddr = bufferaddr;
+ m_buffer_array_ip[ii].buffer_payload.pmem_fd = pmem_fd;
+ m_buffer_array_ip[ii].buffer_payload.buffer_len = size;
+ m_buffer_array_ip[ii].buffer_payload.mmaped_size = size;
+ m_buffer_array_ip[ii].buffer_payload.offset = 0;
+
+ m_buffer_array_ip[ii].buffer_swvdec.p_buffer = bufferaddr;
+ m_buffer_array_ip[ii].buffer_swvdec.size = size;
+ m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
+ (void *) ((unsigned long) ii);
+
+ m_buffer_array_ip[ii].buffer_populated = true;
+
+ OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, %d bytes",
+ ii,
+ bufferaddr,
+ size);
+
+ (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr;
+ (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
+ (*pp_buffer_hdr)->nAllocLen = size;
+ (*pp_buffer_hdr)->pAppPrivate = p_app_data;
+ (*pp_buffer_hdr)->nInputPortIndex = OMX_CORE_PORT_INDEX_IP;
+ (*pp_buffer_hdr)->pInputPortPrivate =
+ (void *) &(m_buffer_array_ip[ii].buffer_payload);
+
+ m_port_ip.populated = port_ip_populated();
+ m_port_ip.unpopulated = OMX_FALSE;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated",
+ m_port_ip.def.nBufferCountActual);
+ retval = OMX_ErrorInsufficientResources;
+ }
+
+buffer_allocate_ip_exit:
+ return retval;
+}
+
+/**
+ * @brief Allocate output buffer, and output buffer info array if necessary.
+ *
+ * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
+ * structure.
+ * @param[in] p_app_data: Pointer to IL client app data.
+ * @param[in] size: Size of buffer to be allocated in bytes.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_allocate_op(
+ OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
+ OMX_PTR p_app_data,
+ OMX_U32 size)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ if (size != m_port_op.def.nBufferSize)
+ {
+ OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
+ "configured size (%d bytes)",
+ size,
+ m_port_op.def.nBufferSize);
+ retval = OMX_ErrorBadParameter;
+ goto buffer_allocate_op_exit;
+ }
+
+ if (m_buffer_array_op == NULL)
+ {
+ // output buffer info array not allocated; allocate here
+
+ OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
+ m_port_op.def.nBufferCountActual,
+ (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
+
+ if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
+ {
+ goto buffer_allocate_op_exit;
+ }
+ }
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_op[ii].buffer_populated == false)
+ {
+ OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
+ break;
+ }
+ }
+
+ if (ii < m_port_op.def.nBufferCountActual)
+ {
+ int pmem_fd = -1;
+
+ unsigned char *bufferaddr;
+
+ OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated",
+ ii,
+ size);
+
+ m_buffer_array_op[ii].ion_info.ion_fd_device =
+ ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info.ion_alloc_data,
+ &m_buffer_array_op[ii].ion_info.ion_fd_data,
+ size,
+ m_port_op.def.nBufferAlignment);
+
+ if (m_buffer_array_op[ii].ion_info.ion_fd_device < 0)
+ {
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_op_exit;
+ }
+
+ pmem_fd = m_buffer_array_op[ii].ion_info.ion_fd_data.fd;
+
+ bufferaddr = (unsigned char *) mmap(NULL,
+ size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ pmem_fd,
+ 0);
+
+ if (bufferaddr == MAP_FAILED)
+ {
+ OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
+ pmem_fd,
+ size);
+ close(pmem_fd);
+ ion_memory_free(&m_buffer_array_op[ii].ion_info);
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_op_exit;
+ }
+
+ *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
+
+ m_buffer_array_op[ii].buffer_payload.bufferaddr = bufferaddr;
+ m_buffer_array_op[ii].buffer_payload.pmem_fd = pmem_fd;
+ m_buffer_array_op[ii].buffer_payload.buffer_len = size;
+ m_buffer_array_op[ii].buffer_payload.mmaped_size = size;
+ m_buffer_array_op[ii].buffer_payload.offset = 0;
+
+ m_buffer_array_op[ii].buffer_swvdec.p_buffer = bufferaddr;
+ m_buffer_array_op[ii].buffer_swvdec.size = size;
+ m_buffer_array_op[ii].buffer_swvdec.p_client_data =
+ (void *) ((unsigned long) ii);
+
+ m_buffer_array_op[ii].buffer_populated = true;
+
+ OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, %d bytes",
+ ii,
+ bufferaddr,
+ size);
+
+ (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr;
+ (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION;
+ (*pp_buffer_hdr)->nAllocLen = size;
+ (*pp_buffer_hdr)->pAppPrivate = p_app_data;
+ (*pp_buffer_hdr)->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP;
+ (*pp_buffer_hdr)->pOutputPortPrivate =
+ (void *) &(m_buffer_array_op[ii].buffer_payload);
+
+ m_port_op.populated = port_op_populated();
+ m_port_op.unpopulated = OMX_FALSE;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated",
+ m_port_op.def.nBufferCountActual);
+ retval = OMX_ErrorInsufficientResources;
+ }
+
+buffer_allocate_op_exit:
+ return retval;
+}
+
+/**
+ * @brief Allocate input buffer info array.
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr;
+
+ if (m_buffer_array_ip != NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_ip_hdr_exit;
+ }
+
+ // input buffer info array not allocated; allocate here
+
+ OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
+ m_port_ip.def.nBufferCountActual,
+ (m_port_ip.def.nBufferCountActual > 1) ? "s" : "");
+
+ m_buffer_array_ip =
+ (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
+ m_port_ip.def.nBufferCountActual);
+
+ if (m_buffer_array_ip == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
+ "%d element%s, %d bytes requested",
+ m_port_ip.def.nBufferCountActual,
+ (m_port_ip.def.nBufferCountActual > 1) ? "s" : "",
+ sizeof(OMX_SWVDEC_BUFFER_INFO) *
+ m_port_ip.def.nBufferCountActual);
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_ip_hdr_exit;
+ }
+
+ for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
+ {
+ p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header;
+
+ // reset file descriptors
+
+ m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
+ m_buffer_array_ip[ii].ion_info.ion_fd_device = -1;
+
+ m_buffer_array_ip[ii].buffer_swvdec.p_client_data =
+ (void *) ((unsigned long) ii);
+
+ p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ p_buffer_hdr->nOutputPortIndex = OMX_CORE_PORT_INDEX_IP;
+ p_buffer_hdr->pOutputPortPrivate =
+ (void *) &(m_buffer_array_ip[ii].buffer_payload);
+ }
+
+buffer_allocate_ip_hdr_exit:
+ return retval;
+}
+
+/**
+ * @brief Allocate output buffer info array.
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr;
+
+ if (m_buffer_array_op != NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("buffer info array already allocated");
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_op_hdr_exit;
+ }
+
+ // output buffer info array not allocated; allocate here
+
+ OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
+ m_port_op.def.nBufferCountActual,
+ (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
+
+ m_buffer_array_op =
+ (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO),
+ m_port_op.def.nBufferCountActual);
+
+ if (m_buffer_array_op == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; "
+ "%d element%s, %d bytes requested",
+ m_port_op.def.nBufferCountActual,
+ (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
+ sizeof(OMX_SWVDEC_BUFFER_INFO) *
+ m_port_op.def.nBufferCountActual);
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_allocate_op_hdr_exit;
+ }
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ p_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
+
+ // reset file descriptors
+
+ m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
+ m_buffer_array_op[ii].ion_info.ion_fd_device = -1;
+
+ m_buffer_array_op[ii].buffer_swvdec.p_client_data =
+ (void *) ((unsigned long) ii);
+
+ p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ p_buffer_hdr->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP;
+ p_buffer_hdr->pOutputPortPrivate =
+ (void *) &(m_buffer_array_op[ii].buffer_payload);
+ }
+
+buffer_allocate_op_hdr_exit:
+ return retval;
+}
+
+/**
+ * @brief Use buffer allocated by IL client; allocate output buffer info array
+ * if necessary.
+ *
+ * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type
+ * structure.
+ * @param[in] p_app_data: Pointer to IL client app data.
+ * @param[in] size: Size of buffer to be allocated in bytes.
+ * @param[in] p_buffer: Pointer to buffer to be used.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_use_op(
+ OMX_BUFFERHEADERTYPE **pp_buffer_hdr,
+ OMX_PTR p_app_data,
+ OMX_U32 size,
+ OMX_U8 *p_buffer)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ (void) size;
+
+ if (m_buffer_array_op == NULL)
+ {
+ // output buffer info array not allocated; allocate here
+
+ OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s",
+ m_port_op.def.nBufferCountActual,
+ (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
+
+ if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone)
+ {
+ goto buffer_use_op_exit;
+ }
+ }
+
+ if (m_meta_buffer_mode && (m_meta_buffer_array == NULL))
+ {
+ // meta buffer info array not allocated; allocate here
+
+ OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s",
+ m_port_op.def.nBufferCountActual,
+ (m_port_op.def.nBufferCountActual > 1) ? "s" : "");
+
+ if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone)
+ {
+ goto buffer_use_op_exit;
+ }
+ }
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_op[ii].buffer_populated == false)
+ {
+ OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii);
+ break;
+ }
+ }
+
+ if (ii < m_port_op.def.nBufferCountActual)
+ {
+ struct vdec_bufferpayload *p_buffer_payload;
+
+ SWVDEC_BUFFER *p_buffer_swvdec;
+
+ *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header;
+ p_buffer_payload = &m_buffer_array_op[ii].buffer_payload;
+ p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec;
+
+ if (m_meta_buffer_mode)
+ {
+ p_buffer_swvdec->size = m_port_op.def.nBufferSize;
+ p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
+
+ m_buffer_array_op[ii].buffer_populated = true;
+
+ (*pp_buffer_hdr)->pBuffer = p_buffer;
+ (*pp_buffer_hdr)->pAppPrivate = p_app_data;
+ (*pp_buffer_hdr)->nAllocLen =
+ sizeof(struct VideoDecoderOutputMetaData);
+
+ OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)",
+ ii,
+ *pp_buffer_hdr);
+
+ m_port_op.populated = port_op_populated();
+ m_port_op.unpopulated = OMX_FALSE;
+ }
+ else if (m_android_native_buffers)
+ {
+ private_handle_t *p_handle;
+
+ OMX_U8 *p_buffer_mapped;
+
+ p_handle = (private_handle_t *) p_buffer;
+
+ if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize)
+ {
+ OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to "
+ "configured size (%d bytes)",
+ p_handle->size,
+ m_port_op.def.nBufferSize);
+
+ retval = OMX_ErrorBadParameter;
+ goto buffer_use_op_exit;
+ }
+
+ m_port_op.def.nBufferSize = p_handle->size;
+
+ p_buffer_mapped = (OMX_U8 *) mmap(NULL,
+ p_handle->size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ p_handle->fd,
+ 0);
+
+ if (p_buffer_mapped == MAP_FAILED)
+ {
+ OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d",
+ p_handle->fd,
+ p_handle->size);
+
+ retval = OMX_ErrorInsufficientResources;
+ goto buffer_use_op_exit;
+ }
+
+ p_buffer_payload->bufferaddr = p_buffer_mapped;
+ p_buffer_payload->pmem_fd = p_handle->fd;
+ p_buffer_payload->buffer_len = p_handle->size;
+ p_buffer_payload->mmaped_size = p_handle->size;
+ p_buffer_payload->offset = 0;
+
+ p_buffer_swvdec->p_buffer = p_buffer_mapped;
+ p_buffer_swvdec->size = m_port_op.def.nBufferSize;
+ p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii);
+
+ m_buffer_array_op[ii].buffer_populated = true;
+
+ (*pp_buffer_hdr)->pBuffer = (m_android_native_buffers ?
+ ((OMX_U8 *) p_handle) :
+ p_buffer_mapped);
+ (*pp_buffer_hdr)->pAppPrivate = p_app_data;
+ (*pp_buffer_hdr)->nAllocLen = m_port_op.def.nBufferSize;
+
+ m_buffer_array_op[ii].ion_info.ion_fd_data.fd = p_handle->fd;
+
+ OMX_SWVDEC_LOG_HIGH("op buffer %d: %p",
+ ii,
+ *pp_buffer_hdr);
+
+ m_port_op.populated = port_op_populated();
+ m_port_op.unpopulated = OMX_FALSE;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor "
+ "'android native buffers' enabled");
+ retval = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("all %d op buffers populated",
+ m_port_op.def.nBufferCountActual);
+ retval = OMX_ErrorInsufficientResources;
+ }
+
+buffer_use_op_exit:
+ return retval;
+}
+
+/**
+ * @brief De-allocate input buffer.
+ *
+ * @param[in] p_buffer_hdr: Pointer to buffer header structure.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip(
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ if (p_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ goto buffer_deallocate_ip_exit;
+ }
+ else if (m_buffer_array_ip == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated");
+ retval = OMX_ErrorBadParameter;
+ goto buffer_deallocate_ip_exit;
+ }
+
+ for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
+ {
+ if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header))
+ {
+ OMX_SWVDEC_LOG_LOW("%p has index %d",
+ p_buffer_hdr->pBuffer,
+ ii);
+ break;
+ }
+ }
+
+ if (ii < m_port_ip.def.nBufferCountActual)
+ {
+ if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0)
+ {
+ m_buffer_array_ip[ii].buffer_populated = false;
+
+ m_port_ip.populated = OMX_FALSE;
+
+ munmap(m_buffer_array_ip[ii].buffer_payload.bufferaddr,
+ m_buffer_array_ip[ii].buffer_payload.mmaped_size);
+
+ close(m_buffer_array_ip[ii].buffer_payload.pmem_fd);
+ m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1;
+
+ ion_memory_free(&m_buffer_array_ip[ii].ion_info);
+
+ // check if all buffers are unpopulated
+ for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_ip[ii].buffer_populated)
+ break;
+ }
+
+ // if no buffers are populated, de-allocate input buffer info array
+ if (ii == m_port_ip.def.nBufferCountActual)
+ {
+ buffer_deallocate_ip_info_array();
+ m_port_ip.unpopulated = OMX_TRUE;
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d",
+ p_buffer_hdr->pBuffer,
+ m_buffer_array_ip[ii].buffer_payload.pmem_fd);
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
+ retval = OMX_ErrorBadParameter;
+ }
+
+buffer_deallocate_ip_exit:
+ return retval;
+}
+
+/**
+ * @brief De-allocate output buffer.
+ *
+ * @param[in] p_buffer_hdr: Pointer to buffer header structure.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op(
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ unsigned int ii;
+
+ if (p_buffer_hdr == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL");
+ retval = OMX_ErrorBadParameter;
+ goto buffer_deallocate_op_exit;
+ }
+ else if (m_buffer_array_op == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("op buffer array not allocated");
+ retval = OMX_ErrorBadParameter;
+ goto buffer_deallocate_op_exit;
+ }
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header))
+ {
+ OMX_SWVDEC_LOG_LOW("%p has index %d",
+ p_buffer_hdr->pBuffer,
+ ii);
+ break;
+ }
+ }
+
+ if (ii < m_port_op.def.nBufferCountActual)
+ {
+ assert(m_buffer_array_op[ii].buffer_payload.pmem_fd > 0);
+
+ if (m_meta_buffer_mode)
+ {
+ // do nothing; munmap() & close() done in FBD or RR
+ }
+ else if (m_android_native_buffers)
+ {
+ munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
+ m_buffer_array_op[ii].buffer_payload.mmaped_size);
+ m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
+ }
+ else if (m_sync_frame_decoding_mode)
+ {
+ munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
+ m_buffer_array_op[ii].buffer_payload.mmaped_size);
+ close(m_buffer_array_op[ii].buffer_payload.pmem_fd);
+ m_buffer_array_op[ii].buffer_payload.pmem_fd = -1;
+ ion_memory_free(&m_buffer_array_op[ii].ion_info);
+ }
+ else
+ {
+ assert(0);
+ }
+
+ m_buffer_array_op[ii].buffer_populated = false;
+
+ m_port_op.populated = OMX_FALSE;
+
+ // check if all buffers are unpopulated
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_op[ii].buffer_populated)
+ break;
+ }
+
+ // if no buffers are populated, de-allocate output buffer info array
+ if (ii == m_port_op.def.nBufferCountActual)
+ {
+ buffer_deallocate_op_info_array();
+ m_port_op.unpopulated = OMX_TRUE;
+
+ if (m_meta_buffer_mode)
+ {
+ meta_buffer_array_deallocate();
+ }
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer);
+ retval = OMX_ErrorBadParameter;
+ }
+
+buffer_deallocate_op_exit:
+ return retval;
+}
+
+/**
+ * @brief De-allocate input buffer info array.
+ */
+void omx_swvdec::buffer_deallocate_ip_info_array()
+{
+ assert(m_buffer_array_ip != NULL);
+
+ free(m_buffer_array_ip);
+ m_buffer_array_ip = NULL;
+}
+
+/**
+ * @brief De-allocate output buffer info array.
+ */
+void omx_swvdec::buffer_deallocate_op_info_array()
+{
+ assert(m_buffer_array_op != NULL);
+
+ free(m_buffer_array_op);
+ m_buffer_array_op = NULL;
+}
+
+/**
+ * @brief Allocate meta buffer info array.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *)
+ calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO),
+ m_port_op.def.nBufferCountActual));
+
+ if (m_meta_buffer_array == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; "
+ "%d element%s, %d bytes requested",
+ m_port_op.def.nBufferCountActual,
+ (m_port_op.def.nBufferCountActual > 1) ? "s" : "",
+ sizeof(OMX_SWVDEC_META_BUFFER_INFO) *
+ m_port_op.def.nBufferCountActual);
+
+ retval = OMX_ErrorInsufficientResources;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief De-allocate meta buffer info array.
+ */
+void omx_swvdec::meta_buffer_array_deallocate()
+{
+ assert(m_meta_buffer_array != NULL);
+
+ free(m_meta_buffer_array);
+ m_meta_buffer_array = NULL;
+}
+
+/**
+ * @brief Add meta buffer reference.
+ *
+ * @param[in] index:
+ * @param[in] fd:
+ * @param[in] offset:
+ */
+void omx_swvdec::meta_buffer_ref_add(unsigned int index,
+ unsigned int fd,
+ unsigned int offset)
+{
+ pthread_mutex_lock(&m_meta_buffer_array_mutex);
+
+ if ((m_meta_buffer_array[index].dup_fd != 0) &&
+ (m_meta_buffer_array[index].fd != fd) &&
+ (m_meta_buffer_array[index].offset != offset))
+ {
+ OMX_SWVDEC_LOG_LOW("index %d taken by fd %d, offset %d",
+ index,
+ m_meta_buffer_array[index].fd,
+ m_meta_buffer_array[index].offset);
+ }
+ else
+ {
+ if (m_meta_buffer_array[index].dup_fd == 0)
+ {
+ m_meta_buffer_array[index].fd = fd;
+ m_meta_buffer_array[index].dup_fd = dup(fd);
+ m_meta_buffer_array[index].offset = offset;
+ }
+
+ m_meta_buffer_array[index].ref_count++;
+ }
+
+ pthread_mutex_unlock(&m_meta_buffer_array_mutex);
+}
+
+/**
+ * @brief Remove meta buffer reference.
+ *
+ * @param[in] fd:
+ * @param[in] offset:
+ */
+void omx_swvdec::meta_buffer_ref_remove(unsigned int fd,
+ unsigned int offset)
+{
+ unsigned int ii;
+
+ pthread_mutex_lock(&m_meta_buffer_array_mutex);
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if ((m_meta_buffer_array[ii].fd == fd) &&
+ (m_meta_buffer_array[ii].offset == offset))
+ {
+ m_meta_buffer_array[ii].ref_count--;
+
+ if (m_meta_buffer_array[ii].ref_count == 0)
+ {
+ close(m_meta_buffer_array[ii].dup_fd);
+
+ m_meta_buffer_array[ii].fd = 0;
+ m_meta_buffer_array[ii].dup_fd = 0;
+ m_meta_buffer_array[ii].offset = 0;
+
+ munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr,
+ m_buffer_array_op[ii].buffer_payload.mmaped_size);
+
+ m_buffer_array_op[ii].buffer_payload.bufferaddr = NULL;
+ m_buffer_array_op[ii].buffer_payload.offset = 0;
+ m_buffer_array_op[ii].buffer_payload.mmaped_size = 0;
+
+ m_buffer_array_op[ii].buffer_swvdec.p_buffer = NULL;
+ m_buffer_array_op[ii].buffer_swvdec.size = 0;
+ }
+
+ break;
+ }
+ }
+
+ assert(ii < m_port_op.def.nBufferCountActual);
+
+ pthread_mutex_unlock(&m_meta_buffer_array_mutex);
+}
+
+/**
+ * @brief Check if ip port is populated, i.e., if all ip buffers are populated.
+ *
+ * @retval true
+ * @retval false
+ */
+OMX_BOOL omx_swvdec::port_ip_populated()
+{
+ OMX_BOOL retval = OMX_FALSE;
+
+ if (m_buffer_array_ip != NULL)
+ {
+ unsigned int ii;
+
+ for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_ip[ii].buffer_populated == false)
+ {
+ break;
+ }
+ }
+
+ if (ii == m_port_ip.def.nBufferCountActual)
+ {
+ retval = OMX_TRUE;
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Check if op port is populated, i.e., if all op buffers are populated.
+ *
+ * @retval true
+ * @retval false
+ */
+OMX_BOOL omx_swvdec::port_op_populated()
+{
+ OMX_BOOL retval = OMX_FALSE;
+
+ if (m_buffer_array_op != NULL)
+ {
+ unsigned int ii;
+
+ for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++)
+ {
+ if (m_buffer_array_op[ii].buffer_populated == false)
+ {
+ break;
+ }
+ }
+
+ if (ii == m_port_op.def.nBufferCountActual)
+ {
+ retval = OMX_TRUE;
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Flush input, output, or both input & output ports.
+ *
+ * @param[in] port_index: Index of port to flush.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (((port_index == OMX_CORE_PORT_INDEX_IP) &&
+ m_port_ip.flush_inprogress) ||
+ ((port_index == OMX_CORE_PORT_INDEX_OP) &&
+ m_port_op.flush_inprogress) ||
+ ((port_index == OMX_ALL) &&
+ m_port_ip.flush_inprogress &&
+ m_port_op.flush_inprogress))
+ {
+ OMX_SWVDEC_LOG_HIGH("flush port %d already in progress", port_index);
+ }
+ else
+ {
+ SWVDEC_FLUSH_TYPE swvdec_flush_type;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ if (port_index == OMX_CORE_PORT_INDEX_IP)
+ {
+ m_port_ip.flush_inprogress = OMX_TRUE;
+
+ // no separate SwVdec flush type for input
+ }
+ else if (port_index == OMX_CORE_PORT_INDEX_OP)
+ {
+ m_port_op.flush_inprogress = OMX_TRUE;
+
+ swvdec_flush_type = (m_port_ip.flush_inprogress ?
+ SWVDEC_FLUSH_TYPE_ALL :
+ SWVDEC_FLUSH_TYPE_OP);
+
+ if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
+ swvdec_flush_type)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+ else if (port_index == OMX_ALL)
+ {
+ m_port_ip.flush_inprogress = OMX_TRUE;
+ m_port_op.flush_inprogress = OMX_TRUE;
+
+ swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL;
+
+ if ((retval_swvdec = swvdec_flush(m_swvdec_handle,
+ swvdec_flush_type)) !=
+ SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+ else
+ {
+ assert(0);
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Allocate & map ION memory.
+ */
+int omx_swvdec::ion_memory_alloc_map(struct ion_allocation_data *p_alloc_data,
+ struct ion_fd_data *p_fd_data,
+ OMX_U32 size,
+ OMX_U32 alignment)
+{
+ int fd = -EINVAL;
+ int rc = -EINVAL;
+
+ if ((p_alloc_data == NULL) || (p_fd_data == NULL) || (size == 0))
+ {
+ OMX_SWVDEC_LOG_ERROR("invalid arguments");
+ goto ion_memory_alloc_map_exit;
+ }
+
+ if ((fd = open("/dev/ion", O_RDONLY)) < 0)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", fd);
+ goto ion_memory_alloc_map_exit;
+ }
+
+ p_alloc_data->len = size;
+ p_alloc_data->align = (alignment < 4096) ? 4096 : alignment;
+ p_alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
+ p_alloc_data->flags = 0;
+
+ OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %d, align %d",
+ p_alloc_data->heap_id_mask,
+ p_alloc_data->len,
+ p_alloc_data->align);
+
+ rc = ioctl(fd, ION_IOC_ALLOC, p_alloc_data);
+
+ if (rc || (p_alloc_data->handle == 0))
+ {
+ OMX_SWVDEC_LOG_ERROR("ioctl() for allocation failed");
+ close(fd);
+ fd = -ENOMEM;
+ goto ion_memory_alloc_map_exit;
+ }
+
+ p_fd_data->handle = p_alloc_data->handle;
+
+ if (ioctl(fd, ION_IOC_MAP, p_fd_data))
+ {
+ struct vdec_ion ion_buf_info;
+
+ OMX_SWVDEC_LOG_ERROR("ioctl() for mapping failed");
+
+ ion_buf_info.ion_alloc_data = *p_alloc_data;
+ ion_buf_info.ion_fd_device = fd;
+ ion_buf_info.ion_fd_data = *p_fd_data;
+
+ ion_memory_free(&ion_buf_info);
+
+ p_fd_data->fd = -1;
+ close(fd);
+ fd = -ENOMEM;
+ goto ion_memory_alloc_map_exit;
+ }
+
+ion_memory_alloc_map_exit:
+ return fd;
+}
+
+/**
+ * @brief Free ION memory.
+ */
+void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info)
+{
+ if (p_ion_buf_info == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL");
+ goto ion_memory_free_exit;
+ }
+
+ if (ioctl(p_ion_buf_info->ion_fd_device,
+ ION_IOC_FREE,
+ &p_ion_buf_info->ion_alloc_data.handle))
+ {
+ OMX_SWVDEC_LOG_ERROR("ioctl() for freeing failed");
+ }
+
+ close(p_ion_buf_info->ion_fd_device);
+
+ p_ion_buf_info->ion_fd_device = -1;
+ p_ion_buf_info->ion_alloc_data.handle = 0;
+ p_ion_buf_info->ion_fd_data.fd = -1;
+
+ion_memory_free_exit:
+ return;
+}
+
+/**
+ * ----------------------------
+ * component callback functions
+ * ----------------------------
+ */
+
+/**
+ * @brief Empty buffer done callback.
+ *
+ * @param[in] p_buffer_ip: Pointer to input buffer structure.
+ */
+void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip)
+{
+ unsigned long index = (unsigned long) p_buffer_ip->p_client_data;
+
+ async_post_event(OMX_SWVDEC_EVENT_EBD,
+ (unsigned long) &m_buffer_array_ip[index].buffer_header,
+ index);
+}
+
+/**
+ * @brief Fill buffer done callback.
+ *
+ * @param[in] p_buffer_op: Pointer to output buffer structure.
+ */
+void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op)
+{
+ unsigned long index = (unsigned long) p_buffer_op->p_client_data;
+
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr;
+
+ if (index < ((unsigned long) m_port_op.def.nBufferCountActual))
+ {
+ p_buffer_hdr = &m_buffer_array_op[index].buffer_header;
+
+ p_buffer_hdr->nFlags = p_buffer_op->flags;
+ p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp;
+ p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode &&
+ p_buffer_op->filled_length) ?
+ p_buffer_hdr->nAllocLen :
+ p_buffer_op->filled_length);
+ }
+
+ async_post_event(OMX_SWVDEC_EVENT_FBD,
+ (unsigned long) &m_buffer_array_op[index].buffer_header,
+ index);
+}
+
+/**
+ * @brief Event handler callback.
+ *
+ * @param[in] event: Event.
+ * @param[in] p_data: Pointer to event-specific data.
+ */
+void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data)
+{
+ switch (event)
+ {
+
+ case SWVDEC_EVENT_FLUSH_ALL_DONE:
+ {
+ async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0);
+ async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
+ break;
+ }
+
+ case SWVDEC_EVENT_FLUSH_OP_DONE:
+ {
+ async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0);
+ break;
+ }
+
+ case SWVDEC_EVENT_RELEASE_REFERENCE:
+ {
+ SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data;
+
+ unsigned long index = (unsigned long) p_buffer_op->p_client_data;
+
+ OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer);
+
+ assert(index < ((unsigned long) m_port_op.def.nBufferCountActual));
+
+ if (m_meta_buffer_mode)
+ {
+ meta_buffer_ref_remove(
+ m_buffer_array_op[index].buffer_payload.pmem_fd,
+ m_buffer_array_op[index].buffer_payload.offset);
+ }
+
+ break;
+ }
+
+ case SWVDEC_EVENT_RECONFIG_REQUIRED:
+ {
+ async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0);
+ break;
+ }
+
+ case SWVDEC_EVENT_FATAL_ERROR:
+ default:
+ {
+ async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0);
+ break;
+ }
+
+ }
+}
+
+/**
+ * @brief Translate SwVdec status return value to OMX error type return value.
+ *
+ * @param[in] retval_swvdec: SwVdec status return value.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec)
+{
+ OMX_ERRORTYPE retval_omx;
+
+ switch (retval_swvdec)
+ {
+
+ SWVDEC_STATUS_SUCCESS:
+ retval_omx = OMX_ErrorNone;
+ break;
+
+ SWVDEC_STATUS_FAILURE:
+ retval_omx = OMX_ErrorUndefined;
+ break;
+
+ SWVDEC_STATUS_NULL_POINTER:
+ SWVDEC_STATUS_INVALID_PARAMETERS:
+ retval_omx = OMX_ErrorBadParameter;
+ break;
+
+ SWVDEC_STATUS_INVALID_STATE:
+ retval_omx = OMX_ErrorInvalidState;
+ break;
+
+ SWVDEC_STATUS_INSUFFICIENT_RESOURCES:
+ retval_omx = OMX_ErrorInsufficientResources;
+ break;
+
+ SWVDEC_STATUS_UNSUPPORTED:
+ retval_omx = OMX_ErrorUnsupportedSetting;
+ break;
+
+ SWVDEC_STATUS_NOT_IMPLEMENTED:
+ retval_omx = OMX_ErrorNotImplemented;
+ break;
+
+ default:
+ retval_omx = OMX_ErrorUndefined;
+ break;
+
+ }
+
+ return retval_omx;
+}
+
+/**
+ * @brief Create asynchronous thread.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_thread_create()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ pthread_attr_t thread_attributes;
+
+ if (sem_init(&m_async_thread.sem_thread_created, 0, 0))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore");
+ retval = OMX_ErrorInsufficientResources;
+ }
+ else if (sem_init(&m_async_thread.sem_event, 0, 0))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore");
+ retval = OMX_ErrorInsufficientResources;
+ }
+ else if (pthread_attr_init(&thread_attributes))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object");
+ retval = OMX_ErrorInsufficientResources;
+ }
+ else if (pthread_attr_setdetachstate(&thread_attributes,
+ PTHREAD_CREATE_JOINABLE))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute");
+ retval = OMX_ErrorInsufficientResources;
+
+ pthread_attr_destroy(&thread_attributes);
+ }
+ else
+ {
+ m_async_thread.created = false;
+ m_async_thread.exit = false;
+
+ if (pthread_create(&m_async_thread.handle,
+ &thread_attributes,
+ (void *(*)(void *)) async_thread,
+ this))
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to create async thread");
+ retval = OMX_ErrorInsufficientResources;
+
+ pthread_attr_destroy(&thread_attributes);
+ }
+ else
+ {
+ if (pthread_setname_np(m_async_thread.handle, "swvdec_async"))
+ {
+ // don't return error
+ OMX_SWVDEC_LOG_ERROR("failed to set async thread name");
+ }
+
+ sem_wait(&m_async_thread.sem_thread_created);
+ m_async_thread.created = true;
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Destroy asynchronous thread.
+ */
+void omx_swvdec::async_thread_destroy()
+{
+ if (m_async_thread.created)
+ {
+ m_async_thread.exit = true;
+ sem_post(&m_async_thread.sem_event);
+
+ pthread_join(m_async_thread.handle, NULL);
+ m_async_thread.created = false;
+ }
+
+ m_async_thread.exit = false;
+
+ sem_destroy(&m_async_thread.sem_event);
+ sem_destroy(&m_async_thread.sem_thread_created);
+}
+
+/**
+ * @brief Post event to appropriate queue.
+ *
+ * @param[in] event_id: Event ID.
+ * @param[in] event_param1: Event parameter 1.
+ * @param[in] event_param2: Event parameter 2.
+ *
+ * @retval true if post event successful
+ * @retval false if post event unsuccessful
+ */
+bool omx_swvdec::async_post_event(unsigned long event_id,
+ unsigned long event_param1,
+ unsigned long event_param2)
+{
+ OMX_SWVDEC_EVENT_INFO event_info;
+
+ bool retval = true;
+
+ event_info.event_id = event_id;
+ event_info.event_param1 = event_param1;
+ event_info.event_param2 = event_param2;
+
+ switch (event_id)
+ {
+
+ case OMX_SWVDEC_EVENT_ETB:
+ case OMX_SWVDEC_EVENT_EBD:
+ {
+ retval = m_queue_port_ip.push(&event_info);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_FTB:
+ case OMX_SWVDEC_EVENT_FBD:
+ {
+ retval = m_queue_port_op.push(&event_info);
+ break;
+ }
+
+ default:
+ {
+ retval = m_queue_command.push(&event_info);
+ break;
+ }
+
+ }
+
+ if (retval == true)
+ {
+ sem_post(&m_async_thread.sem_event);
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Asynchronous thread.
+ *
+ * @param[in] p_cmp: Pointer to OMX SwVdec component class.
+ */
+void omx_swvdec::async_thread(void *p_cmp)
+{
+ if (p_cmp == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
+ }
+ else
+ {
+ omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp;
+
+ ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread;
+
+ OMX_SWVDEC_LOG_HIGH("created");
+
+ sem_post(&p_async_thread->sem_thread_created);
+
+ while (p_async_thread->exit == false)
+ {
+ sem_wait(&p_async_thread->sem_event);
+
+ if (p_async_thread->exit == true)
+ {
+ break;
+ }
+
+ p_omx_swvdec->async_process_event(p_cmp);
+ }
+ }
+
+ OMX_SWVDEC_LOG_HIGH("exiting");
+}
+
+/**
+ * @brief Process event.
+ *
+ * @param[in] p_cmp: Pointer to OMX SwVdec component class.
+ */
+void omx_swvdec::async_process_event(void *p_cmp)
+{
+ omx_swvdec *p_omx_swvdec;
+
+ OMX_SWVDEC_EVENT_INFO event_info;
+
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (p_cmp == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("p_cmp = NULL");
+ goto async_process_event_exit;
+ }
+
+ p_omx_swvdec = (omx_swvdec *) p_cmp;
+
+ // NOTE: queues popped in order of priority; do not change!
+
+ if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) &&
+ (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) &&
+ (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false))
+ {
+ OMX_SWVDEC_LOG_LOW("no event popped");
+ goto async_process_event_exit;
+ }
+
+ switch (event_info.event_id)
+ {
+
+ case OMX_SWVDEC_EVENT_CMD:
+ {
+ OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1;
+ OMX_U32 param = (OMX_U32) event_info.event_param2;
+
+ retval = p_omx_swvdec->async_process_event_cmd(cmd, param);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_CMD_ACK:
+ {
+ OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1;
+ OMX_U32 param = (OMX_U32) event_info.event_param2;
+
+ retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_ERROR:
+ {
+ OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1;
+
+ retval = p_omx_swvdec->async_process_event_error(error_code);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_ETB:
+ {
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr =
+ (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+
+ unsigned int index = event_info.event_param2;
+
+ retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_FTB:
+ {
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr =
+ (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+
+ unsigned int index = event_info.event_param2;
+
+ retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_EBD:
+ {
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr =
+ (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+
+ unsigned int index = event_info.event_param2;
+
+ retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_FBD:
+ {
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr =
+ (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+
+ unsigned int index = event_info.event_param2;
+
+ retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_EOS:
+ {
+ retval = p_omx_swvdec->async_process_event_eos();
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_FLUSH_PORT_IP:
+ {
+ retval = p_omx_swvdec->async_process_event_flush_port_ip();
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_FLUSH_PORT_OP:
+ {
+ retval = p_omx_swvdec->async_process_event_flush_port_op();
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_PORT_RECONFIG:
+ {
+ retval = p_omx_swvdec->async_process_event_port_reconfig();
+ break;
+ }
+
+ default:
+ {
+ assert(0);
+ retval = OMX_ErrorUndefined;
+ break;
+ }
+
+ }
+
+ if (retval != OMX_ErrorNone)
+ {
+ p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
+ }
+
+async_process_event_exit:
+ return;
+}
+
+/**
+ * @brief Process command event.
+ *
+ * @param[in] cmd: Command.
+ * @param[in] param: Command parameter.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd,
+ OMX_U32 param)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ bool cmd_ack = false; // set to 'true' if command is to be acknowledged
+
+ SWVDEC_STATUS retval_swvdec;
+
+ switch (cmd)
+ {
+
+ case OMX_CommandStateSet:
+ {
+ retval = async_process_event_cmd_state_set(&cmd_ack,
+ (OMX_STATETYPE) param);
+ break;
+ }
+
+ case OMX_CommandFlush:
+ {
+ retval = async_process_event_cmd_flush((unsigned int) param);
+ break;
+ }
+
+ case OMX_CommandPortDisable:
+ {
+ retval = async_process_event_cmd_port_disable(&cmd_ack,
+ (unsigned int) param);
+ break;
+ }
+
+ case OMX_CommandPortEnable:
+ {
+ retval = async_process_event_cmd_port_enable(&cmd_ack,
+ (unsigned int) param);
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
+
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch (cmd)
+
+ // post appropriate event
+
+ if (retval != OMX_ErrorNone)
+ {
+ async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0);
+ }
+ else if (cmd_ack)
+ {
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param);
+ }
+
+ // post to command semaphore
+ sem_post(&m_sem_cmd);
+
+ return retval;
+}
+
+/**
+ * @brief Process command acknowledgement event.
+ *
+ * @param[in] cmd: Command.
+ * @param[in] param: Command parameter.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd,
+ OMX_U32 param)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ switch (cmd)
+ {
+
+ case OMX_CommandStateSet:
+ {
+ m_state = (OMX_STATETYPE) param;
+
+ OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
+ "OMX_CommandStateSet, %s",
+ OMX_STATETYPE_STRING(m_state));
+
+ m_callback.EventHandler(&m_cmp,
+ m_app_data,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ (OMX_U32) m_state,
+ NULL);
+ break;
+ }
+
+ case OMX_CommandFlush:
+ case OMX_CommandPortEnable:
+ case OMX_CommandPortDisable:
+ {
+ if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress)
+ {
+ m_port_reconfig_inprogress = false;
+ }
+
+ OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, "
+ "%s, port index %d",
+ OMX_COMMANDTYPE_STRING(cmd),
+ param);
+
+ m_callback.EventHandler(&m_cmp,
+ m_app_data,
+ OMX_EventCmdComplete,
+ cmd,
+ param,
+ NULL);
+ break;
+ }
+
+ default:
+ {
+ OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd);
+ retval = OMX_ErrorBadParameter;
+ break;
+ }
+
+ } // switch (cmd)
+
+ return retval;
+}
+
+/**
+ * @brief Process error event.
+ *
+ * @param[in] error_code: Error code.
+ *
+ * @retval OMX_ErrorNone
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code)
+{
+ if (error_code == OMX_ErrorInvalidState)
+ {
+ m_state = OMX_StateInvalid;
+ }
+
+ OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x",
+ error_code);
+
+ m_callback.EventHandler(&m_cmp,
+ m_app_data,
+ OMX_EventError,
+ (OMX_U32) error_code,
+ 0,
+ NULL);
+
+ return OMX_ErrorNone;
+}
+
+/**
+ * @brief Process OMX_CommandStateSet.
+ *
+ * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
+ * @param[in] state_new: New state to which transition is requested.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set(
+ bool *p_cmd_ack,
+ OMX_STATETYPE state_new)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ SWVDEC_STATUS retval_swvdec;
+
+ OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested",
+ OMX_STATETYPE_STRING(m_state),
+ OMX_STATETYPE_STRING(state_new));
+
+ /**
+ * Only the following state transitions are allowed via CommandStateSet:
+ *
+ * LOADED -> IDLE -> EXECUTING
+ * LOADED <- IDLE <- EXECUTING
+ */
+
+ if (m_state == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state));
+ retval = OMX_ErrorInvalidState;
+ }
+ else if (state_new == OMX_StateInvalid)
+ {
+ OMX_SWVDEC_LOG_ERROR("requested transition to state %s",
+ OMX_STATETYPE_STRING(state_new));
+ retval = OMX_ErrorInvalidState;
+ }
+ else if ((m_state == OMX_StateLoaded) &&
+ (state_new == OMX_StateIdle))
+ {
+ if ((m_port_ip.populated == OMX_TRUE) &&
+ (m_port_op.populated == OMX_TRUE))
+ {
+ // start SwVdec
+ if ((retval_swvdec = swvdec_start(m_swvdec_handle)) ==
+ SWVDEC_STATUS_SUCCESS)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to start SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+ else
+ {
+ m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE);
+
+ OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending");
+ }
+ }
+ else if ((m_state == OMX_StateIdle) &&
+ (state_new == OMX_StateExecuting))
+ {
+ *p_cmd_ack = true;
+ }
+ else if ((m_state == OMX_StateExecuting) &&
+ (state_new == OMX_StateIdle))
+ {
+ m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE);
+
+ OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending");
+
+ retval = flush(OMX_ALL);
+ }
+ else if ((m_state == OMX_StateIdle) &&
+ (state_new == OMX_StateLoaded))
+ {
+ if ((m_port_ip.unpopulated == OMX_TRUE) &&
+ (m_port_op.unpopulated == OMX_TRUE))
+ {
+ // stop SwVdec
+ if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) ==
+ SWVDEC_STATUS_SUCCESS)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec");
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+ else
+ {
+ m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED);
+
+ OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending");
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal",
+ OMX_STATETYPE_STRING(m_state),
+ OMX_STATETYPE_STRING(state_new));
+
+ retval = ((state_new == m_state) ?
+ OMX_ErrorSameState :
+ OMX_ErrorIncorrectStateTransition);
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Process OMX_CommandFlush.
+ *
+ * @param[in] port_index: Index of port to flush.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_LOG_HIGH("flush port %d requested", port_index);
+
+ if (port_index == OMX_CORE_PORT_INDEX_IP)
+ {
+ m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
+
+ OMX_SWVDEC_LOG_LOW("ip port flush pending");
+ }
+ else if (port_index == OMX_CORE_PORT_INDEX_OP)
+ {
+ m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
+
+ OMX_SWVDEC_LOG_LOW("op port flush pending");
+ }
+ else if (port_index == OMX_ALL)
+ {
+ m_status_flags |= (1 << PENDING_PORT_FLUSH_IP);
+ m_status_flags |= (1 << PENDING_PORT_FLUSH_OP);
+
+ OMX_SWVDEC_LOG_LOW("ip & op ports flush pending");
+ }
+
+ retval = flush(port_index);
+
+ return retval;
+}
+
+/**
+ * @brief Process OMX_CommandPortDisable.
+ *
+ * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
+ * @param[in] port_index: Index of port to disable.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable(
+ bool *p_cmd_ack,
+ unsigned int port_index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_LOG_HIGH("disable port %d requested", port_index);
+
+ if (port_index == OMX_CORE_PORT_INDEX_IP)
+ {
+ if (m_port_ip.enabled == OMX_FALSE)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip port already disabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else
+ {
+ m_port_ip.enabled = OMX_FALSE;
+
+ if (m_port_ip.unpopulated)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
+
+ OMX_SWVDEC_LOG_LOW("ip port disable pending");
+
+ if (m_port_ip.num_pending_buffers)
+ {
+ retval = flush(port_index);
+ }
+ }
+ }
+ }
+ else if (port_index == OMX_CORE_PORT_INDEX_OP)
+ {
+ if (m_port_op.enabled == OMX_FALSE)
+ {
+ OMX_SWVDEC_LOG_ERROR("op port already disabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else
+ {
+ m_port_op.enabled = OMX_FALSE;
+
+ if (m_port_op.unpopulated)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
+
+ OMX_SWVDEC_LOG_LOW("op port disable pending");
+
+ if (m_port_op.num_pending_buffers)
+ {
+ retval = flush(port_index);
+ }
+ }
+ }
+ }
+ else if (port_index == OMX_ALL)
+ {
+ if (m_port_ip.enabled == OMX_FALSE)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip port already disabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else if (m_port_op.enabled == OMX_FALSE)
+ {
+ OMX_SWVDEC_LOG_ERROR("op port already disabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else
+ {
+ if (m_port_ip.unpopulated && m_port_op.unpopulated)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ m_port_ip.enabled = OMX_FALSE;
+ m_port_op.enabled = OMX_FALSE;
+
+ if (m_port_ip.unpopulated == OMX_FALSE)
+ {
+ m_status_flags |= (1 << PENDING_PORT_DISABLE_IP);
+
+ OMX_SWVDEC_LOG_LOW("ip port disable pending");
+
+ if (m_port_ip.num_pending_buffers)
+ {
+ retval = flush(port_index);
+ }
+ }
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_port_op.unpopulated == OMX_FALSE))
+ {
+ m_status_flags |= (1 << PENDING_PORT_DISABLE_OP);
+
+ OMX_SWVDEC_LOG_LOW("op port disable pending");
+
+ if (m_port_op.num_pending_buffers)
+ {
+ retval = flush(port_index);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid");
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Process OMX_CommandPortEnable.
+ *
+ * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable.
+ * @param[in] port_index: Index of port to enable.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable(
+ bool *p_cmd_ack,
+ unsigned int port_index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_LOG_HIGH("enable port %d requested", port_index);
+
+ if (port_index == OMX_CORE_PORT_INDEX_IP)
+ {
+ if (m_port_ip.enabled)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip port already enabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else
+ {
+ m_port_ip.enabled = OMX_TRUE;
+
+ if (m_port_ip.populated)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
+
+ OMX_SWVDEC_LOG_LOW("ip port enable pending");
+ }
+ }
+ }
+ else if (port_index == OMX_CORE_PORT_INDEX_OP)
+ {
+ if (m_port_op.enabled)
+ {
+ OMX_SWVDEC_LOG_ERROR("op port already enabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else
+ {
+ m_port_op.enabled = OMX_TRUE;
+
+ if (m_port_op.populated)
+ {
+ *p_cmd_ack = true;
+ }
+ else
+ {
+ m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
+
+ OMX_SWVDEC_LOG_LOW("op port enable pending");
+ }
+ }
+ }
+ else if (port_index == OMX_ALL)
+ {
+ if (m_port_ip.enabled)
+ {
+ OMX_SWVDEC_LOG_ERROR("ip port already enabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else if (m_port_op.enabled)
+ {
+ OMX_SWVDEC_LOG_ERROR("op port already enabled");
+ retval = OMX_ErrorBadPortIndex;
+ }
+ else
+ {
+ m_port_ip.enabled = OMX_TRUE;
+ m_port_op.enabled = OMX_TRUE;
+
+ if (m_port_ip.populated && m_port_op.populated)
+ {
+ *p_cmd_ack = true;
+ }
+ else if (m_port_ip.populated == false)
+ {
+ m_status_flags |= (1 << PENDING_PORT_ENABLE_IP);
+
+ OMX_SWVDEC_LOG_LOW("ip port enable pending");
+ }
+ else if (m_port_op.populated == false)
+ {
+ m_status_flags |= (1 << PENDING_PORT_ENABLE_OP);
+
+ OMX_SWVDEC_LOG_LOW("op port enable pending");
+ }
+ }
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("port index '%d' invalid");
+ retval = OMX_ErrorBadPortIndex;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Process ETB event.
+ *
+ * @param[in] p_buffer_hdr: Pointer to buffer header.
+ * @param[in] index: Index of buffer in input buffer info array.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_etb(
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr,
+ unsigned int index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ m_port_ip.num_pending_buffers++;
+
+ if ((p_buffer_hdr->nFilledLen == 0) &&
+ ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0))
+ {
+ OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
+ "zero length & no EOS flag",
+ p_buffer_hdr,
+ p_buffer_hdr->pBuffer);
+
+ async_post_event(OMX_SWVDEC_EVENT_EBD,
+ (unsigned long) p_buffer_hdr,
+ (unsigned long) index);
+ }
+ else if (m_port_ip.flush_inprogress)
+ {
+ OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
+ "ip port flush in progress",
+ p_buffer_hdr,
+ p_buffer_hdr->pBuffer);
+
+ async_post_event(OMX_SWVDEC_EVENT_EBD,
+ (unsigned long) p_buffer_hdr,
+ (unsigned long) index);
+ }
+ else
+ {
+ SWVDEC_STATUS retval_swvdec;
+
+ SWVDEC_BUFFER *p_buffer_swvdec =
+ &(m_buffer_array_ip[index].buffer_swvdec);
+
+ if (p_buffer_hdr->nFilledLen &&
+ ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0))
+ {
+ m_ts_list.push(p_buffer_hdr->nTimeStamp);
+ }
+
+ assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer);
+
+ p_buffer_swvdec->flags = p_buffer_hdr->nFlags;
+ p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp;
+ p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen;
+
+ m_diag.dump_ip(p_buffer_swvdec->p_buffer,
+ p_buffer_swvdec->filled_length);
+
+ retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle,
+ p_buffer_swvdec);
+
+ if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Process FTB event.
+ *
+ * @param[in] p_buffer_hdr: Pointer to buffer header.
+ * @param[in] index: Index of buffer in output buffer info array.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_ftb(
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr,
+ unsigned int index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ m_port_op.num_pending_buffers++;
+
+ if (m_port_op.flush_inprogress)
+ {
+ OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; "
+ "op port flush in progress",
+ p_buffer_hdr,
+ m_buffer_array_op[index].buffer_swvdec.p_buffer);
+
+ async_post_event(OMX_SWVDEC_EVENT_FBD,
+ (unsigned long) p_buffer_hdr,
+ (unsigned long) index);
+ }
+ else
+ {
+ SWVDEC_STATUS retval_swvdec;
+
+ SWVDEC_BUFFER *p_buffer_swvdec =
+ &(m_buffer_array_op[index].buffer_swvdec);
+
+ retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec);
+
+ if (retval_swvdec != SWVDEC_STATUS_SUCCESS)
+ {
+ retval = retval_swvdec2omx(retval_swvdec);
+ }
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Process EBD event.
+ *
+ * @param[in] p_buffer_hdr: Pointer to buffer header.
+ * @param[in] index: Index of buffer in output buffer info array.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_ebd(
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr,
+ unsigned int index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (index < m_port_ip.def.nBufferCountActual)
+ {
+ m_port_ip.num_pending_buffers--;
+
+ // should ideally be set in swvdec_empty_buffer_done()
+ p_buffer_hdr->nFilledLen = 0;
+
+ OMX_SWVDEC_LOG_CALLBACK(
+ "EmptyBufferDone(): %p, buffer %p",
+ p_buffer_hdr,
+ m_buffer_array_ip[index].buffer_swvdec.p_buffer);
+
+ m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
+ retval = OMX_ErrorBadParameter;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Process FBD event.
+ *
+ * @param[in] p_buffer_hdr: Pointer to buffer header.
+ * @param[in] index: Index of buffer in output buffer info array.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_fbd(
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr,
+ unsigned int index)
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (index < m_port_op.def.nBufferCountActual)
+ {
+ OMX_U8 *p_buffer;
+
+ p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer;
+
+ m_port_op.num_pending_buffers--;
+
+ if (m_port_op.flush_inprogress)
+ {
+ p_buffer_hdr->nFilledLen = 0;
+ p_buffer_hdr->nTimeStamp = 0;
+ p_buffer_hdr->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
+ }
+
+ if (p_buffer_hdr->nFilledLen)
+ {
+ if (m_sync_frame_decoding_mode)
+ {
+ p_buffer_hdr->nTimeStamp = 0;
+ }
+ else
+ {
+ if (m_ts_list.pop(&p_buffer_hdr->nTimeStamp) == false)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to pop timestamp from list");
+ }
+ }
+
+ m_diag.dump_op(p_buffer,
+ m_frame_dimensions.width,
+ m_frame_dimensions.height,
+ m_frame_attributes.stride,
+ m_frame_attributes.scanlines);
+ }
+
+ if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS)
+ {
+ async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0);
+
+ m_ts_list.reset();
+ }
+
+ if (m_meta_buffer_mode &&
+ ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0)
+ {
+ meta_buffer_ref_remove(
+ m_buffer_array_op[index].buffer_payload.pmem_fd,
+ m_buffer_array_op[index].buffer_payload.offset);
+ }
+
+ OMX_SWVDEC_LOG_CALLBACK(
+ "FillBufferDone(): %p, buffer %p, "
+ "flags 0x%08x, timestamp %lld",
+ p_buffer_hdr,
+ p_buffer,
+ p_buffer_hdr->nFlags,
+ p_buffer_hdr->nTimeStamp);
+
+ m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr);
+ }
+ else
+ {
+ OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index);
+ retval = OMX_ErrorBadParameter;
+ }
+
+async_process_event_fbd_exit:
+ return retval;
+}
+
+/**
+ * @brief Process EOS event.
+ *
+ * @retval OMX_ErrorNone
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_eos()
+{
+ OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
+ "OMX_EventBufferFlag, port %d, EOS",
+ OMX_CORE_PORT_INDEX_OP);
+
+ m_callback.EventHandler(&m_cmp,
+ m_app_data,
+ OMX_EventBufferFlag,
+ OMX_CORE_PORT_INDEX_OP,
+ OMX_BUFFERFLAG_EOS,
+ NULL);
+
+ return OMX_ErrorNone;
+}
+
+/**
+ * @brief Process input port flush event.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_EVENT_INFO event_info;
+
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr;
+
+ unsigned int index;
+
+ while (m_queue_port_ip.pop(&event_info))
+ {
+ switch (event_info.event_id)
+ {
+
+ case OMX_SWVDEC_EVENT_ETB:
+ {
+ p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+ index = event_info.event_param2;
+
+ // compensate decrement in async_process_event_ebd()
+ m_port_ip.num_pending_buffers++;
+
+ retval = async_process_event_ebd(p_buffer_hdr, index);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_EBD:
+ {
+ p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+ index = event_info.event_param2;
+
+ retval = async_process_event_ebd(p_buffer_hdr, index);
+ break;
+ }
+
+ default:
+ {
+ assert(0);
+ break;
+ }
+
+ }
+ }
+
+ assert(m_port_ip.num_pending_buffers == 0);
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_status_flags & (1 << PENDING_PORT_FLUSH_IP)))
+ {
+ m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandFlush,
+ OMX_CORE_PORT_INDEX_IP);
+ }
+
+ m_port_ip.flush_inprogress = OMX_FALSE;
+
+ return retval;
+}
+
+/**
+ * @brief Process output port flush event.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ OMX_SWVDEC_EVENT_INFO event_info;
+
+ OMX_BUFFERHEADERTYPE *p_buffer_hdr;
+
+ unsigned int index;
+
+ while (m_queue_port_op.pop(&event_info))
+ {
+ switch (event_info.event_id)
+ {
+
+ case OMX_SWVDEC_EVENT_FTB:
+ {
+ p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+ index = event_info.event_param2;
+
+ // compensate decrement in async_process_event_fbd()
+ m_port_op.num_pending_buffers++;
+
+ retval = async_process_event_fbd(p_buffer_hdr, index);
+ break;
+ }
+
+ case OMX_SWVDEC_EVENT_FBD:
+ {
+ p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1;
+ index = event_info.event_param2;
+
+ retval = async_process_event_fbd(p_buffer_hdr, index);
+ break;
+ }
+
+ default:
+ {
+ assert(0);
+ break;
+ }
+
+ }
+ }
+
+ assert(m_port_op.num_pending_buffers == 0);
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_status_flags & (1 << PENDING_PORT_FLUSH_OP)))
+ {
+ m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandFlush,
+ OMX_CORE_PORT_INDEX_OP);
+ }
+
+ if ((retval == OMX_ErrorNone) &&
+ (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE)))
+ {
+ m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE);
+
+ async_post_event(OMX_SWVDEC_EVENT_CMD_ACK,
+ OMX_CommandStateSet,
+ OMX_StateIdle);
+ }
+
+ if (m_port_reconfig_inprogress == false)
+ {
+ m_ts_list.reset();
+ }
+
+ m_port_op.flush_inprogress = OMX_FALSE;
+
+ return retval;
+}
+
+/**
+ * @brief Process port reconfiguration event.
+ *
+ * @retval OMX_ERRORTYPE
+ */
+OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig()
+{
+ OMX_ERRORTYPE retval = OMX_ErrorNone;
+
+ if (m_port_reconfig_inprogress)
+ {
+ OMX_SWVDEC_LOG_ERROR("port reconfiguration in progress");
+ retval = OMX_ErrorIncorrectStateOperation;
+ }
+ else
+ {
+ m_port_reconfig_inprogress = true;
+
+ OMX_SWVDEC_LOG_CALLBACK("EventHandler(): "
+ "OMX_EventPortSettingsChanged, port %d",
+ OMX_CORE_PORT_INDEX_OP);
+
+ m_callback.EventHandler(&m_cmp,
+ m_app_data,
+ OMX_EventPortSettingsChanged,
+ OMX_CORE_PORT_INDEX_OP,
+ 0,
+ NULL);
+ }
+
+ return retval;
+}
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_swvdec_utils.cpp b/mm-video-v4l2/vidc/vdec/src/omx_swvdec_utils.cpp
new file mode 100644
index 00000000..d07a63be
--- /dev/null
+++ b/mm-video-v4l2/vidc/vdec/src/omx_swvdec_utils.cpp
@@ -0,0 +1,461 @@
+/**
+ * @copyright
+ *
+ * Copyright (c) 2015, 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_utils.cpp
+ *
+ * @brief
+ *
+ * OMX software video decoder utility functions source.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include <cutils/properties.h>
+
+#include "omx_swvdec_utils.h"
+
+#define OMX_SWVDEC_LOGLEVEL_DEFAULT 2 ///< default OMX SwVdec loglevel
+
+unsigned int g_omx_swvdec_logmask = (1 << OMX_SWVDEC_LOGLEVEL_DEFAULT) - 1;
+ ///< global OMX SwVdec logmask variable definition
+
+/**
+ * @brief Initialize OMX SwVdec log level & mask.
+ */
+void omx_swvdec_log_init()
+{
+ int omx_swvdec_loglevel = OMX_SWVDEC_LOGLEVEL_DEFAULT;
+
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+
+ if (property_get("omx_swvdec.log.level", property_value, NULL))
+ {
+ omx_swvdec_loglevel = atoi(property_value);
+
+ if (omx_swvdec_loglevel > 3)
+ omx_swvdec_loglevel = 3;
+ if (omx_swvdec_loglevel < 0)
+ omx_swvdec_loglevel = 0;
+
+ OMX_SWVDEC_LOG_LOW(
+ "omx_swvdec.log.level: %d; %s",
+ omx_swvdec_loglevel,
+ (omx_swvdec_loglevel == 3) ? "error, high, & low logs" :
+ ((omx_swvdec_loglevel == 2) ? "error & high logs" :
+ ((omx_swvdec_loglevel == 1) ? "error logs" :
+ "no logs")));
+ }
+
+ g_omx_swvdec_logmask = (unsigned int) ((1 << omx_swvdec_loglevel) - 1);
+}
+
+/**
+ * @brief OMX SwVdec queue constructor.
+ */
+omx_swvdec_queue::omx_swvdec_queue()
+{
+ memset(m_queue, 0, sizeof(m_queue));
+
+ m_count_total = OMX_SWVDEC_QUEUE_ELEMENTS;
+ m_count_filled = 0;
+ m_index_write = 0;
+ m_index_read = 0;
+
+ pthread_mutex_init(&m_mutex, NULL);
+}
+
+/**
+ * @brief OMX SwVdec queue destructor.
+ */
+omx_swvdec_queue::~omx_swvdec_queue()
+{
+ pthread_mutex_destroy(&m_mutex);
+}
+
+/**
+ * @brief Push event to queue.
+ *
+ * @param[in] p_event_info: Pointer to event information structure.
+ *
+ * @retval true if push successful
+ * @retval false if push unsuccessful
+ */
+bool omx_swvdec_queue::push(OMX_SWVDEC_EVENT_INFO *p_event_info)
+{
+ bool retval = true;
+
+ pthread_mutex_lock(&m_mutex);
+
+ if (m_count_filled < m_count_total)
+ {
+ m_queue[m_index_write] = *p_event_info;
+
+ m_index_write = (m_index_write + 1) % m_count_total;
+ m_count_filled++;
+ }
+ else
+ {
+ retval = false;
+ }
+
+ pthread_mutex_unlock(&m_mutex);
+
+ return retval;
+}
+
+/**
+ * @brief Pop event from queue.
+ *
+ * @param[in,out] p_event_info: Pointer to event information structure.
+ *
+ * @retval true if pop successful
+ * @retval false if pop unsuccessful
+ */
+bool omx_swvdec_queue::pop(OMX_SWVDEC_EVENT_INFO *p_event_info)
+{
+ bool retval = true;
+
+ pthread_mutex_lock(&m_mutex);
+
+ if (m_count_filled > 0)
+ {
+ *p_event_info = m_queue[m_index_read];
+
+ memset(&m_queue[m_index_read], 0, sizeof(OMX_SWVDEC_EVENT_INFO));
+
+ m_index_read = (m_index_read + 1) % m_count_total;
+ m_count_filled--;
+ }
+ else
+ {
+ retval = false;
+ }
+
+ pthread_mutex_unlock(&m_mutex);
+
+ return retval;
+}
+
+/**
+ * @brief OMX SwVdec timestamp list constructor.
+ */
+omx_swvdec_ts_list::omx_swvdec_ts_list()
+{
+ reset();
+
+ pthread_mutex_init(&m_mutex, NULL);
+}
+
+/**
+ * @brief OMX SwVdec timestamp list destructor.
+ */
+omx_swvdec_ts_list::~omx_swvdec_ts_list()
+{
+ pthread_mutex_destroy(&m_mutex);
+}
+
+/**
+ * @brief Reset timestamp list.
+ */
+void omx_swvdec_ts_list::reset()
+{
+ memset(m_list, 0, sizeof(m_list));
+ m_count_filled = 0;
+}
+
+/**
+ * @brief Push timestamp to list, keeping lowest-valued timestamp at the end.
+ *
+ * @param[in] timestamp: Timestamp.
+ *
+ * @retval true if push successful
+ * @retval false if push unsuccessful
+ */
+bool omx_swvdec_ts_list::push(long long timestamp)
+{
+ bool retval = true;
+
+ pthread_mutex_lock(&m_mutex);
+
+ if (m_count_filled < OMX_SWVDEC_TS_LIST_ELEMENTS)
+ {
+ int index_curr, index_prev;
+
+ long long timestamp_tmp;
+
+ // insert timestamp into list
+
+ m_list[m_count_filled].filled = true;
+ m_list[m_count_filled].timestamp = timestamp;
+ m_count_filled++;
+
+ // iterate backwards
+
+ index_curr = m_count_filled - 1;
+ index_prev = m_count_filled - 2;
+
+ while ((index_curr > 0) &&
+ (m_list[index_curr].timestamp > m_list[index_prev].timestamp))
+ {
+ // swap timestamps
+
+ timestamp_tmp = m_list[index_prev].timestamp;
+ m_list[index_prev].timestamp = m_list[index_curr].timestamp;
+ m_list[index_curr].timestamp = timestamp_tmp;
+
+ index_curr--;
+ index_prev--;
+ }
+ }
+ else
+ {
+ retval = false;
+ }
+
+ pthread_mutex_unlock(&m_mutex);
+
+ return retval;
+}
+
+/**
+ * @brief Pop timestamp from list.
+ *
+ * @param[in,out] p_timestamp: Pointer to timestamp variable.
+ *
+ * @retval true if pop successful
+ * @retval false if pop unsuccessful
+ */
+bool omx_swvdec_ts_list::pop(long long *p_timestamp)
+{
+ bool retval;
+
+ pthread_mutex_lock(&m_mutex);
+
+ if (m_count_filled)
+ {
+ *p_timestamp = m_list[m_count_filled - 1].timestamp;
+ m_list[m_count_filled - 1].filled = false;
+ m_count_filled--;
+
+ retval = true;
+ }
+ else
+ {
+ retval = false;
+ }
+
+ pthread_mutex_unlock(&m_mutex);
+
+ return retval;
+}
+
+/**
+ * @brief OMX SwVdec diagnostics class constructor.
+ */
+omx_swvdec_diag::omx_swvdec_diag():
+ m_dump_ip(0),
+ m_dump_op(0),
+ m_filename_ip(NULL),
+ m_filename_op(NULL),
+ m_file_ip(NULL),
+ m_file_op(NULL)
+{
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+
+ if (property_get("omx_swvdec.dump.ip", property_value, NULL))
+ {
+ m_dump_ip = atoi(property_value);
+ OMX_SWVDEC_LOG_LOW("omx_swvdec.dump.ip: %d", m_dump_ip);
+ }
+
+ if (property_get("omx_swvdec.dump.op", property_value, NULL))
+ {
+ m_dump_op = atoi(property_value);
+ OMX_SWVDEC_LOG_LOW("omx_swvdec.dump.op: %d", m_dump_op);
+ }
+
+ if (property_get("omx_swvdec.filename.ip",
+ property_value,
+ DIAG_FILENAME_IP))
+ {
+ OMX_SWVDEC_LOG_LOW("omx_swvdec.filename.ip: %s", m_filename_ip);
+
+ m_filename_ip =
+ (char *) malloc((strlen(property_value) + 1) * sizeof(char));
+
+ if (m_filename_ip == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to allocate %d bytes for "
+ "input filename string",
+ (strlen(property_value) + 1) * sizeof(char));
+ }
+ else
+ {
+ strncpy(m_filename_ip, property_value, strlen(property_value) + 1);
+ }
+ }
+
+ if (property_get("omx_swvdec.filename.op",
+ property_value,
+ DIAG_FILENAME_OP))
+ {
+ OMX_SWVDEC_LOG_LOW("omx_swvdec.filename.op: %s", m_filename_op);
+
+ m_filename_op =
+ (char *) malloc((strlen(property_value) + 1) * sizeof(char));
+
+ if (m_filename_op == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("failed to allocate %d bytes for "
+ "output filename string",
+ (strlen(property_value) + 1) * sizeof(char));
+ }
+ else
+ {
+ strncpy(m_filename_op, property_value, strlen(property_value) + 1);
+ }
+ }
+
+ if (m_dump_ip && (m_filename_ip != NULL))
+ {
+ if ((m_file_ip = fopen(m_filename_ip, "rb")) == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cannot open input file '%s'", m_filename_ip);
+ m_dump_ip = 0;
+ }
+ }
+ else
+ {
+ m_dump_ip = 0;
+ }
+
+ if (m_dump_op && (m_filename_op != NULL))
+ {
+ if ((m_file_op = fopen(m_filename_op, "rb")) == NULL)
+ {
+ OMX_SWVDEC_LOG_ERROR("cannot open output file '%s'", m_filename_op);
+ m_dump_op = 0;
+ }
+ }
+ else
+ {
+ m_dump_op = 0;
+ }
+}
+
+/**
+ * @brief OMX SwVdec diagnostics class destructor.
+ */
+omx_swvdec_diag::~omx_swvdec_diag()
+{
+ if (m_file_op)
+ {
+ fclose(m_file_op);
+ m_file_op = NULL;
+ }
+
+ if (m_file_ip)
+ {
+ fclose(m_file_ip);
+ m_file_ip = NULL;
+ }
+
+ if (m_filename_op)
+ {
+ free(m_filename_op);
+ m_filename_op = NULL;
+ }
+
+ if (m_filename_ip)
+ {
+ free(m_filename_ip);
+ m_filename_ip = NULL;
+ }
+}
+
+/**
+ * @brief Dump input bitstream to file.
+ *
+ * @param[in] p_buffer: Pointer to input bitstream buffer.
+ * @param[in] filled_length: Bitstream buffer's filled length.
+ */
+void omx_swvdec_diag::dump_ip(unsigned char *p_buffer,
+ unsigned int filled_length)
+{
+ if (m_dump_ip)
+ {
+ fwrite(p_buffer, sizeof(unsigned char), filled_length, m_file_ip);
+ }
+}
+
+/**
+ * @brief Dump output YUV to file.
+ *
+ * @param[in] p_buffer: Pointer to output YUV buffer.
+ * @param[in] width: Frame width.
+ * @param[in] height: Frame height.
+ * @param[in] stride: Frame stride.
+ * @param[in] scanlines: Frame scanlines.
+ */
+void omx_swvdec_diag::dump_op(unsigned char *p_buffer,
+ unsigned int width,
+ unsigned int height,
+ unsigned int stride,
+ unsigned int scanlines)
+{
+ if (m_dump_op)
+ {
+ unsigned char *p_buffer_y;
+ unsigned char *p_buffer_uv;
+
+ unsigned int ii;
+
+ p_buffer_y = p_buffer;
+ p_buffer_uv = p_buffer + (stride * scanlines);
+
+ for (ii = 0; ii < height; ii++)
+ {
+ fwrite(p_buffer_y, sizeof(unsigned char), width, m_file_op);
+
+ p_buffer_y += stride;
+ }
+
+ for (ii = 0; ii < (height / 2); ii++)
+ {
+ fwrite(p_buffer_uv, sizeof(unsigned char), width, m_file_op);
+
+ p_buffer_uv += stride;
+ }
+ }
+}