summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm-core/inc/OMX_QCOMExtns.h14
-rw-r--r--mm-core/inc/QOMX_AudioExtensions.h4
-rw-r--r--mm-core/src/8937/registry_table.c32
-rwxr-xr-x[-rw-r--r--]mm-core/src/8937/registry_table_android.c32
-rw-r--r--mm-video-v4l2/vidc/common/Android.mk3
-rw-r--r--mm-video-v4l2/vidc/vdec/Android.mk28
-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/inc/omx_vdec.h20
-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
-rw-r--r--mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp340
-rw-r--r--mm-video-v4l2/vidc/venc/inc/omx_video_base.h6
-rw-r--r--mm-video-v4l2/vidc/venc/inc/omx_video_common.h4
-rw-r--r--mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h2
-rw-r--r--mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h6
-rw-r--r--mm-video-v4l2/vidc/venc/src/omx_video_base.cpp68
-rw-r--r--mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp33
-rw-r--r--mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp146
19 files changed, 7558 insertions, 114 deletions
diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h
index 38e7f5e9..efe8cf48 100644
--- a/mm-core/inc/OMX_QCOMExtns.h
+++ b/mm-core/inc/OMX_QCOMExtns.h
@@ -1764,6 +1764,7 @@ typedef enum QOMX_VPP_HQVCONTROLTYPE {
VPP_HQV_CONTROL_CADE = 0x1,
VPP_HQV_CONTROL_CNR = 0x04,
VPP_HQV_CONTROL_AIE = 0x05,
+ VPP_HQV_CONTROL_FRC = 0x06,
VPP_HQV_CONTROL_CUST = 0x07,
VPP_HQV_CONTROL_GLOBAL_DEMO = VPP_HQV_CONTROL_GLOBAL_START,
VPP_HQV_CONTROL_MAX,
@@ -1775,6 +1776,15 @@ typedef enum QOMX_VPP_HQV_HUE_MODE {
VPP_HQV_HUE_MODE_MAX,
} QOMX_VPP_HQV_HUE_MODE;
+typedef enum QOMX_VPP_HQV_FRC_MODE {
+ VPP_HQV_FRC_MODE_OFF,
+ VPP_HQV_FRC_MODE_LOW,
+ VPP_HQV_FRC_MODE_MED,
+ VPP_HQV_FRC_MODE_HIGH,
+ VPP_HQV_FRC_MODE_MAX,
+} QOMX_VPP_HQV_FRC_MODE;
+
+
typedef struct QOMX_VPP_HQVCTRL_CADE {
QOMX_VPP_HQV_MODE mode;
OMX_U32 level;
@@ -1804,6 +1814,9 @@ typedef struct QOMX_VPP_HQVCTRL_GLOBAL_DEMO {
OMX_U32 process_percent;
} QOMX_VPP_HQVCTRL_GLOBAL_DEMO;
+typedef struct QOMX_VPP_HQVCTRL_FRC {
+ QOMX_VPP_HQV_FRC_MODE mode;
+} QOMX_VPP_HQVCTRL_FRC;
typedef struct QOMX_VPP_HQVCONTROL {
QOMX_VPP_HQV_MODE mode;
@@ -1814,6 +1827,7 @@ typedef struct QOMX_VPP_HQVCONTROL {
QOMX_VPP_HQVCTRL_AIE aie;
QOMX_VPP_HQVCTRL_CUSTOM custom;
QOMX_VPP_HQVCTRL_GLOBAL_DEMO global_demo;
+ QOMX_VPP_HQVCTRL_FRC frc;
};
} QOMX_VPP_HQVCONTROL;
diff --git a/mm-core/inc/QOMX_AudioExtensions.h b/mm-core/inc/QOMX_AudioExtensions.h
index 1603e1aa..17fa59c0 100644
--- a/mm-core/inc/QOMX_AudioExtensions.h
+++ b/mm-core/inc/QOMX_AudioExtensions.h
@@ -515,6 +515,7 @@ typedef struct QOMX_AUDIO_PARAM_ALACTYPE {
OMX_U32 nSize; /* Size of the structure in bytes */
OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
OMX_U32 nPortIndex; /* Port that this structure applies to */
+ OMX_BOOL bBytesStreamMode; /*enable byte stream mode*/
OMX_U32 nFrameLength; /* Frames per packet when no explicit frames per packet setting is present in the packet header */
OMX_U8 nCompatibleVersion; /* Indicates the compatible version */
OMX_U8 nBitDepth; /* Bit depth of the source PCM data */
@@ -533,6 +534,7 @@ typedef struct QOMX_AUDIO_PARAM_APETYPE {
OMX_U32 nSize; /* Size of the structure in bytes */
OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
OMX_U32 nPortIndex; /* Port that this structure applies to */
+ OMX_BOOL bBytesStreamMode; /*enable byte stream mode*/
OMX_U16 nCompatibleVersion; /* Indicates the compatible version */
OMX_U16 nCompressionLevel; /* The compression level present in the encoded packet */
OMX_U32 nFormatFlags; /* Reserved parameter for future use */
@@ -571,6 +573,7 @@ enum {
kKeyIndexAlacAvgBitRate = 16,
kKeyIndexAlacSamplingRate = 20,
kKeyIndexAlacChannelLayoutTag = 24,
+ kKeyIndexAlacMax = kKeyIndexAlacChannelLayoutTag,
};
enum {
@@ -584,6 +587,7 @@ enum {
kKeyIndexApeNumChannels = 22,
kKeyIndexApeSampleRate = 24,
kKeyIndexApeSeekTablePresent = 28,
+ kKeyIndexApeMax = kKeyIndexApeSeekTablePresent,
};
enum {
diff --git a/mm-core/src/8937/registry_table.c b/mm-core/src/8937/registry_table.c
index 5d04681e..2fde23aa 100644
--- a/mm-core/src/8937/registry_table.c
+++ b/mm-core/src/8937/registry_table.c
@@ -279,6 +279,22 @@ omx_core_cb_type core[] =
}
},
{
+ "OMX.qti.audio.decoder.alac.sw",
+ NULL, // Create instance function
+ // Unique instance handle
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ NULL, // Shared object library handle
+ "libOmxAlacDecSw.so",
+ {
+ "audio_decoder.alac"
+ }
+ },
+ {
"OMX.qcom.audio.decoder.ape",
NULL, // Create instance function
// Unique instance handle
@@ -295,6 +311,22 @@ omx_core_cb_type core[] =
}
},
{
+ "OMX.qti.audio.decoder.ape.sw",
+ NULL, // Create instance function
+ // Unique instance handle
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ NULL, // Shared object library handle
+ "libOmxApeDecSw.so",
+ {
+ "audio_decoder.ape"
+ }
+ },
+ {
"OMX.qcom.audio.encoder.aac",
NULL, // Create instance function
// Unique instance handle
diff --git a/mm-core/src/8937/registry_table_android.c b/mm-core/src/8937/registry_table_android.c
index f1285220..7da8fecc 100644..100755
--- a/mm-core/src/8937/registry_table_android.c
+++ b/mm-core/src/8937/registry_table_android.c
@@ -312,6 +312,22 @@ omx_core_cb_type core[] =
}
},
{
+ "OMX.qti.audio.decoder.alac.sw",
+ NULL, // Create instance function
+ // Unique instance handle
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ NULL, // Shared object library handle
+ "libOmxAlacDecSw.so",
+ {
+ "audio_decoder.alac"
+ }
+ },
+ {
"OMX.qcom.audio.decoder.ape",
NULL, // Create instance function
// Unique instance handle
@@ -328,6 +344,22 @@ omx_core_cb_type core[] =
}
},
{
+ "OMX.qti.audio.decoder.ape.sw",
+ NULL, // Create instance function
+ // Unique instance handle
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ NULL, // Shared object library handle
+ "libOmxApeDecSw.so",
+ {
+ "audio_decoder.ape"
+ }
+ },
+ {
"OMX.qcom.audio.encoder.aac",
NULL, // Create instance function
// Unique instance handle
diff --git a/mm-video-v4l2/vidc/common/Android.mk b/mm-video-v4l2/vidc/common/Android.mk
index 2453f0d4..9f2adc06 100644
--- a/mm-video-v4l2/vidc/common/Android.mk
+++ b/mm-video-v4l2/vidc/common/Android.mk
@@ -31,6 +31,7 @@ LOCAL_MODULE := libOmxVidcCommon
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := $(libmm-vidc-def)
LOCAL_C_INCLUDES := $(libmm-vidc-inc)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_PRELINK_MODULE := false
LOCAL_SHARED_LIBRARIES := liblog libutils libcutils libdl
@@ -38,6 +39,8 @@ LOCAL_SHARED_LIBRARIES := liblog libutils libcutils libdl
LOCAL_SRC_FILES := src/extra_data_handler.cpp
LOCAL_SRC_FILES += src/vidc_color_converter.cpp
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
include $(BUILD_STATIC_LIBRARY)
# ---------------------------------------------------------------------------------
diff --git a/mm-video-v4l2/vidc/vdec/Android.mk b/mm-video-v4l2/vidc/vdec/Android.mk
index 0d27319f..1b9e9ddc 100644
--- a/mm-video-v4l2/vidc/vdec/Android.mk
+++ b/mm-video-v4l2/vidc/vdec/Android.mk
@@ -30,7 +30,8 @@ TARGETS_THAT_USE_HEVC_ADSP_HEAP := msm8226 msm8974
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_SUPPORT_UBWC := msm8996 titanium
+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/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index a17624bb..a0305454 100644
--- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -455,9 +455,11 @@ class omx_vdec: public qc_omx_component
void buf_ref_add(int nPortIndex);
void buf_ref_remove();
OMX_ERRORTYPE set_dpb(bool is_split_mode, int dpb_color_format);
- OMX_ERRORTYPE decide_dpb_buffer_mode();
+ OMX_ERRORTYPE decide_dpb_buffer_mode(bool force_split_mode);
void request_perf_level(enum vidc_perf_level perf_level);
int dpb_bit_depth;
+ bool async_thread_force_stop;
+ volatile bool message_thread_stop;
private:
// Bit Positions
@@ -523,6 +525,7 @@ class omx_vdec: public qc_omx_component
OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED = 0x16,
OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING = 0x17,
OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD = 0x18,
+ OMX_COMPONENT_CLOSE_MSG = 0x19
};
enum vc1_profile_type {
@@ -777,7 +780,6 @@ class omx_vdec: public qc_omx_component
nativebuffer native_buffer[MAX_NUM_INPUT_OUTPUT_BUFFERS];
#endif
-
//*************************************************************
//*******************MEMBER VARIABLES *************************
//*************************************************************
@@ -951,6 +953,7 @@ class omx_vdec: public qc_omx_component
OMX_CONFIG_RECTTYPE rectangle;
OMX_U32 prev_n_filled_len;
bool is_down_scalar_enabled;
+ bool m_force_down_scalar;
#endif
struct custom_buffersize {
OMX_U32 input_buffersize;
@@ -980,6 +983,11 @@ class omx_vdec: public qc_omx_component
OMX_ERRORTYPE enable_adaptive_playback(unsigned long width, unsigned long height);
bool is_thulium_v1;
static bool m_disable_ubwc_mode;
+ OMX_U32 m_downscalar_width;
+ OMX_U32 m_downscalar_height;
+ int decide_downscalar();
+ int enable_downscalar();
+ int disable_downscalar();
unsigned int m_fill_output_msg;
bool client_set_fps;
@@ -1125,8 +1133,8 @@ class omx_vdec: public qc_omx_component
OMX_COLOR_FORMATTYPE formatsDefault[] = {
[0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed,
[1] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
- [2] = OMX_COLOR_FormatYUV420Planar,
- [3] = OMX_COLOR_FormatYUV420SemiPlanar,
+ [2] = OMX_COLOR_FormatYUV420SemiPlanar,
+ [3] = OMX_COLOR_FormatYUV420Planar,
[4] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView,
};
format = (index < sizeof(formatsDefault) / sizeof(OMX_COLOR_FORMATTYPE)) ?
@@ -1134,8 +1142,8 @@ class omx_vdec: public qc_omx_component
} else {
OMX_COLOR_FORMATTYPE formatsDefault[] = {
[0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
- [1] = OMX_COLOR_FormatYUV420Planar,
- [2] = OMX_COLOR_FormatYUV420SemiPlanar,
+ [1] = OMX_COLOR_FormatYUV420SemiPlanar,
+ [2] = OMX_COLOR_FormatYUV420Planar,
[3] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView,
};
format = (index < sizeof(formatsDefault) / sizeof(OMX_COLOR_FORMATTYPE)) ?
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;
+ }
+ }
+}
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
index 5b79be67..b33a7651 100644
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
@@ -167,13 +167,13 @@ void* async_message_thread (void *input)
int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
- while (1) {
+ while (!omx->async_thread_force_stop) {
rc = poll(pfds, 2, POLL_TIMEOUT);
if (!rc) {
DEBUG_PRINT_ERROR("Poll timedout");
break;
- } else if (rc < 0) {
- DEBUG_PRINT_ERROR("Error while polling: %d", rc);
+ } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
+ DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
break;
}
if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
@@ -337,9 +337,27 @@ void* message_thread(void *input)
unsigned char id;
int n;
+ fd_set readFds;
+ int res = 0;
+ struct timeval tv;
+
DEBUG_PRINT_HIGH("omx_vdec: message thread start");
prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
- while (1) {
+ while (!omx->message_thread_stop) {
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&readFds);
+ FD_SET(omx->m_pipe_in, &readFds);
+
+ res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
+ if (res < 0) {
+ DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
+ continue;
+ } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
+ continue;
+ }
n = read(omx->m_pipe_in, &id, 1);
@@ -350,6 +368,7 @@ void* message_thread(void *input)
if (1 == n) {
omx->process_event_cb(omx, id);
}
+
if ((n < 0) && (errno != EINTR)) {
DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
break;
@@ -364,7 +383,11 @@ void post_message(omx_vdec *omx, unsigned char id)
int ret_value;
DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out);
ret_value = write(omx->m_pipe_out, &id, 1);
- DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
+ if (ret_value <= 0) {
+ DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
+ } else {
+ DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
+ }
}
// omx_cmd_queue destructor
@@ -724,6 +747,8 @@ omx_vdec::omx_vdec(): m_error_propogated(false),
async_thread_id = 0;
msg_thread_created = false;
async_thread_created = false;
+ async_thread_force_stop = false;
+ message_thread_stop = false;
#ifdef _ANDROID_ICS_
memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
#endif
@@ -752,6 +777,9 @@ omx_vdec::omx_vdec(): m_error_propogated(false),
dynamic_buf_mode = false;
out_dynamic_list = NULL;
is_down_scalar_enabled = false;
+ m_downscalar_width = 0;
+ m_downscalar_height = 0;
+ m_force_down_scalar = 0;
m_reconfig_height = 0;
m_reconfig_width = 0;
m_smoothstreaming_mode = false;
@@ -848,16 +876,25 @@ omx_vdec::~omx_vdec()
{
m_pmem_info = NULL;
DEBUG_PRINT_HIGH("In OMX vdec Destructor");
+ if (msg_thread_created) {
+ DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
+ message_thread_stop = true;
+ post_message(this, OMX_COMPONENT_CLOSE_MSG);
+ DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
+ pthread_join(msg_thread_id,NULL);
+ }
close(m_pipe_in);
close(m_pipe_out);
- DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
- if (msg_thread_created)
- pthread_join(msg_thread_id,NULL);
+ m_pipe_in = -1;
+ m_pipe_out = -1;
DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
- if(!eventfd_write(m_poll_efd, 1)) {
- if (async_thread_created)
- pthread_join(async_thread_id,NULL);
+ if(eventfd_write(m_poll_efd, 1)) {
+ DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
+ async_thread_force_stop = true;
}
+
+ if (async_thread_created)
+ pthread_join(async_thread_id,NULL);
unsubscribe_to_events(drv_ctx.video_driver_fd);
close(m_poll_efd);
close(drv_ctx.video_driver_fd);
@@ -929,7 +966,7 @@ OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
}
-OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode()
+OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
@@ -942,14 +979,18 @@ OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode()
if (cpu_access) {
if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
- if (m_force_compressed_for_dpb || is_res_above_1080p) {
+ if ((m_force_compressed_for_dpb || is_res_above_1080p) &&
+ !force_split_mode) {
//split DPB-OPB
//DPB -> UBWC , OPB -> Linear
eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
+ } else if (force_split_mode) {
+ //DPB -> Linear, OPB -> Linear
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
} else {
- //DPB-OPB combined linear
- eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
- }
+ //DPB-OPB combined linear
+ eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
+ }
} else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
//split DPB-OPB
//DPB -> UBWC, OPB -> Linear
@@ -957,8 +998,14 @@ OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode()
}
} else { //no cpu access
if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
- //DPB-OPB combined UBWC
- eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
+ if (force_split_mode) {
+ //split DPB-OPB
+ //DPB -> UBWC, OPB -> UBWC
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
+ } else {
+ //DPB-OPB combined UBWC
+ eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
+ }
} else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
//split DPB-OPB
//DPB -> UBWC, OPB -> UBWC
@@ -971,6 +1018,155 @@ OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode()
return eRet;
}
+int omx_vdec::enable_downscalar()
+{
+ int rc = 0;
+ struct v4l2_control control;
+ struct v4l2_format fmt;
+
+ if (is_down_scalar_enabled) {
+ DEBUG_PRINT_LOW("%s: already enabled", __func__);
+ return 0;
+ }
+
+ DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
+ rc = decide_dpb_buffer_mode(true);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
+ return rc;
+ }
+ is_down_scalar_enabled = true;
+
+ memset(&control, 0x0, sizeof(struct v4l2_control));
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
+ control.value = 1;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
+ return rc;
+ }
+
+ return 0;
+}
+
+int omx_vdec::disable_downscalar()
+{
+ int rc = 0;
+ struct v4l2_control control;
+
+ if (!is_down_scalar_enabled) {
+ DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
+ return 0;
+ }
+
+ rc = decide_dpb_buffer_mode(false);
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
+ return rc;
+ }
+ is_down_scalar_enabled = false;
+
+ return rc;
+}
+
+int omx_vdec::decide_downscalar()
+{
+ int rc = 0;
+ struct v4l2_format fmt;
+ enum color_fmts color_format;
+
+ if (!m_downscalar_width || !m_downscalar_height) {
+ DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
+ return 0;
+ }
+
+ if (m_force_down_scalar) {
+ DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
+ return 0;
+ }
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
+ return rc;
+ }
+
+ DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d", __func__,
+ fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height);
+
+ if (fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) {
+ rc = enable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
+ return rc;
+ }
+
+ OMX_U32 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
+ fmt.fmt.pix_mp.width : m_downscalar_width;
+ OMX_U32 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
+ fmt.fmt.pix_mp.height : m_downscalar_height;
+ switch (capture_capability) {
+ case V4L2_PIX_FMT_NV12:
+ color_format = COLOR_FMT_NV12;
+ break;
+ case V4L2_PIX_FMT_NV12_UBWC:
+ color_format = COLOR_FMT_NV12_UBWC;
+ break;
+ case V4L2_PIX_FMT_NV12_TP10_UBWC:
+ color_format = COLOR_FMT_NV12_BPP10_UBWC;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("Color format not recognized\n");
+ rc = OMX_ErrorUndefined;
+ return rc;
+ }
+
+ rc = update_resolution(width, height,
+ VENUS_Y_STRIDE(color_format, width), VENUS_Y_SCANLINES(color_format, height));
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed \n", __func__, width, height);
+ return rc;
+ }
+ } else {
+
+ rc = disable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
+ return rc;
+ }
+
+ rc = update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
+ fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: update_resolution WxH %dx%d failed\n", __func__, fmt.fmt.pix_mp.width,
+ fmt.fmt.pix_mp.height);
+ return rc;
+ }
+ }
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
+ return rc;
+ }
+
+ rc = get_buffer_req(&drv_ctx.op_buf);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
+ return rc;
+ }
+
+ return rc;
+}
+
/* ======================================================================
FUNCTION
omx_vdec::OMXCntrlProcessMsgCb
@@ -2238,6 +2434,25 @@ OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
drv_ctx.idr_only_decoding = 0;
+#ifdef _ANDROID_
+ property_get("vidc.dec.downscalar_width",property_value,"0");
+ if (atoi(property_value)) {
+ m_downscalar_width = atoi(property_value);
+ }
+ property_get("vidc.dec.downscalar_height",property_value,"0");
+ if (atoi(property_value)) {
+ m_downscalar_height = atoi(property_value);
+ }
+
+ if (m_downscalar_width < m_decoder_capability.min_width ||
+ m_downscalar_height < m_decoder_capability.min_height) {
+ m_downscalar_width = 0;
+ m_downscalar_height = 0;
+ }
+
+ DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
+ m_downscalar_width, m_downscalar_height);
+#endif
m_state = OMX_StateLoaded;
#ifdef DEFAULT_EXTRADATA
if ((strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",
@@ -2778,6 +2993,11 @@ OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
// Skip the event notification
bFlag = 0;
+ /* enable/disable downscaling if required */
+ ret = decide_downscalar();
+ if (ret) {
+ DEBUG_PRINT_LOW("decide_downscalar failed\n");
+ }
}
}
} else if (cmd == OMX_CommandPortDisable) {
@@ -3218,7 +3438,7 @@ OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
(OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
- decide_dpb_buffer_mode();
+ decide_dpb_buffer_mode(is_down_scalar_enabled);
eRet = update_portdef(portDefn);
if (eRet == OMX_ErrorNone)
m_port_def = *portDefn;
@@ -3657,7 +3877,7 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
/* update output port resolution with client supplied dimensions
in case scaling is enabled, else it follows input resolution set
*/
- decide_dpb_buffer_mode();
+ decide_dpb_buffer_mode(is_down_scalar_enabled);
if (is_down_scalar_enabled) {
DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
(unsigned int)portDefn->format.video.nFrameWidth,
@@ -4385,25 +4605,22 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
struct v4l2_control control;
int rc;
- if (pParam) {
- is_down_scalar_enabled = pParam->bEnable;
- if (is_down_scalar_enabled) {
- control.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
- control.value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
- DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar value = %d", pParam->bEnable);
- rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
- if (rc < 0) {
- DEBUG_PRINT_ERROR("Failed to set down scalar on driver.");
- eRet = OMX_ErrorUnsupportedSetting;
- }
- control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
- control.value = 1;
- rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
- if (rc < 0) {
- DEBUG_PRINT_ERROR("Failed to set keep aspect ratio on driver.");
- eRet = OMX_ErrorUnsupportedSetting;
- }
+ DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
+
+ if (pParam && pParam->bEnable) {
+ rc = enable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_force_down_scalar = pParam->bEnable;
+ } else {
+ rc = disable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
+ return OMX_ErrorUnsupportedSetting;
}
+ m_force_down_scalar = pParam->bEnable;
}
break;
}
@@ -4650,6 +4867,12 @@ OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
struct v4l2_control control;
+ if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
+ DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
+ eRet = OMX_ErrorNotImplemented;
+ break;
+ }
+
control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
coding->bCabac = (OMX_BOOL)
@@ -4941,6 +5164,8 @@ OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
if (ret)
DEBUG_PRINT_ERROR("Failed to set picture type decode");
+
+ return ret;
} else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
@@ -8090,13 +8315,37 @@ int omx_vdec::async_message_process (void *context, void* message)
if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
!(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
!(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
+ unsigned int index = v4l2_buf_ptr->index;
+ unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
+ struct v4l2_plane *plane = v4l2_buf_ptr->m.planes;
omx->time_stamp_dts.remove_time_stamp(
omxhdr->nTimeStamp,
(omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
?true:false);
+ plane[0].bytesused = 0;
+ plane[0].m.userptr =
+ (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
+ (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
+ plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
+ plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
+ plane[0].data_offset = 0;
v4l2_buf_ptr->flags = 0x0;
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ plane[extra_idx].bytesused = 0;
+ plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
+#ifdef USE_ION
+ plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
+#endif
+ plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].data_offset = 0;
+ } else if (extra_idx >= VIDEO_MAX_PLANES) {
+ DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
+ return -1;
+ }
+
if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
- DEBUG_PRINT_ERROR("Failed to queue buffer back to driver");
+ DEBUG_PRINT_ERROR("Failed to queue buffer back to driver: %d, %d, %d", v4l2_buf_ptr->length, v4l2_buf_ptr->m.planes[0].reserved[0], v4l2_buf_ptr->m.planes[1].reserved[0]);
return -1;
}
break;
@@ -8947,8 +9196,14 @@ int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
}
alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
- if (secure_mode && (alloc_data->flags & ION_SECURE))
+ if (secure_mode && (alloc_data->flags & ION_SECURE)) {
alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
+ }
+
+ /* Use secure display cma heap for obvious reasons. */
+ if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
+ alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
+ }
rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
if (rc || !alloc_data->handle) {
@@ -9882,6 +10137,7 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
struct msm_vidc_vqzip_sei_payload *vqzip_payload;
vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
+ p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
append_vqzip_extradata(p_extra, vqzip_payload);
p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
}
@@ -10017,6 +10273,10 @@ OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
}
}
if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
+ if (secure_mode) {
+ DEBUG_PRINT_HIGH("ExtnUser Extra Data not supported for secure sessions");
+ return OMX_ErrorUnsupportedSetting;
+ }
control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
index 2864ba5c..eb403090 100644
--- a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
+++ b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
@@ -234,7 +234,7 @@ class omx_video: public qc_omx_component
virtual bool dev_loaded_stop_done(void) = 0;
virtual bool is_secure_session(void) = 0;
virtual int dev_handle_output_extradata(void*) = 0;
- virtual int dev_handle_input_extradata(void*) = 0;
+ virtual int dev_handle_input_extradata(void*, int) = 0;
virtual void dev_set_extradata_cookie(void*) = 0;
virtual int dev_set_format(int) = 0;
virtual bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height) = 0;
@@ -355,6 +355,7 @@ class omx_video: public qc_omx_component
pthread_t async_thread_id;
bool async_thread_created;
bool msg_thread_created;
+ volatile bool msg_thread_stop;
OMX_U8 m_nkind[128];
@@ -430,7 +431,8 @@ class omx_video: public qc_omx_component
OMX_COMPONENT_GENERATE_LTRUSE_FAILED = 0x12,
OMX_COMPONENT_GENERATE_ETB_OPQ = 0x13,
OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING = 0x14,
- OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD = 0x15
+ OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD = 0x15,
+ OMX_COMPONENT_CLOSE_MSG = 0x16
};
struct omx_event {
diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_common.h b/mm-video-v4l2/vidc/venc/inc/omx_video_common.h
index 50e85e2c..58f14fa0 100644
--- a/mm-video-v4l2/vidc/venc/inc/omx_video_common.h
+++ b/mm-video-v4l2/vidc/venc/inc/omx_video_common.h
@@ -64,6 +64,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define OMX_CORE_720P_HEIGHT 720
#define OMX_CORE_1080P_WIDTH 1920
#define OMX_CORE_1080P_HEIGHT 1080
+#define OMX_CORE_4KUHD_WIDTH 3840
+#define OMX_CORE_4KUHD_HEIGHT 2160
+#define OMX_CORE_4KDCI_WIDTH 4096
+#define OMX_CORE_4KDCI_HEIGHT 2160
enum PortIndexType {
PORT_INDEX_IN = 0,
diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h
index a6b58a8b..8ccd6785 100644
--- a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h
+++ b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h
@@ -60,7 +60,7 @@ class omx_venc: public omx_video
OMX_U32 m_nVenc_format;
class venc_dev *handle;
int dev_handle_output_extradata(void *);
- int dev_handle_input_extradata(void *);
+ int dev_handle_input_extradata(void *, int);
void dev_set_extradata_cookie(void *);
int dev_set_format(int);
private:
diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
index 65384bc4..0d5ef09f 100644
--- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
+++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
@@ -282,6 +282,7 @@ public:
void setCookieForConfig(void *cookie);
ssize_t getBufferSize();
unsigned int getBufferCount();
+ bool vqzip_sei_found;
};
struct statistics {
@@ -400,10 +401,11 @@ class venc_dev
bool m_max_allowed_bitrate_check;
pthread_t m_tid;
bool async_thread_created;
+ bool async_thread_force_stop;
class omx_venc *venc_handle;
int append_mbi_extradata(void *, struct msm_vidc_extradata_header*);
bool handle_output_extradata(void *);
- bool handle_input_extradata(void *);
+ bool handle_input_extradata(void *, int);
int venc_set_format(int);
bool deinterlace_enabled;
bool hw_overload;
@@ -491,7 +493,7 @@ class venc_dev
bool venc_set_hybrid_hierp(QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* hhp);
bool venc_set_batch_size(OMX_U32 size);
bool venc_calibrate_gop();
- void venc_set_vqzip_defaults();
+ bool venc_set_vqzip_defaults();
bool venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode);
bool venc_set_max_hierp(OMX_U32 hierp_layers);
bool venc_set_baselayerid(OMX_U32 baseid);
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
index fa1ada42..fc189127 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -128,9 +128,28 @@ void* message_thread(void *input)
unsigned char id;
int n;
- DEBUG_PRINT_LOW("omx_venc: message thread start");
+ fd_set readFds;
+ int res = 0;
+ struct timeval tv;
+
+ DEBUG_PRINT_HIGH("omx_venc: message thread start");
prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0);
- while (1) {
+ while (!omx->msg_thread_stop) {
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&readFds);
+ FD_SET(omx->m_pipe_in, &readFds);
+
+ res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
+ if (res < 0) {
+ DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
+ continue;
+ } else if (res == 0 /*timeout*/ || omx->msg_thread_stop) {
+ continue;
+ }
+
n = read(omx->m_pipe_in, &id, 1);
if (0 == n) {
break;
@@ -142,17 +161,26 @@ void* message_thread(void *input)
#ifdef QLE_BUILD
if (n < 0) break;
#else
- if ((n < 0) && (errno != EINTR)) break;
+ if ((n < 0) && (errno != EINTR)) {
+ DEBUG_PRINT_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
+ break;
+ }
#endif
}
- DEBUG_PRINT_LOW("omx_venc: message thread stop");
+ DEBUG_PRINT_HIGH("omx_venc: message thread stop");
return 0;
}
void post_message(omx_video *omx, unsigned char id)
{
DEBUG_PRINT_LOW("omx_venc: post_message %d", id);
- write(omx->m_pipe_out, &id, 1);
+ int ret_value;
+ ret_value = write(omx->m_pipe_out, &id, 1);
+ if (ret_value <= 0) {
+ DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
+ } else {
+ DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value);
+ }
}
// omx_cmd_queue destructor
@@ -271,13 +299,15 @@ omx_video::omx_video():
m_etb_count(0),
m_fbd_count(0),
m_event_port_settings_sent(false),
- hw_overload(false)
+ hw_overload(false),
+ m_graphicBufferSize(0)
{
DEBUG_PRINT_HIGH("omx_video(): Inside Constructor()");
memset(&m_cmp,0,sizeof(m_cmp));
memset(&m_pCallbacks,0,sizeof(m_pCallbacks));
async_thread_created = false;
msg_thread_created = false;
+ msg_thread_stop = false;
mUsesColorConversion = false;
pthread_mutex_init(&m_lock, NULL);
@@ -302,11 +332,16 @@ omx_video::omx_video():
omx_video::~omx_video()
{
DEBUG_PRINT_HIGH("~omx_video(): Inside Destructor()");
+ if (msg_thread_created) {
+ msg_thread_stop = true;
+ post_message(this, OMX_COMPONENT_CLOSE_MSG);
+ DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
+ pthread_join(msg_thread_id,NULL);
+ }
close(m_pipe_in);
close(m_pipe_out);
- DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
- if (msg_thread_created)
- pthread_join(msg_thread_id,NULL);
+ m_pipe_in = -1;
+ m_pipe_out = -1;
DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit");
/*For V4L2 based drivers, pthread_join is done in device_close
* so no need to do it here*/
@@ -3699,8 +3734,16 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
return OMX_ErrorUndefined;
}
}
- if (m_sExtraData && !dev_handle_input_extradata((void *)buffer))
+ if (m_sExtraData && !dev_handle_input_extradata((void *)buffer, fd)) {
DEBUG_PRINT_ERROR("Failed to parse input extradata\n");
+#ifdef _ANDROID_ICS_
+ omx_release_meta_buffer(buffer);
+#endif
+ post_event ((unsigned long)buffer,0,OMX_COMPONENT_GENERATE_EBD);
+ /*Generate an async error and move to invalid state*/
+ pending_input_buffers--;
+ return OMX_ErrorBadParameter;
+ }
#ifdef _MSM8974_
if (dev_empty_buf(buffer, pmem_data_buf,nBufIndex,fd) != true)
#else
@@ -4524,6 +4567,9 @@ int omx_video::alloc_map_ion_memory(int size,
alloc_data->align = SECURE_ALIGN;
alloc_data->flags = flag;
alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
+ if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
+ alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
+ }
DEBUG_PRINT_HIGH("ION ALLOC sec buf: size %u align %u flags %x",
(unsigned int)alloc_data->len, (unsigned int)alloc_data->align,
alloc_data->flags);
@@ -5099,7 +5145,7 @@ OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp,
if (!mUsesColorConversion && !mUseProxyColorFormat)
emptyEosBufHdr.nAllocLen = m_sInPortDef.nBufferSize;
else if (mUseProxyColorFormat)
- emptyEosBufHdr.nAllocLen = m_graphicBufferSize;
+ emptyEosBufHdr.nAllocLen = m_graphicBufferSize > 0 ? m_graphicBufferSize : m_sInPortDef.nBufferSize;
if (dev_empty_buf(&emptyEosBufHdr, 0, index, m_pInput_pmem[index].fd) != true) {
DEBUG_PRINT_ERROR("ERROR: in dev_empty_buf for empty eos buffer");
dev_free_buf(&Input_pmem_info, PORT_INDEX_IN);
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
index 677c5804..3868326c 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -485,7 +485,6 @@ OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role)
m_sParamAVC.nPFrames = (m_sOutPortFormat.xFramerate * 2 - 1); // 2 second intra period for default outport fps
m_sParamAVC.nBFrames = 0;
m_sParamAVC.bUseHadamard = OMX_FALSE;
- m_sParamAVC.nRefFrames = 1;
m_sParamAVC.nRefIdx10ActiveMinus1 = 1;
m_sParamAVC.nRefIdx11ActiveMinus1 = 0;
m_sParamAVC.bEnableUEP = OMX_FALSE;
@@ -852,31 +851,31 @@ OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
memcpy(&avc_param, pParam, sizeof( struct OMX_VIDEO_PARAM_AVCTYPE));
DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc");
+ avc_param.nBFrames = 0;
if ((pParam->eProfile == OMX_VIDEO_AVCProfileHigh)||
(pParam->eProfile == OMX_VIDEO_AVCProfileMain)) {
-#ifdef _MSM8974_
- if ((pParam->nBFrames && (pParam->nBFrames <= 4))|| (bframes && (bframes <=4))) {
- avc_param.nBFrames = (pParam->nBFrames > (unsigned int) bframes)? pParam->nBFrames : bframes;
- avc_param.nRefFrames = (avc_param.nBFrames < 4)? avc_param.nBFrames + 1 : 4;
- } else {
- avc_param.nBFrames = 0;
- avc_param.nRefFrames = 1;
+
+ if (pParam->nBFrames) {
+ avc_param.nBFrames = pParam->nBFrames;
+ DEBUG_PRINT_LOW("B frames set using Client setparam to %d",
+ avc_param.nBFrames);
}
- DEBUG_PRINT_HIGH("AVC: RefFrames: %u, BFrames: %u", (unsigned int)avc_param.nRefFrames, (unsigned int)avc_param.nBFrames);
+ if (bframes ) {
+ avc_param.nBFrames = bframes;
+ DEBUG_PRINT_LOW("B frames set using setprop to %d",
+ avc_param.nBFrames);
+ }
+
+ DEBUG_PRINT_HIGH("AVC: BFrames: %u", (unsigned int)avc_param.nBFrames);
avc_param.bEntropyCodingCABAC = (OMX_BOOL)(avc_param.bEntropyCodingCABAC && entropy);
avc_param.nCabacInitIdc = entropy ? avc_param.nCabacInitIdc : 0;
-#endif
} else {
- if (pParam->nRefFrames != 1) {
- DEBUG_PRINT_ERROR("Warning: Only 1 RefFrame is supported, changing RefFrame from %u to 1)", (unsigned int)pParam->nRefFrames);
- avc_param.nRefFrames = 1;
- }
if (pParam->nBFrames) {
DEBUG_PRINT_ERROR("Warning: B frames not supported");
- avc_param.nBFrames = 0;
}
}
+
if (handle->venc_set_param(&avc_param,OMX_IndexParamVideoAvc) != true) {
return OMX_ErrorUnsupportedSetting;
}
@@ -2226,9 +2225,9 @@ int omx_venc::dev_handle_output_extradata(void *buffer)
return handle->handle_output_extradata(buffer);
}
-int omx_venc::dev_handle_input_extradata(void *buffer)
+int omx_venc::dev_handle_input_extradata(void *buffer, int fd)
{
- return handle->handle_input_extradata(buffer);
+ return handle->handle_input_extradata(buffer, fd);
}
void omx_venc::dev_set_extradata_cookie(void *cookie)
diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index a6179cb5..b30422b1 100644
--- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -230,6 +230,7 @@ venc_dev::venc_dev(class omx_venc *venc_class):mInputExtradata(venc_class), mOut
stopped = 1;
paused = false;
async_thread_created = false;
+ async_thread_force_stop = false;
color_format = 0;
hw_overload = false;
mBatchSize = 0;
@@ -321,7 +322,7 @@ void* venc_dev::async_venc_message_thread (void *input)
memset(&stats, 0, sizeof(statistics));
memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- while (1) {
+ while (!omx->handle->async_thread_force_stop) {
pthread_mutex_lock(&omx->handle->pause_resume_mlock);
if (omx->handle->paused) {
@@ -357,8 +358,8 @@ void* venc_dev::async_venc_message_thread (void *input)
DEBUG_PRINT_HIGH("Poll timedout, pipeline stalled due to client/firmware ETB: %d, EBD: %d, FTB: %d, FBD: %d",
omx->handle->etb, omx->handle->ebd, omx->handle->ftb, omx->handle->fbd);
continue;
- } else if (rc < 0) {
- DEBUG_PRINT_ERROR("Error while polling: %d", rc);
+ } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
+ DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
break;
}
@@ -595,7 +596,7 @@ int venc_dev::append_mbi_extradata(void *dst, struct msm_vidc_extradata_header*
return mbi->nDataSize + sizeof(*mbi);
}
-bool venc_dev::handle_input_extradata(void *buffer)
+bool venc_dev::handle_input_extradata(void *buffer, int fd)
{
OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer;
OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
@@ -606,6 +607,21 @@ bool venc_dev::handle_input_extradata(void *buffer)
int extra_fd;
unsigned offset;
ssize_t extra_size;
+ struct v4l2_control control;
+
+ memset(&control, 0, sizeof(control));
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &control) < 0) {
+ return false;
+ }
+
+ if (!(control.value == V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS ||
+ control.value == V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI ||
+ control.value == V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP ||
+ control.value == V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP)) {
+ DEBUG_PRINT_LOW("Input extradata not enabled");
+ return true;
+ }
/*
* At this point encoder component doesn't know where the extradata is
@@ -624,7 +640,7 @@ bool venc_dev::handle_input_extradata(void *buffer)
}
unsigned char *pVirt;
int size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
- pVirt= (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, extra_fd, 0);
+ pVirt= (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
p_extra = (OMX_OTHER_EXTRADATATYPE *) ((unsigned long)(pVirt + ((width * height * 3) / 2) + 3)&(~3));
char *p_extradata = userptr;
@@ -668,10 +684,14 @@ bool venc_dev::handle_input_extradata(void *buffer)
qp_payload = (OMX_QCOM_EXTRADATA_QP *)p_extra->data;
payload = (struct msm_vidc_frame_qp_payload *)(data->data);
payload->frame_qp = qp_payload->nQP;
- DEBUG_PRINT_LOW("FRame QP = %d", payload->frame_qp);
+ DEBUG_PRINT_LOW("Frame QP = %d", payload->frame_qp);
data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
break;
}
+ case OMX_ExtraDataVQZipSEI:
+ DEBUG_PRINT_LOW("VQZIP SEI Found ");
+ mInputExtradata.vqzip_sei_found = true;
+ break;
default:
break;
}
@@ -679,14 +699,22 @@ bool venc_dev::handle_input_extradata(void *buffer)
p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
}
- data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct VQZipStats) + 3)&(~3);
- data->nVersion.nVersion = OMX_SPEC_VERSION;
- data->nPortIndex = 0;
- data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_YUVSTATS_INFO;
- data->nDataSize = sizeof(struct VQZipStats);
- vqzip.fill_stats_data((void*)pVirt, (void*) data->data);
-
- data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+ if (control.value == V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS ||
+ control.value == V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI) {
+ if (!mInputExtradata.vqzip_sei_found) {
+ DEBUG_PRINT_ERROR("VQZIP is enabled, But no VQZIP SEI found. Rejecting the session");
+ munmap(pVirt, size);
+ mInputExtradata.put(userptr);
+ return false;
+ }
+ data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct VQZipStats) + 3)&(~3);
+ data->nVersion.nVersion = OMX_SPEC_VERSION;
+ data->nPortIndex = 0;
+ data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_YUVSTATS_INFO;
+ data->nDataSize = sizeof(struct VQZipStats);
+ vqzip.fill_stats_data((void*)pVirt, (void*) data->data);
+ data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+ }
data->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
data->nVersion.nVersion = OMX_SPEC_VERSION;
@@ -696,6 +724,7 @@ bool venc_dev::handle_input_extradata(void *buffer)
}
munmap(pVirt, size);
+ mInputExtradata.put(userptr);
return true;
}
@@ -1306,11 +1335,14 @@ void venc_dev::venc_close()
if ((int)m_nDriver_fd >= 0) {
DEBUG_PRINT_HIGH("venc_close E");
- if(!eventfd_write(m_poll_efd, 1)) {
- if (async_thread_created)
- pthread_join(m_tid,NULL);
+ if(eventfd_write(m_poll_efd, 1)) {
+ DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
+ async_thread_force_stop = true;
}
+ if (async_thread_created)
+ pthread_join(m_tid,NULL);
+
DEBUG_PRINT_HIGH("venc_close X");
unsubscribe_to_events(m_nDriver_fd);
close(m_poll_efd);
@@ -2636,10 +2668,24 @@ unsigned venc_dev::venc_set_message_thread_id(pthread_t tid)
return 0;
}
-void venc_dev::venc_set_vqzip_defaults()
+bool venc_dev::venc_set_vqzip_defaults()
{
struct v4l2_control control;
- int rc = 0;
+ int rc = 0, num_mbs_per_frame;
+
+ num_mbs_per_frame = m_sVenc_cfg.input_height * m_sVenc_cfg.input_width;
+
+ switch (num_mbs_per_frame) {
+ case OMX_CORE_720P_WIDTH * OMX_CORE_720P_HEIGHT:
+ case OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT:
+ case OMX_CORE_4KUHD_WIDTH * OMX_CORE_4KUHD_HEIGHT:
+ case OMX_CORE_4KDCI_WIDTH * OMX_CORE_4KDCI_HEIGHT:
+ break;
+ default:
+ DEBUG_PRINT_ERROR("VQZIP is not supported for this resoultion : %d X %d",
+ m_sVenc_cfg.input_width, m_sVenc_cfg.input_height);
+ return false;
+ }
control.id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL;
control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF;
@@ -2660,6 +2706,21 @@ void venc_dev::venc_set_vqzip_defaults()
if (rc)
DEBUG_PRINT_ERROR("Failed to set B frame period for VQZIP");
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE;
+ control.value = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY;
+
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc)
+ DEBUG_PRINT_ERROR("Failed to set Max quality for VQZIP");
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
+ control.value = 1;
+
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc)
+ DEBUG_PRINT_ERROR("Failed to set IDR period for VQZIP");
+
+ return true;
}
@@ -2683,8 +2744,8 @@ unsigned venc_dev::venc_start(void)
__func__, codec_profile.profile, profile_level.level);
}
- if (vqzip_sei_info.enabled)
- venc_set_vqzip_defaults();
+ if (vqzip_sei_info.enabled && !venc_set_vqzip_defaults())
+ return 1;
venc_config_print();
@@ -3113,6 +3174,7 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index,
return false;
}
} else if (!color_format) {
+ int usage = 0;
if (meta_buf->buffer_type == kMetadataBufferTypeCameraSource) {
native_handle_t *hnd = (native_handle_t*)meta_buf->meta_handle;
@@ -3121,25 +3183,25 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index,
return false;
}
+ if (!mBatchSize && hnd->numFds + hnd->numInts > 3) {
+ usage = hnd->data[3];
+ } else if (mBatchSize) {
+ usage = BatchInfo::getColorFormatAt(hnd, 0);
+ }
+ if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709) {
+ buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
+ }
+
if (!streaming[OUTPUT_PORT] && !(m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGB32 ||
m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGBA8888_UBWC)) {
- int usage = 0;
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12;
fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height;
fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width;
- if (!mBatchSize && hnd->numFds + hnd->numInts > 3) {
- usage = hnd->data[3];
- } else if (mBatchSize) {
- usage = BatchInfo::getColorFormatAt(hnd, 0);
- }
if (usage & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
}
- if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709) {
- buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
- }
fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("Failed setting color format in Camerasource %x", m_sVenc_cfg.inputformat);
@@ -5396,6 +5458,18 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
rate_ctrl.rcmode = control.value;
}
+ if (eControlRate == OMX_Video_ControlRateVariable && (supported_rc_modes & RC_VBR_CFR)
+ && m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
+ /* Enable VQZIP SEI by default for camcorder RC modes */
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI;
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI_ENABLE;
+ DEBUG_PRINT_HIGH("Set VQZIP SEI:");
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control) < 0) {
+ DEBUG_PRINT_HIGH("Non-Fatal: Request to set VQZIP failed");
+ }
+ }
+
return status;
}
@@ -6491,10 +6565,13 @@ encExtradata::encExtradata(class omx_venc *venc_handle)
{
mCount = 0;
mSize = 0;
+ mUaddr = NULL;
+ memset(&mIon, -1, sizeof(struct venc_ion));
+ memset(mIndex, 0, sizeof(mIndex));
mVencHandle = venc_handle;
mDbgEtbCount = 0;
- memset(mIndex, 0, sizeof(mIndex));
pthread_mutex_init(&lock, NULL);
+ vqzip_sei_found = false;
}
encExtradata::~encExtradata()
@@ -6503,6 +6580,7 @@ encExtradata::~encExtradata()
mCount = 0;
mSize = 0;
mVencHandle = NULL;
+ pthread_mutex_destroy(&lock);
}
OMX_ERRORTYPE encExtradata::__allocate()
@@ -6552,7 +6630,7 @@ int encExtradata::__get(char **userptr, int *fd, unsigned *offset, ssize_t *size
}
}
if (i >= mCount) {
- DEBUG_PRINT_ERROR("No Free extradata available");
+ DEBUG_PRINT_HIGH("No Free extradata available");
return -1;
}
*userptr = mUaddr + i * mSize;
@@ -6723,10 +6801,10 @@ void encExtradata::update(unsigned int count, ssize_t size)
void encExtradata::__debug()
{
- DEBUG_PRINT_ERROR("encExtradata: this: %p, mCount: %d, mSize: %d, mUaddr: %p, mVencHandle: %p",
+ DEBUG_PRINT_HIGH("encExtradata: this: %p, mCount: %d, mSize: %d, mUaddr: %p, mVencHandle: %p",
this, mCount, mSize, mUaddr, mVencHandle);
for (unsigned i = 0; i < mCount; i++) {
- DEBUG_PRINT_ERROR("index: %d, status: %d, cookie: %#x\n", i, mIndex[i].status, mIndex[i].cookie);
+ DEBUG_PRINT_HIGH("index: %d, status: %d, cookie: %#x\n", i, mIndex[i].status, mIndex[i].cookie);
}
}