Add mm-video from codeaurora.
Imported from codeaurora with no changes - does not compile.
Source: git://codeaurora.org/platform/vendor/qcom-opensource/omx/mm-video.git
branch: eclair
sha1: 5ff99d2db47c7a2e07f8803e8d1a0485c5cb9e32
Change-Id: Ic9e6711677888b1232b7c57fc82b2edeba36a553
diff --git a/omx/mm-video/Android.mk b/omx/mm-video/Android.mk
new file mode 100644
index 0000000..bb2622e
--- /dev/null
+++ b/omx/mm-video/Android.mk
@@ -0,0 +1,50 @@
+#--------------------------------------------------------------------------
+#Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#--------------------------------------------------------------------------
+
+OMX_VIDEO_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+ifeq "$(findstring qsd8250,$(TARGET_PRODUCT))" "qsd8250"
+ include $(OMX_VIDEO_PATH)/qdsp6/vdec/Android.mk
+ include $(OMX_VIDEO_PATH)/qdsp6/venc/Android.mk
+endif
+
+ifeq "$(findstring qsd8650a,$(TARGET_PRODUCT))" "qsd8650a"
+ include $(OMX_VIDEO_PATH)/qdsp6/vdec/Android.mk
+ include $(OMX_VIDEO_PATH)/qdsp6/venc/Android.mk
+endif
+
+ifeq "$(findstring msm7630,$(TARGET_PRODUCT))" "msm7630"
+ include $(OMX_VIDEO_PATH)/vidc/vdec/Android.mk
+ include $(OMX_VIDEO_PATH)/vidc/venc/Android.mk
+endif
+
+ifeq "$(findstring msm8660,$(TARGET_PRODUCT))" "msm8660"
+ include $(OMX_VIDEO_PATH)/vidc/vdec/Android.mk
+ include $(OMX_VIDEO_PATH)/vidc/venc/Android.mk
+endif
\ No newline at end of file
diff --git a/omx/mm-video/Makefile b/omx/mm-video/Makefile
new file mode 100644
index 0000000..dc56261
--- /dev/null
+++ b/omx/mm-video/Makefile
@@ -0,0 +1,8 @@
+all:
+ @echo "invoking opensource mm-video make"
+ $(MAKE) -C qdsp6/vdec
+ $(MAKE) -C qdsp6/venc
+
+install:
+ $(MAKE) -C qdsp6/vdec install
+ $(MAKE) -C qdsp6/venc install
diff --git a/omx/mm-video/qdsp6/vdec/Android.mk b/omx/mm-video/qdsp6/vdec/Android.mk
new file mode 100644
index 0000000..483cada
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/Android.mk
@@ -0,0 +1,121 @@
+#--------------------------------------------------------------------------
+#Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#--------------------------------------------------------------------------
+
+ifneq ($(BUILD_TINY_ANDROID),true)
+
+ROOT_DIR := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PATH:= $(ROOT_DIR)
+
+# ---------------------------------------------------------------------------------
+# Common definitons
+# ---------------------------------------------------------------------------------
+
+libOmxVdec-def := -g -O3
+libOmxVdec-def += -DQC_MODIFIED
+libOmxVdec-def += -DVERBOSE
+libOmxVdec-def += -D_DEBUG
+libOmxVdec-def += -DUSE_LOGE_FOR_DECODER
+libOmxVdec-def += -D_ANDROID_
+libOmxVdec-def += -DPROFILE_DECODER
+libOmxVdec-def += -Du32="unsigned int"
+libOmxVdec-def += -Du8="unsigned char"
+
+# ---------------------------------------------------------------------------------
+# Make the Shared library (libOmxVdec)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+libOmxVdec-inc := $(LOCAL_PATH)/src
+libOmxVdec-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore
+
+LOCAL_MODULE := libOmxVdec
+LOCAL_CFLAGS := $(libOmxVdec-def)
+LOCAL_C_INCLUDES := $(libOmxVdec-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libutils liblog libbinder libcutils
+
+LOCAL_SRC_FILES := src/adsp.c
+LOCAL_SRC_FILES += src/pmem.c
+LOCAL_SRC_FILES += src/qutility.c
+LOCAL_SRC_FILES += src/vdec.cpp
+LOCAL_SRC_FILES += src/omx_vdec.cpp
+LOCAL_SRC_FILES += src/omx_vdec_linux.cpp
+LOCAL_SRC_FILES += src/omx_vdec_inpbuf.cpp
+LOCAL_SRC_FILES += src/MP4_Utils.cpp
+LOCAL_SRC_FILES += src/H264_Utils.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
+# ---------------------------------------------------------------------------------
+# Make the apps-test (mm-vdec-omx-test)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+mm-vdec-test-inc := $(LOCAL_PATH)/src
+mm-vdec-test-inc += $(LOCAL_PATH)/test
+mm-vdec-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore
+
+LOCAL_MODULE := mm-vdec-omx-test
+LOCAL_CFLAGS := $(libOmxVdec-def)
+LOCAL_C_INCLUDES := $(mm-vdec-test-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libmm-omxcore libOmxVdec libbinder
+
+LOCAL_SRC_FILES := test/omx_vdec_test.cpp
+LOCAL_SRC_FILES += test/queue.c
+
+include $(BUILD_EXECUTABLE)
+
+# ---------------------------------------------------------------------------------
+# Make the vdec-property-mgr (mm-vdec-omx-property-mgr)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+mm-vdec-property-mgr-inc := $(LOCAL_PATH)
+
+LOCAL_MODULE := mm-vdec-omx-property-mgr
+LOCAL_CFLAGS := $(libOmxVdec-def)
+LOCAL_C_INCLUDES := $(mm-vdec-property-mgr-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libcutils
+
+LOCAL_SRC_FILES := test/omx_vdec_property_mgr.cpp
+
+include $(BUILD_EXECUTABLE)
+
+endif #BUILD_TINY_ANDROID
+
+# ---------------------------------------------------------------------------------
+# END
+# ---------------------------------------------------------------------------------
+
diff --git a/omx/mm-video/qdsp6/vdec/Makefile b/omx/mm-video/qdsp6/vdec/Makefile
new file mode 100644
index 0000000..4d8cbd0
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/Makefile
@@ -0,0 +1,91 @@
+# ---------------------------------------------------------------------------------
+# MM-VIDEO-OSS-8K-VDEC
+# ---------------------------------------------------------------------------------
+
+# cross-compiler flags
+CFLAGS += -Wall
+CFLAGS += -Wundef
+CFLAGS += -Wstrict-prototypes
+CFLAGS += -Wno-trigraphs
+#CFLAGS += -Werror
+
+# cross-compile flags specific to shared objects
+CFLAGS_SO += -fpic
+
+# required pre-processor flags
+CPPFLAGS += -D__packed__=
+CPPFLAGS += -DIMAGE_APPS_PROC
+CPPFLAGS += -DFEATURE_Q_SINGLE_LINK
+CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR
+CPPFLAGS += -DFEATURE_LINUX
+CPPFLAGS += -DFEATURE_NATIVELINUX
+CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS
+CPPFLAGS += -DPROFILE_DECODER
+CPPFLAGS += -DUSE_PMEM_ADSP_CACHED
+CPPFLAGS += -Du32="unsigned int"
+CPPFLAGS += -Du8="unsigned char"
+CPPFLAGS += -Iinc
+CPPFLAGS += -Isrc
+
+# linker flags
+LDFLAGS += -L$(SYSROOT)/usr/lib
+
+# linker flags for shared objects
+LDFLAGS_SO += -shared
+
+# defintions
+LIBMAJOR := $(basename $(basename $(LIBVER)))
+LIBINSTALLDIR := $(DESTDIR)usr/lib
+BININSTALLDIR := $(DESTDIR)usr/bin
+
+# ---------------------------------------------------------------------------------
+# BUILD
+# ---------------------------------------------------------------------------------
+all: libOmxVdec.so.$(LIBVER) mm-vdec-omx-test
+
+install:
+ echo "installing opensource video decoder in $(DESTDIR)"
+ if [ ! -d $(LIBINSTALLDIR) ]; then mkdir -p $(LIBINSTALLDIR); fi
+ if [ ! -d $(BININSTALLDIR) ]; then mkdir -p $(BININSTALLDIR); fi
+ install -m 555 libOmxVdec.so.$(LIBVER) $(LIBINSTALLDIR)
+ cd $(LIBINSTALLDIR) && ln -s libOmxVdec.so.$(LIBVER) libOmxVdec.so.$(LIBMAJOR)
+ cd $(LIBINSTALLDIR) && ln -s libOmxVdec.so.$(LIBMAJOR) libOmxVdec.so
+ install -m 555 mm-vdec-omx-test $(BININSTALLDIR)
+
+# ---------------------------------------------------------------------------------
+# COMPILE LIBRARY
+# ---------------------------------------------------------------------------------
+SRCS := src/adsp.c
+SRCS += src/pmem.c
+SRCS += src/qutility.c
+SRCS += src/vdec.cpp
+SRCS += src/omx_vdec.cpp
+SRCS += src/omx_vdec_linux.cpp
+SRCS += src/omx_vdec_inpbuf.cpp
+SRCS += src/MP4_Utils.cpp
+SRCS += src/H264_Utils.cpp
+
+LDLIBS := -lpthread
+LDLIBS += -lrt
+LDLIBS += -lstdc++
+LDLIBS += -lOmxCore
+
+libOmxVdec.so.$(LIBVER): $(SRCS)
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxVdec.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS)
+
+# ---------------------------------------------------------------------------------
+# COMPILE TEST APP
+# ---------------------------------------------------------------------------------
+TEST_LDLIBS := -lpthread
+TEST_LDLIBS += -ldl
+TEST_LDLIBS += -lOmxCore
+
+TEST_SRCS := test/omx_vdec_test.cpp
+TEST_SRCS += test/queue.c
+
+mm-vdec-omx-test: libOmxVdec.so.$(LIBVER) $(TEST_SRCS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS)
+
+# ---------------------------------------------------------------------------------
+# END
+# ---------------------------------------------------------------------------------
diff --git a/omx/mm-video/qdsp6/vdec/src/H264_Utils.cpp b/omx/mm-video/qdsp6/vdec/src/H264_Utils.cpp
new file mode 100644
index 0000000..b4ff9cc
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/H264_Utils.cpp
@@ -0,0 +1,1577 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*========================================================================
+ O p e n M M
+ V i d e o U t i l i t i e s
+
+*//** @file H264_Utils.cpp
+ This module contains utilities and helper routines.
+
+@par EXTERNALIZED FUNCTIONS
+
+@par INITIALIZATION AND SEQUENCING REQUIREMENTS
+ (none)
+
+*//*====================================================================== */
+
+
+/* =======================================================================
+
+ INCLUDE FILES FOR MODULE
+
+========================================================================== */
+#include "H264_Utils.h"
+#include "omx_vdec.h"
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef _ANDROID_
+#include "cutils/properties.h"
+#endif
+
+#include "qtv_msg.h"
+
+/* =======================================================================
+
+ DEFINITIONS AND DECLARATIONS FOR MODULE
+
+This section contains definitions for constants, macros, types, variables
+and other items needed by this module.
+
+========================================================================== */
+
+#define SIZE_NAL_FIELD_MAX 4
+#define BASELINE_PROFILE 66
+#define MAIN_PROFILE 77
+#define HIGH_PROFILE 100
+
+#define MAX_SUPPORTED_LEVEL 32
+
+RbspParser::RbspParser(const uint8 * _begin, const uint8 * _end)
+:begin(_begin), end(_end), pos(-1), bit(0),
+cursor(0xFFFFFF), advanceNeeded(true)
+{
+}
+
+// Destructor
+/*lint -e{1540} Pointer member neither freed nor zeroed by destructor
+ * No problem
+ */
+RbspParser::~RbspParser()
+{
+}
+
+// Return next RBSP byte as a word
+uint32 RbspParser::next()
+{
+ if (advanceNeeded)
+ advance();
+ //return static_cast<uint32> (*pos);
+ return static_cast < uint32 > (begin[pos]);
+}
+
+// Advance RBSP decoder to next byte
+void RbspParser::advance()
+{
+ ++pos;
+ //if (pos >= stop)
+ if (begin + pos == end) {
+ /*lint -e{730} Boolean argument to function
+ * I don't see a problem here
+ */
+ //throw false;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->NEED TO THROW THE EXCEPTION...\n");
+ }
+ cursor <<= 8;
+ //cursor |= static_cast<uint32> (*pos);
+ cursor |= static_cast < uint32 > (begin[pos]);
+ if ((cursor & 0xFFFFFF) == 0x000003) {
+ advance();
+ }
+ advanceNeeded = false;
+}
+
+// Decode unsigned integer
+uint32 RbspParser::u(uint32 n)
+{
+ uint32 i, s, x = 0;
+ for (i = 0; i < n; i += s) {
+ s = static_cast < uint32 > STD_MIN(static_cast < int >(8 - bit),
+ static_cast < int >(n - i));
+ x <<= s;
+
+ x |= ((next() >> ((8 - static_cast < uint32 > (bit)) - s)) &
+ ((1 << s) - 1));
+
+ bit = (bit + s) % 8;
+ if (!bit) {
+ advanceNeeded = true;
+ }
+ }
+ return x;
+}
+
+// Decode unsigned integer Exp-Golomb-coded syntax element
+uint32 RbspParser::ue()
+{
+ int leadingZeroBits = -1;
+ for (uint32 b = 0; !b; ++leadingZeroBits) {
+ b = u(1);
+ }
+ return ((1 << leadingZeroBits) - 1) +
+ u(static_cast < uint32 > (leadingZeroBits));
+}
+
+// Decode signed integer Exp-Golomb-coded syntax element
+int32 RbspParser::se()
+{
+ const uint32 x = ue();
+ if (!x)
+ return 0;
+ else if (x & 1)
+ return static_cast < int32 > ((x >> 1) + 1);
+ else
+ return -static_cast < int32 > (x >> 1);
+}
+
+void H264_Utils::allocate_rbsp_buffer(uint32 inputBufferSize)
+{
+ m_rbspBytes = (byte *) malloc(inputBufferSize);
+ m_prv_nalu.nal_ref_idc = 0;
+ m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
+}
+
+H264_Utils::H264_Utils():m_height(0), m_width(0), m_rbspBytes(NULL),
+ m_default_profile_chk(true), m_default_level_chk(true)
+{
+#ifdef _ANDROID_
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+ if(0 != property_get("persist.omxvideo.profilecheck", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_profile_chk = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "H264_Utils:: Constr failed in \
+ getting value for the Android property [persist.omxvideo.profilecheck]");
+ }
+
+ if(0 != property_get("persist.omxvideo.levelcheck", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_level_chk = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "H264_Utils:: Constr failed in \
+ getting value for the Android property [persist.omxvideo.levelcheck]");
+ }
+#endif
+ initialize_frame_checking_environment();
+}
+
+H264_Utils::~H264_Utils()
+{
+/* if(m_pbits)
+ {
+ delete(m_pbits);
+ m_pbits = NULL;
+ }
+*/
+ if (m_rbspBytes) {
+ free(m_rbspBytes);
+ m_rbspBytes = NULL;
+ }
+}
+
+/***********************************************************************/
+/*
+FUNCTION:
+ H264_Utils::initialize_frame_checking_environment
+
+DESCRIPTION:
+ Extract RBSP data from a NAL
+
+INPUT/OUTPUT PARAMETERS:
+ None
+
+RETURN VALUE:
+ boolean
+
+SIDE EFFECTS:
+ None.
+*/
+/***********************************************************************/
+void H264_Utils::initialize_frame_checking_environment()
+{
+ m_forceToStichNextNAL = false;
+}
+
+/***********************************************************************/
+/*
+FUNCTION:
+ H264_Utils::extract_rbsp
+
+DESCRIPTION:
+ Extract RBSP data from a NAL
+
+INPUT/OUTPUT PARAMETERS:
+ <In>
+ buffer : buffer containing start code or nal length + NAL units
+ buffer_length : the length of the NAL buffer
+ start_code : If true, start code is detected,
+ otherwise size nal length is detected
+ size_of_nal_length_field: size of nal length field
+
+ <Out>
+ rbsp_bistream : extracted RBSP bistream
+ rbsp_length : the length of the RBSP bitstream
+ nal_unit : decoded NAL header information
+
+RETURN VALUE:
+ boolean
+
+SIDE EFFECTS:
+ None.
+*/
+/***********************************************************************/
+
+boolean H264_Utils::extract_rbsp(OMX_IN OMX_U8 * buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_U8 * rbsp_bistream,
+ OMX_OUT OMX_U32 * rbsp_length,
+ OMX_OUT NALU * nal_unit)
+{
+ byte coef1, coef2, coef3;
+ uint32 pos = 0;
+ uint32 nal_len = buffer_length;
+ uint32 sizeofNalLengthField = 0;
+ uint32 zero_count;
+ boolean eRet = true;
+ boolean start_code = (size_of_nal_length_field == 0) ? true : false;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "extract_rbsp\n");
+
+ if (start_code) {
+ // Search start_code_prefix_one_3bytes (0x000001)
+ coef2 = buffer[pos++];
+ coef3 = buffer[pos++];
+ do {
+ if (pos >= buffer_length) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Error at extract rbsp line %d",
+ __LINE__);
+ return false;
+ }
+
+ coef1 = coef2;
+ coef2 = coef3;
+ coef3 = buffer[pos++];
+ } while (coef1 || coef2 || coef3 != 1);
+ } else if (size_of_nal_length_field) {
+ /* This is the case to play multiple NAL units inside each access unit */
+ /* Extract the NAL length depending on sizeOfNALength field */
+ sizeofNalLengthField = size_of_nal_length_field;
+ nal_len = 0;
+ while (size_of_nal_length_field--) {
+ nal_len |=
+ buffer[pos++] << (size_of_nal_length_field << 3);
+ }
+ if (nal_len >= buffer_length) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d",
+ __LINE__);
+ return false;
+ }
+ }
+
+ if (nal_len > buffer_length) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d", __LINE__);
+ return false;
+ }
+ if (pos + 1 > (nal_len + sizeofNalLengthField)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d", __LINE__);
+ return false;
+ }
+ if (nal_unit->forbidden_zero_bit = (buffer[pos] & 0x80)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d", __LINE__);
+ }
+ nal_unit->nal_ref_idc = (buffer[pos] & 0x60) >> 5;
+ nal_unit->nalu_type = buffer[pos++] & 0x1f;
+ *rbsp_length = 0;
+
+ if (nal_unit->nalu_type == NALU_TYPE_EOSEQ ||
+ nal_unit->nalu_type == NALU_TYPE_EOSTREAM)
+ return eRet;
+
+ zero_count = 0;
+ while (pos < (nal_len + sizeofNalLengthField)) //similar to for in p-42
+ {
+ if (zero_count == 2) {
+ if (buffer[pos] == 0x03) {
+ pos++;
+ zero_count = 0;
+ continue;
+ }
+ if (buffer[pos] <= 0x01) {
+ if (start_code) {
+ *rbsp_length -= 2;
+ pos -= 2;
+ break;
+ }
+ }
+ zero_count = 0;
+ }
+ zero_count++;
+ if (buffer[pos] != 0)
+ zero_count = 0;
+
+ rbsp_bistream[(*rbsp_length)++] = buffer[pos++];
+ }
+
+ return eRet;
+}
+
+/*===========================================================================
+FUNCTION:
+ H264_Utils::iSNewFrame
+
+DESCRIPTION:
+ Returns true if NAL parsing successfull otherwise false.
+
+INPUT/OUTPUT PARAMETERS:
+ <In>
+ buffer : buffer containing start code or nal length + NAL units
+ buffer_length : the length of the NAL buffer
+ start_code : If true, start code is detected,
+ otherwise size nal length is detected
+ size_of_nal_length_field: size of nal length field
+ <out>
+ isNewFrame: true if the NAL belongs to a differenet frame
+ false if the NAL belongs to a current frame
+
+RETURN VALUE:
+ boolean true, if nal parsing is successful
+ false, if the nal parsing has errors
+
+SIDE EFFECTS:
+ None.
+===========================================================================*/
+bool H264_Utils::isNewFrame(OMX_IN OMX_U8 * buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_BOOL & isNewFrame,
+ bool & isUpdateTimestamp)
+{
+ NALU nal_unit;
+ uint16 first_mb_in_slice = 0;
+ uint32 numBytesInRBSP = 0;
+ bool eRet = true;
+ isUpdateTimestamp = false;
+
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_h264_nal_type %p nal_length %d nal_length_field %d\n",
+ buffer, buffer_length, size_of_nal_length_field);
+
+ if (false ==
+ extract_rbsp(buffer, buffer_length, size_of_nal_length_field,
+ m_rbspBytes, &numBytesInRBSP, &nal_unit)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "get_h264_nal_type - ERROR at extract_rbsp\n");
+ isNewFrame = OMX_FALSE;
+ eRet = false;
+ } else {
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Nalu type: %d",nal_unit.nalu_type);
+
+ switch (nal_unit.nalu_type) {
+ case NALU_TYPE_IDR:
+ case NALU_TYPE_NON_IDR:
+ {
+ RbspParser rbsp_parser(m_rbspBytes,
+ (m_rbspBytes +
+ numBytesInRBSP));
+ first_mb_in_slice = rbsp_parser.ue();
+
+ if (m_forceToStichNextNAL) {
+ isNewFrame = OMX_FALSE;
+ if(!first_mb_in_slice){
+ isUpdateTimestamp = true;
+ }
+ } else {
+ if ((!first_mb_in_slice) || /*(slice.prv_frame_num != slice.frame_num ) || */
+ ((m_prv_nalu.nal_ref_idc !=
+ nal_unit.nal_ref_idc)
+ && (nal_unit.nal_ref_idc *
+ m_prv_nalu.nal_ref_idc == 0))
+ ||
+ /*( ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) && (nal_unit.nalu_type == NALU_TYPE_IDR)) && (slice.idr_pic_id != slice.prv_idr_pic_id) ) || */
+ ((m_prv_nalu.nalu_type !=
+ nal_unit.nalu_type)
+ &&
+ ((m_prv_nalu.nalu_type ==
+ NALU_TYPE_IDR)
+ || (nal_unit.nalu_type ==
+ NALU_TYPE_IDR)))) {
+ isNewFrame = OMX_TRUE;
+ } else {
+ isNewFrame = OMX_FALSE;
+ }
+ }
+ m_forceToStichNextNAL = false;
+ break;
+ }
+ default:
+ {
+ isNewFrame =
+ (m_forceToStichNextNAL ? OMX_FALSE :
+ OMX_TRUE);
+ m_forceToStichNextNAL = true;
+ break;
+ }
+ } // end of switch
+ } // end of if
+ m_prv_nalu = nal_unit;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_h264_nal_type - newFrame value %d\n", isNewFrame);
+ return eRet;
+}
+
+/**************************************************************************
+ ** This function parses an H.264 Annex B formatted bitstream, returning the
+ ** next frame in the format required by MP4 (specified in ISO/IEC 14496-15,
+ ** section 5.2.3, "AVC Sample Structure Definition"), and recovering any
+ ** header (sequence and picture parameter set NALUs) information, formatting
+ ** it as a header block suitable for writing to video format services.
+ **
+ ** IN const uint8 *encodedBytes
+ ** This points to the H.264 Annex B formatted video bitstream, starting
+ ** with the next frame for which to locate frame boundaries.
+ **
+ ** IN uint32 totalBytes
+ ** This is the total number of bytes left in the H.264 video bitstream,
+ ** from the given starting position.
+ **
+ ** INOUT H264StreamInfo &streamInfo
+ ** This structure contains state information about the stream as it has
+ ** been so far parsed.
+ **
+ ** OUT vector<uint8> &frame
+ ** The properly MP4 formatted H.264 frame will be stored here.
+ **
+ ** OUT uint32 &bytesConsumed
+ ** This is set to the total number of bytes parsed from the bitstream.
+ **
+ ** OUT uint32 &nalSize
+ ** The true size of the NAL (without padding zeroes)
+ **
+ ** OUT bool &keyFrame
+ ** Indicator whether this is an I-frame
+ **
+ ** IN bool stripSeiAud
+ ** If set, any SEI or AU delimiter NALUs are stripped out.
+ *************************************************************************/
+bool H264_Utils::parseHeader(uint8 * encodedBytes,
+ uint32 totalBytes,
+ uint32 sizeOfNALLengthField,
+ unsigned &height,
+ unsigned &width,
+ bool & bInterlace,
+ unsigned &cropx,
+ unsigned &cropy,
+ unsigned &cropdx, unsigned &cropdy)
+{
+ bool keyFrame = FALSE;
+ bool stripSeiAud = FALSE;
+ bool nalSize = FALSE;
+ uint64 bytesConsumed = 0;
+ uint8 frame[64];
+ struct H264ParamNalu temp = { 0 };
+
+ // Scan NALUs until a frame boundary is detected. If this is the first
+ // frame, scan a second time to find the end of the frame. Otherwise, the
+ // first boundary found is the end of the current frame. While scanning,
+ // collect any sequence/parameter set NALUs for use in constructing the
+ // stream header.
+ bool inFrame = true;
+ bool inNalu = false;
+ bool vclNaluFound = false;
+ uint8 naluType = 0;
+ uint32 naluStart = 0, naluSize = 0;
+ uint32 prevVclFrameNum = 0, vclFrameNum = 0;
+ bool prevVclFieldPicFlag = false, vclFieldPicFlag = false;
+ bool prevVclBottomFieldFlag = false, vclBottomFieldFlag = false;
+ uint8 prevVclNalRefIdc = 0, vclNalRefIdc = 0;
+ uint32 prevVclPicOrderCntLsb = 0, vclPicOrderCntLsb = 0;
+ int32 prevVclDeltaPicOrderCntBottom = 0, vclDeltaPicOrderCntBottom = 0;
+ int32 prevVclDeltaPicOrderCnt0 = 0, vclDeltaPicOrderCnt0 = 0;
+ int32 prevVclDeltaPicOrderCnt1 = 0, vclDeltaPicOrderCnt1 = 0;
+ uint8 vclNaluType = 0;
+ uint32 vclPicOrderCntType = 0;
+ uint64 pos;
+ uint64 posNalDetected = 0xFFFFFFFF;
+ uint32 cursor = 0xFFFFFFFF;
+ unsigned int profile_id = 0, level_id = 0;
+
+ H264ParamNalu *seq = NULL, *pic = NULL;
+ // used to determin possible infinite loop condition
+ int loopCnt = 0;
+ for (pos = 0;; ++pos) {
+ // return early, found possible infinite loop
+ if (loopCnt > 100000)
+ return 0;
+ // Scan ahead next byte.
+ cursor <<= 8;
+ cursor |= static_cast < uint32 > (encodedBytes[pos]);
+
+ if (sizeOfNALLengthField != 0) {
+ inNalu = true;
+ naluStart = sizeOfNALLengthField;
+ }
+ // If in NALU, scan forward until an end of NALU condition is
+ // detected.
+ if (inNalu) {
+ if (sizeOfNALLengthField == 0) {
+ // Detect end of NALU condition.
+ if (((cursor & 0xFFFFFF) == 0x000000)
+ || ((cursor & 0xFFFFFF) == 0x000001)
+ || (pos >= totalBytes)) {
+ inNalu = false;
+ if (pos < totalBytes) {
+ pos -= 3;
+ }
+ naluSize =
+ static_cast < uint32 >
+ ((static_cast < uint32 >
+ (pos) - naluStart) + 1);
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->1.nalusize=%x pos=%x naluStart=%x\n",
+ naluSize, pos, naluStart);
+ } else {
+ ++loopCnt;
+ continue;
+ }
+ }
+ // Determine NALU type.
+ naluType = (encodedBytes[naluStart] & 0x1F);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->2.naluType=%x....\n",
+ naluType);
+ if (naluType == 5)
+ keyFrame = true;
+
+ // For NALUs in the frame having a slice header, parse additional
+ // fields.
+ bool isVclNalu = false;
+ if ((naluType == 1) || (naluType == 2)
+ || (naluType == 5)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->3.naluType=%x....\n",
+ naluType);
+ // Parse additional fields.
+ RbspParser rbsp(&encodedBytes[naluStart + 1],
+ &encodedBytes[naluStart +
+ naluSize]);
+ vclNaluType = naluType;
+ vclNalRefIdc =
+ ((encodedBytes[naluStart] >> 5) & 0x03);
+ (void)rbsp.ue();
+ (void)rbsp.ue();
+ const uint32 picSetID = rbsp.ue();
+ pic = this->pic.find(picSetID);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->4.sizeof %x %x\n",
+ this->pic.size(),
+ this->seq.size());
+ if (!pic) {
+ if (this->pic.empty()) {
+ // Found VCL NALU before needed picture parameter set
+ // -- assume that we started parsing mid-frame, and
+ // discard the rest of the frame we're in.
+ inFrame = false;
+ //frame.clear ();
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->5.pic empty........\n");
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->6.FAILURE to parse..break frm here");
+ break;
+ }
+ }
+ if (pic) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->7.sizeof %x %x\n",
+ this->pic.size(),
+ this->seq.size());
+ seq = this->seq.find(pic->seqSetID);
+ if (!seq) {
+ if (this->seq.empty()) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->8.seq empty........\n");
+ // Found VCL NALU before needed sequence parameter
+ // set -- assume that we started parsing
+ // mid-frame, and discard the rest of the frame
+ // we're in.
+ inFrame = false;
+ //frame.clear ();
+ } else {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->9.FAILURE to parse...break");
+ break;
+ }
+ }
+ }
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->10.sizeof %x %x\n",
+ this->pic.size(),
+ this->seq.size());
+ if (pic && seq) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->11.pic and seq[%x][%x]........\n",
+ pic, seq);
+ isVclNalu = true;
+ vclFrameNum =
+ rbsp.u(seq->log2MaxFrameNumMinus4 +
+ 4);
+ if (!seq->frameMbsOnlyFlag) {
+ vclFieldPicFlag =
+ (rbsp.u(1) == 1);
+ if (vclFieldPicFlag) {
+ vclBottomFieldFlag =
+ (rbsp.u(1) == 1);
+ }
+ } else {
+ vclFieldPicFlag = false;
+ vclBottomFieldFlag = false;
+ }
+ if (vclNaluType == 5) {
+ (void)rbsp.ue();
+ }
+ vclPicOrderCntType =
+ seq->picOrderCntType;
+ if (seq->picOrderCntType == 0) {
+ vclPicOrderCntLsb = rbsp.u
+ (seq->
+ log2MaxPicOrderCntLsbMinus4
+ + 4);
+ if (pic->picOrderPresentFlag
+ && !vclFieldPicFlag) {
+ vclDeltaPicOrderCntBottom
+ = rbsp.se();
+ } else {
+ vclDeltaPicOrderCntBottom
+ = 0;
+ }
+ } else {
+ vclPicOrderCntLsb = 0;
+ vclDeltaPicOrderCntBottom = 0;
+ }
+ if ((seq->picOrderCntType == 1)
+ && !seq->
+ deltaPicOrderAlwaysZeroFlag) {
+ vclDeltaPicOrderCnt0 =
+ rbsp.se();
+ if (pic->picOrderPresentFlag
+ && !vclFieldPicFlag) {
+ vclDeltaPicOrderCnt1 =
+ rbsp.se();
+ } else {
+ vclDeltaPicOrderCnt1 =
+ 0;
+ }
+ } else {
+ vclDeltaPicOrderCnt0 = 0;
+ vclDeltaPicOrderCnt1 = 0;
+ }
+ }
+ }
+ //////////////////////////////////////////////////////////////////
+ // Perform frame boundary detection.
+ //////////////////////////////////////////////////////////////////
+
+ // The end of the bitstream is always a boundary.
+ bool boundary = (pos >= totalBytes);
+
+ // The first of these NALU types always mark a boundary, but skip
+ // any that occur before the first VCL NALU in a new frame.
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->12.naluType[%x].....\n",
+ naluType);
+ if ((((naluType >= 6) && (naluType <= 9))
+ || ((naluType >= 13) && (naluType <= 18)))
+ && (vclNaluFound || !inFrame)) {
+ boundary = true;
+ }
+ // If a VCL NALU is found, compare with the last VCL NALU to
+ // determine if they belong to different frames.
+ else if (vclNaluFound && isVclNalu) {
+ // Clause 7.4.1.2.4 -- detect first VCL NALU through
+ // parsing of portions of the NALU header and slice
+ // header.
+ /*lint -e{731} Boolean argument to equal/not equal
+ * It's ok
+ */
+ if ((prevVclFrameNum != vclFrameNum)
+ || (prevVclFieldPicFlag != vclFieldPicFlag)
+ || (prevVclBottomFieldFlag !=
+ vclBottomFieldFlag)
+ || ((prevVclNalRefIdc != vclNalRefIdc)
+ && ((prevVclNalRefIdc == 0)
+ || (vclNalRefIdc == 0)))
+ || ((vclPicOrderCntType == 0)
+ &&
+ ((prevVclPicOrderCntLsb !=
+ vclPicOrderCntLsb)
+ || (prevVclDeltaPicOrderCntBottom !=
+ vclDeltaPicOrderCntBottom)))
+ || ((vclPicOrderCntType == 1)
+ && ((prevVclDeltaPicOrderCnt0
+ != vclDeltaPicOrderCnt0)
+ || (prevVclDeltaPicOrderCnt1
+ != vclDeltaPicOrderCnt1)))) {
+ boundary = true;
+ }
+ }
+ // If a frame boundary is reached and we were in the frame in
+ // which at least one VCL NALU was found, we are done processing
+ // this frame. Remember to back up to NALU start code to make
+ // sure it is available for when the next frame is parsed.
+ if (boundary && inFrame && vclNaluFound) {
+ pos = static_cast < uint64 > (naluStart - 3);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->13.Break \n");
+ break;
+ }
+ inFrame = (inFrame || boundary);
+
+ // Process sequence and parameter set NALUs specially.
+ if ((naluType == 7) || (naluType == 8)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->14.naluType[%x].....\n",
+ naluType);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->15.sizeof %x %x\n",
+ this->pic.size(),
+ this->seq.size());
+ H264ParamNaluSet & naluSet =
+ ((naluType == 7) ? this->seq : this->pic);
+
+ // Parse parameter set ID and other stream information.
+ H264ParamNalu newParam;
+ RbspParser rbsp(&encodedBytes[naluStart + 1],
+ &encodedBytes[naluStart +
+ naluSize]);
+ uint32 id;
+ if (naluType == 7) {
+
+ unsigned int tmp;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->16.naluType[%x].....\n",
+ naluType);
+ profile_id = rbsp.u(8);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.prfoile[%d].....\n",
+ profile_id);
+
+ tmp = rbsp.u(8);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.prfoilebytes[%x].....\n",
+ tmp);
+
+ level_id = rbsp.u(8);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.level[%d].....\n",
+ level_id);
+
+ id = newParam.seqSetID = rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.seqID[%d].....\n",
+ id);
+ if (profile_id == 100) {
+ //Chroma_format_idc
+ tmp = rbsp.ue();
+ if (tmp == 3) {
+ //residual_colour_transform_flag
+ (void)rbsp.u(1);
+ }
+ //bit_depth_luma_minus8
+ (void)rbsp.ue();
+ //bit_depth_chroma_minus8
+ (void)rbsp.ue();
+ //qpprime_y_zero_transform_bypass_flag
+ (void)rbsp.u(1);
+ // seq_scaling_matrix_present_flag
+ tmp = rbsp.u(1);
+ if (tmp) {
+ unsigned int tmp1, t;
+ //seq_scaling_list_present_flag
+ for (t = 0; t < 6; t++) {
+ tmp1 =
+ rbsp.u(1);
+ if (tmp1) {
+ unsigned
+ int
+ last_scale
+ =
+ 8,
+ next_scale
+ =
+ 8,
+ delta_scale;
+ for (int
+ j =
+ 0;
+ j <
+ 16;
+ j++)
+ {
+ if (next_scale) {
+ delta_scale
+ =
+ rbsp.
+ se
+ ();
+ next_scale
+ =
+ (last_scale
+ +
+ delta_scale
+ +
+ 256)
+ %
+ 256;
+ }
+ last_scale
+ =
+ next_scale
+ ?
+ next_scale
+ :
+ last_scale;
+ }
+ }
+ }
+ for (t = 0; t < 2; t++) {
+ tmp1 =
+ rbsp.u(1);
+ if (tmp1) {
+ unsigned
+ int
+ last_scale
+ =
+ 8,
+ next_scale
+ =
+ 8,
+ delta_scale;
+ for (int
+ j =
+ 0;
+ j <
+ 64;
+ j++)
+ {
+ if (next_scale) {
+ delta_scale
+ =
+ rbsp.
+ se
+ ();
+ next_scale
+ =
+ (last_scale
+ +
+ delta_scale
+ +
+ 256)
+ %
+ 256;
+ }
+ last_scale
+ =
+ next_scale
+ ?
+ next_scale
+ :
+ last_scale;
+ }
+ }
+ }
+ }
+
+ }
+ newParam.log2MaxFrameNumMinus4 =
+ rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.log2MaxFrameNumMinu[%d].....\n",
+ newParam.
+ log2MaxFrameNumMinus4);
+ newParam.picOrderCntType = rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.picOrderCntType[%d].....\n",
+ newParam.picOrderCntType);
+ if (newParam.picOrderCntType == 0) {
+ newParam.
+ log2MaxPicOrderCntLsbMinus4
+ = rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.log2MaxPicOrderCntLsbMinus4 [%d].....\n",
+ newParam.
+ log2MaxPicOrderCntLsbMinus4);
+ } else if (newParam.picOrderCntType ==
+ 1) {
+ newParam.
+ deltaPicOrderAlwaysZeroFlag
+ = (rbsp.u(1) == 1);
+ (void)rbsp.se();
+ (void)rbsp.se();
+ const uint32
+ numRefFramesInPicOrderCntCycle
+ = rbsp.ue();
+ for (uint32 i = 0;
+ i <
+ numRefFramesInPicOrderCntCycle;
+ ++i) {
+ (void)rbsp.se();
+ }
+ }
+ tmp = rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.numrefFrames[%d].....\n",
+ tmp);
+ tmp = rbsp.u(1);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.gapsflag[%x].....\n",
+ tmp);
+ newParam.picWidthInMbsMinus1 =
+ rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.picWidthInMbsMinus1[%d].....\n",
+ newParam.
+ picWidthInMbsMinus1);
+ newParam.picHeightInMapUnitsMinus1 =
+ rbsp.ue();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->33.gapsflag[%d].....\n",
+ newParam.
+ picHeightInMapUnitsMinus1);
+ newParam.frameMbsOnlyFlag =
+ (rbsp.u(1) == 1);
+ if (!newParam.frameMbsOnlyFlag)
+ (void)rbsp.u(1);
+ (void)rbsp.u(1);
+ tmp = rbsp.u(1);
+ newParam.crop_left = 0;
+ newParam.crop_right = 0;
+ newParam.crop_top = 0;
+ newParam.crop_bot = 0;
+
+ if (tmp) {
+ newParam.crop_left = rbsp.ue();
+ newParam.crop_right = rbsp.ue();
+ newParam.crop_top = rbsp.ue();
+ newParam.crop_bot = rbsp.ue();
+ }
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser--->34 crop left %d, right %d, top %d, bot %d\n",
+ newParam.crop_left,
+ newParam.crop_right,
+ newParam.crop_top,
+ newParam.crop_bot);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->17.naluType[%x].....\n",
+ naluType);
+ id = newParam.picSetID = rbsp.ue();
+ newParam.seqSetID = rbsp.ue();
+ (void)rbsp.u(1);
+ newParam.picOrderPresentFlag =
+ (rbsp.u(1) == 1);
+ }
+
+ // We currently don't support updating existing parameter
+ // sets.
+ //const H264ParamNaluSet::const_iterator it = naluSet.find (id);
+ H264ParamNalu *it = naluSet.find(id);
+ if (it) {
+ const uint32 tempSize = static_cast < uint32 > (it->nalu); // ???
+ if ((naluSize != tempSize)
+ || (0 !=
+ memcmp(&encodedBytes[naluStart],
+ &it->nalu,
+ static_cast <
+ int >(naluSize)))) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->18.H264 stream contains two or \
+ more parameter set NALUs having the \
+ same ID -- this requires either a \
+ separate parameter set ES or \
+ multiple sample description atoms, \
+ neither of which is currently \
+ supported!");
+ break;
+ }
+ }
+ // Otherwise, add NALU to appropriate NALU set.
+ else {
+ H264ParamNalu *newParamInSet =
+ naluSet.find(id);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->19.newParamInset[%x]\n",
+ newParamInSet);
+ if (!newParamInSet) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->20.newParamInset[%x]\n",
+ newParamInSet);
+ newParamInSet = &temp;
+ memcpy(newParamInSet, &newParam,
+ sizeof(struct
+ H264ParamNalu));
+ }
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->21.encodebytes=%x naluStart=%x\n",
+ encodedBytes, naluStart,
+ naluSize, newParamInSet);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->22.naluSize=%x newparaminset=%p\n",
+ naluSize, newParamInSet);
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->23.-->0x%x 0x%x 0x%x 0x%x\n",
+ (encodedBytes +
+ naluStart),
+ (encodedBytes +
+ naluStart + 1),
+ (encodedBytes +
+ naluStart + 2),
+ (encodedBytes +
+ naluStart + 3));
+
+ memcpy(&newParamInSet->nalu,
+ (encodedBytes + naluStart),
+ sizeof(newParamInSet->nalu));
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "H264Parser-->24.nalu=0x%x \n",
+ newParamInSet->nalu);
+ naluSet.insert(id, newParamInSet);
+ }
+ }
+ // Otherwise, if we are inside the frame, convert the NALU
+ // and append it to the frame output, if its type is acceptable.
+ else if (inFrame && (naluType != 0) && (naluType < 12)
+ && (!stripSeiAud || (naluType != 9)
+ && (naluType != 6))) {
+ uint8 sizeBuffer[4];
+ sizeBuffer[0] =
+ static_cast < uint8 > (naluSize >> 24);
+ sizeBuffer[1] =
+ static_cast < uint8 >
+ ((naluSize >> 16) & 0xFF);
+ sizeBuffer[2] =
+ static_cast < uint8 >
+ ((naluSize >> 8) & 0xFF);
+ sizeBuffer[3] =
+ static_cast < uint8 > (naluSize & 0xFF);
+ /*lint -e{1025, 1703, 119, 64, 534}
+ * These are known lint issues
+ */
+ //frame.insert (frame.end (), sizeBuffer,
+ // sizeBuffer + sizeof (sizeBuffer));
+ /*lint -e{1025, 1703, 119, 64, 534, 632}
+ * These are known lint issues
+ */
+ //frame.insert (frame.end (), encodedBytes + naluStart,
+ // encodedBytes + naluStart + naluSize);
+ }
+ // If NALU was a VCL, save VCL NALU parameters
+ // for use in frame boundary detection.
+ if (isVclNalu) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->25.isvclnalu check passed\n");
+ vclNaluFound = true;
+ prevVclFrameNum = vclFrameNum;
+ prevVclFieldPicFlag = vclFieldPicFlag;
+ prevVclNalRefIdc = vclNalRefIdc;
+ prevVclBottomFieldFlag = vclBottomFieldFlag;
+ prevVclPicOrderCntLsb = vclPicOrderCntLsb;
+ prevVclDeltaPicOrderCntBottom =
+ vclDeltaPicOrderCntBottom;
+ prevVclDeltaPicOrderCnt0 = vclDeltaPicOrderCnt0;
+ prevVclDeltaPicOrderCnt1 = vclDeltaPicOrderCnt1;
+ }
+ }
+ // If not currently in a NALU, detect next NALU start code.
+ if ((cursor & 0xFFFFFF) == 0x000001) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->26..here\n");
+ inNalu = true;
+ naluStart = static_cast < uint32 > (pos + 1);
+ if (0xFFFFFFFF == posNalDetected)
+ posNalDetected = pos - 2;
+ } else if (pos >= totalBytes) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->27.pos[%x] totalBytes[%x]\n",
+ pos, totalBytes);
+ break;
+ }
+ }
+
+ uint64 tmpPos = 0;
+ // find the first non-zero byte
+ if (pos > 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->28.last loop[%x]\n", pos);
+ tmpPos = pos - 1;
+ while (tmpPos != 0 && encodedBytes[tmpPos] == 0)
+ --tmpPos;
+ // add 1 to get the beginning of the start code
+ ++tmpPos;
+ }
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->29.tmppos=%ld bytesConsumed=%x %x\n",
+ tmpPos, bytesConsumed, posNalDetected);
+ bytesConsumed = tmpPos;
+ nalSize = static_cast < uint32 > (bytesConsumed - posNalDetected);
+
+ // Fill in the height and width
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->30.seq[%x] pic[%x]\n", this->seq.size(),
+ this->pic.size());
+ if (this->seq.size()) {
+ m_height =
+ (unsigned)(16 *
+ (2 -
+ (this->seq.begin()->frameMbsOnlyFlag)) *
+ (this->seq.begin()->picHeightInMapUnitsMinus1 +
+ 1));
+ m_width =
+ (unsigned)(16 *
+ (this->seq.begin()->picWidthInMbsMinus1 + 1));
+ if ((m_height % 16) != 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Height %d is not a multiple of 16",
+ m_height);
+ m_height = (m_height / 16 + 1) * 16;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Height adjusted to %d \n", m_height);
+ }
+ if ((m_width % 16) != 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Width %d is not a multiple of 16",
+ m_width);
+ m_width = (m_width / 16 + 1) * 16;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Width adjusted to %d \n", m_width);
+ }
+ height = m_height;
+ width = m_width;
+ bInterlace = (!this->seq.begin()->frameMbsOnlyFlag);
+ cropx = this->seq.begin()->crop_left << 1;
+ cropy = this->seq.begin()->crop_top << 1;
+ cropdx =
+ width -
+ ((this->seq.begin()->crop_left +
+ this->seq.begin()->crop_right) << 1);
+ cropdy =
+ height -
+ ((this->seq.begin()->crop_top +
+ this->seq.begin()->crop_bot) << 1);
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->31.cropdy [%x] cropdx[%x]\n",
+ cropdy, cropdx);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264Parser-->31.Height [%x] Width[%x]\n", height,
+ width);
+ }
+ this->seq.eraseall();
+ this->pic.eraseall();
+ return validate_profile_and_level(profile_id, level_id);;
+}
+
+/* ======================================================================
+FUNCTION
+ H264_Utils::parse_first_h264_input_buffer
+
+DESCRIPTION
+ parse first h264 input buffer
+
+PARAMETERS
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer.
+
+RETURN VALUE
+ true if success
+ false otherwise
+========================================================================== */
+OMX_U32 H264_Utils::parse_first_h264_input_buffer(OMX_IN OMX_BUFFERHEADERTYPE *
+ buffer,
+ OMX_U32
+ size_of_nal_length_field)
+{
+ OMX_U32 c1, c2, c3, curr_ptr = 0;
+ OMX_U32 i, j, aSize[4], size = 0;
+ OMX_U32 header_len = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264 clip, NAL length field %d\n",
+ size_of_nal_length_field);
+
+ if (buffer == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - buffer is NULL\n");
+ }
+
+ if (size_of_nal_length_field == 0) {
+ /* Start code with a lot of 0x00 before 0x00 0x00 0x01
+ Need to move pBuffer to the first 0x00 0x00 0x00 0x01 */
+ c1 = 1;
+ c2 = buffer->pBuffer[curr_ptr++];
+ c3 = buffer->pBuffer[curr_ptr++];
+ do {
+ if (curr_ptr >= buffer->nFilledLen) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR: parse_first_h264_input_buffer - Couldn't find the first 2 NAL (SPS and PPS)\n");
+ return 0;
+ }
+ c1 = c2;
+ c2 = c3;
+ c3 = buffer->pBuffer[curr_ptr++];
+ } while (c1 || c2 || c3 == 0);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "curr_ptr = %d\n", curr_ptr);
+ if (curr_ptr > 4) {
+ // There are unnecessary 0x00
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Remove unnecessary 0x00 at SPS\n");
+ memmove(buffer->pBuffer, &buffer->pBuffer[curr_ptr - 4],
+ buffer->nFilledLen - curr_ptr - 4);
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "dat clip, NAL length field %d\n",
+ size_of_nal_length_field);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Start code SPS 0x00 00 00 01\n");
+ curr_ptr = 4;
+ /* Start code 00 00 01 */
+ for (OMX_U8 i = 0; i < 2; i++) {
+ c1 = 1;
+ c2 = buffer->pBuffer[curr_ptr++];
+ c3 = buffer->pBuffer[curr_ptr++];
+ do {
+ if (curr_ptr >= buffer->nFilledLen) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR: parse_first_h264_input_buffer - Couldn't find the first 2 NAL (SPS and PPS)\n");
+ break;
+ }
+ c1 = c2;
+ c2 = c3;
+ c3 = buffer->pBuffer[curr_ptr++];
+ } while (c1 || c2 || c3 != 1);
+ }
+ header_len = curr_ptr - 4;
+ } else {
+ /* NAL length clip */
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "NAL length clip, NAL length field %d\n",
+ size_of_nal_length_field);
+ /* SPS size */
+ for (i = 0; i < SIZE_NAL_FIELD_MAX - size_of_nal_length_field;
+ i++) {
+ aSize[SIZE_NAL_FIELD_MAX - 1 - i] = 0;
+ }
+ for (j = 0; i < SIZE_NAL_FIELD_MAX; i++, j++) {
+ aSize[SIZE_NAL_FIELD_MAX - 1 - i] = buffer->pBuffer[j];
+ }
+ size = (uint32) (*((uint32 *) (aSize)));
+ header_len = size + size_of_nal_length_field;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMX - SPS length %d\n", header_len);
+
+ /* PPS size */
+ for (i = 0; i < SIZE_NAL_FIELD_MAX - size_of_nal_length_field;
+ i++) {
+ aSize[SIZE_NAL_FIELD_MAX - 1 - i] = 0;
+ }
+ for (j = header_len; i < SIZE_NAL_FIELD_MAX; i++, j++) {
+ aSize[SIZE_NAL_FIELD_MAX - 1 - i] = buffer->pBuffer[j];
+ }
+ size = (uint32) (*((uint32 *) (aSize)));
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMX - PPS size %d\n", size);
+ header_len += size + size_of_nal_length_field;
+ }
+ return header_len;
+}
+
+OMX_U32 H264_Utils::check_header(OMX_IN OMX_BUFFERHEADERTYPE * buffer,
+ OMX_U32 sizeofNAL, bool & isPartial,
+ OMX_U32 headerState)
+{
+ byte coef1, coef2, coef3;
+ uint32 pos = 0;
+ uint32 nal_len = 0, nal_len2 = 0;
+ uint32 sizeofNalLengthField = 0;
+ uint32 zero_count;
+ OMX_U32 eRet = -1;
+ OMX_U8 *nal1_ptr = NULL, *nal2_ptr = NULL;
+
+ isPartial = true;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "H264_Utils::check_header ");
+
+ if (!sizeofNAL) {
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "check_header: start code %d",
+ buffer->nFilledLen);
+ // Search start_code_prefix_one_3bytes (0x000001)
+ coef2 = buffer->pBuffer[pos++];
+ coef3 = buffer->pBuffer[pos++];
+ do {
+ if (pos >= buffer->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d",
+ __LINE__);
+ return eRet;
+ }
+
+ coef1 = coef2;
+ coef2 = coef3;
+ coef3 = buffer->pBuffer[pos++];
+ } while (coef1 || coef2 || coef3 != 1);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "check_header: start code got fisrt NAL %d", pos);
+ nal1_ptr = (OMX_U8 *) & buffer->pBuffer[pos];
+
+ // Search start_code_prefix_one_3bytes (0x000001)
+ if (pos + 2 < buffer->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "check_header: start code looking for second NAL %d",
+ pos);
+ isPartial = false;
+ coef2 = buffer->pBuffer[pos++];
+ coef3 = buffer->pBuffer[pos++];
+ do {
+ if (pos >= buffer->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Error at extract rbsp line %d",
+ __LINE__);
+ isPartial = true;
+ break;
+ }
+
+ coef1 = coef2;
+ coef2 = coef3;
+ coef3 = buffer->pBuffer[pos++];
+ } while (coef1 || coef2 || coef3 != 1);
+ }
+ if (!isPartial) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: start code two nals in one buffer %d",
+ pos);
+ nal2_ptr = (OMX_U8 *) & buffer->pBuffer[pos];
+ if (((nal1_ptr[0] & 0x1f) == NALU_TYPE_SPS)
+ && ((nal2_ptr[0] & 0x1f) == NALU_TYPE_PPS)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "check_header: start code two nals in one buffer SPS+PPS %d",
+ pos);
+ eRet = 0;
+ } else if (((nal1_ptr[0] & 0x1f) == NALU_TYPE_SPS) && (buffer->nFilledLen < 512)) {
+ eRet = 0;
+ }
+
+
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "check_header: start code partial nal in one buffer %d",
+ pos);
+ if (headerState == 0
+ && ((nal1_ptr[0] & 0x1f) == NALU_TYPE_SPS)) {
+ eRet = 0;
+ } else if (((nal1_ptr[0] & 0x1f) == NALU_TYPE_PPS)) {
+ eRet = 0;
+ } else
+ eRet = -1;
+ }
+
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: size nal %d", sizeofNAL);
+ /* This is the case to play multiple NAL units inside each access unit */
+ /* Extract the NAL length depending on sizeOfNALength field */
+ sizeofNalLengthField = sizeofNAL;
+ nal_len = 0;
+ while (sizeofNAL--) {
+ nal_len |= buffer->pBuffer[pos++] << (sizeofNAL << 3);
+ }
+ if (nal_len >= buffer->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d",
+ __LINE__);
+ return eRet;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: size nal got fist NAL %d",
+ nal_len);
+ nal1_ptr = (OMX_U8 *) & buffer->pBuffer[pos];
+ if ((nal_len + sizeofNalLengthField) < buffer->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: getting second NAL %d",
+ buffer->nFilledLen);
+ isPartial = false;
+ pos += nal_len;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: getting second NAL position %d",
+ pos);
+ sizeofNAL = sizeofNalLengthField;
+ nal_len2 = 0;
+ while (sizeofNAL--) {
+ nal_len2 |=
+ buffer->pBuffer[pos++] << (sizeofNAL << 3);
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: getting second NAL %d",
+ nal_len2);
+ if (nal_len + nal_len2 + 2 * sizeofNalLengthField >
+ buffer->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error at extract rbsp line %d",
+ __LINE__);
+ return eRet;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: size nal got second NAL %d",
+ nal_len);
+ nal2_ptr = (OMX_U8 *) & buffer->pBuffer[pos];
+ }
+
+ if (!isPartial) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: size nal partial nal ");
+ if (((nal1_ptr[0] & 0x1f) == NALU_TYPE_SPS)
+ && ((nal2_ptr[0] & 0x1f) == NALU_TYPE_PPS)) {
+ eRet = 0;
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "check_header: size nal full header");
+ if (headerState == 0
+ && ((nal1_ptr[0] & 0x1f) == NALU_TYPE_SPS)) {
+ eRet = 0;
+ } else if (((nal1_ptr[0] & 0x1f) == NALU_TYPE_PPS)) {
+ eRet = 0;
+ } else
+ eRet = -1;
+ }
+
+ }
+ return eRet;
+}
+
+/*===========================================================================
+FUNCTION:
+ validate_profile_and_level
+
+DESCRIPTION:
+ This function validate the profile and level that is supported.
+
+INPUT/OUTPUT PARAMETERS:
+ uint32 profile
+ uint32 level
+
+RETURN VALUE:
+ false it it's not supported
+ true otherwise
+
+SIDE EFFECTS:
+ None.
+===========================================================================*/
+bool H264_Utils::validate_profile_and_level(uint32 profile, uint32 level)
+{
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H264 profile %d, level %d\n", profile, level);
+
+ if ((m_default_profile_chk &&
+ profile != BASELINE_PROFILE &&
+ profile != MAIN_PROFILE &&
+ profile != HIGH_PROFILE) || (m_default_level_chk && level > MAX_SUPPORTED_LEVEL)
+ ) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/H264_Utils.h b/omx/mm-video/qdsp6/vdec/src/H264_Utils.h
new file mode 100755
index 0000000..1ca06bf
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/H264_Utils.h
@@ -0,0 +1,222 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef H264_UTILS_H
+#define H264_UTILS_H
+
+/*========================================================================
+
+ O p e n M M
+ U t i l i t i e s a n d H e l p e r R o u t i n e s
+
+*//** @file H264_Utils.h
+This module contains H264 video decoder utilities and helper routines.
+
+*//*====================================================================== */
+
+
+/* =======================================================================
+
+ INCLUDE FILES FOR MODULE
+
+========================================================================== */
+#include<stdio.h>
+#include "Map.h"
+#include "qtypes.h"
+#include "OMX_Core.h"
+
+#define STD_MIN(x,y) (((x) < (y)) ? (x) : (y))
+
+/* =======================================================================
+
+ DATA DECLARATIONS
+
+========================================================================== */
+
+/* -----------------------------------------------------------------------
+** Constant / Define Declarations
+** ----------------------------------------------------------------------- */
+// Common format block header definitions
+#define MT_VIDEO_META_STREAM_HEADER 0x00
+#define MT_VIDEO_MEDIA_STREAM_HEADER 0x01
+#define MT_VIDEO_META_MEDIA_STREAM_HEADER 0x02
+
+// H.264 format block header definitions
+#define MT_VIDEO_H264_ACCESS_UNIT_FORMAT 0x00
+#define MT_VIDEO_H264_NAL_FORMT 0x01
+#define MT_VIDEO_H264_BYTE_FORMAT 0x02
+#define MT_VIDEO_H264_BYTE_STREAM_FORMAT 0x00
+#define MT_VIDEO_H264_NAL_UNIT_STREAM_FORMAT 0x01
+#define MT_VIDEO_H264_FORMAT_BLOCK_HEADER_SIZE 18
+
+// MPEG-4 format block header definitions
+#define MT_VIDEO_MPEG4_VOP_FORMAT 0x00
+#define MT_VIDEO_MPEG4_SLICE_FORMAT 0x01
+#define MT_VIDEO_MPEG4_BYTE_FORMAT 0x02
+#define MT_VIDEO_MPEG4_FORMAT_BLOCK_HEADER_SIZE 15
+
+// H.263 format block header definitions
+#define MT_VIDEO_H263_PICTURE_FORMAT 0x00
+#define MT_VIDEO_H263_GOB_FORMAT 0x01
+#define MT_VIDEO_H263_SLICE_STRUCTURED_FORMAT 0x02
+#define MT_VIDEO_H263_BYTE_FORMAT 0x03
+#define MT_VIDEO_H263_FORMAT_BLOCK_HEADER_SIZE 16
+
+/* =======================================================================
+** Function Declarations
+** ======================================================================= */
+
+/* -----------------------------------------------------------------------
+** Type Declarations
+** ----------------------------------------------------------------------- */
+
+// This type is used when parsing an H.264 bitstream to collect H.264 NAL
+// units that need to go in the meta data.
+struct H264ParamNalu {
+ uint32 picSetID;
+ uint32 seqSetID;
+ uint32 picOrderCntType;
+ bool frameMbsOnlyFlag;
+ bool picOrderPresentFlag;
+ uint32 picWidthInMbsMinus1;
+ uint32 picHeightInMapUnitsMinus1;
+ uint32 log2MaxFrameNumMinus4;
+ uint32 log2MaxPicOrderCntLsbMinus4;
+ bool deltaPicOrderAlwaysZeroFlag;
+ //std::vector<uint8> nalu;
+ uint32 nalu;
+ uint32 crop_left;
+ uint32 crop_right;
+ uint32 crop_top;
+ uint32 crop_bot;
+};
+//typedef map<uint32, H264ParamNalu> H264ParamNaluSet;
+typedef Map < uint32, H264ParamNalu * >H264ParamNaluSet;
+
+typedef enum {
+ NALU_TYPE_UNSPECIFIED = 0,
+ NALU_TYPE_NON_IDR,
+ NALU_TYPE_PARTITION_A,
+ NALU_TYPE_PARTITION_B,
+ NALU_TYPE_PARTITION_C,
+ NALU_TYPE_IDR,
+ NALU_TYPE_SEI,
+ NALU_TYPE_SPS,
+ NALU_TYPE_PPS,
+ NALU_TYPE_ACCESS_DELIM,
+ NALU_TYPE_EOSEQ,
+ NALU_TYPE_EOSTREAM,
+ NALU_TYPE_FILLER_DATA,
+ NALU_TYPE_RESERVED,
+} NALU_TYPE;
+
+// NAL header information
+typedef struct {
+ uint32 nal_ref_idc;
+ uint32 nalu_type;
+ uint32 forbidden_zero_bit;
+} NALU;
+
+// This structure contains persistent information about an H.264 stream as it
+// is parsed.
+//struct H264StreamInfo {
+// H264ParamNaluSet pic;
+// H264ParamNaluSet seq;
+//};
+
+class RbspParser
+/******************************************************************************
+ ** This class is used to convert an H.264 NALU (network abstraction layer
+ ** unit) into RBSP (raw byte sequence payload) and extract bits from it.
+ *****************************************************************************/
+{
+ public:
+ RbspParser(const uint8 * begin, const uint8 * end);
+
+ virtual ~ RbspParser();
+
+ uint32 next();
+ void advance();
+ uint32 u(uint32 n);
+ uint32 ue();
+ int32 se();
+
+ private:
+ const uint8 *begin, *end;
+ int32 pos;
+ uint32 bit;
+ uint32 cursor;
+ bool advanceNeeded;
+};
+
+class H264_Utils {
+ public:
+ H264_Utils();
+ ~H264_Utils();
+ void initialize_frame_checking_environment();
+ void allocate_rbsp_buffer(uint32 inputBufferSize);
+ bool isNewFrame(OMX_IN OMX_U8 * bitstream,
+ OMX_IN OMX_U32 bitstream_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_BOOL & isNewFrame,
+ bool & isUpdateTimestamp);
+ bool parseHeader(uint8 * encodedBytes,
+ uint32 totalBytes,
+ uint32 nal_len,
+ unsigned &height,
+ unsigned &width,
+ bool & bInterlace,
+ unsigned &cropx,
+ unsigned &cropy, unsigned &cropdx, unsigned &cropdy);
+ OMX_U32 parse_first_h264_input_buffer(OMX_IN OMX_BUFFERHEADERTYPE *
+ buffer,
+ OMX_U32 size_of_nal_length_field);
+ OMX_U32 check_header(OMX_IN OMX_BUFFERHEADERTYPE * buffer,
+ OMX_U32 sizeofNAL, bool & isPartial,
+ OMX_U32 headerState);
+
+ private:
+ boolean extract_rbsp(OMX_IN OMX_U8 * buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_U8 * rbsp_bistream,
+ OMX_OUT OMX_U32 * rbsp_length,
+ OMX_OUT NALU * nal_unit);
+ bool validate_profile_and_level(uint32 profile, uint32 level);
+
+ bool m_default_profile_chk;
+ bool m_default_level_chk;
+ unsigned m_height;
+ unsigned m_width;
+ H264ParamNaluSet pic;
+ H264ParamNaluSet seq;
+ uint8 *m_rbspBytes;
+ NALU m_prv_nalu;
+ bool m_forceToStichNextNAL;
+};
+
+#endif /* H264_UTILS_H */
diff --git a/omx/mm-video/qdsp6/vdec/src/MP4_Utils.cpp b/omx/mm-video/qdsp6/vdec/src/MP4_Utils.cpp
new file mode 100755
index 0000000..d303d1c
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/MP4_Utils.cpp
@@ -0,0 +1,1163 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "MP4_Utils.h"
+#include "omx_vdec.h"
+# include <stdio.h>
+
+#ifdef _ANDROID_
+#include "cutils/properties.h"
+#endif
+
+
+/* -----------------------------------------------------------------------
+** Forward Declarations
+** ----------------------------------------------------------------------- */
+
+/* =======================================================================
+** Function Definitions
+** ======================================================================= */
+
+/*<EJECT>*/
+/*===========================================================================
+FUNCTION:
+ MP4_Utils constructor
+
+DESCRIPTION:
+ Constructs an instance of the Mpeg4 Utilitys.
+
+RETURN VALUE:
+ None.
+===========================================================================*/
+MP4_Utils::MP4_Utils()
+{
+#ifdef _ANDROID_
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+#endif
+
+ m_SrcWidth = 0;
+ m_SrcHeight = 0;
+ m_default_profile_chk = true;
+ m_default_level_chk = true;
+
+#ifdef _ANDROID_
+ if(0 != property_get("persist.omxvideo.profilecheck", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_profile_chk = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "MP4_Utils:: Constr failed in \
+ getting value for the Android property [persist.omxvideo.profilecheck]");
+ }
+
+ if(0 != property_get("persist.omxvideo.levelcheck", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_level_chk = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "MP4_Utils:: Constr failed in \
+ getting value for the Android property [persist.omxvideo.levelcheck]");
+ }
+#endif
+}
+
+/* <EJECT> */
+/*===========================================================================
+
+FUNCTION:
+ MP4_Utils destructor
+
+DESCRIPTION:
+ Destructs an instance of the Mpeg4 Utilities.
+
+RETURN VALUE:
+ None.
+===========================================================================*/
+MP4_Utils::~MP4_Utils()
+{
+}
+
+/* <EJECT> */
+/*===========================================================================
+FUNCTION:
+ read_bit_field
+
+DESCRIPTION:
+ This helper function reads a field of given size (in bits) out of a raw
+ bitstream.
+
+INPUT/OUTPUT PARAMETERS:
+ posPtr: Pointer to posInfo structure, containing current stream position
+ information
+
+ size: Size (in bits) of the field to be read; assumed size <= 32
+
+ NOTE: The bitPos is the next available bit position in the byte pointed to
+ by the bytePtr. The bit with the least significant position in the byte
+ is considered bit number 0.
+
+RETURN VALUE:
+ Value of the bit field required (stored in a 32-bit value, right adjusted).
+
+SIDE EFFECTS:
+ None.
+---------------------------------------------------------------------------*/
+uint32 MP4_Utils::read_bit_field(posInfoType * posPtr, uint32 size) {
+ uint8 *bits = &posPtr->bytePtr[0];
+ uint32 bitBuf =
+ (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
+
+ uint32 value = (bitBuf >> (32 - posPtr->bitPos - size)) & MASK(size);
+
+ /* Update the offset in preparation for next field */
+ posPtr->bitPos += size;
+
+ while (posPtr->bitPos >= 8) {
+ posPtr->bitPos -= 8;
+ posPtr->bytePtr++;
+ }
+ return value;
+
+}
+
+/* <EJECT> */
+/*===========================================================================
+FUNCTION:
+ find_code
+
+DESCRIPTION:
+ This helper function searches a bitstream for a specific 4 byte code.
+
+INPUT/OUTPUT PARAMETERS:
+ bytePtr: pointer to starting location in the bitstream
+ size: size (in bytes) of the bitstream
+ codeMask: mask for the code we are looking for
+ referenceCode: code we are looking for
+
+RETURN VALUE:
+ Pointer to a valid location if the code is found; 0 otherwise.
+
+SIDE EFFECTS:
+ None.
+---------------------------------------------------------------------------*/
+static uint8 *find_code
+ (uint8 * bytePtr, uint32 size, uint32 codeMask, uint32 referenceCode) {
+ uint32 code = 0xFFFFFFFF;
+ for (uint32 i = 0; i < size; i++) {
+ code <<= 8;
+ code |= *bytePtr++;
+
+ if ((code & codeMask) == referenceCode) {
+ return bytePtr;
+ }
+ }
+
+ printf("Unable to find code\n");
+
+ return NULL;
+}
+
+/*
+=============================================================================
+FUNCTION:
+ populateHeightNWidthFromShortHeader
+
+DESCRIPTION:
+ This function parses the short header and populates frame height and width
+ into MP4_Utils.
+
+INPUT/OUTPUT PARAMETERS:
+ psBits - pointer to input stream of bits
+
+RETURN VALUE:
+ Error code
+
+SIDE EFFECTS:
+ None.
+
+=============================================================================
+*/
+int16 MP4_Utils::populateHeightNWidthFromShortHeader(mp4StreamType * psBits) {
+ bool extended_ptype = false;
+ bool opptype_present = false;
+ bool fCustomSourceFormat = false;
+ uint32 marker_bit;
+ uint32 source_format;
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_dataBeginPtr = psBits->data;
+ //22 -> short_video_start_marker
+ if (SHORT_VIDEO_START_MARKER != read_bit_field(&m_posInfo, 22))
+ return MP4_INVALID_VOL_PARAM;
+ //8 -> temporal_reference
+ //1 -> marker bit
+ //1 -> split_screen_indicator
+ //1 -> document_camera_indicator
+ //1 -> full_picture_freeze_release
+ read_bit_field(&m_posInfo, 13);
+ source_format = read_bit_field(&m_posInfo, 3);
+ switch (source_format) {
+ case 1:
+ // sub-QCIF
+ m_SrcWidth = 128;
+ m_SrcHeight = 96;
+ break;
+
+ case 2:
+ // QCIF
+ m_SrcWidth = 176;
+ m_SrcHeight = 144;
+ break;
+
+ case 3:
+ // CIF
+ m_SrcWidth = 352;
+ m_SrcHeight = 288;
+ break;
+
+ case 4:
+ // 4CIF
+ m_SrcWidth = 704;
+ m_SrcHeight = 576;
+ break;
+
+ case 5:
+ // 16CIF
+ m_SrcWidth = 1408;
+ m_SrcHeight = 1152;
+ break;
+
+ case 7:
+ extended_ptype = true;
+ break;
+
+ default:
+ return MP4_INVALID_VOL_PARAM;
+ }
+
+ if (extended_ptype) {
+ /* Plus PTYPE (PLUSPTYPE)
+ ** This codeword of 12 or 30 bits is comprised of up to three subfields:
+ ** UFEP, OPPTYPE, and MPPTYPE. OPPTYPE is present only if UFEP has a
+ ** particular value.
+ */
+
+ /* Update Full Extended PTYPE (UFEP) */
+ uint32 ufep = read_bit_field(&m_posInfo, 3);
+ switch (ufep) {
+ case 0:
+ /* Only MMPTYPE fields are included in current picture header, the
+ ** optional part of PLUSPTYPE (OPPTYPE) is not present
+ */
+ opptype_present = false;
+ break;
+
+ case 1:
+ /* all extended PTYPE fields (OPPTYPE and MPPTYPE) are included in
+ ** current picture header
+ */
+ opptype_present = true;
+ break;
+
+ default:
+ return MP4ERROR_UNSUPPORTED_UFEP;
+ }
+
+ if (opptype_present) {
+ /* The Optional Part of PLUSPTYPE (OPPTYPE) (18 bits) */
+ /* source_format */
+ source_format = read_bit_field(&m_posInfo, 3);
+ switch (source_format) {
+ case 1:
+ /* sub-QCIF */
+ m_SrcWidth = 128;
+ m_SrcHeight = 96;
+ break;
+
+ case 2:
+ /* QCIF */
+ m_SrcWidth = 176;
+ m_SrcHeight = 144;
+ break;
+
+ case 3:
+ /* CIF */
+ m_SrcWidth = 352;
+ m_SrcHeight = 288;
+ break;
+
+ case 4:
+ /* 4CIF */
+ m_SrcWidth = 704;
+ m_SrcHeight = 576;
+ break;
+
+ case 5:
+ /* 16CIF */
+ m_SrcWidth = 1408;
+ m_SrcHeight = 1152;
+ break;
+
+ case 6:
+ /* custom source format */
+ fCustomSourceFormat = true;
+ break;
+
+ default:
+ return MP4ERROR_UNSUPPORTED_SOURCE_FORMAT;
+ }
+
+ /* Custom PCF */
+ read_bit_field(&m_posInfo, 1);
+
+ /* Continue parsing to determine whether H.263 Profile 1,2, or 3 is present.
+ ** Only Baseline profile P0 is supported
+ ** Baseline profile doesn't have any ANNEX supported.
+ ** This information is used initialize the DSP. First parse past the
+ ** unsupported optional custom PCF and Annexes D, E, and F.
+ */
+ uint32 PCF_Annex_D_E_F = read_bit_field(&m_posInfo, 3);
+ if (PCF_Annex_D_E_F != 0)
+ return MP4ERROR_UNSUPPORTED_SOURCE_FORMAT;
+
+ /* Parse past bit for Annex I, J, K, N, R, S, T */
+ uint32 PCF_Annex_I_J_K_N_R_S_T =
+ read_bit_field(&m_posInfo, 7);
+ if (PCF_Annex_I_J_K_N_R_S_T != 0)
+ return MP4ERROR_UNSUPPORTED_SOURCE_FORMAT;
+
+ /* Parse past one marker bit, and three reserved bits */
+ read_bit_field(&m_posInfo, 4);
+
+ /* Parse past the 9-bit MPPTYPE */
+ read_bit_field(&m_posInfo, 9);
+
+ /* Read CPM bit */
+ uint32 continuous_presence_multipoint =
+ read_bit_field(&m_posInfo, 1);
+ if (fCustomSourceFormat) {
+ if (continuous_presence_multipoint) {
+ /* PSBI always follows immediately after CPM if CPM = "1", so parse
+ ** past the PSBI.
+ */
+ read_bit_field(&m_posInfo, 2);
+ }
+ /* Extract the width and height from the Custom Picture Format (CPFMT) */
+ uint32 pixel_aspect_ration_code =
+ read_bit_field(&m_posInfo, 4);
+ if (pixel_aspect_ration_code == 0)
+ return MP4_INVALID_VOL_PARAM;
+
+ uint32 picture_width_indication =
+ read_bit_field(&m_posInfo, 9);
+ m_SrcWidth =
+ ((picture_width_indication & 0x1FF) +
+ 1) << 2;
+
+ marker_bit = read_bit_field(&m_posInfo, 1);
+ if (marker_bit == 0)
+ return MP4_INVALID_VOL_PARAM;
+
+ uint32 picture_height_indication =
+ read_bit_field(&m_posInfo, 9);
+ m_SrcHeight =
+ (picture_height_indication & 0x1FF) << 2;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_FATAL,
+ "m_SrcHeight = %d\n",
+ m_SrcHeight);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_FATAL,
+ "m_SrcWidth = %d\n", m_SrcWidth);
+ }
+ } else {
+ /* UFEP must be "001" for INTRA picture types */
+ return MP4_INVALID_VOL_PARAM;
+ }
+ }
+ if (m_SrcWidth * m_SrcHeight >
+ MP4_MAX_DECODE_WIDTH * MP4_MAX_DECODE_HEIGHT) {
+ /* Frame dimesions greater than maximum size supported */
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Frame Dimensions not supported %d %d",
+ m_SrcWidth, m_SrcHeight);
+ return MP4ERROR_UNSUPPORTED_SOURCE_FORMAT;
+ }
+ return MP4ERROR_SUCCESS;
+}
+
+/* <EJECT> */
+/*===========================================================================
+
+FUNCTION:
+ populateHeightNWidthFromVolHeader
+
+DESCRIPTION:
+ This function parses the VOL header and populates frame height and width
+ into MP4_Utils.
+
+NOTE:
+ Q6 repeates the same parsing at its end and in the case of parsing failure it
+ wont tell us the reason, so we need to repeat atleast a abridged version
+ of parse, to know the reason if there is a parse failure.
+
+INPUT/OUTPUT PARAMETERS:
+ psBits - pointer to input stream of bits
+
+RETURN VALUE:
+ Error code
+
+SIDE EFFECTS:
+ None.
+
+===========================================================================*/
+
+bool MP4_Utils::parseHeader(mp4StreamType * psBits) {
+ uint32 profile_and_level_indication = 0;
+ uint8 VerID = 1; /* default value */
+ long hxw = 0;
+
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_dataBeginPtr = psBits->data;
+
+
+
+ /* parsing Visual Object Seqence(VOS) header */
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ MASK(32),
+ VISUAL_OBJECT_SEQUENCE_START_CODE);
+
+ if ( m_posInfo.bytePtr == NULL )
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,"Video bit stream is not starting \
+ with VISUAL_OBJECT_SEQUENCE_START_CODE");
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+
+ uint32 start_marker = read_bit_field (&m_posInfo, 32);
+ if ( (start_marker & SHORT_HEADER_MASK) == SHORT_HEADER_START_MARKER )
+ {
+ if(MP4ERROR_SUCCESS == populateHeightNWidthFromShortHeader(psBits))
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,"Short Header Found and parsed succesfully");
+ return true;
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Short Header parsing failure");
+ return false;
+ }
+ }
+ else
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK, "Could not find short header either");
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ }
+ }
+ else
+ {
+ uint32 profile_and_level_indication = read_bit_field (&m_posInfo, 8);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "MP4 profile and level %lx",profile_and_level_indication);
+
+ if ((m_default_profile_chk && m_default_level_chk)
+ && (profile_and_level_indication != RESERVED_OBJECT_TYPE)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL0)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL1)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL2)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL3)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL4A)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL5)
+ && (profile_and_level_indication != SIMPLE_PROFILE_LEVEL6)
+ && (profile_and_level_indication != SIMPLE_SCALABLE_PROFILE_LEVEL0)
+ && (profile_and_level_indication != SIMPLE_SCALABLE_PROFILE_LEVEL1)
+ && (profile_and_level_indication != SIMPLE_SCALABLE_PROFILE_LEVEL2)
+ && (profile_and_level_indication != ADVANCED_SIMPLE_PROFILE_LEVEL0)
+ && (profile_and_level_indication != ADVANCED_SIMPLE_PROFILE_LEVEL1)
+ && (profile_and_level_indication != ADVANCED_SIMPLE_PROFILE_LEVEL2)
+ && (profile_and_level_indication != ADVANCED_SIMPLE_PROFILE_LEVEL3)
+ && (profile_and_level_indication != ADVANCED_SIMPLE_PROFILE_LEVEL4)
+ && (profile_and_level_indication != ADVANCED_SIMPLE_PROFILE_LEVEL5))
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_FATAL,
+ "Caution: INVALID_PROFILE_AND_LEVEL 0x%lx \n",profile_and_level_indication);
+ return false;
+ }
+ }
+
+
+
+
+ /* parsing Visual Object(VO) header*/
+ /* note: for now, we skip over the user_data */
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ MASK(32),
+ VISUAL_OBJECT_START_CODE);
+ if(m_posInfo.bytePtr == NULL)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Could not find VISUAL_OBJECT_START_CODE");
+
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ }
+ else
+ {
+ uint32 is_visual_object_identifier = read_bit_field (&m_posInfo, 1);
+ if ( is_visual_object_identifier )
+ {
+ /* visual_object_verid*/
+ read_bit_field (&m_posInfo, 4);
+ /* visual_object_priority*/
+ read_bit_field (&m_posInfo, 3);
+ }
+
+ /* visual_object_type*/
+ uint32 visual_object_type = read_bit_field (&m_posInfo, 4);
+ if ( visual_object_type != VISUAL_OBJECT_TYPE_VIDEO_ID )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "visual_object_type can only be VISUAL_OBJECT_TYPE_VIDEO_ID");
+ return false;
+ }
+ /* skipping video_signal_type params*/
+
+
+ /*parsing Video Object header*/
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ VIDEO_OBJECT_START_CODE_MASK,
+ VIDEO_OBJECT_START_CODE);
+ if ( m_posInfo.bytePtr == NULL )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_FATAL,
+ "Unable to find VIDEO_OBJECT_START_CODE");
+ return false;
+ }
+ }
+
+ /* parsing Video Object Layer(VOL) header */
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ VIDEO_OBJECT_LAYER_START_CODE_MASK,
+ VIDEO_OBJECT_LAYER_START_CODE);
+ if ( m_posInfo.bytePtr == NULL )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Unable to find VIDEO_OBJECT_LAYER_START_CODE");
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ SHORT_HEADER_MASK,
+ SHORT_HEADER_START_CODE);
+ if( m_posInfo.bytePtr )
+ {
+ if(MP4ERROR_SUCCESS == populateHeightNWidthFromShortHeader(psBits))
+ {
+ return true;
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Short Header parsing failure");
+ return false;
+ }
+ }
+ else
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,
+ "Unable to find VIDEO_OBJECT_LAYER or SHORT_HEADER START CODE");
+ return MP4_INVALID_VOL_PARAM;
+ }
+ }
+
+ // 1 -> random accessible VOL
+ read_bit_field(&m_posInfo, 1);
+
+ uint32 video_object_type_indication = read_bit_field (&m_posInfo, 8);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Video Object Type %lx",video_object_type_indication);
+ if ( (video_object_type_indication != SIMPLE_OBJECT_TYPE) &&
+ (video_object_type_indication != SIMPLE_SCALABLE_OBJECT_TYPE) &&
+ (video_object_type_indication != CORE_OBJECT_TYPE) &&
+ (video_object_type_indication != ADVANCED_SIMPLE) &&
+ (video_object_type_indication != RESERVED_OBJECT_TYPE) &&
+ (video_object_type_indication != MAIN_OBJECT_TYPE))
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Video Object Type not supported %lx",video_object_type_indication);
+ return false;
+ }
+ /* is_object_layer_identifier*/
+ uint32 is_object_layer_identifier = read_bit_field (&m_posInfo, 1);
+ if ( is_object_layer_identifier )
+ {
+ uint32 video_object_layer_verid = read_bit_field (&m_posInfo, 4);
+ uint32 video_object_layer_priority = read_bit_field (&m_posInfo, 3);
+ VerID = (unsigned char)video_object_layer_verid;
+ }
+
+ /* aspect_ratio_info*/
+ uint32 aspect_ratio_info = read_bit_field (&m_posInfo, 4);
+ if ( aspect_ratio_info == EXTENDED_PAR )
+ {
+ /* par_width*/
+ read_bit_field (&m_posInfo, 8);
+ /* par_height*/
+ read_bit_field (&m_posInfo, 8);
+ }
+
+
+
+ /* vol_control_parameters */
+ uint32 vol_control_parameters = read_bit_field (&m_posInfo, 1);
+ if ( vol_control_parameters )
+ {
+ /* chroma_format*/
+ uint32 chroma_format = read_bit_field (&m_posInfo, 2);
+ if ( chroma_format != 1 )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "returning CHROMA_FORMAT_NOT_4_2_0 ");
+ return false;
+ }
+
+ /* low_delay*/
+ uint32 low_delay = read_bit_field (&m_posInfo, 1);
+ if ( !low_delay )
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,"Possible B_VOPs in bitstream.");
+ }
+
+ /* vbv_parameters (annex D)*/
+ uint32 vbv_parameters = read_bit_field (&m_posInfo, 1);
+ if ( vbv_parameters )
+ {
+ /* first_half_bitrate*/
+ uint32 first_half_bitrate = read_bit_field (&m_posInfo, 15);
+ uint32 marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* latter_half_bitrate*/
+ uint32 latter_half_bitrate = read_bit_field (&m_posInfo, 15);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ uint32 VBVPeakBitRate = (first_half_bitrate << 15) + latter_half_bitrate;
+ if ( VBVPeakBitRate > MAX_BITRATE )
+ {
+ QTV_MSG_PRIO1(QTVDIAG_VIDEO_TASK, QTVDIAG_PRIO_ERROR,
+ "VBV MAX_BITRATE_EXCEEDED %lx",VBVPeakBitRate);
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_VIDEO_TASK, QTVDIAG_PRIO_ERROR,
+ "VBV Peak bit rate %lx",VBVPeakBitRate);
+ }
+
+ /* first_half_vbv_buffer_size*/
+ uint32 first_half_vbv_buffer_size = read_bit_field (&m_posInfo, 15);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* latter_half_vbv_buffer_size*/
+ uint32 latter_half_vbv_buffer_size = read_bit_field (&m_posInfo, 3);
+
+ uint32 VBVBufferSize = (first_half_vbv_buffer_size << 3) + latter_half_vbv_buffer_size;
+ if ( VBVBufferSize > MAX_VBVBUFFERSIZE )
+ {
+ QTV_MSG_PRIO1(QTVDIAG_VIDEO_TASK, QTVDIAG_PRIO_ERROR,
+ "VBV MAX_VBVBUFFERSIZE_EXCEEDED %lx",VBVBufferSize);
+ }
+
+ /* first_half_vbv_occupancy*/
+ uint32 first_half_vbv_occupancy = read_bit_field (&m_posInfo, 11);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* latter_half_vbv_occupancy*/
+ uint32 latter_half_vbv_occupancy = read_bit_field (&m_posInfo, 15);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+ }/* vbv_parameters*/
+ }/*vol_control_parameters*/
+
+
+ /* video_object_layer_shape*/
+ uint32 video_object_layer_shape = read_bit_field (&m_posInfo, 2);
+ uint8 VOLShape = (unsigned char)video_object_layer_shape;
+ if ( VOLShape != MPEG4_SHAPE_RECTANGULAR )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "NON RECTANGULAR_SHAPE detected, it is not supported");
+ return false;
+ }
+
+ /* marker_bit*/
+ uint32 marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1 )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* vop_time_increment_resolution*/
+ uint32 vop_time_increment_resolution = read_bit_field (&m_posInfo, 16);
+ uint16 TimeIncrementResolution = (unsigned short)vop_time_increment_resolution;
+ /* marker_bit*/
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1 )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* compute the nr. of bits for time information in bitstream*/
+ {
+ int i,j;
+ uint8 NBitsTime=0;
+ i = TimeIncrementResolution-1;
+ j = 0;
+ while (i)
+ {
+ j++;
+ i>>=1;
+ }
+ if (j)
+ NBitsTime = j;
+ else
+ /* the time increment resolution is 1, so we need one bit to
+ ** represent it
+ */
+ NBitsTime = 1;
+
+ /* fixed_vop_rate*/
+ uint32 fixed_vop_rate = read_bit_field (&m_posInfo, 1);
+ if ( fixed_vop_rate )
+ {
+ /* fixed_vop_increment*/
+ read_bit_field (&m_posInfo, NBitsTime);
+ }
+ }
+
+
+ /* marker_bit*/
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1 )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* video_object_layer_width*/
+ m_SrcWidth = (uint16)read_bit_field (&m_posInfo, 13);
+
+ /* marker_bit*/
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1 )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+ /* video_object_layer_height*/
+ m_SrcHeight = (uint16)read_bit_field (&m_posInfo, 13);
+
+ /* marker_bit*/
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1 )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "Marker bit not enabled, VOL header parsing failure ");
+ return false;
+ }
+
+
+ /* interlaced*/
+ uint32 interlaced = read_bit_field (&m_posInfo, 1);
+ if (interlaced)
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,"INTERLACED frames detected");
+ }
+
+ /* obmc_disable*/
+ uint32 obmc_disable = read_bit_field (&m_posInfo, 1);
+ if ( !obmc_disable )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "returning OBMC_Enabled it is not supported ");
+ return false;
+ }
+
+ /* Nr. of bits for sprite_enabled is 1 for version 1, and 2 for
+ ** version 2, according to p. 114, Table v2-2. */
+ /* sprite_enable*/
+ uint32 sprite_enable = read_bit_field (&m_posInfo,VerID);
+ if ( sprite_enable )
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_FATAL,
+ "returning SPRITE_VOP_NG Not Supported ");
+ return false;
+ }
+
+ uint32 not_8_bit = read_bit_field (&m_posInfo, 1);
+ if ( not_8_bit )
+ {
+ /* quant_precision*/
+ uint32 quant_precision = read_bit_field (&m_posInfo, 4);
+ if ( quant_precision < MIN_QUANTPRECISION
+ || quant_precision > MAX_QUANTPRECISION )
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,"returning INVALID_QUANT_PRECISION ");
+ return false;
+ }
+
+ /* bits_per_pixel*/
+ uint32 BitsPerPixel = read_bit_field (&m_posInfo, 4);
+ if ( BitsPerPixel < 4 || BitsPerPixel > 12 )
+ {
+ QTV_MSG(QTVDIAG_VIDEO_TASK,"returning INVALID_BITS_PER_PIXEL ");
+ return false;
+ }
+ }
+
+ /* quant_type*/
+ if (read_bit_field (&m_posInfo, 1)) {
+ /*load_intra_quant_mat*/
+ if (read_bit_field (&m_posInfo, 1)) {
+ unsigned char cnt = 2, data;
+ /*intra_quant_mat */
+ read_bit_field (&m_posInfo, 8);
+ data = read_bit_field (&m_posInfo, 8);
+ while (data && cnt < 64) {
+ data = read_bit_field (&m_posInfo, 8);
+ cnt++;
+ }
+ }
+ /*load_non_intra_quant_mat*/
+ if (read_bit_field (&m_posInfo, 1)) {
+ unsigned char cnt = 2, data;
+ /*non_intra_quant_mat */
+ read_bit_field (&m_posInfo, 8);
+ data = read_bit_field (&m_posInfo, 8);
+ while (data && cnt < 64) {
+ data = read_bit_field (&m_posInfo, 8);
+ cnt++;
+ }
+ }
+ }
+ if ( VerID != 1 )
+ {
+ /* quarter_sample*/
+ read_bit_field (&m_posInfo, 1);
+ }
+ /* complexity_estimation_disable*/
+ read_bit_field (&m_posInfo, 1);
+ /* resync_marker_disable*/
+ read_bit_field (&m_posInfo, 1);
+ /* data_partitioned*/
+ if ( read_bit_field (&m_posInfo, 1) ) {
+ hxw = m_SrcWidth* m_SrcHeight;
+ if(hxw > (OMX_CORE_WVGA_WIDTH*OMX_CORE_WVGA_HEIGHT)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Data partition clips not supported for Greater than WVGA resolution \n");
+ return false;
+ }
+ }
+
+ return true;
+
+}
+
+/*===========================================================================
+
+FUNCTION:
+ parseSparkHeader
+
+DESCRIPTION:
+ This function decodes the Spark header and populates the frame width and
+ frame height info in the MP4_Utils members.
+
+INPUT/OUTPUT PARAMETERS:
+ psBits - pointer to input stream of bits
+
+RETURN VALUE:
+ Error code
+
+SIDE EFFECTS:
+ None.
+
+===========================================================================*/
+bool MP4_Utils::parseSparkHeader(mp4StreamType * psBits)
+{
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_dataBeginPtr = psBits->data;
+
+ if (psBits->numBytes < 30)
+ {
+ printf("SPARK header length less than 30\n");
+ return false;
+ }
+ // try to find SPARK format 0 start code which is the same as h263 start code
+
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ SHORT_HEADER_MASK,
+ SHORT_HEADER_START_CODE);
+
+ if ( m_posInfo.bytePtr == NULL )
+ {
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ //Could not find SPARK format 0 start code
+ //Now, try to find SPARK format 1 start code
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ SHORT_HEADER_MASK,
+ SPARK1_START_CODE);
+ }
+
+ if (m_posInfo.bytePtr == NULL)
+ {
+ printf("Could not find SPARK format 0 or format 1 headers\n");
+ return false;
+ }
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+
+ // skip 22 bits of the start code
+ read_bit_field(&m_posInfo, 22);
+
+ // skip 8 bits of Temporal reference field
+ read_bit_field(&m_posInfo, 8);
+
+ // read the source format
+ uint32 sourceFormat = 0;
+ sourceFormat = read_bit_field(&m_posInfo, 3);
+
+ switch (sourceFormat)
+ {
+ case 0:
+ m_SrcWidth = read_bit_field(&m_posInfo, 8);
+ m_SrcHeight = read_bit_field(&m_posInfo, 8);
+ break;
+ case 1:
+ m_SrcWidth = read_bit_field(&m_posInfo, 16);
+ m_SrcHeight = read_bit_field(&m_posInfo, 16);
+ break;
+ case 2: // CIF
+ m_SrcWidth = 352;
+ m_SrcHeight = 288;
+ break;
+ case 3: // QCIF
+ m_SrcWidth = 176;
+ m_SrcHeight = 144;
+ break;
+ case 4: // SQCIF
+ m_SrcWidth = 128;
+ m_SrcHeight = 96;
+ break;
+ case 5: // QVGA
+ m_SrcWidth = 320;
+ m_SrcHeight = 240;
+ break;
+ case 6:
+ m_SrcWidth = 160;
+ m_SrcHeight = 120;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/* <EJECT> */
+
+/*
+=============================================================================
+FUNCTION:
+ HasFrame
+
+DESCRIPTION:
+ This function parses the buffer in the OMX_BUFFERHEADER to check if there is a VOP
+
+INPUT/OUTPUT PARAMETERS:
+ buffer - pointer to OMX buffer header
+
+RETURN VALUE:
+ true if the buffer contains a VOP, false otherwise.
+
+SIDE EFFECTS:
+ None.
+
+=============================================================================
+*/
+bool MP4_Utils::HasFrame(OMX_IN OMX_BUFFERHEADERTYPE * buffer)
+{
+ return find_code(buffer->pBuffer, buffer->nFilledLen,
+ VOP_START_CODE_MASK, VOP_START_CODE) != NULL;
+}
+
+/*===========================================================================
+FUNCTION:
+ MP4_Utils::parse_frames_in_chunk
+
+DESCRIPTION:
+ Calculates number of valid frames present in the chunk based on frame header
+ and set the timestamp interval based on the previous timestamp interval
+
+INPUT/OUTPUT PARAMETERS:
+ IN const uint8* pBitstream
+ IN uint32 size
+ IN int64 timestamp_interval
+ OUT mp4_frame_info_type *frame_info
+
+RETURN VALUE:
+ number of VOPs in chunk
+
+SIDE EFFECTS:
+ noOfVopsInSameChunk is modified with number of frames in the chunk.
+===========================================================================*/
+uint32 MP4_Utils::parse_frames_in_chunk(const uint8* pBitstream,
+ uint32 size,
+ int64 timestamp_interval,
+ mp4_frame_info_type *frame_info)
+{
+ int i = 0;
+ uint32 code = 0;
+ uint32 noOfVopsInSameChunk = 0;
+ uint32 vopType = -1;
+
+ if (timestamp_interval == 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"Timestamp interval = 0. Setting the timestamp interval into 33");
+ timestamp_interval = 33;
+ }
+
+ if (size == 0)
+ {
+ code = (pBitstream[i]<<24) | (pBitstream[i+1]<<16) | (pBitstream[i+2]<<8) | pBitstream[i+3];
+ i += 4;
+ }
+
+ for (; (i<size) && (noOfVopsInSameChunk < MAX_FRAMES_IN_CHUNK); ++i)
+ {
+ if (code == VOP_START_CODE)
+ {
+ frame_info[noOfVopsInSameChunk].offset = i-4;
+ if(noOfVopsInSameChunk > 0)
+ {
+ frame_info[noOfVopsInSameChunk-1].size = (i-4)-(frame_info[noOfVopsInSameChunk-1].offset);
+ frame_info[noOfVopsInSameChunk].timestamp_increment = timestamp_interval * (noOfVopsInSameChunk-1);
+ }
+ vopType = 0x000000c0 & (pBitstream[i]);
+ if(0x00000000 == vopType) frame_info[noOfVopsInSameChunk].vopType = MPEG4_I_VOP;
+ else if(0x00000040 == vopType) frame_info[noOfVopsInSameChunk].vopType = MPEG4_P_VOP;
+ else if(0x00000080 == vopType) frame_info[noOfVopsInSameChunk].vopType = MPEG4_B_VOP;
+ else if(0x000000c0 == vopType) frame_info[noOfVopsInSameChunk].vopType = MPEG4_S_VOP;
+ noOfVopsInSameChunk++;
+ code = 0;
+ }
+ else if (code == VOL_START_CODE)
+ {
+ frame_info[noOfVopsInSameChunk].offset = i-4;
+ frame_info[noOfVopsInSameChunk].vopType = NO_VOP;
+
+ noOfVopsInSameChunk++;
+ break;
+ }
+ code <<= 8;
+ code |= (0x000000FF & (pBitstream[i]));
+ }
+
+ if(noOfVopsInSameChunk > 0 && noOfVopsInSameChunk <= MAX_FRAMES_IN_CHUNK)
+ {
+ frame_info[noOfVopsInSameChunk-1].size = size-(frame_info[noOfVopsInSameChunk-1].offset);
+ }
+
+ if(noOfVopsInSameChunk > 1)
+ {
+ frame_info[0].timestamp_increment = timestamp_interval * (noOfVopsInSameChunk-1);
+ }
+ else if (noOfVopsInSameChunk == 1)
+ {
+ frame_info[0].timestamp_increment = 0;
+ }
+
+ if(noOfVopsInSameChunk == MAX_FRAMES_IN_CHUNK)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"NumFramesinChunk reached Max Value, So possible multiple VOPs in the last frame");
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"FramesinChunk %d", noOfVopsInSameChunk);
+ return noOfVopsInSameChunk;
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/MP4_Utils.h b/omx/mm-video/qdsp6/vdec/src/MP4_Utils.h
new file mode 100644
index 0000000..e25e692
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/MP4_Utils.h
@@ -0,0 +1,367 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef MP4_UTILS_H
+#define MP4_UTILS_H
+/*=============================================================================
+ MP4_UTILS.h
+
+DESCRIPTION
+ This file declares an MP4_Utils helper class to help parse the
+ VOL (Video Object Layer) header and the short header in a raw bitstream.
+
+ There is a dependency on MPEG4 decoder.
+
+ Historocally, this was part of MP4_TL.h, and the only way to parse headers
+ was to have an instance of MP4_TL. However, the future direction for MP4_TL
+ is that (a) it's constructor be private, (b) instances are to be created by
+ a static member factory, and (c) this factory can only be called at
+ vdec_create time.
+
+ This poses a problem when we wish to parse VOL (or other) headers before
+ calling vdec_create.
+
+ The initial solution was to permit MP4_TL to be contructed, and have its
+ iDecodeVOLHeader method called without having its Initialize method called,
+ but this required hacking its destructor to not ASSERT when called in the
+ NOTINIT state. This goes against the desire to restrict how and when an
+ MP4_TL object is created. Thus, we factor the code out, in the hopes
+ that the future MP4_TL implementation will use it.
+
+LIMITATIONS:
+
+ABSTRACT:
+ MPEG 4 video decoding and encoding functionality is accomplished by
+ several modules including but not limited to the: media player
+ application, MPEG 4 engine, MPEG 4 video codec, & MPEG 4 audio codec
+ as outlined below:
+
+EXTERNALIZED FUNCTIONS
+ List functions and a brief description that are exported from this file
+
+INITIALIZATION AND SEQUENCING REQUIREMENTS
+ is only needed if the order of operations is important.
+
+
+============================================================================*/
+
+/* ==========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+========================================================================== */
+#include "qtv_msg.h"
+#include "OMX_Core.h"
+#include "qtypes.h"
+
+/* ==========================================================================
+
+ DEFINITIONS AND DECLARATIONS FOR MODULE
+
+This section contains definitions for constants, macros, types, variables
+and other items needed by this module.
+
+========================================================================== */
+
+/*---------------------------------------------------------------------------
+** MPEG 4 Command Queue, Statistics Queue, Free Queues and Available Packets
+**--------------------------------------------------------------------------- */
+
+/* Structure used to manage input data.
+*/
+//#if 0
+typedef unsigned long int uint32; /* Unsigned 32 bit value */
+typedef unsigned short uint16; /* Unsigned 16 bit value */
+typedef unsigned char uint8; /* Unsigned 8 bit value */
+
+typedef signed long int int32; /* Signed 32 bit value */
+typedef signed short int16; /* Signed 16 bit value */
+typedef signed char int8; /* Signed 8 bit value */
+
+typedef unsigned char byte; /* Unsigned 8 bit value type. */
+//#endif
+#define SIMPLE_PROFILE_LEVEL0 0x08
+#define SIMPLE_PROFILE_LEVEL1 0x01
+#define SIMPLE_PROFILE_LEVEL2 0x02
+#define SIMPLE_PROFILE_LEVEL3 0x03
+#define SIMPLE_PROFILE_LEVEL4A 0x04
+#define SIMPLE_PROFILE_LEVEL5 0x05
+#define SIMPLE_PROFILE_LEVEL6 0x06
+
+#define SIMPLE_SCALABLE_PROFILE_LEVEL0 0x10
+#define SIMPLE_SCALABLE_PROFILE_LEVEL1 0x11
+#define SIMPLE_SCALABLE_PROFILE_LEVEL2 0x12
+
+#define SIMPLE_SCALABLE_PROFILE_LEVEL0 0x10
+#define SIMPLE_SCALABLE_PROFILE_LEVEL1 0x11
+#define SIMPLE_SCALABLE_PROFILE_LEVEL2 0x12
+#define ADVANCED_SIMPLE_PROFILE_LEVEL0 0xF0
+#define ADVANCED_SIMPLE_PROFILE_LEVEL1 0xF1
+#define ADVANCED_SIMPLE_PROFILE_LEVEL2 0xF2
+#define ADVANCED_SIMPLE_PROFILE_LEVEL3 0xF3
+#define ADVANCED_SIMPLE_PROFILE_LEVEL4 0xF4
+#define ADVANCED_SIMPLE_PROFILE_LEVEL5 0xF5
+
+#define VISUAL_OBJECT_SEQUENCE_START_CODE 0x000001B0
+#define MP4ERROR_SUCCESS 0
+
+#define VIDEO_OBJECT_LAYER_START_CODE_MASK 0xFFFFFFF0
+#define VIDEO_OBJECT_LAYER_START_CODE 0x00000120
+#define VOP_START_CODE_MASK 0xFFFFFFFF
+#define VOP_START_CODE 0x000001B6
+#define SHORT_HEADER_MASK 0xFFFFFC00
+#define SHORT_HEADER_START_MARKER 0x00008000
+#define SHORT_HEADER_START_CODE 0x00008000
+#define SPARK1_START_CODE 0x00008400
+#define MPEG4_SHAPE_RECTANGULAR 0x00
+#define EXTENDED_PAR 0xF
+#define SHORT_VIDEO_START_MARKER 0x20
+#define MP4_INVALID_VOL_PARAM (0x0001) // unsupported VOL parameter
+#define MP4ERROR_UNSUPPORTED_UFEP -1068
+#define MP4ERROR_UNSUPPORTED_SOURCE_FORMAT -1069
+#define MASK(x) (0xFFFFFFFF >> (32 - (x)))
+#define VISUAL_OBJECT_TYPE_VIDEO_ID 0x1
+#define VISUAL_OBJECT_START_CODE 0x000001B5
+#define VIDEO_OBJECT_START_CODE_MASK 0xFFFFFFE0
+#define VIDEO_OBJECT_START_CODE 0x00000100
+
+#define RESERVED_OBJECT_TYPE 0x0
+#define SIMPLE_OBJECT_TYPE 0x1
+#define SIMPLE_SCALABLE_OBJECT_TYPE 0x2
+#define CORE_OBJECT_TYPE 0x3
+#define MAIN_OBJECT_TYPE 0x4
+#define N_BIT_OBJECT_TYPE 0x5
+#define BASIC_ANIMATED_2D_TEXTURE 0x6
+#define ANIMATED_2D_MESH 0x7
+#define ADVANCED_SIMPLE 0x11
+
+
+#define SIMPLE_L1_MAX_VBVBUFFERSIZE 10 /* VBV Max Buffer size=10 (p. 498) */
+#define SIMPLE_L1_MAX_BITRATE 160 /* is is 64kpbs or 160 400bits/sec units */
+#define SIMPLE_L2_MAX_VBVBUFFERSIZE 40 /* VBV Max Buffer size = 40 */
+#define SIMPLE_L2_MAX_BITRATE 320 /* 320 400bps units = 128kpbs */
+#define SIMPLE_L3_MAX_VBVBUFFERSIZE 40 /* VBV Max Buffer size = 40 */
+#define SIMPLE_L3_MAX_BITRATE 960 /* 960 400bps units = 384kpbs */
+
+/* The MP4 decoder currently supports Simple Profile@L3 */
+#define MAX_VBVBUFFERSIZE (SIMPLE_L3_MAX_VBVBUFFERSIZE)
+#define MAX_BITRATE (SIMPLE_L3_MAX_BITRATE)
+
+#define MAX_QUANTPRECISION 9
+#define MIN_QUANTPRECISION 3
+
+#define MP4_VGA_WIDTH 640
+#define MP4_VGA_HEIGHT 480
+#define MP4_WVGA_WIDTH 800
+#define MP4_WVGA_HEIGHT 480
+
+#define MP4_MAX_DECODE_WIDTH MP4_WVGA_WIDTH
+#define MP4_MAX_DECODE_HEIGHT MP4_WVGA_HEIGHT
+
+typedef struct {
+ unsigned char *data;
+ unsigned long int numBytes;
+} mp4StreamType;
+
+#define MAX_FRAMES_IN_CHUNK 10
+#define VOP_START_CODE 0x000001B6
+#define VOL_START_CODE 0x000001B0
+
+typedef enum VOPTYPE
+{
+ NO_VOP = -1, // bitstream contains no VOP.
+ MPEG4_I_VOP = 0, // bitstream contains an MPEG4 I-VOP
+ MPEG4_P_VOP = 1, // bitstream contains an MPEG4 P-VOP
+ MPEG4_B_VOP = 2, // bitstream contains an MPEG4 B-VOP
+ MPEG4_S_VOP = 3, // bitstream contains an MPEG4 S-VOP
+} VOP_TYPE;
+
+typedef struct
+{
+ uint32 timestamp_increment;
+ uint32 offset;
+ uint32 size;
+ VOP_TYPE vopType;
+} mp4_frame_info_type;
+
+
+class MP4_Utils {
+ private:
+ struct posInfoType {
+ uint8 *bytePtr;
+ uint8 bitPos;
+ };
+
+ posInfoType m_posInfo;
+ byte *m_dataBeginPtr;
+
+ uint16 m_SrcWidth, m_SrcHeight; // Dimensions of the source clip
+
+ bool m_default_profile_chk;
+ bool m_default_level_chk;
+
+ public:
+
+ uint16 SrcWidth(void) const {
+ return m_SrcWidth;
+ } uint16 SrcHeight(void)const {
+ return m_SrcHeight;
+ } static bool HasFrame(OMX_IN OMX_BUFFERHEADERTYPE * buffer);
+
+ /* <EJECT> */
+/*===========================================================================
+
+FUNCTION:
+ MP4_Utils constructor
+
+DESCRIPTION:
+ Constructs an instance of the MP4 Parser.
+
+RETURN VALUE:
+ None.
+===========================================================================*/
+ MP4_Utils();
+
+/* <EJECT> */
+/*===========================================================================
+
+FUNCTION:
+ MP4_Utils destructor
+
+DESCRIPTION:
+ Destructs an instance of the MP4_Utils.
+
+RETURN VALUE:
+ None.
+===========================================================================*/
+ ~MP4_Utils();
+
+/*
+============================================================================
+*/
+ int16 populateHeightNWidthFromShortHeader(mp4StreamType * psBits);
+
+/* <EJECT> */
+/*===========================================================================
+
+FUNCTION:
+ iDecodeVOLHeader
+
+DESCRIPTION:
+ This function decodes the VOL (Visual Object Layer) header
+ (ISO/IEC 14496-2:1999/Amd.1:2000(E), section 6.3.3)
+
+INPUT/OUTPUT PARAMETERS:
+ psBits - pointer to input stream of bits
+ psVOL - pointer to structure containing VOL information required
+ by the decoder
+
+RETURN VALUE:
+ Error code
+
+SIDE EFFECTS:
+ None.
+
+===========================================================================*/
+ bool parseHeader(mp4StreamType * psBits);
+
+/* <EJECT> */
+
+/*===========================================================================
+
+FUNCTION:
+ parseSparkHeader
+
+DESCRIPTION:
+ This function decodes the Spark header and populates the frame width and
+ frame height info in the MP4_Utils members.
+
+INPUT/OUTPUT PARAMETERS:
+ psBits - pointer to input stream of bits
+
+RETURN VALUE:
+ Error code
+
+SIDE EFFECTS:
+ None.
+
+===========================================================================*/
+ bool parseSparkHeader(mp4StreamType * psBits);
+
+/* <EJECT> */
+/*===========================================================================
+FUNCTION:
+ read_bit_field
+
+DESCRIPTION:
+ This helper function reads a field of given size (in bits) out of a raw
+ bitstream.
+
+INPUT/OUTPUT PARAMETERS:
+ posPtr: Pointer to posInfo structure, containing current stream position
+ information
+
+ size: Size (in bits) of the field to be read; assumed size <= 32
+
+ NOTE: The bitPos is the next available bit position in the byte pointed to
+ by the bytePtr. The bit with the least significant position in the byte
+ is considered bit number 0.
+
+RETURN VALUE:
+ Value of the bit field required (stored in a 32-bit value, right adjusted).
+
+SIDE EFFECTS:
+ None.
+---------------------------------------------------------------------------*/
+ static uint32 read_bit_field(posInfoType * posPtr, uint32 size);
+/*===========================================================================
+FUNCTION:
+ MP4_Utils::parse_frames_in_chunk
+
+DESCRIPTION:
+ Calculates number of valid frames present in the chunk based on frame header
+ and set the timestamp interval based on the previous timestamp interval
+
+INPUT/OUTPUT PARAMETERS:
+ const uint8* pBitstream [IN]
+ uint32 size [IN]
+ int64 timestamp_interval [IN]
+ mp4_frame_info_type *frame_info [OUT]
+
+RETURN VALUE:
+ number of VOPs in chunk
+
+SIDE EFFECTS:
+ noOfVopsInSameChunk is modified with number of frames in the chunk.
+===========================================================================*/
+uint32 parse_frames_in_chunk(const uint8* pBitstream,
+ uint32 size,
+ int64 timestamp_interval,
+ mp4_frame_info_type *frame_info);
+
+};
+#endif /* MP4_UTILS_H */
diff --git a/omx/mm-video/qdsp6/vdec/src/Map.h b/omx/mm-video/qdsp6/vdec/src/Map.h
new file mode 100644
index 0000000..b3c7833
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/Map.h
@@ -0,0 +1,215 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _MAP_H_
+#define _MAP_H_
+
+#include <stdio.h>
+using namespace std;
+
+template < typename T, typename T2 > class Map {
+ struct node {
+ T data;
+ T2 data2;
+ node *prev;
+ node *next;
+ node(T t, T2 t2, node * p, node * n):data(t), data2(t2),
+ prev(p), next(n) {
+ }};
+ node *head;
+ node *tail;
+ node *tmp;
+ unsigned size_of_list;
+ static Map < T, T2 > *m_self;
+ public:
+ Map():head(NULL), tail(NULL), tmp(head), size_of_list(0) {
+ }
+ bool empty() const {
+ return (!head || !tail);
+ } operator bool() const {
+ return !empty();
+ } void insert(T, T2);
+ void show();
+ int size();
+ T2 find(T); // Return VALUE
+ T find_ele(T); // Check if the KEY is present or not
+ T2 begin(); //give the first ele
+ bool erase(T);
+ bool eraseall();
+ bool isempty();
+ ~Map() {
+ while (head) {
+ node *temp(head);
+ head = head->next;
+ size_of_list--;
+ delete temp;
+ }
+ }
+};
+
+template < typename T, typename T2 > T2 Map < T, T2 >::find(T d1)
+{
+ tmp = head;
+ while (tmp) {
+ if (tmp->data == d1) {
+ return tmp->data2;
+ }
+ tmp = tmp->next;
+ }
+ return 0;
+}
+
+template < typename T, typename T2 > T Map < T, T2 >::find_ele(T d1)
+{
+ tmp = head;
+ while (tmp) {
+ if (tmp->data == d1) {
+ return tmp->data;
+ }
+ tmp = tmp->next;
+ }
+ return 0;
+}
+
+template < typename T, typename T2 > T2 Map < T, T2 >::begin()
+{
+ tmp = head;
+ if (tmp) {
+ return (tmp->data2);
+ }
+ return 0;
+}
+
+template < typename T, typename T2 > void Map < T, T2 >::show()
+{
+ tmp = head;
+ while (tmp) {
+ printf("%d-->%d\n", tmp->data, tmp->data2);
+ tmp = tmp->next;
+ }
+}
+
+template < typename T, typename T2 > int Map < T, T2 >::size()
+{
+ int count = 0;
+ tmp = head;
+ while (tmp) {
+ tmp = tmp->next;
+ count++;
+ }
+ return count;
+}
+
+template < typename T, typename T2 >
+ void Map < T, T2 >::insert(T data, T2 data2)
+{
+ tail = new node(data, data2, tail, NULL);
+ if (tail->prev)
+ tail->prev->next = tail;
+
+ if (empty()) {
+ head = tail;
+ tmp = head;
+ }
+ tmp = head;
+ size_of_list++;
+}
+
+template < typename T, typename T2 > bool Map < T, T2 >::erase(T d)
+{
+ bool found = false;
+ tmp = head;
+ node *prevnode = tmp;
+ node *tempnode;
+
+ while (tmp) {
+ if ((head == tail) && (head->data == d)) {
+ found = true;
+ tempnode = head;
+ head = tail = NULL;
+ delete tempnode;
+ break;
+ }
+ if ((tmp == head) && (tmp->data == d)) {
+ found = true;
+ tempnode = tmp;
+ tmp = tmp->next;
+ tmp->prev = NULL;
+ head = tmp;
+ tempnode->next = NULL;
+ delete tempnode;
+ break;
+ }
+ if ((tmp == tail) && (tmp->data == d)) {
+ found = true;
+ tempnode = tmp;
+ prevnode->next = NULL;
+ tmp->prev = NULL;
+ tail = prevnode;
+ delete tempnode;
+ break;
+ }
+ if (tmp->data == d) {
+ found = true;
+ prevnode->next = tmp->next;
+ tmp->next->prev = prevnode->next;
+ tempnode = tmp;
+ //tmp = tmp->next;
+ delete tempnode;
+ break;
+ }
+ prevnode = tmp;
+ tmp = tmp->next;
+ }
+ if (found)
+ size_of_list--;
+ return found;
+}
+
+template < typename T, typename T2 > bool Map < T, T2 >::eraseall()
+{
+ node *tempnode;
+ tmp = head;
+ while (head) {
+ tempnode = head;
+ tempnode->next = NULL;
+ head = head->next;
+ delete tempnode;
+ }
+ tail = head = NULL;
+ return true;
+}
+
+template < typename T, typename T2 > bool Map < T, T2 >::isempty()
+{
+ if (!size_of_list)
+ return true;
+ else
+ return false;
+}
+
+#endif // _MAP_H_
diff --git a/omx/mm-video/qdsp6/vdec/src/adsp.c b/omx/mm-video/qdsp6/vdec/src/adsp.c
new file mode 100644
index 0000000..ca86c01
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/adsp.c
@@ -0,0 +1,530 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef T_WINNT
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#else
+#include "qdspext.h"
+#include "qdsprtos.h"
+#define QDSP_mpuVDecCmdQueue 4
+#define QDSP_mpuVDecPktQueue 5
+#endif //T_WINNT
+#include <errno.h>
+#include <pthread.h>
+
+#include "adsp.h"
+#include "qtv_msg.h"
+#include "qutility.h"
+
+#if PROFILE_DECODER
+QPERF_INIT(dsp_decode);
+#endif
+
+#define DEBUG 0 // TEST
+
+#if DEBUG // TEST
+static pthread_mutex_t logMTX;
+static FILE *logFD = NULL;
+static const char *logFN = "/data/adsp_log.txt";
+#endif
+
+struct adsp_module {
+ int fd;
+ int cpu_dma_fd;
+ unsigned long cpu_dma_freq;
+ volatile int dead;
+ volatile int init_done;
+
+ void *ctxt;
+ adsp_msg_frame_done_func frame_done;
+ adsp_msg_buffer_done_func buffer_done;
+
+ pthread_t thr;
+};
+
+#ifndef T_WINNT
+void convertFrameInfoToFrameDetails(struct Vdec_FrameDetailsType *Frame_details,
+ struct vdec_frame_info *pFrame)
+{
+ int i;
+ if (NULL == Frame_details || NULL == pFrame) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "convertFrameInfoToFrameDetails() Frame Details or vdec-frame NULL "
+ "Frame Details: 0x%x, pFrame: 0x%x\n",
+ Frame_details, pFrame);
+ }
+ Frame_details->status = (Vdec_StatusType) pFrame->status; //TBD
+ Frame_details->userData1 = pFrame->data1;
+ Frame_details->userData2 = pFrame->data2;
+ Frame_details->timestamp =
+ (unsigned long long)((unsigned long long)pFrame->
+ timestamp_hi << 32 | (unsigned long long)
+ pFrame->timestamp_lo & 0x0FFFFFFFFLL);
+ Frame_details->calculatedTimeStamp =
+ (unsigned long long)((unsigned long long)pFrame->
+ cal_timestamp_hi << 32 | (unsigned long long)
+ pFrame->cal_timestamp_lo & 0x0FFFFFFFFLL);
+ Frame_details->nDecPicWidth = pFrame->dec_width;
+ Frame_details->nDecPicHeight = pFrame->dec_height;
+ Frame_details->cwin.x1 = pFrame->cwin.x1;
+ Frame_details->cwin.y1 = pFrame->cwin.y1;
+ Frame_details->cwin.x2 = pFrame->cwin.x2;
+ Frame_details->cwin.y2 = pFrame->cwin.y2;
+ for (i = 0; i < MAX_FIELDS; i++) {
+ Frame_details->ePicType[i] =
+ (Vdec_PictureType) pFrame->picture_type[i];
+ }
+ Frame_details->ePicFormat = (Vdec_PictureFormat) pFrame->picture_format;
+ Frame_details->nVC1RangeY = pFrame->vc1_rangeY;
+ Frame_details->nVC1RangeUV = pFrame->vc1_rangeUV;
+ Frame_details->ePicResolution =
+ (Vdec_PictureRes) pFrame->picture_resolution;
+ Frame_details->nRepeatProgFrames = pFrame->frame_disp_repeat;
+ Frame_details->bRepeatFirstField = pFrame->repeat_first_field;
+ Frame_details->bTopFieldFirst = pFrame->top_field_first;
+ Frame_details->bFrameInterpFlag = pFrame->interframe_interp;
+ Frame_details->panScan.numWindows = pFrame->panscan.num;
+ for (i = 0; i < MAX_VC1_PAN_SCAN_WINDOWS; i++) {
+ Frame_details->panScan.winHeight[i] = pFrame->panscan.width[i];
+ Frame_details->panScan.winHeight[i] = pFrame->panscan.height[i];
+ Frame_details->panScan.winHorOffset[i] =
+ pFrame->panscan.xoffset[i];
+ Frame_details->panScan.winVerOffset[i] =
+ pFrame->panscan.yoffset[i];
+ }
+
+ Frame_details->nPercentConcealedMacroblocks =
+ pFrame->concealed_macblk_num;
+ Frame_details->flags = pFrame->flags;
+ Frame_details->performanceStats = pFrame->performance_stats;
+}
+void *adsp_thread(void *_mod)
+{
+ struct adsp_module *mod = _mod;
+ int n;
+ struct vdec_msg vdecMsg;
+ struct Vdec_FrameDetailsType vdec_frame;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_thread: event thread start\n");
+ while (!mod->dead) {
+ if (!mod->init_done)
+ continue;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "adsp_thread: Calling IOCTL_GETMSG fd %d\n",
+ mod->fd);
+ if (ioctl(mod->fd, VDEC_IOCTL_GETMSG, &vdecMsg) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "adsp_thread:VDEC_IOCTL_GETMSG failed\n");
+ continue;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "adsp_thread: %d\n", vdecMsg.id);
+ if (vdecMsg.id == VDEC_MSG_REUSEINPUTBUFFER) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "adsp_thread: Reuse input buffer %d\n",
+ vdecMsg.buf_id);
+ mod->buffer_done(mod->ctxt, (void *)vdecMsg.buf_id);
+ } else if (vdecMsg.id == VDEC_MSG_FRAMEDONE) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "adsp_thread: Frame done %x\n",
+ vdecMsg.vfr_info);
+ convertFrameInfoToFrameDetails(&vdec_frame,
+ &vdecMsg.vfr_info);
+#if PROFILE_DECODER
+ if (vdec_frame.status != VDEC_FLUSH_DONE) {
+ QPERF_END_AND_START(dsp_decode);
+ }
+#endif
+ mod->frame_done(mod->ctxt, &vdec_frame,
+ vdecMsg.vfr_info.data2,
+ vdecMsg.vfr_info.offset);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "adsp_thread:VDEC_IOCTL_GETMSG Unknown Msg ID\n");
+ }
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "h264: event thread stop\n");
+ return 0;
+}
+#endif
+
+void adsp_close(struct adsp_module *mod)
+{
+#if PROFILE_DECODER
+ QPERF_TERMINATE(dsp_decode);
+ QPERF_RESET(dsp_decode);
+#endif
+#ifndef T_WINNT
+ int ret;
+ int thread_ret = 0;
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "adsp_close() mod NULL: 0x%x\n", mod);
+ return ;
+ }
+
+ mod->dead = 1;
+
+ if (ioctl(mod->fd, VDEC_IOCTL_CLOSE, NULL) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VDEC_IOCTL_CLOSE failed\n");
+ return;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "adsp_close: 0x%x",
+ (unsigned)mod);
+
+ /*Wait on the adsp event thread completion */
+
+ ret = pthread_join(mod->thr, (void **)&thread_ret);
+
+ if (ret != 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "*************adsp_close: Could not join on the adsp event thread err=%d!!\n",
+ ret);
+ }
+
+ /*Wait on the adsp event thread completion */
+
+ ret = close(mod->fd);
+ if (ret < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "*************adsp_close ERROR!");
+ }
+ if(mod->cpu_dma_fd > 0) {
+ if(write(mod->cpu_dma_fd, &mod->cpu_dma_freq, sizeof(mod->cpu_dma_freq)) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR - adsp: Request cpu_dma_freq write failed\n");
+ }
+ close(mod->cpu_dma_fd);
+ mod->cpu_dma_fd = 0;
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_close returned %d, fd: %d", ret, mod->fd);
+
+#if DEBUG
+ if (logFD) {
+ pthread_mutex_lock(&logMTX);
+ fclose(logFD);
+ logFD = NULL;
+ pthread_mutex_destroy(&logMTX);
+ }
+#endif
+
+ //sleep(1); /* XXX need better way to stop thread XXX */
+ free(mod);
+ mod = NULL;
+#endif //T_WINNT
+}
+
+struct adsp_module *adsp_open(const char *name, struct adsp_open_info info,
+ void *context, int32 vdec_fd)
+{
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "adsp_open: %s", name);
+ int fds[2], r;
+ struct adsp_module *mod;
+ unsigned long cpu_dma_freq = 1000;
+
+ mod = calloc(1, sizeof(*mod));
+ if (!mod)
+ return 0;
+
+ mod->ctxt = context;
+ mod->frame_done = info.frame_done;
+ mod->buffer_done = info.buffer_done;
+
+#ifndef T_WINNT
+ mod->dead = 0;
+ mod->init_done = 0;
+ r = pthread_create(&mod->thr, 0, adsp_thread, mod);
+ if (r < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - unable to create adsp_thread\n");
+ goto fail_thread;
+ }
+
+ mod->fd = vdec_fd;
+ if(mod->fd < 0) {
+ mod->fd = open("/dev/vdec", O_RDWR);
+ if (mod->fd < 0) {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_FATAL,
+ "adsp: cannot open '%s', fd: %d (%s)\n", name,
+ mod->fd, strerror(errno));
+ goto fail_open;
+ }
+ }
+ mod->cpu_dma_fd = open("/dev/cpu_dma_latency", O_RDWR);
+ if(mod->cpu_dma_fd < 0) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_FATAL,
+ "adsp: cannot open cpu_dma_latency, fd: %d (%s)\n",
+ mod->fd, strerror(errno));
+ } else {
+ if(read(mod->cpu_dma_fd, &mod->cpu_dma_freq, sizeof(mod->cpu_dma_freq)) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "ERROR - adsp: Request cpu_dma_freq read failed\n");
+ }
+ if(write(mod->cpu_dma_fd, &cpu_dma_freq, sizeof(cpu_dma_freq)) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "ERROR - adsp: Request cpu_dma_freq write failed\n");
+ }
+ }
+#if DEBUG
+ if (pthread_mutex_init(&logMTX, NULL) == 0) {
+ if (pthread_mutex_lock(&logMTX) == 0) {
+ if (!logFD) {
+ logFD = fopen(logFN, "a");
+ }
+ if (logFD) {
+ fprintf(logFD, "\n");
+ pthread_mutex_unlock(&logMTX);
+ }
+ }
+ if (!logFD) {
+ pthread_mutex_destroy(&logMTX);
+ }
+ }
+ if (!logFD) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "adsp: unable to log adsp writes\n");
+ }
+#endif
+
+#endif
+
+ return mod;
+ fail_open:
+ mod->dead = 1;
+ fail_thread:
+ free(mod);
+ return 0;
+}
+
+int adsp_set_buffers(struct adsp_module *mod, struct adsp_buffer_info bufinfo)
+{
+ struct vdec_buffer mem;
+ int r;
+
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_set_buffers() mod NULL: 0x%x\n", mod);
+ return -1;
+ }
+
+ mem.pmem_id = bufinfo.buf.pmem_id;
+ mem.buf.buf_type = bufinfo.buf_type;
+ mem.buf.num_buf = bufinfo.numbuf;
+ mem.buf.islast = bufinfo.is_last;
+
+ mem.buf.region.src_id = 0x0106e429;
+ mem.buf.region.offset = bufinfo.buf.offset;
+ mem.buf.region.size = bufinfo.buf.size;
+
+ if (ioctl(mod->fd, VDEC_IOCTL_SETBUFFERS, &mem) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VDEC_IOCTL_SETBUFFERS failed\n");
+ mod->dead = 1;
+ return -1;
+ }
+
+ mod->init_done = 1;
+
+ return 0;
+
+}
+
+int adsp_free_buffers(struct adsp_module *mod, struct adsp_buffer_info bufinfo)
+{
+ struct vdec_buffer mem;
+ int r;
+
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_set_buffers() mod NULL: 0x%x\n", mod);
+ return -1;
+ }
+
+ mem.pmem_id = bufinfo.buf.pmem_id;
+ mem.buf.buf_type = bufinfo.buf_type;
+ mem.buf.num_buf = bufinfo.numbuf;
+ mem.buf.islast = bufinfo.is_last;
+
+ mem.buf.region.src_id = 0x0106e429;
+ mem.buf.region.offset = bufinfo.buf.offset;
+ mem.buf.region.size = bufinfo.buf.size;
+
+ if (ioctl(mod->fd, VDEC_IOCTL_FREEBUFFERS, &mem) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VDEC_IOCTL_SETBUFFERS failed\n");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int adsp_init(struct adsp_module *mod, struct adsp_init *init)
+{
+ struct vdec_init vi;
+ struct vdec_buf_req buf;
+ struct vdec_version ver;
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_init() mod NULL: 0x%x\n", mod);
+ return -1;
+ }
+
+ /* Get the driver version */
+ if (ioctl(mod->fd, VDEC_IOCTL_GETVERSION, &ver) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VDEC_IOCTL_GETVERSION failed setting to default version\n");
+ ver.major = 1;
+ ver.minor = 0;
+ }
+
+ vi.sps_cfg.cfg.width = init->width;
+ vi.sps_cfg.cfg.height = init->height;
+ vi.sps_cfg.cfg.order = init->order;
+ vi.sps_cfg.cfg.notify_enable = init->notify_enable;
+ vi.sps_cfg.cfg.fourcc = init->fourcc;
+ vi.sps_cfg.cfg.vc1_rowbase = init->vc1_rowbase;
+ vi.sps_cfg.cfg.h264_startcode_detect = init->h264_startcode_detect;
+ vi.sps_cfg.cfg.h264_nal_len_size = init->h264_nal_len_size;
+ vi.sps_cfg.cfg.postproc_flag = init->postproc_flag;
+ vi.sps_cfg.cfg.fruc_enable = init->fruc_enable;
+ vi.sps_cfg.cfg.color_format = init->color_format;
+ vi.sps_cfg.seq.header = init->seq_header;
+ vi.sps_cfg.seq.len = init->seq_len;
+ vi.buf_req = &buf;
+
+ /* set the color format based on version */
+ if (ver.major < 2 && init->color_format != 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VDEC_IOCTL_INITIALIZE wrong value for reserved field\n");
+ vi.sps_cfg.cfg.color_format = 0;
+ }
+
+ if (ioctl(mod->fd, VDEC_IOCTL_INITIALIZE, &vi) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VDEC_IOCTL_INITIALIZE failed\n");
+ mod->dead = 1;
+ return -1;
+ }
+ init->buf_req->input.bufnum_min = vi.buf_req->input.num_min_buffers;
+ init->buf_req->input.bufnum_max = vi.buf_req->input.num_max_buffers;
+ init->buf_req->input.bufsize = vi.buf_req->input.bufsize;
+ init->buf_req->output.bufnum_min = vi.buf_req->output.num_min_buffers;
+ init->buf_req->output.bufnum_max = vi.buf_req->output.num_max_buffers;
+ init->buf_req->output.bufsize = vi.buf_req->output.bufsize;
+ init->buf_req->dec_req1.bufnum_min =
+ vi.buf_req->dec_req1.num_min_buffers;
+ init->buf_req->dec_req1.bufnum_max =
+ vi.buf_req->dec_req1.num_max_buffers;
+ init->buf_req->dec_req1.bufsize = vi.buf_req->dec_req1.bufsize;
+ init->buf_req->dec_req2.bufnum_min =
+ vi.buf_req->dec_req2.num_min_buffers;
+ init->buf_req->dec_req2.bufnum_max =
+ vi.buf_req->dec_req2.num_max_buffers;
+ init->buf_req->dec_req2.bufsize = vi.buf_req->dec_req2.bufsize;
+
+ return 0;
+
+}
+int adsp_post_input_buffer(struct adsp_module *mod, struct adsp_input_buf input,
+ unsigned int eos)
+{
+ struct vdec_input_buf ip;
+ struct vdec_queue_status stat;
+
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_post_input_buffer() mod NULL: 0x%x\n", mod);
+ return -1;
+ }
+ ip.pmem_id = input.pmem_id;
+ ip.buffer.avsync_state = input.avsync_state;
+ ip.buffer.data = input.data;
+ ip.buffer.offset = input.offset;
+ ip.buffer.size = input.size;
+ ip.buffer.timestamp_lo = input.timestamp_lo;
+ ip.buffer.timestamp_hi = input.timestamp_hi;
+ ip.buffer.flags = input.flags;
+ ip.queue_status = &stat;
+
+#if PROFILE_DECODER
+ QPERF_START(dsp_decode);
+#endif
+ if (eos) {
+ if (ioctl(mod->fd, VDEC_IOCTL_EOS, NULL) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "adsp:VDEC_IOCTL_EOS failed\n");
+ return -1;
+ }
+ } else {
+ //usleep(1000000);
+ if (ioctl(mod->fd, VDEC_IOCTL_QUEUE, &ip) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "adsp:VDEC_IOCTL_QUEUE failed\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+int adsp_release_frame(struct adsp_module *mod, unsigned int *buf)
+{
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_release_frame() mod NULL: 0x%x\n", mod);
+ return -1;
+ }
+ return ioctl(mod->fd, VDEC_IOCTL_REUSEFRAMEBUFFER, buf);
+
+}
+int adsp_flush(struct adsp_module *mod, unsigned int port)
+{
+ if (NULL == mod) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_flush() mod NULL: 0x%x\n", mod);
+ return -1;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "adsp_flush() Before Flush \n");
+ return ioctl(mod->fd, VDEC_IOCTL_FLUSH, &port);
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/adsp.h b/omx/mm-video/qdsp6/vdec/src/adsp.h
new file mode 100644
index 0000000..6f1c13a
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/adsp.h
@@ -0,0 +1,149 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _ADSP_SIMPLE_H_
+#define _ADSP_SIMPLE_H_
+
+#include <linux/msm_q6vdec.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#include "vdec.h"
+ enum {
+ ADSP_BUFFER_TYPE_INPUT,
+ ADSP_BUFFER_TYPE_OUTPUT,
+ ADSP_BUFFER_TYPE_INTERNAL1,
+ ADSP_BUFFER_TYPE_INTERNAL2,
+ };
+
+ enum {
+ ADSP_COLOR_FORMAT_NV21 = 0x01,
+ ADSP_COLOR_FORMAT_NV21_YAMATO = 0x02,
+ };
+
+ struct adsp_module;
+ struct adsp_pmem_info;
+ struct adsp_buffers {
+ unsigned int pmem_id;
+ unsigned int offset;
+ unsigned int size;
+ };
+
+ struct adsp_buffer_info {
+ unsigned int buf_type;
+ struct adsp_buffers buf;
+ unsigned int numbuf;
+ unsigned int is_last;
+ };
+ struct adsp_buf_data {
+ unsigned int bufnum_min;
+ unsigned int bufnum_max;
+ unsigned int bufsize;
+ };
+ struct adsp_buf_req {
+ unsigned int maxnum_input_buf;
+ struct adsp_buf_data input;
+ struct adsp_buf_data output;
+ struct adsp_buf_data dec_req1;
+ struct adsp_buf_data dec_req2;
+ };
+ struct adsp_init {
+ unsigned int seq_len;
+ unsigned int width;
+ unsigned int height;
+ unsigned int order;
+ unsigned int notify_enable;
+ unsigned int fourcc;
+ unsigned int vc1_rowbase;
+ unsigned int h264_startcode_detect;
+ unsigned int h264_nal_len_size;
+ unsigned int postproc_flag;
+ unsigned int fruc_enable;
+ unsigned int color_format;
+ unsigned char *seq_header;
+ struct adsp_buf_req *buf_req;
+ };
+ struct adsp_input_buf {
+ unsigned int pmem_id;
+ unsigned int offset;
+ unsigned int data;
+ unsigned int size;
+ int timestamp_lo;
+ int timestamp_hi;
+ int avsync_state;
+ unsigned int flags;
+ };
+
+ typedef void (*adsp_msg_frame_done_func) (void *context,
+ Vdec_FrameDetailsType *
+ pframe,
+ unsigned int timestamp,
+ unsigned int offset);
+
+ typedef void (*adsp_msg_buffer_done_func) (void *context,
+ void *buffer_id);
+
+ struct adsp_open_info {
+ adsp_msg_frame_done_func frame_done;
+ adsp_msg_buffer_done_func buffer_done;
+ };
+
+ struct adsp_dec_attr {
+ unsigned int fourcc;
+ unsigned int profile;
+ unsigned int level;
+ unsigned int dec_pic_width;
+ unsigned int dec_pic_height;
+ struct adsp_buf_data input;
+ struct adsp_buf_data output;
+ struct adsp_buf_data dec_req1;
+ struct adsp_buf_data dec_req2;
+ };
+
+ struct adsp_module *adsp_open(const char *name,
+ struct adsp_open_info info,
+ void *context, int32 vdec_fd);
+
+ void adsp_close(struct adsp_module *mod);
+ int adsp_set_buffers(struct adsp_module *mod,
+ struct adsp_buffer_info bufinfo);
+ int adsp_init(struct adsp_module *mod, struct adsp_init *init);
+ int adsp_post_input_buffer(struct adsp_module *mod,
+ struct adsp_input_buf input,
+ unsigned int eos);
+ int adsp_release_frame(struct adsp_module *mod, unsigned int *buf);
+ int adsp_flush(struct adsp_module *mod, unsigned int port);
+ int adsp_free_buffers(struct adsp_module *mod,
+ struct adsp_buffer_info bufinfo);
+ int adsp_get_dec_attr(struct adsp_module *mod,
+ struct adsp_dec_attr *attr);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/omx/mm-video/qdsp6/vdec/src/omx_vdec.cpp b/omx/mm-video/qdsp6/vdec/src/omx_vdec.cpp
new file mode 100755
index 0000000..646eddc
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/omx_vdec.cpp
@@ -0,0 +1,9801 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ O p e n M A X w r a p p e r s
+ O p e n M A X C o r e
+
+*//** @file omx_vdec.c
+ This module contains the implementation of the OpenMAX core & component.
+
+*//*========================================================================*/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+//#define LOG_NDEBUG 0
+#define DEBUG_ON 0
+#include "qtv_msg.h"
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef USE_EGL_IMAGE_GPU
+#include <EGL/egl.h>
+#include <EGL/eglQCOM.h>
+#endif
+
+#ifdef _ANDROID_
+#include "cutils/properties.h"
+#endif //_ANDROID_
+
+#include "adsp.h"
+#include "omx_vdec.h"
+#include "MP4_Utils.h"
+
+#define H264_START_CODE 0x00000001
+#define H264_START_CODE_MASK 0x00FFFFFF
+#define VC1_SP_MP_START_CODE 0xC5000000
+#define VC1_SP_MP_START_CODE_RCV_V1 0x85000000
+
+#define VC1_SP_MP_START_CODE_MASK 0xFF000000
+#define VC1_AP_START_CODE 0x00000100
+#define VC1_AP_START_CODE_MASK 0xFFFFFF00
+#define VC1_STRUCT_C_LEN 5
+
+#define VC1_AP_SLICE_START_CODE 0x0000010B
+#define VC1_AP_SLICE_START_CODE_MASK 0xFFFFFFFF
+#define MAKEFOURCC(ch0,ch1,ch2,ch3) ((uint32)(uint8)(ch0) | \
+ ((uint32)(uint8)(ch1) << 8) | \
+ ((uint32)(uint8)(ch2) << 16) | \
+ ((uint32)(uint8)(ch3) << 24 ))
+#define EGL_BUFFER_HANDLE_QCOM 0x4F00
+#define EGL_BUFFER_OFFSET_QCOM 0x4F01
+
+
+genericQueue::genericQueue()
+{
+ head = NULL;
+ tail = NULL;
+ numElements = 0;
+}
+
+int genericQueue::Enqueue(void *data)
+{
+ if (NULL == data)
+ return 1;
+ node *new_node = new node;
+ new_node->data = data;
+ new_node->next = NULL;
+ if (0 == numElements) {
+ head = new_node;
+ } else {
+ tail->next = new_node;
+ }
+
+ tail = new_node;
+ ++numElements;
+ return 0;
+}
+
+void *genericQueue::Dequeue()
+{
+ if (!head)
+ return NULL;
+ void *retVal = head->data;
+ node *head_next = head->next;
+ delete head;
+ head = head_next;
+ --numElements;
+ if (0 == numElements) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FA: Setting Tail to NULL\n");
+ tail = NULL;
+ }
+ return retVal;
+}
+
+int genericQueue::GetSize()
+{
+ int ret = numElements;
+ return ret;
+}
+
+void *genericQueue::checkHead()
+{
+ void *ret = NULL;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "FA: check Head\n");
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FA: check Head: after mutex\n");
+ if (head)
+ ret = head->data;
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Queue Head is NULL\n");
+ ret = NULL;
+ }
+ return ret;
+}
+
+void *genericQueue::checkTail()
+{
+ void *ret = NULL;
+ if (tail)
+ ret = tail->data;
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Tail is NULL\n");
+ ret = NULL;
+ }
+ return ret;
+}
+
+genericQueue::~genericQueue()
+{
+ node *tmp = head;
+ node *tmp_next;
+ while (tmp) {
+ tmp_next = tmp->next;
+ delete tmp;
+ tmp = tmp_next;
+ }
+ head = NULL;
+ tail = NULL;
+}
+
+// omx_cmd_queue destructor
+omx_vdec::omx_cmd_queue::~omx_cmd_queue()
+{
+ // Nothing to do
+}
+
+// omx cmd queue constructor
+omx_vdec::omx_cmd_queue::omx_cmd_queue():m_read(0), m_write(0), m_size(0)
+{
+ memset(m_q, 0, sizeof(omx_event) * OMX_CORE_CONTROL_CMDQ_SIZE);
+}
+
+// omx cmd queue insert
+bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2,
+ unsigned id)
+{
+ bool ret = true;
+ if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
+ m_q[m_write].id = id;
+ m_q[m_write].param1 = p1;
+ m_q[m_write].param2 = p2;
+ m_q[m_write].canceled = false;
+
+ m_write++;
+ m_size++;
+ if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
+ m_write = 0;
+ }
+ } else {
+ ret = false;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! Command Queue Full\n");
+ }
+ return ret;
+}
+
+// omx cmd queue delete
+bool omx_vdec::omx_cmd_queue::delete_entry(unsigned *p1, unsigned *p2,
+ unsigned *id, bool * canceled)
+{
+ bool ret = true;
+ if (m_size > 0) {
+ *id = m_q[m_read].id;
+ *p1 = m_q[m_read].param1;
+ *p2 = m_q[m_read].param2;
+
+ if (canceled) {
+ *canceled = m_q[m_read].canceled;
+ }
+ // Move the read pointer ahead
+ ++m_read;
+ --m_size;
+ if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
+ m_read = 0;
+ }
+ } else {
+ ret = false;
+ }
+ return ret;
+}
+
+//#define OMX_VDEC_NONUI_VERSION
+#ifdef _ANDROID_
+VideoHeap::VideoHeap(int fd, size_t size, void *base)
+{
+ // dup file descriptor, map once, use pmem
+ init(dup(fd), base, size, 0, "/dev/pmem_adsp");
+}
+#endif // _ANDROID_
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec
+
+DESCRIPTION
+ Constructor
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None.
+========================================================================== */
+omx_vdec::omx_vdec():m_state(OMX_StateInvalid),
+m_app_data(NULL),
+m_loc_use_buf_hdr(NULL), m_vdec(NULL), m_inp_mem_ptr(NULL),
+ //m_inp_bm_ptr(NULL),
+m_out_mem_ptr(NULL),
+ //m_out_bm_ptr(NULL),
+ m_first_pending_buf_idx(-1),
+m_outstanding_frames(-OMX_CORE_NUM_OUTPUT_BUFFERS),
+m_eos_timestamp(0), m_out_buf_count(OMX_CORE_NUM_OUTPUT_BUFFERS),
+ //m_out_bm_count(0),
+ m_inp_buf_count(0),
+m_inp_buf_size(OMX_CORE_INPUT_BUFFER_SIZE),
+m_inp_bPopulated(OMX_FALSE),
+m_out_bPopulated(OMX_FALSE),
+m_height(0),
+m_width(0),
+m_dec_width(0),
+m_dec_height(0),
+m_crop_x(0),
+m_crop_y(0),
+m_crop_dx(0),
+m_crop_dy(0),
+m_bInterlaced(false),
+m_port_height(0),
+m_port_width(0),
+m_nalu_bytes(0),
+m_msg_cnt(0),
+m_cmd_cnt(0),
+m_etb_cnt(0),
+m_ebd_cnt(0),
+m_ftb_cnt(0),
+m_fbd_cnt(0),
+m_inp_bEnabled(OMX_TRUE),
+m_out_bEnabled(OMX_TRUE),
+m_event_port_settings_sent(false),
+m_is_use_buffer(false),
+m_is_input_use_buffer(false),
+m_bEoSNotifyPending(false),
+m_platform_list(NULL),
+m_platform_entry(NULL),
+m_pmem_info(NULL),
+m_h264_utils(NULL),
+m_pcurrent_frame(NULL),
+m_default_arbitrary_bytes(true),
+m_default_arbitrary_bytes_vc1(true),
+m_default_accumulate_subframe(true),
+m_bAccumulate_subframe(false),
+m_bArbitraryBytes(true),
+m_arbitrary_bytes_input_mem_ptr(NULL),
+m_current_arbitrary_bytes_input(NULL),
+m_bPartialFrame(false),
+m_bStartCode(false), m_header_state(HEADER_STATE_RECEIVED_NONE), m_use_pmem(0),
+flush_before_vdec_op_q(NULL),
+m_b_divX_parser(false),
+m_mp4_utils(NULL),
+m_timestamp_interval(0),
+m_prev_timestamp(0),
+m_b_display_order(false),
+m_pPrevFrame(NULL),
+m_codec_format(0),
+m_codec_profile(0),
+m_bInvalidState(false),
+m_display_id(NULL),
+m_is_use_egl_buffer(false)
+{
+ /* Assumption is that , to begin with , we have all the frames with client */
+ memset(m_out_flags, 0x00, (OMX_CORE_NUM_OUTPUT_BUFFERS + 7) / 8);
+ memset(m_flags, 0x00, 4);
+ memset(&m_cmp, 0, sizeof(m_cmp));
+ memset(&m_cb, 0, sizeof(m_cb));
+ memset(&m_vdec_cfg, 0, sizeof(m_vdec_cfg));
+ m_vdec_cfg.vdec_fd = -1;
+ m_vdec_cfg.inputBuffer = NULL;
+ m_vdec_cfg.outputBuffer = NULL;
+ memset(&m_frame_info, 0, sizeof(m_frame_info));
+ memset(m_out_bm_count, 0x0, (OMX_CORE_NUM_OUTPUT_BUFFERS + 7) / 8);
+
+ memset(m_inp_bm_count, 0x0, (MAX_NUM_INPUT_BUFFERS + 7) / 8);
+ memset(&m_arbitrary_bytes_info, 0,
+ sizeof(union omx_arbitrary_bytes_info));
+ for (int i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS; i++) {
+ input[i] = NULL;
+ }
+
+ for (int i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS; i++) {
+ m_arbitrary_bytes_input[i] = NULL;
+ memset(&m_extra_buf_info[i], 0,
+ sizeof(struct
+ omx_extra_arbitrarybytes_buff_info));
+ m_input_buff_info[i].pArbitrary_bytes_freed = NULL;
+ m_input_buff_info[i].bfree_input = true;
+ }
+
+ m_vendor_config.pData = NULL;
+ m_bWaitForResource = false;
+ m_color_format = (OMX_COLOR_FORMATTYPE)OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::~omx_vdec
+
+DESCRIPTION
+ Destructor
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None.
+========================================================================== */
+omx_vdec::~omx_vdec()
+{
+ m_pmem_info = NULL;
+ m_nalu_bytes = 0;
+ m_port_width = m_port_height = 0;
+
+ if (flush_before_vdec_op_q) {
+ delete flush_before_vdec_op_q;
+ flush_before_vdec_op_q = NULL;
+ }
+
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlFrameDoneCbStub
+
+DESCRIPTION
+ Frame done callback from the video decoder
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. frame(I) -- video frame decoded
+
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+void omx_vdec::frame_done_cb_stub(struct vdec_context *ctxt,
+ struct vdec_frame *frame)
+{
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+
+ pThis->post_event((unsigned)ctxt, (unsigned)frame,
+ OMX_COMPONENT_GENERATE_FRAME_DONE);
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::frame_done_display_order_cb
+
+DESCRIPTION
+ Frame done callback from the video decoder with a display order
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. frame(I) -- video frame decoded
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+void omx_vdec::frame_done_display_order_cb(struct vdec_context *ctxt, struct vdec_frame *frame)
+{
+ bool bCurrentBFrame = false;
+
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+ if (pThis->m_pPrevFrame)
+ {
+ if (frame->frameDetails.ePicType[0] == VDEC_PICTURE_TYPE_B)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"frame_done_display_order_cb - b frame");
+ bCurrentBFrame = true;
+ }
+
+ if (bCurrentBFrame)
+ {
+ if (pThis->m_pPrevFrame->timestamp < frame->timestamp)
+ {
+ /* Swap timestamp */
+ pThis->m_pPrevFrame->timestamp ^= frame->timestamp;
+ frame->timestamp ^= pThis->m_pPrevFrame->timestamp;
+ pThis->m_pPrevFrame->timestamp ^= frame->timestamp;
+ }
+ pThis->frame_done_cb(ctxt, frame);
+ }
+ else if (frame->flags & FRAME_FLAG_EOS)
+ {
+ pThis->frame_done_cb(ctxt, pThis->m_pPrevFrame);
+ pThis->frame_done_cb(ctxt, frame);
+ pThis->m_pPrevFrame = NULL;
+ }
+ else
+ {
+ if (pThis->m_pPrevFrame->timestamp > frame->timestamp)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"Warning - previous ts > current ts. And both are non B-frames");
+ }
+ pThis->frame_done_cb(ctxt, pThis->m_pPrevFrame);
+ pThis->m_pPrevFrame = frame;
+ }
+ }
+ else
+ {
+ if (frame->flags & FRAME_FLAG_EOS)
+ {
+ pThis->frame_done_cb(ctxt, frame);
+ }
+ else if (frame->flags & FRAME_FLAG_FLUSHED) {
+ pThis->frame_done_cb(ctxt, frame);
+ }
+ else
+ {
+ pThis->m_pPrevFrame = frame;
+ }
+ }
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlFrameDoneCb
+
+DESCRIPTION
+ Frame done callback from the video decoder
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. frame(I) -- video frame decoded
+
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+void omx_vdec::frame_done_cb(struct vdec_context *ctxt,
+ struct vdec_frame *frame)
+{
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec::frame_done_cb \n");
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+ OMX_BUFFERHEADERTYPE *pBufHdr;
+
+ pBufHdr = (OMX_BUFFERHEADERTYPE *) pThis->m_out_mem_ptr;
+ if (pThis->m_out_mem_ptr) {
+ unsigned int i;
+ for (i = 0; i < pThis->m_out_buf_count; i++, pBufHdr++) {
+ if (pBufHdr->pOutputPortPrivate == frame) {
+ if (BITMASK_ABSENT((pThis->m_out_flags), i)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n Warning: Double framedone - Frame is still with IL client \n");
+ return;
+ }
+ break;
+ }
+ }
+ // Copy from PMEM area to user defined area
+ if (pThis->omx_vdec_get_use_buf_flg()) {
+ pThis->omx_vdec_cpy_user_buf(pBufHdr);
+ }
+
+ if (i < pThis->m_out_buf_count) {
+ BITMASK_CLEAR((pThis->m_out_flags), i);
+ pThis->m_fbd_cnt++;
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FBD: Count %d %x %lld\n",
+ pThis->m_fbd_cnt, pThis->m_out_flags[0],
+ frame->timestamp);
+
+ if (pThis->m_cb.FillBufferDone) {
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
+ NULL;
+
+ if (pBufHdr->pPlatformPrivate) {
+ pPMEMInfo =
+ (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO
+ *)
+ ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
+ pBufHdr->pPlatformPrivate)->
+ entryList->entry;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n PMEM fd %u, Offset %x \n",
+ (unsigned)pPMEMInfo->
+ pmem_fd,
+ (unsigned)pPMEMInfo->
+ offset);
+ }
+
+ if (frame->flags & FRAME_FLAG_FLUSHED) {
+ pBufHdr->nFilledLen = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n **** Flushed Frame-%d **** \n",
+ i);
+ } else {
+ if(!pThis->omx_vdec_get_use_egl_buf_flg()) {
+ pThis->fill_extradata(pBufHdr, frame);
+ }
+ else {
+ pBufHdr->nFilledLen = pThis->get_output_buffer_size();
+ // Invalidate the cache for the size of the decoded frame
+ #ifdef USE_PMEM_ADSP_CACHED
+ vdec_cachemaint(frame->buffer.pmem_id, pBufHdr->pBuffer, pBufHdr->nFilledLen, PMEM_CACHE_INVALIDATE);
+ #endif
+ }
+ }
+
+ // If the decoder provides frame done for last frame then set the eos flag.
+ if ((frame->flags & FRAME_FLAG_EOS)) { /* || // @Temporary blocked
+ ((frame->timestamp > 0) && (frame->timestamp == pThis->m_eos_timestamp))) */
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n **** Frame-%d EOS with last timestamp **** \n",
+ i);
+ pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
+ }
+
+ pBufHdr->nTimeStamp = frame->timestamp;
+
+ PrintFrameHdr(pBufHdr);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FBD %d with TS %d \n",
+ pThis->m_fbd_cnt,
+ (unsigned)pBufHdr->nTimeStamp);
+ ++pThis->m_outstanding_frames;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FBD Outstanding frame cnt %d\n",
+ pThis->m_outstanding_frames);
+#ifdef OMX_VDEC_NONUI_VERSION
+ if ((pThis->m_fbd_cnt < 1)
+ || (frame->flags & FRAME_FLAG_FLUSHED)) {
+ pThis->m_cb.FillBufferDone(&pThis->
+ m_cmp,
+ pThis->
+ m_app_data,
+ pBufHdr);
+ } else {
+ pThis->post_event((unsigned)&pThis->
+ m_cmp,
+ (unsigned)pBufHdr,
+ OMX_COMPONENT_GENERATE_FTB);
+ }
+#else
+ pThis->m_cb.FillBufferDone(&pThis->m_cmp,
+ pThis->m_app_data,
+ pBufHdr);
+#endif
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error: FrameDoneCb Ignored due to NULL callbacks \n");
+ }
+ } else {
+ if(frame->flags & FRAME_FATAL_ERROR) {
+ pThis->m_bInvalidState = true;
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError,
+ OMX_ErrorHardware, 0,
+ NULL);
+ return;
+ }
+ // fake frame provided by the decoder to indicate end of stream
+ else if (frame->flags & FRAME_FLAG_EOS) {
+ OMX_BUFFERHEADERTYPE *pBufHdr =
+ (OMX_BUFFERHEADERTYPE *) pThis->
+ m_out_mem_ptr;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n **** Fake Frame EOS **** \n");
+ for (i = 0; i < pThis->m_out_buf_count;
+ i++, pBufHdr++) {
+ if (BITMASK_PRESENT
+ ((pThis->m_out_flags), i)) {
+ BITMASK_CLEAR((pThis->
+ m_out_flags), i);
+ break;
+ }
+ }
+ if (i < pThis->m_out_buf_count) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "EOS Indication used buffer numbered %d\n",
+ i);
+ pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
+ pBufHdr->nFilledLen = 0;
+ pBufHdr->nTimeStamp = frame->timestamp;
+ if (pBufHdr->nTimeStamp == 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "eos timestamp used is %lld\n",
+ pThis->
+ m_eos_timestamp);
+ pBufHdr->nTimeStamp =
+ pThis->m_eos_timestamp;
+ }
+ pThis->m_cb.FillBufferDone(&pThis->
+ m_cmp,
+ pThis->
+ m_app_data,
+ pBufHdr);
+ pThis->m_bEoSNotifyPending = false;
+ ++pThis->m_outstanding_frames;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "FBD Outstanding frame cnt %d\n",
+ pThis->
+ m_outstanding_frames);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Failed to send EOS to the IL Client\n");
+ pThis->m_bEoSNotifyPending = true;
+ }
+
+ }
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: InvalidCb Ignored due to NULL Out storage \n");
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "frame_done_cb buffer->nTimeStamp %d nFlags %d\n",
+ pBufHdr->nTimeStamp, pBufHdr->nFlags);
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlBufferDoneCbStub
+
+DESCRIPTION
+ Buffer done callback from the decoder. This stub posts the command to the
+ decoder pipe which will be executed by the decoder later to the client.
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. cookie(I) -- Context information related to the specific input buffer
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+void omx_vdec::buffer_done_cb_stub(struct vdec_context *ctxt, void *cookie)
+{
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+
+ pThis->post_event((unsigned)ctxt, (unsigned)cookie,
+ OMX_COMPONENT_GENERATE_BUFFER_DONE);
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlBufferDoneCb
+
+DESCRIPTION
+ Buffer done callback from the decoder.
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. cookie(I) -- Context information related to the specific input buffer
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+void omx_vdec::buffer_done_cb(struct vdec_context *ctxt, void *cookie)
+{
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "buffer Done callback received\n");
+ if (pThis->m_cb.EmptyBufferDone) {
+ OMX_BUFFERHEADERTYPE *bufHdr = (OMX_BUFFERHEADERTYPE *) cookie;
+ PrintFrameHdr(bufHdr);
+ unsigned int nPortIndex =
+ bufHdr - (OMX_BUFFERHEADERTYPE *) pThis->m_inp_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ if (!pThis->is_pending(nPortIndex)) {
+ if (pThis->m_bArbitraryBytes) {
+ pThis->
+ buffer_done_cb_arbitrarybytes(ctxt,
+ cookie);
+ } else {
+ pThis->m_cb.EmptyBufferDone(&pThis->
+ m_cmp,
+ pThis->
+ m_app_data,
+ bufHdr);
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "buffer Done callback received for pending buffer; Ignoring!!\n");
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Warning!! Buffer Done Callback Came with Incorrect buffer\n");
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "BufferDoeCb Ignored due to NULL callbacks \n");
+ }
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::buffer_done_cb_arbitrarybytes
+
+DESCRIPTION
+ Buffer done callback for arbitrary bytes.
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. cookie(I) -- Context information related to the specific input buffer
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+void omx_vdec::buffer_done_cb_arbitrarybytes(struct vdec_context *ctxt,
+ void *cookie)
+{
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+ OMX_BUFFERHEADERTYPE *bufHdr = (OMX_BUFFERHEADERTYPE *) cookie;
+ OMX_S8 extra_buf_index =
+ pThis->find_extra_buffer_index(bufHdr->pBuffer);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "buffer_done_cb_arbitrarybytes %d\n", extra_buf_index);
+
+ if (extra_buf_index != -1) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "buffer Done callback - end of arbitrary bytes buffer!!\n");
+ pThis->free_extra_buffer(extra_buf_index);
+ unsigned int nPortIndex =
+ pThis->m_extra_buf_info[extra_buf_index].
+ arbitrarybytesInput -
+ (OMX_BUFFERHEADERTYPE *) pThis->
+ m_arbitrary_bytes_input_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ pThis->m_cb.EmptyBufferDone(&pThis->m_cmp,
+ pThis->m_app_data,
+ pThis->
+ m_extra_buf_info
+ [extra_buf_index].
+ arbitrarybytesInput);
+ pThis->m_extra_buf_info[extra_buf_index].
+ arbitrarybytesInput = NULL;
+ pThis->push_pending_buffers_proxy();
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Incorrect previous arbitrary bytes buffer %p\n",
+ pThis->m_extra_buf_info[extra_buf_index].
+ arbitrarybytesInput);
+ }
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "buffer Done callback - m_bPartialFrame %d m_current_frame %p\n",
+ pThis->m_bPartialFrame, pThis->m_current_frame);
+
+ pThis->free_input_buffer(bufHdr);
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlProcessMsgCb
+
+DESCRIPTION
+ IL Client callbacks are generated through this routine. The decoder
+ provides the thread context for this routine.
+
+PARAMETERS
+ ctxt -- Context information related to the self.
+ id -- Event identifier. This could be any of the following:
+ 1. Command completion event
+ 2. Buffer done callback event
+ 3. Frame done callback event
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+void omx_vdec::process_event_cb(struct vdec_context *ctxt, unsigned char id)
+{
+ unsigned p1; // Parameter - 1
+ unsigned p2; // Parameter - 2
+ unsigned ident = 0;
+ unsigned qsize = 0; // qsize
+ omx_vdec *pThis = (omx_vdec *) ctxt->extra;
+ bool canceled = false;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCntrlProessMsgCb[%x,%d] Enter: \n", (unsigned)ctxt,
+ (unsigned)id);
+ if (!pThis) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR : ProcessMsgCb: Context is incorrect; bailing out\n");
+ return;
+ }
+ // Protect the shared queue data structure
+ do {
+ canceled = false;
+ pThis->mutex_lock();
+ qsize = pThis->m_ftb_q.m_size;
+ if (qsize) {
+ pThis->m_ftb_q.delete_entry(&p1, &p2, &ident,
+ &canceled);
+ if (canceled) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "canceled ftb %x", p2);
+ pThis->mutex_unlock();
+ continue;
+ }
+ } else {
+ qsize = pThis->m_cmd_q.m_size;
+ if (qsize) {
+ pThis->m_cmd_q.delete_entry(&p1, &p2, &ident);
+ } else if (pThis->m_bArbitraryBytes) {
+ if (pThis->m_current_arbitrary_bytes_input !=
+ NULL) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "process_event_cb - continue using m_current_arbitrary_bytes_input %p\n",
+ pThis->
+ m_current_arbitrary_bytes_input);
+ ident =
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES;
+ } else if (qsize =
+ pThis->m_etb_arbitrarybytes_q.
+ m_size) {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "ETBQ[%d] FTBQ[%d] CMDQ[%d]\n",
+ pThis->
+ m_etb_arbitrarybytes_q.
+ m_size,
+ pThis->m_ftb_q.m_size,
+ pThis->m_cmd_q.m_size);
+ pThis->m_etb_arbitrarybytes_q.
+ delete_entry(&p1, &p2, &ident);
+ pThis->m_current_arbitrary_bytes_input =
+ (OMX_BUFFERHEADERTYPE *) p2;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "set m_current_arbitrary_bytes_input %p %d\n",
+ pThis->
+ m_current_arbitrary_bytes_input);
+ }
+ }
+ }
+ if (qsize) {
+ pThis->m_msg_cnt++;
+ }
+ pThis->mutex_unlock();
+
+ if ((qsize > 0)
+ || (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES)) {
+ id = ident;
+ QTV_MSG_PRIO7(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Process ->%d[%d]ebd %d fbd %d oc %d %x,%x\n",
+ pThis->m_state, ident, pThis->m_etb_cnt,
+ pThis->m_fbd_cnt,
+ pThis->m_outstanding_frames,
+ pThis->m_flags[0] ,
+ pThis->m_out_flags[0]);
+ if (id == OMX_COMPONENT_GENERATE_EVENT) {
+ if (pThis->m_cb.EventHandler) {
+ if (p1 == OMX_CommandStateSet) {
+ pThis->m_state =
+ (OMX_STATETYPE) p2;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Process -> state set to %d \n",
+ pThis->m_state);
+ pThis->m_cb.
+ EventHandler(&pThis->m_cmp,
+ pThis->
+ m_app_data,
+ OMX_EventCmdComplete,
+ p1, p2, NULL);
+ }
+ /* posting error events for illegal state transition */
+ else if (p1 == OMX_EventError) {
+ if (p2 == OMX_ErrorInvalidState) {
+ pThis->m_state =
+ OMX_StateInvalid;
+ pThis->m_cb.
+ EventHandler
+ (&pThis->m_cmp,
+ pThis->m_app_data,
+ OMX_EventError,
+ OMX_ErrorInvalidState,
+ 0, NULL);
+ pThis->
+ execute_omx_flush
+ (OMX_ALL);
+ } else {
+ pThis->m_cb.
+ EventHandler
+ (&pThis->m_cmp,
+ pThis->m_app_data,
+ OMX_EventError, p2,
+ 0, NULL);
+
+ }
+ } else if (p1 == OMX_CommandPortDisable) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Process -> Port %d set to PORT_STATE_DISABLED state \n",
+ p2);
+ pThis->m_cb.
+ EventHandler(&pThis->m_cmp,
+ pThis->
+ m_app_data,
+ OMX_EventCmdComplete,
+ p1, p2, NULL);
+ } else if (p1 == OMX_CommandPortEnable) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Process -> Port %d set to PORT_STATE_ENABLED state \n",
+ p2);
+ pThis->m_cb.
+ EventHandler(&pThis->m_cmp,
+ pThis->
+ m_app_data,
+ OMX_EventCmdComplete,
+ p1, p2, NULL);
+ } else {
+ pThis->m_cb.
+ EventHandler(&pThis->m_cmp,
+ pThis->
+ m_app_data,
+ OMX_EventCmdComplete,
+ p1, p2, NULL);
+ }
+
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error: ProcessMsgCb ignored due to NULL callbacks\n");
+ }
+ } else if (id == OMX_COMPONENT_GENERATE_EVENT_FLUSH) {
+ pThis->m_cb.EventHandler(&pThis->m_cmp,
+ pThis->m_app_data,
+ OMX_EventCmdComplete,
+ p1, p2, NULL);
+ } else if (id == OMX_COMPONENT_GENERATE_BUFFER_DONE) {
+ buffer_done_cb((struct vdec_context *)p1,
+ (void *)p2);
+ } else if (id == OMX_COMPONENT_GENERATE_FRAME_DONE) {
+ if (pThis->m_b_display_order)
+ {
+ frame_done_display_order_cb((struct vdec_context *)p1,(struct vdec_frame *)p2);
+ }
+ else
+ {
+ frame_done_cb((struct vdec_context *)p1,
+ (struct vdec_frame *)p2);
+ }
+ } else if (id == OMX_COMPONENT_GENERATE_ETB) {
+ pThis->
+ empty_this_buffer_proxy_frame_based((OMX_HANDLETYPE) p1, (OMX_BUFFERHEADERTYPE *) p2);
+ } else if (id ==
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES) {
+ pThis->
+ empty_this_buffer_proxy_arbitrary_bytes((OMX_HANDLETYPE) p1, pThis->m_current_arbitrary_bytes_input);
+ } else if (id == OMX_COMPONENT_GENERATE_FTB) {
+ pThis->
+ fill_this_buffer_proxy((OMX_HANDLETYPE) p1,
+ (OMX_BUFFERHEADERTYPE
+ *) p2);
+ } else if (id == OMX_COMPONENT_GENERATE_COMMAND) {
+ pThis->send_command_proxy(&pThis->m_cmp,
+ (OMX_COMMANDTYPE) p1,
+ (OMX_U32) p2,
+ (OMX_PTR) NULL);
+ } else if (id == OMX_COMPONENT_PUSH_PENDING_BUFS) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "process_event_cb :: push_pending_buffer_proxy\n");
+ pThis->push_pending_buffers_proxy();
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error: ProcessMsgCb Ignored due to Invalid Identifier\n");
+ }
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCntrlProessMsgCb[%x,%d] Exit: \n",
+ (unsigned)ctxt, (unsigned)id);
+ }
+
+ if (pThis->m_bArbitraryBytes) {
+ unsigned cmd_ftb_qsize = 0;
+ pThis->mutex_lock();
+ cmd_ftb_qsize =
+ pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size;
+ qsize =
+ cmd_ftb_qsize +
+ pThis->m_etb_arbitrarybytes_q.m_size;
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "process_event_cb %d %d %d\n",
+ pThis->m_cmd_q.m_size,
+ pThis->m_ftb_q.m_size,
+ pThis->m_etb_arbitrarybytes_q.m_size);
+ pThis->mutex_unlock();
+ if (cmd_ftb_qsize == 0 && pThis->m_bWaitForResource) {
+ // if cmd_ftb_qsize >0, always come back to process those, otherwise if we are out of buffer
+ // wait until free_input_buffer is called when q6 sends a buffer done, don't loop forever.
+ qsize = 0;
+ } else if (qsize == 0
+ && pThis->m_current_arbitrary_bytes_input) {
+ qsize = 1;
+ }
+ } else {
+ pThis->mutex_lock();
+ qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size;
+ pThis->mutex_unlock();
+ }
+ } while (qsize > 0);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "process_event_cb Exit\n");
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentInit
+
+DESCRIPTION
+ Initialize the component.
+
+PARAMETERS
+ ctxt -- Context information related to the self.
+ id -- Event identifier. This could be any of the following:
+ 1. Command completion event
+ 2. Buffer done callback event
+ 3. Frame done callback event
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
+{
+
+#ifdef _ANDROID_
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+#endif
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ int r, fd;
+
+ fd = open("/dev/vdec", O_RDWR);
+
+ if(fd < 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Omx_vdec::Comp Init Returning failure\n");
+ // Another decoder instance is running. return from here.
+ return OMX_ErrorInsufficientResources;
+ }
+ //close(fd);
+ m_vdec_cfg.vdec_fd = fd;
+
+#ifdef _ANDROID_
+ if(0 != property_get("persist.omxvideo.arb-bytes", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_arbitrary_bytes = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "OMX_VDEC:: Comp Init failed in \
+ getting value for the Android property [persist.omxvideo.arb-bytes]");
+ }
+
+ if(0 != property_get("persist.omxvideo.arb-bytes-vc1", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_arbitrary_bytes_vc1 = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "OMX_VDEC:: Comp Init failed in \
+ getting value for the Android property [persist.omxvideo.arb-bytes-vc1]");
+ }
+
+ if(0 != property_get("persist.omxvideo.accsubframe", property_value, NULL))
+ {
+ if(!strcmp(property_value, "false"))
+ {
+ m_default_accumulate_subframe = false;
+ }
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "OMX_VDEC:: Comp Init failed in \
+ getting value for the Android property [persist.omxvideo.accsubframe]");
+ }
+#endif
+
+ m_vdec_cfg.buffer_done = buffer_done_cb_stub;
+ m_vdec_cfg.frame_done = frame_done_cb_stub;
+ m_vdec_cfg.process_message = process_event_cb;
+ m_vdec_cfg.height = OMX_CORE_QCIF_HEIGHT;
+ m_vdec_cfg.width = OMX_CORE_QCIF_WIDTH;
+ m_vdec_cfg.extra = this;
+ // Copy the role information which provides the decoder kind
+ strncpy(m_vdec_cfg.kind, role, 128);
+
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('m', 'p', '4', 'v');
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('h', '2', '6', '3');
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('h', '2', '6', '4');
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('w', 'm', 'v', '3');
+ } else
+ if(!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('D', 'I', 'V', 'X');
+ }else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('V', 'P', '6', '0');
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole, "video_decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE);
+ m_vdec_cfg.fourcc = MAKEFOURCC('F', 'L', 'V', '1');
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "\n Unknown Component\n");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx", 27) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Mp4 output buffer Count updated\n");
+ m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
+ m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
+ m_bArbitraryBytes = false;
+ m_b_divX_parser = true;
+ memset(&m_divX_buffer_info, 0, sizeof(m_divX_buffer_info));
+ m_divX_buffer_info.parsing_required = true;
+ m_mp4_utils = new MP4_Utils();
+ m_b_display_order = true;
+ m_codec_format = QOMX_VIDEO_DIVXFormat4;
+ } else if ( (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263", 27) == 0 )
+ || (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark", 28) == 0)
+ || (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4", 28) == 0)
+ ) {
+ m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
+ m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
+ m_mp4_utils = new MP4_Utils();
+ } else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) ==
+ 0) {
+ m_h264_utils = new H264_Utils();
+ m_bAccumulate_subframe = true; // by default
+ m_bAccumulate_subframe = (m_bAccumulate_subframe && m_default_accumulate_subframe);
+ m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_H264;
+ m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_H264;
+ } else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) ==
+ 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "VC1 component init\n");
+ m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
+ m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
+ m_bAccumulate_subframe = true;
+ m_bArbitraryBytes = false;
+ m_bAccumulate_subframe = (m_bAccumulate_subframe && m_default_accumulate_subframe);
+ } else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp", 25) ==
+ 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "VP6 component init\n");
+ m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
+ m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
+ m_bAccumulate_subframe = false;
+ m_bArbitraryBytes = false;
+ }
+
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) == 0)
+ {
+ m_bArbitraryBytes = (m_bArbitraryBytes && m_default_arbitrary_bytes_vc1);
+ }
+ else
+ {
+ m_bArbitraryBytes = (m_bArbitraryBytes && m_default_arbitrary_bytes);
+ }
+
+ m_crop_dy = m_height = m_vdec_cfg.height;
+ m_crop_dx = m_width = m_vdec_cfg.width;
+ m_port_height = m_height;
+ m_port_width = m_width;
+ m_state = OMX_StateLoaded;
+ m_first_pending_buf_idx = -1;
+ flush_before_vdec_op_q = new genericQueue();
+ if(flush_before_vdec_op_q == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,"flush_before_vdec_op_q creation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ eRet = create_msg_thread();
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetComponentVersion
+
+DESCRIPTION
+ Returns the component version.
+
+PARAMETERS
+ TBD.
+
+RETURN VALUE
+ OMX_ErrorNone.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_component_version(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_STRING componentName,
+ OMX_OUT OMX_VERSIONTYPE *
+ componentVersion,
+ OMX_OUT OMX_VERSIONTYPE *
+ specVersion,
+ OMX_OUT OMX_UUIDTYPE *
+ componentUUID)
+{
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Get Comp Version in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ /* TBD -- Return the proper version */
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SendCommand
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_COMMANDTYPE cmd,
+ OMX_IN OMX_U32 param1,
+ OMX_IN OMX_PTR cmdData)
+{
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Send Command in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ post_event((unsigned)cmd, (unsigned)param1,
+ OMX_COMPONENT_GENERATE_COMMAND);
+ semaphore_wait();
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SendCommand
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_COMMANDTYPE cmd,
+ OMX_IN OMX_U32 param1,
+ OMX_IN OMX_PTR cmdData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ // Handle only IDLE and executing
+ OMX_STATETYPE eState = (OMX_STATETYPE) param1;
+ int bFlag = 1;
+
+ if (cmd == OMX_CommandStateSet) {
+ /***************************/
+ /* Current State is Loaded */
+ /***************************/
+ if (m_state == OMX_StateLoaded) {
+ if (eState == OMX_StateIdle) {
+ if (allocate_done() ||
+ (m_inp_bEnabled == OMX_FALSE
+ && m_out_bEnabled == OMX_FALSE)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->Idle\n");
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->Idle-Pending\n");
+ BITMASK_SET(m_flags,
+ OMX_COMPONENT_IDLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Loaded to Loaded */
+ else if (eState == OMX_StateLoaded) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->Loaded\n");
+ post_event(OMX_EventError, OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Loaded to WaitForResources */
+ else if (eState == OMX_StateWaitForResources) {
+ /* Since error is None , we will post an event at the end of this function definition */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->WaitForResources\n");
+ }
+ /* Requesting transition from Loaded to Executing */
+ else if (eState == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->Executing\n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Loaded to Pause */
+ else if (eState == OMX_StatePause) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->Pause\n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Loaded to Invalid */
+ else if (eState == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Loaded-->Invalid\n");
+ post_event(OMX_EventError,
+ OMX_ErrorInvalidState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Loaded-->Invalid(%d Not Handled)\n",
+ eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /***************************/
+ /* Current State is IDLE */
+ /***************************/
+ else if (m_state == OMX_StateIdle) {
+ if (eState == OMX_StateLoaded) {
+ if (release_done()) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Idle-->Loaded\n");
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Idle-->Loaded-Pending\n");
+ BITMASK_SET(m_flags,
+ OMX_COMPONENT_LOADING_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ } else if (eState == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Idle-->Executing\n");
+
+ if (m_bArbitraryBytes) {
+ initialize_arbitrary_bytes_environment
+ ();
+ }
+
+ if (m_h264_utils) {
+ m_h264_utils->
+ initialize_frame_checking_environment
+ ();
+ }
+ }
+ /* Requesting transition from Idle to Idle */
+ else if (eState == OMX_StateIdle) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Idle-->Idle\n");
+ post_event(OMX_EventError, OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Idle to WaitForResources */
+ else if (eState == OMX_StateWaitForResources) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Idle-->WaitForResources\n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Idle to Pause */
+ else if (eState == OMX_StatePause) {
+ /* Since error is None , we will post an event at the end of this function definition */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Idle-->Pause\n");
+ }
+ /* Requesting transition from Idle to Invalid */
+ else if (eState == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Idle-->Invalid\n");
+ post_event(OMX_EventError,
+ OMX_ErrorInvalidState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Idle --> %d Not Handled\n",
+ eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /******************************/
+ /* Current State is Executing */
+ /******************************/
+ else if (m_state == OMX_StateExecuting) {
+ if (eState == OMX_StateIdle) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n OMXCORE-SM: Executing --> Idle \n");
+ execute_omx_flush(OMX_ALL);
+ } else if (eState == OMX_StatePause) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n OMXCORE-SM: Executing --> Paused \n");
+ }
+ /* Requesting transition from Executing to Loaded */
+ else if (eState == OMX_StateLoaded) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n OMXCORE-SM: Executing --> Loaded \n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Executing to WaitForResources */
+ else if (eState == OMX_StateWaitForResources) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n OMXCORE-SM: Executing --> WaitForResources \n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Executing to Executing */
+ else if (eState == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n OMXCORE-SM: Executing --> Executing \n");
+ post_event(OMX_EventError, OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Executing to Invalid */
+ else if (eState == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n OMXCORE-SM: Executing --> Invalid \n");
+ post_event(OMX_EventError,
+ OMX_ErrorInvalidState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Executing --> %d Not Handled\n",
+ eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /***************************/
+ /* Current State is Pause */
+ /***************************/
+ else if (m_state == OMX_StatePause) {
+ if (eState == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Pause --> Executing \n");
+ } else if (eState == OMX_StateIdle) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Pause --> Idle \n");
+ execute_omx_flush(OMX_ALL);
+ }
+ /* Requesting transition from Pause to loaded */
+ else if (eState == OMX_StateLoaded) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n Pause --> loaded \n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Pause to WaitForResources */
+ else if (eState == OMX_StateWaitForResources) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n Pause --> WaitForResources \n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Pause to Pause */
+ else if (eState == OMX_StatePause) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n Pause --> Pause \n");
+ post_event(OMX_EventError, OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Pause to Invalid */
+ else if (eState == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "\n Pause --> Invalid \n");
+ post_event(OMX_EventError,
+ OMX_ErrorInvalidState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Paused --> %d Not Handled\n",
+ eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /***************************/
+ /* Current State is WaitForResources */
+ /***************************/
+ else if (m_state == OMX_StateWaitForResources) {
+ /* Requesting transition from WaitForResources to Loaded */
+ if (eState == OMX_StateLoaded) {
+ /* Since error is None , we will post an event at the end of this function definition */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: WaitForResources-->Loaded\n");
+ }
+ /* Requesting transition from WaitForResources to WaitForResources */
+ else if (eState == OMX_StateWaitForResources) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: WaitForResources-->WaitForResources\n");
+ post_event(OMX_EventError, OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from WaitForResources to Executing */
+ else if (eState == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: WaitForResources-->Executing\n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from WaitForResources to Pause */
+ else if (eState == OMX_StatePause) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: WaitForResources-->Pause\n");
+ post_event(OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from WaitForResources to Invalid */
+ else if (eState == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: WaitForResources-->Invalid\n");
+ post_event(OMX_EventError,
+ OMX_ErrorInvalidState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ /* Requesting transition from WaitForResources to Loaded - is NOT tested by Khronos TS */
+ } else {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: %d --> %d(Not Handled)\n",
+ m_state, eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /********************************/
+ /* Current State is Invalid */
+ /*******************************/
+ else if (m_state == OMX_StateInvalid) {
+ /* State Transition from Inavlid to any state */
+ if (eState ==
+ (OMX_StateLoaded || OMX_StateWaitForResources
+ || OMX_StateIdle || OMX_StateExecuting || OMX_StatePause
+ || OMX_StateInvalid)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM: Invalid -->Loaded\n");
+ post_event(OMX_EventError, OMX_ErrorInvalidState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ } else if (cmd == OMX_CommandFlush) {
+ execute_omx_flush(param1);
+ if (0 == param1 || OMX_ALL == param1) {
+ //generate input flush event only.
+ post_event(OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT_FLUSH);
+ }
+ if (1 == param1 || OMX_ALL == param1) {
+ //generate output flush event only.
+ post_event(OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT_FLUSH);
+ }
+ bFlag = 0;
+ } else if (cmd == OMX_CommandPortEnable) {
+ if (param1 != OMX_CORE_OUTPUT_PORT_INDEX) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM:Enable should be on Ouput Port\n");
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM:Recieved command ENABLE (%d)\n", cmd);
+ // call vdec_open
+ if (!m_vdec && (m_first_pending_buf_idx >= 0)) {
+ if (m_vendor_config.pData) {
+ m_vdec_cfg.sequenceHeader =
+ m_vendor_config.pData;
+ m_vdec_cfg.sequenceHeaderLen =
+ m_vendor_config.nDataSize;
+ m_vdec_cfg.height = m_port_height;
+ m_vdec_cfg.width = m_port_width;
+ m_vdec_cfg.size_of_nal_length_field =
+ m_nalu_bytes;
+ m_vdec_cfg.color_format = m_color_format;
+ m_vdec = vdec_open(&m_vdec_cfg);
+ eRet =
+ (m_vdec ==
+ NULL) ? OMX_ErrorHardware : OMX_ErrorNone;
+ } else {
+ eRet =
+ omx_vdec_create_native_decoder(input
+ [m_first_pending_buf_idx]);
+ }
+
+ if (OMX_ErrorNone != eRet) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Native decoder creation failed\n");
+ semaphore_post();
+ return eRet;
+ }
+ OMX_BUFFERHEADERTYPE *tmp_buf_hdr =
+ (OMX_BUFFERHEADERTYPE *) flush_before_vdec_op_q->
+ Dequeue();
+ while (tmp_buf_hdr) {
+ vdec_release_frame(m_vdec,
+ (vdec_frame *) tmp_buf_hdr->
+ pOutputPortPrivate);
+ tmp_buf_hdr =
+ (OMX_BUFFERHEADERTYPE *)
+ flush_before_vdec_op_q->Dequeue();
+ }
+#ifdef _ANDROID_
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
+ m_pmem_info;
+ // create IMemoryHeap object
+ m_heap_ptr =
+ new
+ VideoHeap(((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer[0]))->
+ buffer.pmem_id, m_vdec->arena[0].size,
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer[0]))->
+ buffer.base);
+ for (unsigned i = 0; i < m_out_buf_count; i++) {
+ pPMEMInfo->pmem_fd = (OMX_U32) m_heap_ptr.get();
+ pPMEMInfo++;
+ }
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "VideoHeap : fd %d data %d size %d\n",
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer[0]))->
+ buffer.pmem_id,
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer[0]))->
+ buffer.base, m_vdec->arena[0].size);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "m_heap_ptr =%d",
+ (unsigned)m_heap_ptr.get());
+#endif //_ANDROID_
+ }
+
+ if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
+ m_inp_bEnabled = OMX_TRUE;
+
+ if ((m_state == OMX_StateLoaded
+ && !BITMASK_PRESENT(m_flags,
+ OMX_COMPONENT_IDLE_PENDING))
+ || allocate_input_done()) {
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Disabled-->Enabled Pending\n");
+ BITMASK_SET(m_flags,
+ OMX_COMPONENT_INPUT_ENABLE_PENDING);
+
+ }
+ // Skip the event notification
+ bFlag = 0;
+ }
+ if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
+ m_out_bEnabled = OMX_TRUE;
+
+ if ((m_state == OMX_StateLoaded
+ && !BITMASK_PRESENT(m_flags,
+ OMX_COMPONENT_IDLE_PENDING))
+ || (allocate_output_done())) {
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM: Disabled-->Enabled Pending\n");
+ BITMASK_SET(m_flags,
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+
+ }
+ // Skip the event notification
+ bFlag = 0;
+ }
+ } else if (cmd == OMX_CommandPortDisable) {
+ if (param1 != OMX_CORE_OUTPUT_PORT_INDEX) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "OMXCORE-SM:Disable should be on Ouput Port\n");
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMXCORE-SM:Recieved command DISABLE (%d)\n",
+ cmd);
+
+ if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
+ m_inp_bEnabled = OMX_FALSE;
+ if ((m_state == OMX_StateLoaded
+ || m_state == OMX_StateIdle)
+ && release_input_done()) {
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ } else {
+ BITMASK_SET(m_flags,
+ OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ if (m_state == OMX_StatePause
+ || m_state == OMX_StateExecuting) {
+ execute_omx_flush
+ (OMX_CORE_INPUT_PORT_INDEX);
+ }
+
+ }
+ // Skip the event notification
+ bFlag = 0;
+ }
+ if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
+ m_out_bEnabled = OMX_FALSE;
+
+ if ((m_state == OMX_StateLoaded
+ || m_state == OMX_StateIdle)
+ && release_output_done()) {
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ } else {
+ BITMASK_SET(m_flags,
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+ if (m_state == OMX_StatePause
+ || m_state == OMX_StateExecuting) {
+ execute_omx_flush
+ (OMX_CORE_OUTPUT_PORT_INDEX);
+ }
+ }
+ // Skip the event notification
+ bFlag = 0;
+ }
+
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: Invalid Command received other than StateSet (%d)\n",
+ cmd);
+ eRet = OMX_ErrorNotImplemented;
+ }
+ if (eRet == OMX_ErrorNone && bFlag) {
+ post_event(cmd, eState, OMX_COMPONENT_GENERATE_EVENT);
+ }
+ semaphore_post();
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ExecuteOmxFlush
+
+DESCRIPTION
+ Executes the OMX flush.
+
+PARAMETERS
+ flushtype - input flush(1)/output flush(0)/ both.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
+{
+ bool bRet = false;
+ if (flushType == 0 || flushType == OMX_ALL) {
+ //flush input only
+ execute_input_flush();
+ }
+ if (flushType == 1 || flushType == OMX_ALL) {
+ //flush output only
+ execute_output_flush();
+ }
+ return bRet;
+}
+
+/*=========================================================================
+FUNCTION : execute_output_flush
+
+DESCRIPTION
+ Executes the OMX flush at OUTPUT PORT.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+==========================================================================*/
+bool omx_vdec::execute_output_flush(void)
+{
+ unsigned i;
+ bool canceled;
+ bool bRet = false;
+ OMX_BUFFERHEADERTYPE *pOutBufHdr =
+ (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ unsigned int p1 = 0;
+ unsigned int p2 = 0;
+ unsigned id = 0;
+ int nFlushFrameCnt = 0;
+
+ if (pOutBufHdr) {
+ unsigned nPortIndex;
+ //We will ignore this Queue once m_vdec is created. This will cause no harm
+ //now since when output buffers are created in m_vdec, m_vdec assumes that
+ //all buffers are with itself.
+ OMX_BUFFERHEADERTYPE *tmp_buf_hdr =
+ (OMX_BUFFERHEADERTYPE *) flush_before_vdec_op_q->Dequeue();
+ while (tmp_buf_hdr) {
+ nPortIndex =
+ tmp_buf_hdr -
+ ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr);
+ BITMASK_CLEAR(m_out_flags, nPortIndex);
+ m_cb.FillBufferDone(&m_cmp, m_app_data, tmp_buf_hdr);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Flushing output buffer = %d",
+ m_out_buf_count);
+ tmp_buf_hdr =
+ (OMX_BUFFERHEADERTYPE *) flush_before_vdec_op_q->
+ Dequeue();
+ }
+ }
+ if (m_vdec) {
+ /* . Execute the decoder flush */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n *** Calling vdec_flush *** \n");
+ if (VDEC_SUCCESS ==
+ vdec_flush_port(m_vdec, &nFlushFrameCnt,
+ VDEC_FLUSH_ALL_PORT)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n *** Flush Succeeded : Flush Frame Cnt %d *** \n",
+ nFlushFrameCnt);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "\n *** Flush Failed *** \n");
+ }
+ }
+ while (m_ftb_q.m_size > 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Flushing FTB Q\n");
+ m_ftb_q.delete_entry(&p1, &p2, &id, &canceled);
+ if (!canceled)
+ m_cb.FillBufferDone(&m_cmp, m_app_data,
+ (OMX_BUFFERHEADERTYPE *) p2);
+ }
+ if (m_b_display_order)
+ {
+ if(m_pPrevFrame) {
+ frame_done_cb((struct vdec_context *)&m_vdec_cfg, m_pPrevFrame);
+ m_pPrevFrame = NULL;
+ }
+ m_divX_buffer_info.parsing_required = true;
+ }
+ return bRet;
+}
+
+/*=========================================================================
+FUNCTION : execute_input_flush
+
+DESCRIPTION
+ Executes the OMX flush at INPUT PORT.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+========================================================================== */
+bool omx_vdec::execute_input_flush(void)
+{
+ bool bRet = false;
+
+ OMX_BUFFERHEADERTYPE *pInpBufHdr =
+ (OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr;
+ if (!pInpBufHdr) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Omx Flush issued at wrong context\n");
+ } else {
+ int nFlushFrameCnt = 0;
+ int i, index;
+ unsigned int p1, p2, ident;
+ /* 1. Take care of the pending buffers in the input side */
+ /* During flush clear the pending buffer index. Otherwise FTB followed by flush
+ ** could push duplicate frames to the decoder
+ */
+ if (m_bArbitraryBytes) {
+ if (m_current_arbitrary_bytes_input) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ " Flush:: current arbitrary bytes not null %x ",
+ m_current_arbitrary_bytes_input);
+ m_current_arbitrary_bytes_input->nFilledLen =
+ m_current_arbitrary_bytes_input->nOffset;
+ m_current_arbitrary_bytes_input->nOffset = 0;
+ index = get_free_extra_buffer_index();
+ if (index != -1) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ " Flush:flushing current bufferindex %d ",
+ index);
+ m_extra_buf_info[index].
+ arbitrarybytesInput =
+ m_current_arbitrary_bytes_input;
+ m_current_arbitrary_bytes_input = NULL;
+ }
+ else {
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ m_current_arbitrary_bytes_input);
+ }
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ " Flush:: qsize %d ",
+ m_etb_arbitrarybytes_q.m_size);
+ while (m_etb_arbitrarybytes_q.
+ delete_entry(&p1, &p2, &ident)) {
+ index = get_free_extra_buffer_index();
+ if (index == -1) {
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ (OMX_BUFFERHEADERTYPE
+ *) p2);
+ continue;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Generating the buffer done in flush, qsize %d\n",
+ m_etb_arbitrarybytes_q.m_size);
+ pInpBufHdr = (OMX_BUFFERHEADERTYPE *) p2;
+ m_extra_buf_info[index].arbitrarybytesInput =
+ pInpBufHdr;
+ //post_event((unsigned)&m_vdec_cfg,(unsigned)pInpBufHdr,OMX_COMPONENT_GENERATE_BUFFER_DONE);
+ }
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (m_extra_buf_info[i].bExtra_pBuffer_in_use) {
+ input[i]->pBuffer =
+ m_extra_buf_info[i].extra_pBuffer;
+ input[i]->nOffset = 0;
+ input[i]->nFilledLen = 0;
+ input[i]->nFlags = 0;
+ if (m_extra_buf_info[i].arbitrarybytesInput) {
+ m_extra_buf_info[i].arbitrarybytesInput->nFilledLen =
+ m_extra_buf_info[i].arbitrarybytesInput->nOffset;
+ m_extra_buf_info[i].arbitrarybytesInput->nOffset = 0;
+ }
+ remove_top_entry();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Generating the buffer done in flush, index %d\n",
+ i);
+ buffer_done_cb_stub(&m_vdec_cfg,
+ input[i]);
+ }
+
+ }
+ if (m_bArbitraryBytes) {
+ initialize_arbitrary_bytes_environment();
+ }
+
+ if (m_h264_utils) {
+ m_h264_utils->
+ initialize_frame_checking_environment();
+ }
+
+ } else {
+ do {
+ if (m_bAccumulate_subframe) {
+ if (m_pcurrent_frame) {
+ unsigned nBufferIndex =
+ m_pcurrent_frame -
+ ((OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Found a valid current Frame in Flush, index %d\n",
+ nBufferIndex);
+ add_entry(nBufferIndex);
+ }
+ m_pcurrent_frame = NULL;
+ m_bPartialFrame = false;
+ if (m_h264_utils) {
+ m_h264_utils->
+ initialize_frame_checking_environment
+ ();
+ }
+ }
+ i = remove_top_entry();
+ if (i >= 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Generating the buffer done in flush, i %d\n",
+ i);
+ pInpBufHdr = input[i];
+ post_event((unsigned)&m_vdec_cfg,
+ (unsigned)pInpBufHdr,
+ OMX_COMPONENT_GENERATE_BUFFER_DONE);
+ }
+ } while (i >= 0);
+ }
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SendCommandEvent
+
+DESCRIPTION
+ Send the event to decoder pipe. This is needed to generate the callbacks
+ in decoder thread context.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::post_event(unsigned int p1, unsigned int p2, unsigned int id)
+{
+ bool bRet = false;
+
+ mutex_lock();
+ m_cmd_cnt++;
+ if (id == OMX_COMPONENT_GENERATE_FTB) {
+ m_ftb_q.insert_entry(p1, p2, id);
+ } else if ((id == OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES)) {
+ m_etb_arbitrarybytes_q.insert_entry(p1, p2, id);
+ } else {
+ m_cmd_q.insert_entry(p1, p2, id);
+ }
+
+ bRet = true;
+ post_message(id);
+ mutex_unlock();
+ // for all messages that needs a callback before
+ // vdec is actually opened, skips the proxy
+ QTV_MSG_PRIO8(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Post -->%d[%x,%d]ebd %d fbd %d oc %d %x,%x \n", m_state,
+ (unsigned)m_vdec, id, m_etb_cnt, m_fbd_cnt,
+ m_outstanding_frames, m_flags[0] , m_out_flags[0]);
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetParameter
+
+DESCRIPTION
+ OMX Get Parameter method implementation
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_INOUT OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "get_parameter: \n");
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Get Param in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if (paramData == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Get Param in Invalid paramData \n");
+ return OMX_ErrorBadParameter;
+ }
+
+ switch (paramIndex) {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamPortDefinition\n");
+
+ portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
+ portDefn->nSize = sizeof(portDefn);
+ portDefn->bEnabled = OMX_TRUE;
+ portDefn->bPopulated = OMX_TRUE;
+ portDefn->eDomain = OMX_PortDomainVideo;
+ portDefn->format.video.nFrameHeight = m_crop_dy;
+ portDefn->format.video.nFrameWidth = m_crop_dx;
+ portDefn->format.video.nStride = m_port_width;
+ portDefn->format.video.nSliceHeight = m_port_height;
+ portDefn->format.video.xFramerate = 25;
+
+ if (0 == portDefn->nPortIndex) {
+ VDecoder_buf_info bufferReq;
+
+ if (!m_inp_buf_count) {
+ if (VDEC_SUCCESS !=
+ vdec_get_input_buf_requirements
+ (&bufferReq)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "get_parameter: ERROR - Failed in get input buffer requirement\n");
+ m_inp_buf_count =
+ OMX_CORE_NUM_INPUT_BUFFERS;
+ m_inp_buf_size =
+ OMX_CORE_INPUT_BUFFER_SIZE;
+ } else {
+ m_inp_buf_count =
+ bufferReq.numbuf;
+ m_inp_buf_size =
+ bufferReq.buffer_size;
+ }
+ }
+ portDefn->nBufferCountActual = m_inp_buf_count;
+ portDefn->nBufferCountMin =
+ OMX_CORE_NUM_INPUT_BUFFERS;
+ portDefn->nBufferSize = m_inp_buf_size;
+ portDefn->eDir = OMX_DirInput;
+ portDefn->format.video.eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portDefn->format.video.eCompressionFormat =
+ OMX_VIDEO_CodingAVC;
+ portDefn->bEnabled = m_inp_bEnabled;
+ portDefn->bPopulated = m_inp_bPopulated;
+ } else if (1 == portDefn->nPortIndex) {
+ int extraDataSize,chroma_height, chroma_width;
+ portDefn->eDir = OMX_DirOutput;
+ if (m_vdec) {
+ portDefn->nBufferCountActual =
+ m_vdec_cfg.numOutputBuffers;
+ portDefn->nBufferCountMin =
+ m_vdec_cfg.numOutputBuffers;
+ } else {
+ portDefn->nBufferCountActual =
+ m_out_buf_count;
+ portDefn->nBufferCountMin =
+ m_out_buf_count;
+ }
+ extraDataSize = get_extradata_size();
+ if (m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka) {
+ portDefn->nBufferSize = (m_port_width * m_port_height + 4095) & ~4095;
+ chroma_height = ((m_port_height >> 1) + 31) & ~31;
+ chroma_width = 2 * ((m_port_width >> 1) + 31) & ~31;
+ portDefn->nBufferSize += (chroma_height * chroma_width) + extraDataSize;
+ } else {
+ portDefn->nBufferSize = m_port_height * m_port_width * 3/2 + extraDataSize;
+ }
+ portDefn->format.video.eColorFormat =
+ m_color_format;
+ portDefn->format.video.eCompressionFormat =
+ OMX_VIDEO_CodingUnused;
+ portDefn->bEnabled = m_out_bEnabled;
+ portDefn->bPopulated = m_out_bPopulated;
+ } else {
+ portDefn->eDir = OMX_DirMax;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ " get_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+ case OMX_IndexParamVideoInit:
+ {
+ OMX_PORT_PARAM_TYPE *portParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoInit\n");
+
+ portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ portParamType->nSize = sizeof(portParamType);
+ portParamType->nPorts = 2;
+ portParamType->nStartPortNumber = 0;
+ break;
+ }
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *) paramData;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoPortFormat\n");
+
+ portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
+ portFmt->nSize = sizeof(portFmt);
+
+ if (0 == portFmt->nPortIndex) {
+ if (0 == portFmt->nIndex) {
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ OMX_VIDEO_CodingAVC;
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ OMX_VIDEO_CodingH263;
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ OMX_VIDEO_CodingMPEG4;
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ OMX_VIDEO_CodingWMV;
+ }else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingVp;
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ portFmt->eColorFormat =
+ OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat =
+ (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingSpark;
+ }
+
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "get_parameter: OMX_IndexParamVideoPortFormat:"
+ " NoMore compression formats\n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (1 == portFmt->nPortIndex) {
+ if (1 == portFmt->nIndex) {
+ portFmt->eColorFormat =
+ (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka;
+ portFmt->eCompressionFormat =
+ OMX_VIDEO_CodingUnused;
+ } else if (0 == portFmt->nIndex) {
+ portFmt->eColorFormat =
+ (OMX_COLOR_FORMATTYPE)
+ OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
+ portFmt->eCompressionFormat =
+ OMX_VIDEO_CodingUnused;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoPortFormat:"
+ " NoMore Color formats\n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "get_parameter: Bad port index %d\n",
+ (int)portFmt->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ /*Component should support this port definition */
+ case OMX_IndexParamAudioInit:
+ {
+ OMX_PORT_PARAM_TYPE *audioPortParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamAudioInit\n");
+ audioPortParamType->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ audioPortParamType->nSize = sizeof(audioPortParamType);
+ audioPortParamType->nPorts = 0;
+ audioPortParamType->nStartPortNumber = 0;
+ break;
+ }
+ /*Component should support this port definition */
+ case OMX_IndexParamImageInit:
+ {
+ OMX_PORT_PARAM_TYPE *imagePortParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamImageInit\n");
+ imagePortParamType->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ imagePortParamType->nSize = sizeof(imagePortParamType);
+ imagePortParamType->nPorts = 0;
+ imagePortParamType->nStartPortNumber = 0;
+ break;
+
+ }
+ /*Component should support this port definition */
+ case OMX_IndexParamOtherInit:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "get_parameter: OMX_IndexParamOtherInit %08x\n",
+ paramIndex);
+ eRet = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
+ comp_role->nSize = sizeof(*comp_role);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Getparameter: OMX_IndexParamStandardComponentRole %d\n",
+ paramIndex);
+ if (NULL != comp_role->cRole) {
+ strncpy((char *)comp_role->cRole,
+ (const char *)m_cRole,
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",
+ paramIndex);
+ eRet = OMX_ErrorBadParameter;
+ }
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamPriorityMgmt:
+ {
+ OMX_PRIORITYMGMTTYPE *priorityMgmType =
+ (OMX_PRIORITYMGMTTYPE *) paramData;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamPriorityMgmt\n");
+ priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
+ priorityMgmType->nSize = sizeof(priorityMgmType);
+
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
+ (OMX_PARAM_BUFFERSUPPLIERTYPE *) paramData;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamCompBufferSupplier\n");
+
+ bufferSupplierType->nSize = sizeof(bufferSupplierType);
+ bufferSupplierType->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ if (0 == bufferSupplierType->nPortIndex)
+ bufferSupplierType->nPortIndex =
+ OMX_BufferSupplyUnspecified;
+ else if (1 == bufferSupplierType->nPortIndex)
+ bufferSupplierType->nPortIndex =
+ OMX_BufferSupplyUnspecified;
+ else
+ eRet = OMX_ErrorBadPortIndex;
+
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoAvc %08x\n",
+ paramIndex);
+ break;
+ }
+
+ case OMX_QcomIndexParamInterlaced:
+ {
+ OMX_QCOM_PARAM_VIDEO_INTERLACETYPE *portInterlace =
+ (OMX_QCOM_PARAM_VIDEO_INTERLACETYPE *) paramData;
+ if (portInterlace->nPortIndex == 1)
+ portInterlace->bInterlace =
+ (OMX_BOOL) m_bInterlaced;
+ else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "get_parameter: Bad port index %d should be queried on only o/p port\n",
+ (int)portInterlace->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x\n",
+ paramIndex);
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
+ if(profileLevelType->nPortIndex == 0) {
+ if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if (profileLevelType->nProfileIndex == 0)
+ {
+ profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
+ profileLevelType->eLevel = OMX_VIDEO_AVCLevel31;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
+ profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+
+ }
+ }
+ else if((!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)))
+ {
+ if (profileLevelType->nProfileIndex == 0)
+ {
+ profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
+ profileLevelType->eLevel = OMX_VIDEO_H263Level60;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
+ profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+
+ }
+ }
+ else if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if (profileLevelType->nProfileIndex == 0)
+ {
+ profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
+ profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+
+ }
+ }
+ else if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if (profileLevelType->nProfileIndex == 0)
+ {
+ profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
+ profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+
+ }
+ }
+ else if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if (profileLevelType->nProfileIndex == 0)
+ {
+ profileLevelType->eProfile = QOMX_VIDEO_VPProfileAdvanced;
+ profileLevelType->eLevel = QOMX_VIDEO_VPFormat6;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
+ profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+
+ }
+ }
+ else if((!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",OMX_MAX_STRINGNAME_SIZE)))
+ {
+ if (profileLevelType->nProfileIndex == 0)
+ {
+ profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
+ profileLevelType->eLevel = OMX_VIDEO_H263Level60;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
+ profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+
+ }
+ }
+
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n",
+ profileLevelType->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ default:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "get_parameter: unknown param %08x\n",
+ paramIndex);
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n get_parameter returning Height %d , Width %d \n",
+ m_height, m_width);
+ return eRet;
+
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::Setparameter
+
+DESCRIPTION
+ OMX Set Parameter method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_IN OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ int i;
+
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Set Param in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if (paramData == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Set Param in Invalid paramData \n");
+ return OMX_ErrorBadParameter;
+ }
+ switch (paramIndex) {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
+ (int)portDefn->format.video.nFrameHeight,
+ (int)portDefn->format.video.nFrameWidth);
+
+ if (((m_state == OMX_StateLoaded) &&
+ !BITMASK_PRESENT(m_flags,
+ OMX_COMPONENT_IDLE_PENDING))
+ /* Or while the I/P or the O/P port or disabled */
+ ||
+ ((OMX_DirInput == portDefn->eDir
+ && m_inp_bEnabled == FALSE)
+ || (OMX_DirOutput == portDefn->eDir
+ && m_out_bEnabled == FALSE))) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Set Parameter called in valid state");
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ if (OMX_DirOutput == portDefn->eDir) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexParamPortDefinition on output port\n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter op port: stride %d\n",
+ (int)portDefn->format.video.
+ nStride);
+ /*
+ If actual buffer count is greater than the Min buffer
+ count,change the actual count.
+ m_inp_buf_count is initialized to OMX_CORE_NUM_INPUT_BUFFERS
+ in the constructor
+ */
+ if (portDefn->nBufferCountActual >
+ m_out_buf_count) {
+ m_out_buf_count =
+ portDefn->nBufferCountActual;
+ } else if (portDefn->nBufferCountActual <
+ m_out_buf_count) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ " Set_parameter: Actual buffer count = %d less than Min Buff count",
+ portDefn->
+ nBufferCountActual);
+ eRet = OMX_ErrorBadParameter;
+ }
+ /* Save the DisplayID to be used in useEGLImage api to query the
+ pmem fd and offset from GPU client.
+ */
+ m_display_id = portDefn->format.video.pNativeWindow;
+
+ } else if (OMX_DirInput == portDefn->eDir) {
+ if (m_height !=
+ portDefn->format.video.nFrameHeight
+ || m_width !=
+ portDefn->format.video.nFrameWidth) {
+ m_crop_x = m_crop_y = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "set_parameter ip port: stride %d\n",
+ (int)portDefn->format.
+ video.nStride);
+ // Re-start case since image dimensions have changed
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\nSetParameter: Dimension mismatch. Old H: %d New H: %d Old W: %d New W: %d\n",
+ m_height,
+ (int)portDefn->format.
+ video.nFrameHeight,
+ m_width,
+ (int)portDefn->format.
+ video.nFrameWidth);
+ m_crop_dy = m_port_height =
+ m_vdec_cfg.height = m_height =
+ portDefn->format.video.nFrameHeight;
+ m_crop_dx = m_port_width =
+ m_vdec_cfg.width = m_width =
+ portDefn->format.video.nFrameWidth;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n VDEC Open with new H %d and W %d\n",
+ m_height, m_width);
+
+ if ((m_height % 16) != 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n Height %d is not a multiple of 16",
+ m_height);
+ m_vdec_cfg.height =
+ (m_height / 16 + 1) * 16;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n Height %d adjusted to %d \n",
+ m_height,
+ m_vdec_cfg.
+ height);
+ }
+
+ if (m_width % 16 != 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n Width %d is not a multiple of 16",
+ m_width);
+ m_vdec_cfg.width =
+ (m_width / 16 + 1) * 16;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n Width %d adjusted to %d \n",
+ m_width,
+ m_vdec_cfg.width);
+ }
+
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "\n set_parameter: Image Dimensions same \n");
+ }
+ /*
+ If actual buffer count is greater than the Min buffer
+ count,change the actual count.
+ m_inp_buf_count is initialized to OMX_CORE_NUM_INPUT_BUFFERS
+ in the constructor
+ */
+ if (portDefn->nBufferCountActual >
+ OMX_CORE_NUM_INPUT_BUFFERS) {
+ m_inp_buf_count =
+ portDefn->nBufferCountActual;
+ } else if (portDefn->nBufferCountActual <
+ OMX_CORE_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ " Set_parameter: Actual buffer count = %d less than Min Buff count",
+ portDefn->
+ nBufferCountActual);
+ eRet = OMX_ErrorBadParameter;
+ }
+
+ } else if (portDefn->eDir == OMX_DirMax) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ " Set_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ }
+ break;
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "set_parameter: OMX_IndexParamVideoPortFormat %d\n",
+ portFmt->eColorFormat);
+ if (1 == portFmt->nPortIndex) {
+ m_color_format = portFmt->eColorFormat;
+ }
+ }
+ break;
+
+ case OMX_QcomIndexPortDefn:
+ {
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
+ (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexQcomParamPortDefinitionType %d\n",
+ portFmt->nFramePackingFormat);
+
+ if (portFmt->nPortIndex == 0) // Input port
+ {
+ if (portFmt->nFramePackingFormat ==
+ OMX_QCOM_FramePacking_Arbitrary) {
+ m_bArbitraryBytes = true;
+ if (strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.avc",
+ 26) == 0
+ ||
+ (strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vc1",
+ 26) == 0)) {
+ m_bAccumulate_subframe = true;
+ } else if (strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vp",
+ 25) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: OMX_QcomIndexPortDefn - Arbitrary not supported for VP6");
+ m_bArbitraryBytes = false;
+ m_bAccumulate_subframe = false;
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if (portFmt->nFramePackingFormat ==
+ OMX_QCOM_FramePacking_OnlyOneCompleteFrame)
+ {
+ m_bArbitraryBytes = false;
+ m_bAccumulate_subframe = false;
+ } else if (portFmt->nFramePackingFormat ==
+ OMX_QCOM_FramePacking_OnlyOneCompleteSubFrame)
+ {
+ m_bArbitraryBytes = false;
+ if (strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.avc",
+ 26) == 0
+ ||
+ (strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vc1",
+ 26) == 0)) {
+ m_bAccumulate_subframe = true;
+ } else if (strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vp",
+ 25) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: OMX_QcomIndexPortDefn - Subframe not supported for VP6");
+ m_bArbitraryBytes = false;
+ m_bAccumulate_subframe = false;
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ }
+ }
+ break;
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexParamStandardComponentRole %s\n",
+ comp_role->cRole);
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((char *)comp_role->cRole,
+ "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((const char *)comp_role->cRole,
+ "video_decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((const char *)comp_role->cRole,
+ "video_decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((const char *)comp_role->cRole,
+ "video_decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((const char *)comp_role->cRole,
+ "video_decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind,
+ "OMX.qcom.video.decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((const char *)comp_role->cRole,
+ "video_decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp
+ ((const char *)comp_role->cRole,
+ "video_decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strncpy((char *)m_cRole,
+ "video_decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown Index %s\n",
+ comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown param %s\n",
+ m_vdec_cfg.kind);
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ break;
+ }
+
+ case OMX_IndexParamPriorityMgmt:
+ {
+ if (m_state != OMX_StateLoaded) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ OMX_PRIORITYMGMTTYPE *priorityMgmtype =
+ (OMX_PRIORITYMGMTTYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexParamPriorityMgmt %d\n",
+ priorityMgmtype->nGroupID);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: priorityMgmtype %d\n",
+ priorityMgmtype->nGroupPriority);
+
+ m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
+ m_priority_mgm.nGroupPriority =
+ priorityMgmtype->nGroupPriority;
+
+ break;
+ }
+
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
+ (OMX_PARAM_BUFFERSUPPLIERTYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
+ bufferSupplierType->eBufferSupplier);
+ if (bufferSupplierType->nPortIndex == 0
+ || bufferSupplierType->nPortIndex == 1)
+ m_buffer_supplier.eBufferSupplier =
+ bufferSupplierType->eBufferSupplier;
+
+ else
+
+ eRet = OMX_ErrorBadPortIndex;
+
+ break;
+
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_IndexParamVideoAvc %d\n",
+ paramIndex);
+ break;
+ }
+ case OMX_QcomIndexParamVideoDivx:
+ {
+ QOMX_VIDEO_PARAM_DIVXTYPE *divxType =
+ (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_QcomIndexParamVideoDivx %d\n",
+ paramIndex);
+ if(divxType->nPortIndex == 0) {
+ m_codec_format = divxType->eFormat;
+ m_codec_profile = divxType->eProfile;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_QcomIndexParamVideoDivx Format %d, Profile %d\n",
+ m_codec_format,m_codec_profile);
+ if(divxType->eFormat == QOMX_VIDEO_DIVXFormat311)
+ m_b_divX_parser = false;
+ }
+ else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "set_parameter: OMX_QcomIndexParamVideoDivx BAD PORT INDEX%d \n",
+ divxType->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_QcomIndexParamVideoVp:
+ {
+ QOMX_VIDEO_PARAM_VPTYPE *vpType =
+ (QOMX_VIDEO_PARAM_VPTYPE *) paramData;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_QcomIndexParamVideoVp %d\n",
+ paramIndex);
+ if(vpType->nPortIndex == 0) {
+ m_codec_format = vpType->eFormat;
+ m_codec_profile = vpType->eProfile;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_QcomIndexParamVideoVp Format %d, Profile %d\n",
+ m_codec_format,m_codec_profile);
+ }
+ else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "set_parameter: OMX_QcomIndexParamVideoVp BAD PORT INDEX%d \n",
+ vpType->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_QcomIndexParamVideoSpark:
+ {
+ QOMX_VIDEO_PARAM_SPARKTYPE *sparkType =
+ (QOMX_VIDEO_PARAM_SPARKTYPE *) paramData;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_QcomIndexParamVideoSpark %d\n",
+ paramIndex);
+
+ if(sparkType->nPortIndex == 0) {
+
+ m_codec_format = sparkType->eFormat;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_parameter: OMX_QcomIndexParamVideoSpark Format %d\n",
+ m_codec_format);
+ }
+ else {
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "set_parameter: OMX_QcomIndexParamVideoSpark BAD PORT INDEX%d \n",
+ sparkType->nPortIndex);
+
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+
+ default:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Setparameter: unknown param %d\n",
+ paramIndex);
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetConfig
+
+DESCRIPTION
+ OMX Get Config Method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_INOUT OMX_PTR configData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Get Config in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ switch (configIndex) {
+ case OMX_QcomIndexConfigInterlaced:
+ {
+ OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
+ (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
+ if (configFmt->nPortIndex == 1) {
+ if (configFmt->nIndex == 0)
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceFrameProgressive;
+ else if (configFmt->nIndex == 1)
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
+ else if (configFmt->nIndex == 2)
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "get_config: OMX_QcomIndexConfigInterlaced:"
+ " NoMore Interlaced formats\n");
+ eRet = OMX_ErrorNoMore;
+ }
+
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "get_config: Bad port index %d queried on only o/p port\n",
+ (int)configFmt->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ default:
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "get_config: unknown param %d\n",
+ configIndex);
+ eRet = OMX_ErrorBadParameter;
+ }
+
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SetConfig
+
+DESCRIPTION
+ OMX Set Config method implementation
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_IN OMX_PTR configData)
+{
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ OMX_VIDEO_CONFIG_NALSIZE *pNal;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "set_config, store the NAL length size\n");
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Set Config in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if (m_state == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "set_config:Ignore in Exe state\n");
+ return ret;
+ }
+ if (configIndex == OMX_IndexVendorVideoExtraData) {
+ OMX_VENDOR_EXTRADATATYPE *config =
+ (OMX_VENDOR_EXTRADATATYPE *) configData;
+ if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc")) {
+ OMX_U32 extra_size;
+ // Parsing done here for the AVC atom is definitely not generic
+ // Currently this piece of code is working, but certainly
+ // not tested with all .mp4 files.
+ // Incase of failure, we might need to revisit this
+ // for a generic piece of code.
+
+ // Retrieve size of NAL length field
+ // byte #4 contains the size of NAL lenght field
+ m_nalu_bytes = (config->pData[4] & 0x03) + 1;
+
+ extra_size = 0;
+ if (m_nalu_bytes > 2) {
+ /* Presently we assume that only one SPS and one PPS in AvC1 Atom */
+ extra_size = (m_nalu_bytes - 2) * 2;
+ }
+ // SPS starts from byte #6
+ OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
+ OMX_U8 *pDestBuf;
+ m_vendor_config.nPortIndex = config->nPortIndex;
+
+ // minus 6 --> SPS starts from byte #6
+ // minus 1 --> picture param set byte to be ignored from avcatom
+ m_vendor_config.nDataSize =
+ config->nDataSize - 6 - 1 + extra_size;
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc(m_vendor_config.nDataSize);
+ OMX_U32 len;
+ OMX_U8 index = 0;
+ // case where SPS+PPS is sent as part of set_config
+ pDestBuf = m_vendor_config.pData;
+
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]\n",
+ m_vendor_config.nPortIndex,
+ m_vendor_config.nDataSize,
+ m_vendor_config.pData);
+ while (index < 2) {
+ uint8 *psize;
+ len = *pSrcBuf;
+ len = len << 8;
+ len |= *(pSrcBuf + 1);
+ psize = (uint8 *) & len;
+ memcpy(pDestBuf + m_nalu_bytes, pSrcBuf + 2,
+ len);
+ for (int i = 0; i < m_nalu_bytes; i++) {
+ pDestBuf[i] =
+ psize[m_nalu_bytes - 1 - i];
+ }
+ //memcpy(pDestBuf,pSrcBuf,(len+2));
+ pDestBuf += len + m_nalu_bytes;
+ pSrcBuf += len + 2;
+ index++;
+ pSrcBuf++; // skip picture param set
+ len = 0;
+ }
+ m_header_state = HEADER_STATE_RECEIVED_COMPLETE;
+ } else
+ if (!strcmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4")) {
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc((config->nDataSize));
+ memcpy(m_vendor_config.pData, config->pData,
+ config->nDataSize);
+ } else
+ if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1"))
+ {
+ if ((((*((OMX_U32 *) config->pData)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE)
+ ||
+ (((*((OMX_U32 *) config->pData)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1)
+ ) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "set_config - VC1 simple/main profile\n");
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc(config->nDataSize);
+ memcpy(m_vendor_config.pData, config->pData,
+ config->nDataSize);
+ } else if (*((OMX_U32 *) config->pData) == 0x0F010000) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "set_config - VC1 Advance profile\n");
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc((config->nDataSize));
+ memcpy(m_vendor_config.pData, config->pData,
+ config->nDataSize);
+ } else if ((config->nDataSize == VC1_STRUCT_C_LEN)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,
+ "set_config - VC1 Simple/Main profile struct C only\n");
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
+ memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "set_config - Error: Unknown VC1 profile\n");
+ }
+ }
+ } else if (configIndex == OMX_IndexConfigVideoNalSize) {
+ pNal =
+ reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
+ m_nalu_bytes = pNal->nNaluBytes;
+ if (m_nalu_bytes == 0) {
+ m_bStartCode = true;
+ } else if (m_nalu_bytes < 0 || m_nalu_bytes > 4) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "set_config, invalid NAL length size [%d]\n",
+ m_nalu_bytes);
+ m_nalu_bytes = 4;
+ m_bStartCode = false;
+ ret = OMX_ErrorBadParameter;
+ } else {
+ m_bStartCode = false;
+ }
+ }
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetExtensionIndex
+
+DESCRIPTION
+ OMX GetExtensionIndex method implementaion. <TBD>
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_STRING paramName,
+ OMX_OUT OMX_INDEXTYPE * indexType)
+{
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "get_extension_index: Error, Not implemented\n");
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Get Extension Index in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetState
+
+DESCRIPTION
+ Returns the state information back to the caller.<TBD>
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Error None if everything is successful.
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_STATETYPE * state)
+{
+ *state = m_state;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_state: Returning the state %d\n", *state);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentTunnelRequest
+
+DESCRIPTION
+ OMX Component Tunnel Request method implementation. <TBD>
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_HANDLETYPE
+ peerComponent,
+ OMX_IN OMX_U32 peerPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE *
+ tunnelSetup)
+{
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: component_tunnel_request Not Implemented\n");
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseInputBuffer
+
+DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_input_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8 * buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
+ unsigned i,temp; // Temporary counter
+ temp = OMX_CORE_NUM_INPUT_BUFFERS;
+ if (bytes <= OMX_CORE_INPUT_BUFFER_SIZE) {
+ if (!m_inp_mem_ptr) {
+ int nBufHdrSize =
+ m_inp_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+ temp = BITMASK_SIZE(m_inp_buf_count);
+ m_inp_mem_ptr =
+ (char *)calloc((nBufHdrSize + temp), 1);
+ m_use_pmem = 0;
+
+ if (m_inp_mem_ptr) {
+ // We have valid Input memory block here
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Ist User Input Buffer(%d,%d,%d)\n",
+ m_inp_buf_count, nBufHdrSize,
+ m_inp_bm_count);
+ if (m_bArbitraryBytes) {
+ if (!m_arbitrary_bytes_input_mem_ptr) {
+ m_arbitrary_bytes_input_mem_ptr
+ =
+ (char *)
+ calloc((nBufHdrSize), 1);
+ }
+ *bufferHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ bufHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ //m_inp_bm_ptr = ((char*)bufHdr) + nBufHdrSize ;
+ m_arbitrary_bytes_input[0] =
+ *bufferHdr;;
+ } else {
+ *bufferHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr;
+ bufHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr;
+ //m_inp_bm_ptr = ((char*)bufHdr) + nBufHdrSize ;
+ input[0] = *bufferHdr;
+ }
+ BITMASK_SET(m_inp_bm_count, 0);
+ // Settting the entire storage nicely
+ for (i = 0; i < m_inp_buf_count; i++, bufHdr++) {
+ memset(bufHdr, 0,
+ sizeof(OMX_BUFFERHEADERTYPE));
+ bufHdr->nSize =
+ sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ bufHdr->nAllocLen =
+ OMX_CORE_INPUT_BUFFER_SIZE;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nInputPortIndex =
+ OMX_CORE_INPUT_PORT_INDEX;
+ //QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Input BufferHdr[%p] index[%d]\n",\
+ bufHdr, i);
+ }
+
+ if (m_bArbitraryBytes) {
+ input[0] = bufHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr;
+ for (i = 0; i < m_inp_buf_count;
+ i++, bufHdr++) {
+ memset(bufHdr, 0,
+ sizeof
+ (OMX_BUFFERHEADERTYPE));
+ bufHdr->pBuffer = NULL;
+ bufHdr->nSize =
+ sizeof
+ (OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ bufHdr->nAllocLen =
+ m_inp_buf_size;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nInputPortIndex =
+ OMX_CORE_INPUT_PORT_INDEX;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "arbitrarybytesInput Buffer %p arbitrarybytesInput[%p]\n",
+ bufHdr->pBuffer,
+ bufHdr);
+
+ if (m_extra_buf_info[i].
+ extra_pBuffer == NULL) {
+ m_extra_buf_info[i].
+ extra_pBuffer =
+ (OMX_U8 *)
+ malloc
+ (m_inp_buf_size);
+ if (m_extra_buf_info[i].
+ extra_pBuffer ==
+ NULL) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get extra_pBuffer\n");
+ eRet =
+ OMX_ErrorInsufficientResources;
+ break;
+ }
+ }
+
+ memset(m_extra_buf_info[i].
+ extra_pBuffer, 0,
+ m_inp_buf_size);
+ m_extra_buf_info[i].
+ bExtra_pBuffer_in_use =
+ false;
+ m_extra_buf_info[i].
+ arbitrarybytesInput = NULL;
+ }
+ }
+ omx_vdec_set_input_use_buf_flg();
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Input buffer memory allocation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ } else {
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (BITMASK_ABSENT(m_inp_bm_count, i)) {
+ // bit space available
+ break;
+ }
+ }
+ if (i < m_inp_buf_count) {
+ if (m_bArbitraryBytes) {
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr) +
+ i;
+ m_arbitrary_bytes_input[i] = *bufferHdr;
+ input[i] =
+ ((OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr) + i;
+ } else {
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr) + i;
+ input[i] = *bufferHdr;
+ }
+ (*bufferHdr)->pAppPrivate = appData;
+ BITMASK_SET(m_inp_bm_count, i);
+ } else {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ (*bufferHdr)->pBuffer = (OMX_U8 *) buffer;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "BUffer Header[%p] buffer=%p\n", *bufferHdr,
+ (*bufferHdr)->pBuffer);
+ } else {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseOutputBuffer
+
+DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_output_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8 * buffer) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
+ unsigned i; // Temporary counter
+ if (!m_out_mem_ptr) {
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Ist Use Output Buffer(%d)\n", m_out_buf_count);
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+ nPMEMInfoSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+ //m_out_bm_count = BITMASK_SIZE(m_out_buf_count);
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",
+ nBufHdrSize, sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize, nPlatformListSize);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::PE %d bmSize %d \n", nPlatformEntrySize,
+ m_out_bm_count);
+
+ /*
+ * Memory for output side involves the following:
+ * 1. Array of Buffer Headers
+ * 2. Platform specific information List
+ * 3. Platform specific Entry List
+ * 4. PMem Information entries
+ * 5. Bitmask array to hold the buffer allocation details
+ * In order to minimize the memory management entire allocation
+ * is done in one step.
+ */
+ /*m_out_mem_ptr = (char *)calloc(nBufHdrSize +
+ nPlatformListSize +
+ nPlatformEntrySize +
+ nPMEMInfoSize +m_out_bm_count, 1); */
+ // Alloc mem for out buffer headers
+ m_out_mem_ptr = (char *)calloc(nBufHdrSize, 1);
+ // Alloc mem for platform specific info
+ char *pPtr = NULL;
+ pPtr = (char *)calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize, 1);
+ // Alloc mem for maintaining a copy of use buf headers
+ char *omxHdr = (char *)calloc(nBufHdrSize, 1);
+ m_loc_use_buf_hdr = (OMX_BUFFERHEADERTYPE *) omxHdr;
+
+ if (m_out_mem_ptr && m_loc_use_buf_hdr && pPtr) {
+ bufHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ m_platform_list =
+ (OMX_QCOM_PLATFORM_PRIVATE_LIST *) pPtr;
+ m_platform_entry = (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *)m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *)m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+ //m_out_bm_ptr = (((char *) pPMEMInfo) + nPMEMInfoSize);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::Memory Allocation Succeeded for OUT port%p\n",
+ m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::bHdr %p OutMem %p PE %p pmem[%p]\n",
+ bufHdr, m_out_mem_ptr, pPlatformEntry,
+ pPMEMInfo);
+ for (i = 0; i < m_out_buf_count; i++) {
+ memset(bufHdr, 0, sizeof(OMX_BUFFERHEADERTYPE));
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = bytes; // get_output_buffer_size();
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex =
+ OMX_CORE_OUTPUT_PORT_INDEX;
+ // Platform specific PMEM Information
+ // Initialize the Platform Entry
+ pPlatformEntry->type =
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+
+ // Assign the buffer space to the bufHdr
+ bufHdr->pBuffer = buffer;
+ // Keep this NULL till vdec_open is done
+ bufHdr->pOutputPortPrivate = NULL;
+ pPMEMInfo->offset = 0;
+ bufHdr->pPlatformPrivate = pPlatformList;
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ *bufferHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ BITMASK_SET(m_out_bm_count, 0x0);
+ } else {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Output buf mem alloc failed[0x%x][0x%x][0x%x]\n",
+ m_out_mem_ptr, m_loc_use_buf_hdr, pPtr);
+ eRet = OMX_ErrorInsufficientResources;
+ return eRet;
+ }
+ } else {
+ for (i = 0; i < m_out_buf_count; i++) {
+ if (BITMASK_ABSENT(m_out_bm_count, i)) {
+ break;
+ }
+ }
+ if (i < m_out_buf_count) {
+ // found an empty buffer at i
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr) + i;
+ (*bufferHdr)->pAppPrivate = appData;
+ (*bufferHdr)->pBuffer = buffer;
+ BITMASK_SET(m_out_bm_count, i);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "All Output Buf Allocated:\n");
+ eRet = OMX_ErrorInsufficientResources;
+ return eRet;
+ }
+ }
+ if (allocate_done()) {
+ omx_vdec_display_in_buf_hdrs();
+ omx_vdec_display_out_buf_hdrs();
+ //omx_vdec_dup_use_buf_hdrs();
+ //omx_vdec_display_out_use_buf_hdrs();
+
+ // If use buffer and pmem alloc buffers
+ // then dont make any local copies of use buf headers
+ omx_vdec_set_use_buf_flg();
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseBuffer
+
+DESCRIPTION
+ OMX Use Buffer method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None , if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8 * buffer) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Use Buffer in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ eRet =
+ use_input_buffer(hComp, bufferHdr, port, appData, bytes,
+ buffer);
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ eRet =
+ use_output_buffer(hComp, bufferHdr, port, appData, bytes,
+ buffer);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: Invalid Port Index received %d\n",
+ (int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ if (allocate_done()) {
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_IDLE_PENDING)) {
+ // Send the callback now
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX
+ && m_out_bPopulated) {
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
+ if (m_event_port_settings_sent) {
+ if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! vdec_commit_memory failed\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventError,
+ OMX_ErrorInsufficientResources, 0,
+ NULL);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ // Populate the Buffer Headers
+ omx_vdec_get_out_buf_hdrs();
+ // Populate Use Buffer Headers
+ if (omx_vdec_get_use_buf_flg()) {
+ omx_vdec_dup_use_buf_hdrs();
+ omx_vdec_get_out_use_buf_hdrs();
+ omx_vdec_add_entries();
+ omx_vdec_display_out_buf_hdrs();
+ }
+
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateInputBuffer
+
+DESCRIPTION
+ Helper function for allocate buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_input_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
+ unsigned i; // Temporary counter
+
+// m_inp_buf_count = OMX_CORE_NUM_INPUT_BUFFERS;
+
+ if (bytes <= OMX_CORE_INPUT_BUFFER_SIZE) {
+ if (!m_inp_mem_ptr) {
+ Vdec_BufferInfo vdec_buf;
+
+ int nBufHdrSize =
+ m_inp_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+ //m_inp_bm_count = BITMASK_SIZE(m_inp_buf_count);
+ m_inp_mem_ptr = (char *)calloc((nBufHdrSize), 1);
+
+ if (m_inp_mem_ptr) {
+ // We have valid Input memory block here
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Allocating First Input Buffer(%d,%d,%d)\n",
+ m_inp_buf_count, nBufHdrSize,
+ m_inp_bm_count);
+ if (m_bArbitraryBytes) {
+ input[0] = bufHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr;
+ } else {
+ input[0] = *bufferHdr = bufHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr;
+// m_inp_bm_ptr = ((char *)buf) + nBufSize;
+ }
+
+ BITMASK_SET(m_inp_bm_count, 0);
+
+ // Settting the entire storage nicely
+ for (i = 0; i < m_inp_buf_count; i++, bufHdr++) {
+ memset(bufHdr, 0,
+ sizeof(OMX_BUFFERHEADERTYPE));
+ if (m_bArbitraryBytes) {
+ bufHdr->pBuffer = NULL;
+ bufHdr->nAllocLen =
+ m_inp_buf_size;
+ } else {
+ if (VDEC_EFAILED ==
+ vdec_allocate_input_buffer
+ (m_inp_buf_size, &vdec_buf,
+ m_use_pmem)) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to allocate memory from vdec\n");
+ bufHdr->pBuffer = NULL;
+ } else {
+ if (m_use_pmem) {
+ if (i == 0) {
+ m_vdec_cfg.
+ inputBuffer
+ =
+ (struct
+ Vdec_BufferInfo
+ *)
+ malloc
+ (sizeof
+ (struct
+ Vdec_BufferInfo)
+ *
+ m_inp_buf_count);
+ if (m_vdec_cfg.inputBuffer == NULL) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get input structures\n");
+ eRet = OMX_ErrorInsufficientResources;
+ break;
+ }
+ m_vdec_cfg.
+ numInputBuffers
+ = 0;
+ }
+
+ m_vdec_cfg.
+ inputBuffer
+ [i].base =
+ vdec_buf.
+ base;
+ m_vdec_cfg.
+ inputBuffer
+ [i].
+ pmem_id =
+ vdec_buf.
+ pmem_id;
+ m_vdec_cfg.
+ inputBuffer
+ [i].
+ bufferSize =
+ vdec_buf.
+ bufferSize;
+ m_vdec_cfg.
+ inputBuffer
+ [i].
+ pmem_offset
+ =
+ vdec_buf.
+ pmem_offset;
+ m_vdec_cfg.
+ inputBuffer
+ [i].state =
+ VDEC_BUFFER_WITH_APP;
+ m_vdec_cfg.
+ numInputBuffers++;
+
+ }
+ bufHdr->pBuffer =
+ (OMX_U8 *) vdec_buf.
+ base;
+ bufHdr->nAllocLen =
+ vdec_buf.bufferSize;
+ }
+ }
+
+ bufHdr->nSize =
+ sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nInputPortIndex =
+ OMX_CORE_INPUT_PORT_INDEX;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Input Buffer %p bufHdr[%p]\n",
+ bufHdr->pBuffer, bufHdr);
+ if (!m_bArbitraryBytes
+ && bufHdr->pBuffer == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get input buffer\n");
+ eRet =
+ OMX_ErrorInsufficientResources;
+ break;
+ }
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Input buffer memory allocation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ if (m_bArbitraryBytes) {
+
+ if (!m_arbitrary_bytes_input_mem_ptr) {
+ m_arbitrary_bytes_input_mem_ptr =
+ (char *)calloc((nBufHdrSize), 1);
+ }
+
+ if (m_arbitrary_bytes_input_mem_ptr) {
+ m_arbitrary_bytes_input[0] =
+ *bufferHdr = bufHdr =
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ for (i = 0; i < m_inp_buf_count;
+ i++, bufHdr++) {
+ memset(bufHdr, 0,
+ sizeof
+ (OMX_BUFFERHEADERTYPE));
+ if (VDEC_EFAILED ==
+ vdec_allocate_input_buffer
+ (m_inp_buf_size, &vdec_buf,
+ m_use_pmem)) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to allocate memory from vdec\n");
+ bufHdr->pBuffer = NULL;
+ } else {
+ if (m_use_pmem) {
+ if (i == 0) {
+ m_vdec_cfg.
+ inputBuffer
+ =
+ (struct
+ Vdec_BufferInfo
+ *)
+ malloc
+ (sizeof
+ (struct
+ Vdec_BufferInfo)
+ *
+ (m_inp_buf_count
+ +
+ OMX_CORE_NUM_INPUT_BUFFERS));
+ if (m_vdec_cfg.inputBuffer == NULL) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get input structures\n");
+ eRet = OMX_ErrorInsufficientResources;
+ break;
+ }
+
+ m_vdec_cfg.
+ numInputBuffers
+ = 0;
+ }
+
+ m_vdec_cfg.
+ inputBuffer
+ [i].base =
+ vdec_buf.
+ base;
+ m_vdec_cfg.
+ inputBuffer
+ [i].
+ pmem_id =
+ vdec_buf.
+ pmem_id;
+ m_vdec_cfg.
+ inputBuffer
+ [i].
+ bufferSize =
+ vdec_buf.
+ bufferSize;
+ m_vdec_cfg.
+ inputBuffer
+ [i].
+ pmem_offset
+ =
+ vdec_buf.
+ pmem_offset;
+ m_vdec_cfg.
+ inputBuffer
+ [i].state =
+ VDEC_BUFFER_WITH_APP;
+ m_vdec_cfg.
+ numInputBuffers++;
+
+ }
+ bufHdr->pBuffer =
+ (OMX_U8 *) vdec_buf.
+ base;
+ bufHdr->nAllocLen =
+ vdec_buf.bufferSize;
+ }
+ bufHdr->nSize =
+ sizeof
+ (OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion =
+ OMX_SPEC_VERSION;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nInputPortIndex =
+ OMX_CORE_INPUT_PORT_INDEX;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "arbitrarybytesInput Buffer %p arbitrarybytesInput[%p]\n",
+ bufHdr->pBuffer,
+ bufHdr);
+ if (bufHdr->pBuffer == NULL) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get arbitrarybytesInput buffer\n");
+ eRet =
+ OMX_ErrorInsufficientResources;
+ break;
+ }
+ }
+ }
+ for (int i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS;
+ i++) {
+ if (m_extra_buf_info[i].extra_pBuffer ==
+ NULL) {
+ //m_extra_buf_info[i].extra_pBuffer = (OMX_U8*) malloc(m_inp_buf_size);
+ if (VDEC_EFAILED ==
+ vdec_allocate_input_buffer
+ (m_inp_buf_size, &vdec_buf,
+ m_use_pmem)) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to allocate memory from vdec\n");
+ bufHdr->pBuffer = NULL;
+ } else {
+ if (m_use_pmem) {
+ m_vdec_cfg.
+ inputBuffer
+ [m_inp_buf_count
+ + i].base =
+ vdec_buf.
+ base;
+ m_vdec_cfg.
+ inputBuffer
+ [m_inp_buf_count
+ +
+ i].
+ pmem_id =
+ vdec_buf.
+ pmem_id;
+ m_vdec_cfg.
+ inputBuffer
+ [m_inp_buf_count
+ +
+ i].
+ bufferSize =
+ vdec_buf.
+ bufferSize;
+ m_vdec_cfg.
+ inputBuffer
+ [m_inp_buf_count
+ +
+ i].
+ pmem_offset
+ =
+ vdec_buf.
+ pmem_offset;
+ m_vdec_cfg.
+ inputBuffer
+ [m_inp_buf_count
+ +
+ i].state =
+ VDEC_BUFFER_WITH_APP;
+ m_vdec_cfg.
+ numInputBuffers++;
+
+ }
+ m_extra_buf_info[i].
+ extra_pBuffer =
+ (OMX_U8 *) vdec_buf.
+ base;
+
+ }
+ if (m_extra_buf_info[i].
+ extra_pBuffer == NULL) {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get extra_pBuffer\n");
+ eRet =
+ OMX_ErrorInsufficientResources;
+ break;
+ }
+ }
+ memset(m_extra_buf_info[i].
+ extra_pBuffer, 0,
+ vdec_buf.bufferSize);
+ m_extra_buf_info[i].
+ bExtra_pBuffer_in_use = false;
+ m_extra_buf_info[i].
+ arbitrarybytesInput = NULL;
+ }
+ }
+ } else {
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (BITMASK_ABSENT(m_inp_bm_count, i)) {
+ // bit space available
+ break;
+ }
+ }
+ if (i < m_inp_buf_count) {
+ // found an empty buffer at i
+ if (m_bArbitraryBytes) {
+ m_arbitrary_bytes_input[i] =
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr) +
+ i;
+ } else {
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *)
+ m_inp_mem_ptr) + i;
+ }
+ input[i] =
+ ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr) +
+ i;
+ (*bufferHdr)->pAppPrivate = appData;
+ BITMASK_SET(m_inp_bm_count, i);
+ } else {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ }
+ } else {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateOutputBuffer
+
+DESCRIPTION
+ Helper fn for AllocateBuffer in the output pin
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything went well.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_output_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
+ unsigned i; // Temporary counter
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Allocating Output Buffer(%d)\n", m_out_mem_ptr);
+ if (!m_out_mem_ptr) {
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Allocating First Output Buffer(%d)\n",
+ m_out_buf_count);
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+
+ nPMEMInfoSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+
+ //m_out_bm_count = BITMASK_SIZE(m_out_buf_count);
+
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",
+ nBufHdrSize, sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize, nPlatformListSize);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "PE %d bmSize %d \n", nPlatformEntrySize,
+ m_out_bm_count);
+
+ /*
+ * Memory for output side involves the following:
+ * 1. Array of Buffer Headers
+ * 2. Platform specific information List
+ * 3. Platform specific Entry List
+ * 4. PMem Information entries
+ * 5. Bitmask array to hold the buffer allocation details
+ * In order to minimize the memory management entire allocation
+ * is done in one step.
+ */
+ //m_out_mem_ptr = (char *)calloc(nBufHdrSize + nPlatformListSize + nPlatformEntrySize +
+ // nPMEMInfoSize +m_out_bm_count, 1);
+ // Alloc mem for output buf headers
+ m_out_mem_ptr = (char *)calloc(nBufHdrSize, 1);
+ // Alloc mem for platform specific info
+ char *pPtr = NULL;
+ pPtr = (char *)calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize, 1);
+ if (m_out_mem_ptr && pPtr) {
+ bufHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ m_platform_list =
+ (OMX_QCOM_PLATFORM_PRIVATE_LIST *) (pPtr);
+ m_platform_entry = (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *)m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *)m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+
+ //m_out_bm_ptr = (((char *) pPMEMInfo) + nPMEMInfoSize);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Memory Allocation Succeeded for OUT port%p\n",
+ m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "bHdr %p OutMem %p PE %p\n", bufHdr,
+ m_out_mem_ptr, pPlatformEntry);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ " Pmem Info = %p \n", pPMEMInfo);
+ for (i = 0; i < m_out_buf_count; i++) {
+ memset(bufHdr, 0, sizeof(OMX_BUFFERHEADERTYPE));
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = 0;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex =
+ OMX_CORE_OUTPUT_PORT_INDEX;
+ // Platform specific PMEM Information
+ // Initialize the Platform Entry
+ //QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Initializing the Platform Entry for %d\n",i);
+ pPlatformEntry->type =
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+ // Keep pBuffer NULL till vdec is opened
+ bufHdr->pBuffer = (OMX_U8 *) 0xDEADBEEF;
+ bufHdr->pOutputPortPrivate = NULL;
+ pPMEMInfo->offset = 0;
+ bufHdr->pPlatformPrivate = pPlatformList;
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ *bufferHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ //m_out_bm_ptr[0]=0x1;
+ BITMASK_SET(m_out_bm_count, 0);
+ } else {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Output buf mem alloc failed[0x%x][0x%x]\n",
+ m_out_mem_ptr, pPtr);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ } else {
+ for (i = 0; i < m_out_buf_count; i++) {
+ if (BITMASK_ABSENT(m_out_bm_count, i)) {
+ break;
+ }
+ }
+ if (i < m_out_buf_count) {
+ // found an empty buffer at i
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr) + i;
+ (*bufferHdr)->pAppPrivate = appData;
+ BITMASK_SET(m_out_bm_count, i);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "All the Output Buffers have been Allocated ; Returning Insufficient \n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ }
+ return eRet;
+}
+
+// AllocateBuffer -- API Call
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateBuffer
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes) {
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Allocate buffer on port %d \n", (int)port);
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Allocate Buf in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ // What if the client calls again.
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ eRet =
+ allocate_input_buffer(hComp, bufferHdr, port, appData,
+ bytes);
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ eRet =
+ allocate_output_buffer(hComp, bufferHdr, port, appData,
+ bytes);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: Invalid Port Index received %d\n",
+ (int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Checking for Output Allocate buffer Done");
+ if (eRet == OMX_ErrorNone) {
+ if (allocate_done()) {
+
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_IDLE_PENDING)) {
+
+ // Send the callback now
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Input allocate done");
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Input enable pending");
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX
+ && m_out_bPopulated) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "output allocate done");
+ if (m_event_port_settings_sent) {
+ if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! vdec_commit_memory failed\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventError,
+ OMX_ErrorInsufficientResources, 0,
+ NULL);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
+
+ // Populate the Buffer Headers
+ if (m_vdec)
+ omx_vdec_get_out_buf_hdrs();
+ // Populate Use Buffer Headers
+ if (omx_vdec_get_use_buf_flg()) {
+ omx_vdec_dup_use_buf_hdrs();
+ omx_vdec_get_out_use_buf_hdrs();
+ omx_vdec_add_entries();
+ omx_vdec_display_out_buf_hdrs();
+ }
+#ifdef _ANDROID_
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
+ m_pmem_info;
+ // create IMemoryHeap object
+ m_heap_ptr =
+ new
+ VideoHeap(((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ pmem_id, m_vdec->arena[0].size,
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ base);
+ for (unsigned i = 0; i < m_out_buf_count; i++) {
+ pPMEMInfo->pmem_fd =
+ (OMX_U32) m_heap_ptr.get();
+ pPMEMInfo++;
+ }
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "VideoHeap : fd %d data %d size %d\n",
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ pmem_id,
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ base, m_vdec->arena[0].size);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "m_heap_ptr =%d",
+ (unsigned)m_heap_ptr.get());
+#endif //_ANDROID_
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "output enable pending");
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Allocate Buffer exit with ret Code %d\n", eRet);
+ return eRet;
+}
+
+// Free Buffer - API call
+/* ======================================================================
+FUNCTION
+ omx_vdec::FreeBuffer
+
+DESCRIPTION
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+void omx_vdec::cancel_ftb_entry(OMX_BUFFERHEADERTYPE * buffer) {
+ int i = 0;
+ mutex_lock();
+ for (i = 0; i < m_ftb_q.m_size; i++) {
+ if (m_ftb_q.m_q[i].param2 == (unsigned)buffer) {
+ m_ftb_q.m_q[i].canceled = true;
+ break;
+ }
+ }
+ mutex_unlock();
+}
+
+// Free Buffer - API call
+/* ======================================================================
+FUNCTION
+ omx_vdec::FreeBuffer
+
+DESCRIPTION
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned int nPortIndex;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "free_buffer \n");
+
+ if (m_state == OMX_StateIdle
+ && (BITMASK_PRESENT(m_flags, OMX_COMPONENT_LOADING_PENDING))) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ " free buffer while Component in Loading pending\n");
+ } else
+ if ((m_inp_bEnabled == OMX_FALSE
+ && port == OMX_CORE_INPUT_PORT_INDEX)
+ || (m_out_bEnabled == OMX_FALSE
+ && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Free Buffer while port %d disabled\n", port);
+ } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Invalid state to free buffer,ports need to be disabled\n");
+ post_event(OMX_EventError, OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ return eRet;
+ } else if (m_state != OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Invalid state to free buffer,port lost Buffers\n");
+ post_event(OMX_EventError, OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ // check if the buffer is valid
+ if (m_bArbitraryBytes) {
+ nPortIndex =
+ buffer -
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ if (m_extra_buf_info[nPortIndex].extra_pBuffer != NULL) {
+ if (omx_vdec_get_input_use_buf_flg()) {
+ free(m_extra_buf_info[nPortIndex].extra_pBuffer);
+ }
+ else {
+ Vdec_BufferInfo buf_info;
+ buf_info.base =
+ m_extra_buf_info[nPortIndex].extra_pBuffer;
+ if (m_use_pmem) {
+ buf_info.bufferSize =
+ m_vdec_cfg.
+ inputBuffer[m_inp_buf_count +
+ nPortIndex].bufferSize;
+ buf_info.pmem_id =
+ m_vdec_cfg.
+ inputBuffer[m_inp_buf_count +
+ nPortIndex].pmem_id;
+ buf_info.pmem_offset =
+ m_vdec_cfg.
+ inputBuffer[m_inp_buf_count +
+ nPortIndex].pmem_offset;
+ }
+ //free(m_extra_buf_info[nPortIndex].extra_pBuffer);
+ vdec_free_input_buffer(&buf_info, m_use_pmem);
+ }
+ m_extra_buf_info[nPortIndex].extra_pBuffer =
+ NULL;
+ }
+ } else {
+ nPortIndex =
+ buffer - (OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on i/p port - Port idx %d \n",
+ nPortIndex);
+ if (nPortIndex < m_inp_buf_count) {
+ if(omx_vdec_get_input_use_buf_flg()) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on i/p port - use buffer so do not free pBuffer %x \n",
+ buffer->pBuffer);
+ }
+ else{
+ Vdec_BufferInfo buf_info;
+ buf_info.base = buffer->pBuffer;
+ if (m_use_pmem) {
+ buf_info.bufferSize =
+ m_vdec_cfg.inputBuffer[m_inp_buf_count +
+ nPortIndex].
+ bufferSize;
+ buf_info.pmem_id =
+ m_vdec_cfg.inputBuffer[m_inp_buf_count +
+ nPortIndex].pmem_id;
+ buf_info.pmem_offset =
+ m_vdec_cfg.inputBuffer[m_inp_buf_count +
+ nPortIndex].
+ pmem_offset;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on i/p port - pBuffer %x \n",
+ buffer->pBuffer);
+ vdec_free_input_buffer(&buf_info, m_use_pmem);
+ buffer->pBuffer = NULL;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on i/p port - before Clear bitmask %x \n",
+ m_inp_bm_count);
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(m_inp_bm_count, nPortIndex);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on i/p port - after Clear bitmask %x \n",
+ m_inp_bm_count);
+ m_inp_bPopulated = OMX_FALSE;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: free_buffer , \
+ Port Index calculation came out Invalid\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if (BITMASK_PRESENT
+ ((m_flags), OMX_COMPONENT_INPUT_DISABLE_PENDING)
+ && release_input_done()) {
+ if (m_use_pmem) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Release input done freeing input buffer \n");
+ if (m_vdec_cfg.inputBuffer) {
+ free(m_vdec_cfg.inputBuffer);
+ m_vdec_cfg.inputBuffer = NULL;
+ }
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "MOVING TO DISABLED STATE \n");
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ if (omx_vdec_get_input_use_buf_flg() && release_input_done()) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Resetting use_buf flag\n");
+ omx_vdec_reset_input_use_buf_flg();
+ }
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ // check if the buffer is valid
+ nPortIndex = buffer - (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ if (nPortIndex < m_out_buf_count) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on o/p port - Port idx %d \n",
+ nPortIndex);
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(m_out_bm_count, nPortIndex);
+ cancel_ftb_entry(buffer);
+ m_out_bPopulated = OMX_FALSE;
+ if (omx_vdec_get_use_buf_flg()) {
+ OMX_BUFFERHEADERTYPE *temp;
+ // Remove both the mappings.
+ temp = m_use_buf_hdrs.find(buffer);
+ if (buffer && temp) {
+ m_use_buf_hdrs.erase(buffer);
+ m_use_buf_hdrs.erase(temp);
+ }
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: free_buffer , \
+ Port Index calculation came out Invalid\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if (BITMASK_PRESENT
+ ((m_flags), OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
+ && release_output_done()) {
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FreeBuffer : If any Disable event pending,post it\n");
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "MOVING TO DISABLED STATE \n");
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+ if (m_vdec) {
+ m_out_buf_count = m_vdec_cfg.numOutputBuffers;
+ omx_vdec_free_output_port_memory();
+ }
+ if(omx_vdec_get_use_egl_buf_flg()) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Resetting use_egl_buf flag\n");
+ omx_vdec_reset_use_elg_buf_flg();
+ }
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ return eRet;
+ }
+ if (omx_vdec_get_use_buf_flg() && release_done()) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Resetting use_buf flag\n");
+ omx_vdec_reset_use_buf_flg();
+ }
+ } else {
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if ((eRet == OMX_ErrorNone) &&
+ (BITMASK_PRESENT(m_flags, OMX_COMPONENT_LOADING_PENDING))) {
+ if (release_done()) {
+ // Send the callback now
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_LOADING_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateLoaded,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::EmptyThisBuffer
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE * buffer)
+{
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer buffer %p, len %d, offset %d timestamp %ld\n",
+ buffer->pBuffer, buffer->nFilledLen, buffer->nOffset,
+ buffer->nTimeStamp);
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ETB in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if (!buffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Buffer Header NULL\n");
+ return OMX_ErrorBadParameter;
+ }
+ if (m_bArbitraryBytes) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer - post event OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES\n");
+ post_event((unsigned)hComp, (unsigned)buffer,
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer - post event OMX_COMPONENT_GENERATE_ETB\n");
+ post_event((unsigned)hComp, (unsigned)buffer,
+ OMX_COMPONENT_GENERATE_ETB);
+ // eRet = empty_this_buffer_frame_based(hComp, buffer);
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::empty_this_buffer_frame_based
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ empty_this_buffer_proxy_frame_based(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer_frame_based - enter\n");
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "empty_this_buffer_frame_based buffer->nTimeStamp %d nFlags %d\n",
+ buffer->nTimeStamp, buffer->nFlags);
+ unsigned height = 0,val_height = 0;
+ unsigned width = 0, val_width = 0;
+ bool bInterlace = false;
+ unsigned cropx = 0, cropy = 0, cropdx = 0, cropdy = 0;
+
+ /*if(m_state == OMX_StateInvalid)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,_ERROR("ETB in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ } */
+
+ if(m_bInvalidState == true)
+ {
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ return OMX_ErrorNone;
+ }
+
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ OMX_ERRORTYPE ret1 = OMX_ErrorNone;
+ OMX_U32 ret2;
+ bool has_frame = true;
+ unsigned nBufferIndex =
+ buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ if (m_event_port_settings_sent == true) {
+ if (m_bAccumulate_subframe == false) {
+ add_entry(nBufferIndex);
+ return OMX_ErrorNone;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer - m_event_port_settings_sent == true\n");
+ return add_entry_subframe_stitching(buffer);
+ }
+ }
+ if (!m_vdec) {
+ if (nBufferIndex > m_inp_buf_count) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "omx_vdec::etb--> Buffer Index Invalid\n");
+ return OMX_ErrorBadPortIndex;
+ }
+
+ if ((strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26)
+ == 0)
+ && m_header_state != HEADER_STATE_RECEIVED_COMPLETE) {
+ bool is_partial;
+
+ has_frame = false;
+ ret2 =
+ m_h264_utils->check_header(buffer, m_nalu_bytes,
+ is_partial,
+ (OMX_U32)
+ m_header_state);
+
+ if (ret2 == -1) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "omx_vdec::etb--> Wrong Data before recieving the header\n");
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ return OMX_ErrorFormatNotDetected;
+ } else {
+ if (is_partial) {
+ if (m_header_state ==
+ HEADER_STATE_RECEIVED_NONE) {
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc(buffer->
+ nFilledLen);
+ memcpy(m_vendor_config.pData,
+ buffer->pBuffer,
+ buffer->nFilledLen);
+ m_vendor_config.nDataSize =
+ buffer->nFilledLen;
+ m_header_state =
+ HEADER_STATE_RECEIVED_PARTIAL;
+ } else {
+ if (m_vendor_config.pData) {
+ OMX_U8 *tempData;
+ tempData =
+ m_vendor_config.
+ pData;
+ m_vendor_config.pData =
+ (OMX_U8 *)
+ malloc(buffer->
+ nFilledLen +
+ m_vendor_config.
+ nDataSize);
+ memcpy(m_vendor_config.
+ pData, tempData,
+ m_vendor_config.
+ nDataSize);
+ memcpy(m_vendor_config.
+ pData +
+ m_vendor_config.
+ nDataSize,
+ buffer->pBuffer,
+ buffer->
+ nFilledLen);
+ m_vendor_config.
+ nDataSize +=
+ buffer->nFilledLen;
+ free(tempData);
+ m_header_state =
+ HEADER_STATE_RECEIVED_COMPLETE;
+ } else {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "omx_vdec::etb--> header_state partial but pData NULL\n");
+ return
+ OMX_ErrorFormatNotDetected;
+ }
+ }
+ } else {
+ if (m_vendor_config.pData) {
+ free(m_vendor_config.pData);
+ }
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc(buffer->
+ nFilledLen);
+ memcpy(m_vendor_config.pData,
+ buffer->pBuffer,
+ buffer->nFilledLen);
+ m_vendor_config.nDataSize =
+ buffer->nFilledLen;
+ m_header_state =
+ HEADER_STATE_RECEIVED_COMPLETE;
+ }
+ if (m_header_state !=
+ HEADER_STATE_RECEIVED_COMPLETE) {
+ buffer_done_cb_stub(&m_vdec_cfg,
+ buffer);
+ return OMX_ErrorNone;
+ }
+ }
+ } else
+ if ((strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
+ 28) == 0))
+ {
+ has_frame = MP4_Utils::HasFrame(buffer);
+ } else
+ if ((strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ 26) == 0))
+ {
+ if(!m_bArbitraryBytes)
+ has_frame = false;
+ } else
+ if ((strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
+ 27) == 0))
+ {
+ if (m_codec_format != QOMX_VIDEO_DIVXFormat311)
+ has_frame = MP4_Utils::HasFrame(buffer);
+
+ }
+
+ ret =
+ omx_vdec_check_port_settings(buffer, height, width,
+ bInterlace, cropx, cropy,
+ cropdx, cropdy);
+ if (ret != OMX_ErrorNone) {
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
+ OMX_ErrorFormatNotDetected , 0, NULL);
+ return ret;
+ }
+ m_bInterlaced = bInterlace;
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "ETB::after parsing-->Ht[%d] Wd[%d] m_ht[%d] m_wdth[%d]\n",
+ height, width, m_height, m_width);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "ETB::after parsing-->cropdy[%d] Cropdx[%d] \n",
+ cropdy, cropdx);
+ m_crop_x = cropx;
+ m_crop_y = cropy;
+ m_crop_dx = cropdx;
+ m_crop_dy = cropdy;
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "ETB::after parsing-->Height[%d] Width[%d] m_ht[%d] m_wdth[%d]\n",
+ height, width, m_height, m_width);
+ if (m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka)
+ {
+ val_height = (m_crop_dy + 15) & ~15;
+ val_width = (m_crop_dx + 15) & ~15;
+ }
+ else
+ {
+ val_height = height;
+ val_width = width;
+ }
+
+ if ((ret1 =
+ omx_vdec_validate_port_param(val_height,
+ val_width)) == OMX_ErrorNone) {
+ m_port_height = height;
+ m_port_width = width;
+ // Create native decoder to figure out the output buffer count and size.
+ ret = omx_vdec_create_native_decoder(buffer);
+ if (OMX_ErrorNone != ret) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Native decoder creation failed\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventError,
+ OMX_ErrorInsufficientResources, 0,
+ NULL);
+ return ret;
+ }
+
+ if ((m_crop_dy == height == m_height)
+ && (m_crop_dx == width == m_width)
+ && (m_out_buf_count == m_vdec_cfg.numOutputBuffers)
+ && (!m_bInterlaced)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "Port setting Changed is not needed\n");
+ if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! vdec_commit_memory failed\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventError,
+ OMX_ErrorInsufficientResources, 0,
+ NULL);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ // Populate Output Buffer Headers
+ omx_vdec_get_out_buf_hdrs();
+ // Populate Use Buffer Headers
+ if (omx_vdec_get_use_buf_flg()) {
+ omx_vdec_dup_use_buf_hdrs();
+ omx_vdec_get_out_use_buf_hdrs();
+ omx_vdec_display_out_buf_hdrs();
+ omx_vdec_add_entries();
+ omx_vdec_display_out_use_buf_hdrs();
+ }
+ OMX_BUFFERHEADERTYPE *tmp_buf_hdr =
+ (OMX_BUFFERHEADERTYPE *)
+ flush_before_vdec_op_q->Dequeue();
+ while (tmp_buf_hdr) {
+ vdec_release_frame(m_vdec,
+ (vdec_frame *)
+ tmp_buf_hdr->
+ pOutputPortPrivate);
+ tmp_buf_hdr =
+ (OMX_BUFFERHEADERTYPE *)
+ flush_before_vdec_op_q->Dequeue();
+ }
+#ifdef _ANDROID_
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
+ m_pmem_info;
+ // create IMemoryHeap object
+ m_heap_ptr =
+ new
+ VideoHeap(((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ pmem_id, m_vdec->arena[0].size,
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ base);
+ for (unsigned i = 0;
+ i < m_vdec_cfg.numOutputBuffers; i++) {
+ pPMEMInfo->pmem_fd =
+ (OMX_U32) m_heap_ptr.get();
+ pPMEMInfo++;
+ }
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "VideoHeap : fd %d data %d size %d\n",
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ pmem_id,
+ ((vdec_frame *) (&m_vdec_cfg.
+ outputBuffer
+ [0]))->buffer.
+ base, m_vdec->arena[0].size);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "m_heap_ptr =%d",
+ (unsigned)m_heap_ptr.get());
+#endif //_ANDROID_
+ } else {
+ // Store the Ht and Width param so that the client can do a GetParam
+ m_event_port_settings_sent = true;
+ // Notify Apps about the Event [ PortSettingsChangedEvent ]
+ if (m_cb.EventHandler) {
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventPortSettingsChanged,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ 0, NULL);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Sending OMX EVENT PORT_SETTINGS_CHANGED EVENT \n");
+ }
+ if (has_frame) {
+ if (m_bAccumulate_subframe == false
+ || (buffer->
+ nFlags & OMX_BUFFERFLAG_EOS)) {
+ add_entry(nBufferIndex);
+ return OMX_ErrorNone;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "After sending Port Setting Change Event\n");
+ return
+ add_entry_subframe_stitching
+ (buffer);
+ }
+ }
+ }
+ if (!has_frame) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "There is no frame to send - do buffer done and return\n");
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ return OMX_ErrorNone;
+ }
+ } else {
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
+ ret1, 0, NULL);
+ return ret1;
+ }
+ }
+
+ return empty_this_buffer_proxy(hComp, buffer);
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::empty_this_buffer_proxy_arbitrary_bytes
+
+DESCRIPTION
+ This routine is used to push the arbritary bit stream to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ empty_this_buffer_proxy_arbitrary_bytes(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec::empty_this_buffer_proxy_arbitrary_bytes - m_current_arbitrary_bytes_input %p %p\n",
+ m_current_arbitrary_bytes_input, m_vdec);
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_arbitrary_bytes in Invalid State\n");
+ m_current_arbitrary_bytes_input = NULL;
+ return OMX_ErrorInvalidState;
+ }
+ if (m_bInvalidState) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_arbitrary_bytes in Invalid State Flag true\n");
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ return OMX_ErrorNone;
+ }
+
+ if (!m_bPartialFrame) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Start to get complete new frame %x\n",
+ m_current_frame);
+ m_current_frame = get_free_input_buffer();
+ if (m_current_frame == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "omx_vdec::empty_this_buffer_proxy_arbitrary_bytes, waiting for resource");
+ m_bWaitForResource = true;
+ return OMX_ErrorNone;
+ }
+ m_current_frame->pBuffer = buffer->pBuffer + buffer->nOffset;
+ m_current_frame->nOffset = 0;
+ m_current_frame->nFilledLen = 0;
+ }
+
+ if (!m_vdec) {
+ if (m_vendor_config.pData) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Sending SPS+PPS as part of vdec_open\n");
+ } else {
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
+ 28) == 0) {
+ m_arbitrary_bytes_info.start_code.m_start_code =
+ VOP_START_CODE;
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask = VOP_START_CODE_MASK;
+ m_bStartCode = true;
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
+ 27) == 0) {
+ m_arbitrary_bytes_info.start_code.m_start_code =
+ VOP_START_CODE;
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask = VOP_START_CODE_MASK;
+ m_bStartCode = true;
+ }else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
+ 28) == 0) {
+ if (m_codec_format == QOMX_VIDEO_SparkFormat1) {
+ m_arbitrary_bytes_info.start_code.m_start_code =
+ SPARK1_START_CODE;
+ }
+ else {
+ m_arbitrary_bytes_info.start_code.m_start_code =
+ SHORT_HEADER_START_CODE;
+ }
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask = SHORT_HEADER_MASK;
+ m_bStartCode = true;
+ }else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
+ 27) == 0) {
+ m_arbitrary_bytes_info.start_code.m_start_code =
+ SHORT_HEADER_START_CODE;
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask = SHORT_HEADER_MASK;
+ m_bStartCode = true;
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
+ 26) == 0) {
+ if (m_nalu_bytes == 0) {
+ m_arbitrary_bytes_info.start_code.
+ m_start_code = H264_START_CODE;
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask =
+ H264_START_CODE_MASK;
+ m_bStartCode = true;
+ } else {
+ m_bStartCode = false;
+ }
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ 26) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "VC1 clip \n");
+ if ((((*((OMX_U32 *) m_current_frame->pBuffer))
+ & VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE)
+ ||
+ (((*((OMX_U32 *) m_current_frame->pBuffer))
+ & VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1)
+ ) {
+
+ OMX_U32 *pBuf32;
+ OMX_U8 *pBuf8;
+
+ pBuf32 =
+ (OMX_U32 *) m_current_frame->
+ pBuffer;
+
+ /* size of struct C or sequence header appears right after the number of frames information in the sequence header */
+ m_vdec_cfg.sequenceHeaderLen =
+ *(++pBuf32);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_arbitrary_bytes: sequence header len: %d \n",
+ m_vdec_cfg.
+ sequenceHeaderLen);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "VC1 clip - Simple Main Profile\n");
+
+ if (m_vendor_config.pData) {
+ free(m_vendor_config.pData);
+ }
+ m_vendor_config.nPortIndex = 0;
+ if (((*
+ ((OMX_U32 *) m_current_frame->
+ pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE) {
+ m_vendor_config.nDataSize =
+ OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC
+ +
+ m_vdec_cfg.
+ sequenceHeaderLen;
+ m_arbitrary_bytes_info.
+ frame_size.
+ m_timestamp_field_present =
+ 1;
+ } else
+ if (((*
+ ((OMX_U32 *) m_current_frame->
+ pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1) {
+ m_vendor_config.nDataSize =
+ OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC
+ +
+ m_vdec_cfg.
+ sequenceHeaderLen;
+ /* set the time stamp field to be 0 so that the timestamp field is not parsed for RCV V1 format */
+ m_arbitrary_bytes_info.
+ frame_size.
+ m_timestamp_field_present =
+ 0;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_arbitrary_bytes: m_vendor_config.nDataSize: %d \n",
+ m_vendor_config.
+ nDataSize);
+
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc(m_vendor_config.
+ nDataSize);
+ memcpy(m_vendor_config.pData,
+ m_current_arbitrary_bytes_input->
+ pBuffer +
+ m_current_arbitrary_bytes_input->
+ nOffset,
+ m_vendor_config.nDataSize);
+
+ m_current_arbitrary_bytes_input->
+ nFilledLen -=
+ m_vendor_config.nDataSize;
+ memmove
+ (m_current_arbitrary_bytes_input->
+ pBuffer,
+ m_current_arbitrary_bytes_input->
+ pBuffer +
+ m_vendor_config.nDataSize,
+ m_current_arbitrary_bytes_input->
+ nFilledLen);
+ m_bStartCode = false;
+ m_bAccumulate_subframe = false;
+
+ } else
+ if (*((OMX_U32 *) m_current_frame->pBuffer)
+ == 0x0F010000) {
+ m_arbitrary_bytes_info.start_code.
+ m_start_code = VC1_AP_START_CODE;
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask =
+ VC1_AP_START_CODE_MASK;
+ m_bStartCode = true;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer_proxy_arbitrary_bytes - Warning: Possibility of Simple Main VC1 profile without sequence layer\n");
+ }
+ }
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Start code 0x%.8x mask 0x%.8x\n",
+ m_arbitrary_bytes_info.start_code.
+ m_start_code,
+ m_arbitrary_bytes_info.start_code.
+ m_start_code_mask);
+ }
+ }
+
+ if (get_one_complete_frame(m_current_frame)) {
+ empty_this_buffer_proxy_frame_based(hComp, m_current_frame);
+ } else {
+ int pend_idx = get_first_pending_index();
+ if (pend_idx >= 0) {
+ push_pending_buffers_proxy();
+ }
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::empty_this_buffer_proxy
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE *
+ buffer) {
+ int push_cnt = 0;
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "EMPTY THIS BUFFER...%p\n", buffer);
+
+ ++m_etb_cnt;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "ETB: Count %u TS %lld\n", m_etb_cnt, buffer->nTimeStamp);
+
+ if (m_bAccumulate_subframe) {
+ ret = empty_this_buffer_proxy_subframe_stitching(buffer);
+ } else {
+ unsigned nPortIndex =
+ buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ if (nPortIndex < m_inp_buf_count) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Original Empty this buffer\n");
+ int pend_idx = get_first_pending_index();
+ if (pend_idx >= 0 && (pend_idx != (int)nPortIndex)) {
+ // Buffer-2 will hold the existing buffer in hand
+ // We are trying to append the data to buffer2
+ OMX_BUFFERHEADERTYPE *buffer2 = input[pend_idx];
+ signed long long T1 = buffer->nTimeStamp;
+ signed long long T2 = buffer2->nTimeStamp;
+ {
+ add_entry(nPortIndex);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Setting the pending flag for buffer-%d (%x) \n",
+ nPortIndex + 1,
+ m_flags[0] );
+ push_cnt = push_pending_buffers_proxy();
+ }
+ } else {
+ push_cnt += push_one_input_buffer(buffer);
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy pushed %d frames to the decoder\n",
+ push_cnt);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "FATAL ERROR: Why client is pushing the invalid buffer\n");
+ ret = OMX_ErrorFormatNotDetected;
+ }
+ }
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::empty_this_buffer_subframe_stitching
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder considering the subframe stitching
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ empty_this_buffer_proxy_subframe_stitching(OMX_BUFFERHEADERTYPE * buffer) {
+#if DEBUG_ON
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_subframe_stitching, length %d offset %d\n",
+ buffer->nFilledLen, buffer->nOffset);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", buffer->pBuffer[buffer->nOffset + i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+
+ if (m_pcurrent_frame) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_subframe_stitching, current length %d offset %d\n",
+ m_pcurrent_frame->nFilledLen,
+ m_pcurrent_frame->nOffset);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", m_pcurrent_frame->pBuffer[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+ int pend_idx = -1;
+ int push_cnt = 0;
+ unsigned nPortIndex = buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ bool isUpdatetimestamp = false;
+ bool is_frame_no_error = true;
+
+ if (nPortIndex < m_inp_buf_count) {
+ OMX_BOOL isNewFrame = OMX_TRUE;
+ if (buffer->nFilledLen > 0) {
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
+ 26) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_subframe_stitching- H264\n");
+ is_frame_no_error =
+ m_h264_utils->isNewFrame(buffer->pBuffer +
+ buffer->nOffset,
+ buffer->nFilledLen,
+ m_vdec_cfg.
+ size_of_nal_length_field,
+ isNewFrame,
+ isUpdatetimestamp);
+ if(isUpdatetimestamp && (m_pcurrent_frame != NULL)) {
+ m_pcurrent_frame->nTimeStamp = buffer->nTimeStamp;
+ }
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ 26) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_subframe_stitching- VC1\n");
+ is_frame_no_error =
+ find_new_frame_ap_vc1(buffer->pBuffer +
+ buffer->nOffset,
+ buffer->nFilledLen,
+ isNewFrame);
+ }
+ if (false == is_frame_no_error) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "empty_this_buffer_proxy_subframe_stitching- Bit stream Error send Eventerro\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventError,
+ OMX_ErrorStreamCorrupt, 0,
+ NULL);
+ return OMX_ErrorStreamCorrupt;
+
+ }
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "After Subframe stitching process %d\n",
+ isNewFrame);
+
+ if (OMX_TRUE == isNewFrame) {
+ pend_idx = get_first_pending_index();
+
+ nPortIndex =
+ m_pcurrent_frame -
+ ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Subframe stitching - NEW Frame %d %d\n",
+ pend_idx, nPortIndex);
+ if (pend_idx >= 0 && (pend_idx != (int)nPortIndex)) {
+ add_entry(nPortIndex);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Setting the pending flag for buffer-%d (%x) \n",
+ nPortIndex + 1, m_flags[0] );
+ push_cnt = push_pending_buffers_proxy();
+ } else if (m_pcurrent_frame) {
+ push_cnt +=
+ push_one_input_buffer(m_pcurrent_frame);
+ }
+
+ if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Subframe stitching - EOS\n");
+
+ pend_idx = get_first_pending_index();
+ nPortIndex =
+ buffer -
+ ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ if (pend_idx >= 0
+ && (pend_idx != (int)nPortIndex)) {
+ add_entry(nPortIndex);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Setting the pending flag for buffer-%d (%x) \n",
+ nPortIndex + 1,
+ m_flags[0] );
+ push_cnt = push_pending_buffers_proxy();
+ } else {
+ push_cnt +=
+ push_one_input_buffer(buffer);
+ }
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer_proxy_subframe_stitching pushed %d frames to the decoder\n",
+ push_cnt);
+ m_pcurrent_frame = buffer;
+ if (m_bArbitraryBytes) {
+ m_pcurrent_frame->pBuffer +=
+ m_pcurrent_frame->nOffset;
+ m_pcurrent_frame->nOffset = 0;
+ }
+ }
+ } else {
+ if (m_bArbitraryBytes) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "empty_this_buffer_proxy_subframe_stitching arbitrary bytes - SUBFRAME_TYPE_PREVIOUS_FRAME\n");
+ if (m_pcurrent_frame == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "DUDE - It's not a new frame but m_pcurrent_frame is NULL - It's a good case for first Subframe\n");
+ m_pcurrent_frame = buffer;
+ } else
+ if (find_extra_buffer_index
+ (m_pcurrent_frame->pBuffer) != -1) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Copy the new buffer to the current frame allocLen %d\n",
+ m_pcurrent_frame->
+ nAllocLen);
+ memcpy(m_pcurrent_frame->pBuffer +
+ m_pcurrent_frame->nFilledLen,
+ buffer->pBuffer +
+ buffer->nOffset,
+ buffer->nFilledLen);
+ m_pcurrent_frame->nFilledLen +=
+ buffer->nFilledLen;
+ } else
+ if (find_extra_buffer_index(buffer->pBuffer)
+ != -1) {
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Buffer %p must be an extra buffer size of current len %d extra len %d extra offset %d\n",
+ buffer->pBuffer,
+ m_pcurrent_frame->
+ nFilledLen,
+ buffer->nFilledLen,
+ buffer->nOffset);
+ memmove(buffer->pBuffer +
+ m_pcurrent_frame->nFilledLen,
+ buffer->pBuffer +
+ buffer->nOffset,
+ buffer->nFilledLen);
+ memcpy(buffer->pBuffer,
+ m_pcurrent_frame->pBuffer,
+ m_pcurrent_frame->nFilledLen);
+
+ /* We need to swap pBuffer pointer so buffer done cb will free the unused pbuffer */
+ OMX_U8 *temp =
+ m_pcurrent_frame->pBuffer;
+ m_pcurrent_frame->pBuffer =
+ buffer->pBuffer;
+ buffer->pBuffer = temp;
+ m_pcurrent_frame->nFilledLen +=
+ buffer->nFilledLen;
+ } else
+ if ((m_pcurrent_frame->pBuffer +
+ m_pcurrent_frame->nFilledLen ==
+ buffer->pBuffer + buffer->nOffset)
+ && (m_pcurrent_frame->nFilledLen +
+ buffer->nFilledLen <=
+ m_pcurrent_frame->nAllocLen)) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "No need memcpy, current length %d added by %d\n",
+ m_pcurrent_frame->
+ nFilledLen,
+ buffer->nFilledLen);
+ m_pcurrent_frame->nFilledLen +=
+ buffer->nFilledLen;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Buffer is not enough. Need to get extra buffer \n");
+ OMX_S8 index =
+ get_free_extra_buffer_index();
+ if (index != -1) {
+ memcpy(m_extra_buf_info[index].
+ extra_pBuffer,
+ m_pcurrent_frame->
+ pBuffer,
+ m_pcurrent_frame->
+ nFilledLen);
+ memcpy(m_extra_buf_info[index].
+ extra_pBuffer +
+ m_pcurrent_frame->
+ nFilledLen,
+ buffer->pBuffer +
+ buffer->nOffset,
+ buffer->nFilledLen);
+ m_pcurrent_frame->pBuffer =
+ m_extra_buf_info[index].
+ extra_pBuffer;
+ m_pcurrent_frame->nFilledLen +=
+ buffer->nFilledLen;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Couldn't find extra buffer\n");
+ return OMX_ErrorHardware;
+ }
+ }
+ } else // non arbitrary bytes - previous frame
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Subframe stitching - Previous Frame\n");
+ if (m_pcurrent_frame == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "It's not a new frame but m_pcurrent_frame is NULL - it's a good case for the first Subframe\n");
+ m_pcurrent_frame = buffer;
+ } else if (m_pcurrent_frame->nFilledLen +
+ buffer->nFilledLen <=
+ m_pcurrent_frame->nAllocLen) {
+ // Stitching the current buffer into previous one
+ memcpy(&m_pcurrent_frame->
+ pBuffer[m_pcurrent_frame->
+ nFilledLen],
+ buffer->pBuffer,
+ buffer->nFilledLen);
+ m_pcurrent_frame->nFilledLen +=
+ buffer->nFilledLen;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Not enough memory - Stitching failed \n");
+ ret = OMX_ErrorFormatNotDetected;
+ }
+ }
+
+ m_pcurrent_frame->nFlags |= buffer->nFlags;
+
+ if (m_pcurrent_frame->nFlags & OMX_BUFFERFLAG_EOS) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Subframe stitching partial frame - EOS\n");
+
+ pend_idx = get_first_pending_index();
+ nPortIndex =
+ m_pcurrent_frame -
+ ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ if (pend_idx >= 0
+ && (pend_idx != (int)nPortIndex)) {
+ add_entry(nPortIndex);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Setting the pending flag for buffer-%d (%x) \n",
+ nPortIndex + 1,
+ m_flags[0] );
+ push_cnt = push_pending_buffers_proxy();
+ } else {
+ push_cnt +=
+ push_one_input_buffer
+ (m_pcurrent_frame);
+ }
+ }
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "FATAL ERROR: Why client is pushing the invalid buffer\n");
+ ret = OMX_ErrorFormatNotDetected;
+ }
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::add_entry_subframe_stitching
+
+DESCRIPTION
+ add_entry scenarion when SUBFRAME stitching required
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ add_entry_subframe_stitching(OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
+#if DEBUG_ON
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "add_entry_subframe_stitching, length %d\n",
+ buffer->nFilledLen);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", buffer->pBuffer[buffer->nOffset + i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+
+ if (m_pcurrent_frame) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "add_entry_subframe_stitching, current length %d offset %d\n",
+ m_pcurrent_frame->nFilledLen,
+ m_pcurrent_frame->nOffset);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", m_pcurrent_frame->pBuffer[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ unsigned nBufferIndex =
+ m_pcurrent_frame - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ OMX_BOOL isNewFrame = OMX_FALSE;
+ bool isUpdatetimestamp = false;
+ bool is_frame_no_error = true;
+
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "add_entry_subframe_stitching- H264\n");
+ is_frame_no_error =
+ m_h264_utils->isNewFrame(buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen,
+ m_vdec_cfg.
+ size_of_nal_length_field,
+ isNewFrame,
+ isUpdatetimestamp);
+ if(isUpdatetimestamp && (m_pcurrent_frame != NULL)) {
+ m_pcurrent_frame->nTimeStamp = buffer->nTimeStamp;
+ }
+ } else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) ==
+ 0) {
+ is_frame_no_error =
+ find_new_frame_ap_vc1(buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen, isNewFrame);
+ }
+ if (false == is_frame_no_error) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Subframe stitching - Bit stream Error send Eventerro\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
+ OMX_ErrorStreamCorrupt, 0, NULL);
+ return OMX_ErrorStreamCorrupt;
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "add_entry_subframe_stitching\n");
+
+ if (OMX_TRUE == isNewFrame) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "add_entry_subframe_stitching - NEW Frame\n");
+ if (m_pcurrent_frame != NULL || buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ if(m_pcurrent_frame == NULL)
+ {
+ m_pcurrent_frame = buffer;
+ nBufferIndex = m_pcurrent_frame - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ }
+ m_pcurrent_frame->nFlags |= buffer->nFlags;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "add_entry_subframe_stitching - add entry previous buffer\n");
+ add_entry(nBufferIndex);
+ }
+ m_pcurrent_frame = buffer;
+ if (m_bArbitraryBytes) {
+ m_pcurrent_frame->pBuffer += m_pcurrent_frame->nOffset;
+ m_pcurrent_frame->nOffset = 0;
+ }
+ } else if (m_bArbitraryBytes) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "add_entry_subframe_stitching arbitrary bytes - SUBFRAME_TYPE_PREVIOUS_FRAME\n");
+ if (m_pcurrent_frame == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "It's not a new frame but m_pcurrent_frame is NULL - It's a good case for first Subframe\n");
+ m_pcurrent_frame = buffer;
+ } else if (find_extra_buffer_index(m_pcurrent_frame->pBuffer) != -1) { /*/
+ (m_pcurrent_frame->nFilledLen + buffer->nFilledLen <= m_pcurrent_frame->nAllocLen)) */
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Copy the new buffer to the current frame allocLen %d\n",
+ m_pcurrent_frame->nAllocLen);
+ memcpy(m_pcurrent_frame->pBuffer +
+ m_pcurrent_frame->nFilledLen,
+ buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen);
+ m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
+ m_pcurrent_frame->nTimeStamp = buffer->nTimeStamp;
+
+ if(buffer->nFlags & OMX_BUFFERFLAG_EOS ) {
+ m_pcurrent_frame->nFlags |= buffer->nFlags;
+ add_entry(nBufferIndex);
+ }
+
+ } else if (find_extra_buffer_index(buffer->pBuffer) != -1) {
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Buffer %p must be an extra buffer size of current len %d extra len %d extra offset %d\n",
+ buffer->pBuffer,
+ m_pcurrent_frame->nFilledLen,
+ buffer->nFilledLen, buffer->nOffset);
+ memmove(buffer->pBuffer + m_pcurrent_frame->nFilledLen,
+ buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen);
+ memcpy(buffer->pBuffer, m_pcurrent_frame->pBuffer,
+ m_pcurrent_frame->nFilledLen);
+
+ /* We need to swap pBuffer pointer so buffer done cb will free the unused pbuffer */
+ OMX_U8 *temp = m_pcurrent_frame->pBuffer;
+ m_pcurrent_frame->pBuffer = buffer->pBuffer;
+ buffer->pBuffer = temp;
+ m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
+ } else
+ if ((m_pcurrent_frame->pBuffer +
+ m_pcurrent_frame->nFilledLen ==
+ buffer->pBuffer + buffer->nOffset)
+ && (m_pcurrent_frame->nFilledLen + buffer->nFilledLen <=
+ m_pcurrent_frame->nAllocLen)) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "No need memcpy, current length %d added by %d\n",
+ m_pcurrent_frame->nFilledLen,
+ buffer->nFilledLen);
+ m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Buffer is not enough. Need to get extra buffer \n");
+ OMX_S8 index = get_free_extra_buffer_index();
+ if (index != -1) {
+ memcpy(m_extra_buf_info[index].extra_pBuffer,
+ m_pcurrent_frame->pBuffer,
+ m_pcurrent_frame->nFilledLen);
+ memcpy(m_extra_buf_info[index].extra_pBuffer +
+ m_pcurrent_frame->nFilledLen,
+ buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen);
+ m_pcurrent_frame->pBuffer =
+ m_extra_buf_info[index].extra_pBuffer;
+ m_pcurrent_frame->nFilledLen +=
+ buffer->nFilledLen;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Couldn't find extra buffer\n");
+ return OMX_ErrorHardware;
+ }
+ }
+
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ } else // non arbitrary bytes previous frame
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "add_entry_subframe_stitching - SUBFRAME_TYPE_PREVIOUS_FRAME\n");
+ if (m_pcurrent_frame == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "It's not a new frame but m_pcurrent_frame is NULL - It's a good case for first Subframe\n");
+ m_pcurrent_frame = buffer;
+ } else if (m_pcurrent_frame->nFilledLen + buffer->nFilledLen <=
+ m_pcurrent_frame->nAllocLen) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Concat the current Subframe into previous one, size of prev %d current %d\n",
+ m_pcurrent_frame->nFilledLen,
+ buffer->nFilledLen);
+ // Stitching the current buffer into previous one
+ memcpy(&m_pcurrent_frame->
+ pBuffer[m_pcurrent_frame->nFilledLen],
+ buffer->pBuffer, buffer->nFilledLen);
+ m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR - Not enough memory - Stitching failed \n");
+ ret = OMX_ErrorFormatNotDetected;
+ }
+ buffer_done_cb_stub(&m_vdec_cfg, buffer);
+ }
+
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::PushPendingBuffers
+
+DESCRIPTION
+ Internal method used to push the pending buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+unsigned omx_vdec::push_pending_buffers(void) {
+ post_event(0, 0, OMX_COMPONENT_PUSH_PENDING_BUFS);
+ return 0;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::PushPendingBufers
+
+DESCRIPTION
+ This routine is used to push the pending buffers if decoder
+ has space.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ Returns the push count. either 0, 1 or 2.
+
+========================================================================== */
+ unsigned omx_vdec::push_pending_buffers_proxy(void) {
+ unsigned push_cnt = 0;
+ unsigned int ret = 0;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec::push_pending_buffer_proxy\n");
+ while (is_pending()) {
+ // If both buffers are pending try to push the first one
+ int pend_idx = get_first_pending_index();
+ ret = push_one_input_buffer(input[pend_idx]);
+ if (ret == 0) {
+ // If we are not able to push then skip the next step
+ return push_cnt;
+ }
+ push_cnt += ret;
+ }
+ if (get_first_pending_index() >= (int)m_inp_buf_count) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "FATAL Error: pending index invalid\n");
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "push_pending_buffers pushed %d frames to the decoder\n",
+ push_cnt);
+ return push_cnt;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::PushOneInputBuffer
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ True if it is able to the push the buffer to the decoders.
+
+========================================================================== */
+unsigned omx_vdec::push_one_input_buffer(OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
+ unsigned push_cnt = 0;
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "push_one_input_buffer pBuffer %p, nOffset %d, nFilledLen %d\n",
+ buffer->pBuffer, buffer->nOffset, buffer->nFilledLen);
+
+ unsigned nPortIndex = buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ if (nPortIndex < m_inp_buf_count) {
+ if (m_b_divX_parser)
+ {
+ if (m_prev_timestamp < buffer->nTimeStamp)
+ {
+ if ((m_timestamp_interval > (buffer->nTimeStamp - m_prev_timestamp)) ||
+ (m_timestamp_interval == 0))
+ {
+ m_timestamp_interval = buffer->nTimeStamp - m_prev_timestamp;
+ }
+ m_prev_timestamp = buffer->nTimeStamp;
+ }
+
+ if (m_divX_buffer_info.parsing_required)
+ {
+ m_divX_buffer_info.nFrames = m_mp4_utils->parse_frames_in_chunk(
+ buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen,
+ m_timestamp_interval,
+ m_divX_buffer_info.frame_info);
+ m_divX_buffer_info.parsing_required = false;
+ }
+
+ if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) && (m_divX_buffer_info.nFrames == 0))
+ {
+ // Zero length EOS
+ m_divX_buffer_info.nFrames = 1 ;
+ }
+
+ while (m_divX_buffer_info.last_decoded_index < m_divX_buffer_info.nFrames)
+ {
+ memset(&m_frame_info,0,sizeof(m_frame_info));
+ m_frame_info.data = buffer->pBuffer + buffer->nOffset +
+ m_divX_buffer_info.frame_info[m_divX_buffer_info.last_decoded_index].offset;
+ m_frame_info.len = m_divX_buffer_info.frame_info[m_divX_buffer_info.last_decoded_index].size;
+ m_frame_info.timestamp = buffer->nTimeStamp +
+ m_divX_buffer_info.frame_info[m_divX_buffer_info.last_decoded_index].timestamp_increment;
+
+ bool all_done = (m_divX_buffer_info.last_decoded_index == m_divX_buffer_info.nFrames - 1)?true:false;
+ remove_top_entry();
+ if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) && all_done)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"empty_this_buffer: EOS received with TS %d\n",(int)buffer->nTimeStamp);
+ m_eos_timestamp = buffer->nTimeStamp;
+ m_frame_info.flags = FRAME_FLAG_EOS;
+ }
+ void *cookie = ((all_done)?buffer:NULL);
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"Post input buffer %d ts %d", m_ebd_cnt, m_frame_info.timestamp);
+ int nRet = vdec_post_input_buffer(m_vdec, &(m_frame_info), cookie, m_use_pmem);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"vdec_post_input_buffer returned %d\n",nRet);
+ if(VDEC_EOUTOFBUFFERS == nRet)
+ {
+ push_back_entry(nPortIndex);
+ break;
+ }
+ else if (all_done)
+ {
+ ++m_ebd_cnt;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n ETB Count %u \n", m_ebd_cnt);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n First pending buffer index is set to %d (%x)\n",
+ m_first_pending_buf_idx, m_flags[0] );
+ push_cnt++;
+
+ memset(&m_divX_buffer_info, 0, sizeof(m_divX_buffer_info));
+ m_divX_buffer_info.parsing_required = true;
+ break;
+ }
+ else
+ {
+ m_divX_buffer_info.last_decoded_index++;
+ }
+ }
+ }
+ else {
+ memset(&m_frame_info, 0, sizeof(m_frame_info));
+ if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "empty_this_buffer: EOS received with TS %d\n",
+ (int)buffer->nTimeStamp);
+ m_eos_timestamp = buffer->nTimeStamp;
+ m_frame_info.flags = FRAME_FLAG_EOS;
+ }
+ PrintFrameHdr(buffer);
+ m_frame_info.data = buffer->pBuffer + buffer->nOffset;
+ m_frame_info.len = buffer->nFilledLen;
+ m_frame_info.timestamp = buffer->nTimeStamp;
+ m_frame_info.flags = buffer->nFlags;
+ remove_top_entry();
+ int nRet =
+ vdec_post_input_buffer(m_vdec, &(m_frame_info), buffer,
+ m_use_pmem);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_post_input_buffer returned %d\n", nRet);
+ if (VDEC_EOUTOFBUFFERS == nRet) {
+ push_back_entry(nPortIndex);
+ } else {
+ ++m_ebd_cnt;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n ETB Count %u \n", m_ebd_cnt);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n First pending buffer index is set to %d (%x)\n",
+ m_first_pending_buf_idx, m_flags[0] );
+ push_cnt++;
+
+ }
+ }
+ }
+ return push_cnt;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::FillThisBuffer
+
+DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "FTB in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (m_out_bEnabled == OMX_FALSE) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "FTB when port disabled \n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ post_event((unsigned)hComp, (unsigned)buffer,
+ OMX_COMPONENT_GENERATE_FTB);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::FillThisBuffer
+
+DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE *
+ bufferAdd) {
+ OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
+ // pOutMem points to the start of the array
+ unsigned nPortIndex = buffer - ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr);
+
+ if ((m_event_port_settings_sent == true) || !m_vdec
+ || (m_out_bEnabled != OMX_TRUE)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMX_VDEC::FTB --> Decoder Not initialised\n");
+ flush_before_vdec_op_q->Enqueue((void *)buffer);
+ BITMASK_SET((m_out_flags), nPortIndex);
+ return OMX_ErrorNone;
+ }
+
+ m_ftb_cnt++;
+ PrintFrameHdr(buffer);
+ unsigned push_cnt = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB Outstanding frame cnt %d\n", m_outstanding_frames);
+
+ if(m_bInvalidState == true)
+ {
+ m_cb.FillBufferDone(&m_cmp, m_app_data, buffer);
+ return OMX_ErrorNone;
+ }
+
+ if (omx_vdec_get_use_buf_flg()) {
+ // Get the PMEM buf
+ OMX_BUFFERHEADERTYPE *tempHdr;
+ tempHdr = m_use_buf_hdrs.find(buffer);
+ if (tempHdr) {
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB::Found bufHdr[0x%x]0x%x-->0x%x\n",
+ buffer, buffer->pBuffer, tempHdr,
+ tempHdr->pBuffer);
+ // Map the pBuf add to pMEM address.
+ buffer = tempHdr;
+
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB::No match found bufHdr[0x%x] \n",
+ buffer);
+ }
+ }
+ if (nPortIndex < m_out_buf_count) {
+ if (m_state == OMX_StateExecuting) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB:: push_pending_buffer_proxy\n");
+ push_cnt = push_pending_buffers_proxy();
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB Pushed %d input frames at the same time\n",
+ push_cnt);
+
+ if (BITMASK_PRESENT((m_out_flags), nPortIndex)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB[%d] Ignored \n", nPortIndex);
+ return OMX_ErrorNone;
+ }
+
+ if (true == m_bEoSNotifyPending) {
+ unsigned int i = 0;
+ OMX_BUFFERHEADERTYPE *pBufHdr =
+ &(((OMX_BUFFERHEADERTYPE *)
+ m_out_mem_ptr)[nPortIndex]);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB: EOS notify pending - Generate EOS using buffer[%d]\n",
+ nPortIndex);
+ pBufHdr->nFlags = OMX_BUFFERFLAG_EOS;
+ pBufHdr->nFilledLen = 0;
+ pBufHdr->nTimeStamp = m_eos_timestamp;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FBD Outstanding frame cnt %d\n",
+ m_outstanding_frames);
+ m_bEoSNotifyPending = false;
+ if (omx_vdec_get_use_buf_flg()) {
+ // get the pMEM corresponding to the pBUF
+ // copy the pMEM contents to pBUF
+ }
+ m_cb.FillBufferDone(&m_cmp, m_app_data, pBufHdr);
+ } else {
+ vdec_frame *frame =
+ (vdec_frame *) buffer->pOutputPortPrivate;
+
+ if (frame->flags) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB Reset frame flags\n");
+ frame->flags = 0;
+ }
+
+ if (buffer->nFlags) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "FTB Reset buffer hdr flags\n");
+ buffer->nFlags = 0;
+ }
+
+ BITMASK_SET((m_out_flags), nPortIndex);
+ // Release frame should be called only while executing
+ // We stash the h64 frame inside the OutputPortPrivate field
+ --m_outstanding_frames;
+ vdec_release_frame(m_vdec,
+ (vdec_frame *) buffer->
+ pOutputPortPrivate);
+ }
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "FATAL ERROR:Invalid Port Index[%d]\n",
+ nPortIndex);
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SetCallbacks
+
+DESCRIPTION
+ Set the callbacks.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_CALLBACKTYPE * callbacks,
+ OMX_IN OMX_PTR appData) {
+ m_cb = *callbacks;
+ m_app_data = appData;
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentDeInit
+
+DESCRIPTION
+ Destroys the component and release memory allocated to the heap.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) {
+
+ OMX_BUFFERHEADERTYPE *bufferHdr = NULL;
+ int i;
+ if (OMX_StateLoaded != m_state) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "WARNING:Rxd DeInit,OMX not in LOADED state %d\n",
+ m_state);
+ for(i =0; i <m_inp_buf_count; i++ ) {
+ if(m_bArbitraryBytes && m_arbitrary_bytes_input_mem_ptr) {
+ bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *)m_arbitrary_bytes_input_mem_ptr) + i;
+ }
+ else if (m_inp_mem_ptr) {
+ bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr) + i;
+ }
+ if(bufferHdr && bufferHdr->pBuffer && !omx_vdec_get_input_use_buf_flg()) {
+ Vdec_BufferInfo buf_info;
+ buf_info.base = bufferHdr->pBuffer;
+ if (m_use_pmem) {
+ buf_info.bufferSize =
+ m_vdec_cfg.inputBuffer[i].bufferSize;
+ buf_info.pmem_id =
+ m_vdec_cfg.inputBuffer[i].pmem_id;
+ buf_info.pmem_offset =
+ m_vdec_cfg.inputBuffer[i].pmem_offset;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_buffer on i/p port - pBuffer %x \n",
+ bufferHdr->pBuffer);
+ vdec_free_input_buffer(&buf_info, m_use_pmem);
+ }
+
+ }
+ }
+ if (m_bArbitraryBytes) {
+ for (i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS; i++) {
+ if (m_extra_buf_info[i].extra_pBuffer) {
+ if(omx_vdec_get_input_use_buf_flg()) {
+ free(m_extra_buf_info[i].extra_pBuffer);
+ }
+ else {
+ Vdec_BufferInfo buf_info;
+ buf_info.base =
+ m_extra_buf_info[i].extra_pBuffer;
+ if (m_use_pmem) {
+ buf_info.bufferSize =
+ m_vdec_cfg.
+ inputBuffer[m_inp_buf_count +
+ i].bufferSize;
+ buf_info.pmem_id =
+ m_vdec_cfg.
+ inputBuffer[m_inp_buf_count +
+ i].pmem_id;
+ buf_info.pmem_offset =
+ m_vdec_cfg.
+ inputBuffer[m_inp_buf_count +
+ i].pmem_offset;
+ }
+ //free(m_extra_buf_info[nPortIndex].extra_pBuffer);
+ vdec_free_input_buffer(&buf_info, m_use_pmem);
+ }
+ m_extra_buf_info[i].extra_pBuffer = NULL;
+ }
+ }
+ }
+
+ if (m_vdec) {
+ vdec_close(m_vdec);
+ m_vdec_cfg.vdec_fd = -1;
+ m_vdec = NULL;
+ }
+
+ if (m_vdec_cfg.vdec_fd >= 0) {
+ close(m_vdec_cfg.vdec_fd);
+ m_vdec_cfg.vdec_fd = -1;
+ }
+
+ if (m_inp_mem_ptr) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the Input Memory\n");
+ free(m_inp_mem_ptr);
+ m_inp_mem_ptr = NULL;
+ }
+ if (m_arbitrary_bytes_input_mem_ptr) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the Input Memory\n");
+ free(m_arbitrary_bytes_input_mem_ptr);
+ m_arbitrary_bytes_input_mem_ptr = NULL;
+ }
+ if (m_loc_use_buf_hdr) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the UseBuffer Header Memory\n");
+ }
+ if (m_use_buf_hdrs.size()) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "WARNING::Cleanup Not correct\n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "WARNING::Num of ele still in the container=%d\n",
+ m_use_buf_hdrs.size());
+ m_use_buf_hdrs.show();
+ m_use_buf_hdrs.eraseall();
+
+ }
+ if (m_h264_utils) {
+ delete m_h264_utils;
+ m_h264_utils = NULL;
+ }
+ if(m_mp4_utils)
+ {
+ delete m_mp4_utils;
+ m_mp4_utils = NULL;
+ }
+
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Unread mesg FTB-Q[%d] CMD-Q[%d] ETB-Q[%d]\n",
+ m_ftb_q.m_size, m_cmd_q.m_size,
+ m_etb_arbitrarybytes_q.m_size);
+ // Reset counters in mesg queues
+ m_ftb_q.m_size = 0;
+ m_cmd_q.m_size = 0;
+ m_etb_arbitrarybytes_q.m_size = 0;
+ m_ftb_q.m_read = m_ftb_q.m_write = 0;
+ m_cmd_q.m_read = m_cmd_q.m_write = 0;
+ m_etb_arbitrarybytes_q.m_read = m_etb_arbitrarybytes_q.m_write = 0;
+
+ if (m_vendor_config.pData) {
+ free(m_vendor_config.pData);
+ m_vendor_config.pData = NULL;
+ }
+#ifdef _ANDROID_
+ // Clear the strong reference
+ m_heap_ptr.clear();
+#endif // _ANDROID_
+ omx_vdec_free_output_port_memory();
+
+ return OMX_ErrorNone;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::use_egl_output_buffer
+
+DESCRIPTION
+ OMX Use EGL Image method implementation <TBD>.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Not Implemented error.
+
+========================================================================== */
+
+OMX_ERRORTYPE omx_vdec::use_egl_output_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN void *eglImage)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
+ unsigned i; // Temporary counter
+#ifdef USE_EGL_IMAGE_GPU
+ PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
+ EGLint fd = -1, offset = 0;
+#else
+ int fd = -1, offset = 0;
+#endif
+ vdec_frame *output_buf;
+#ifdef USE_EGL_IMAGE_GPU
+ if(m_display_id == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Display ID is not set by IL client and EGL image can't be used with out this \n");
+ return OMX_ErrorInsufficientResources;
+
+ }
+
+ egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
+ eglGetProcAddress("eglQueryImageKHR");
+
+ egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,
+ &fd);
+
+ egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,
+ &offset);
+#else //with OMX test app
+ struct temp_egl {
+ int pmem_fd;
+ int offset;
+ };
+ struct temp_egl *temp_egl_id;
+ temp_egl_id = (struct temp_egl *)eglImage;
+ fd = temp_egl_id->pmem_fd;
+ offset = temp_egl_id->offset;
+#endif
+
+ if (fd < 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Improper pmem fd by EGL clinet %d \n",fd);
+ return OMX_ErrorInsufficientResources;
+ }
+ if (!m_out_mem_ptr) {
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Ist Use Output Buffer(%d)\n", m_out_buf_count);
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+ nPMEMInfoSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+ //m_out_bm_count = BITMASK_SIZE(m_out_buf_count);
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",
+ nBufHdrSize, sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize, nPlatformListSize);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::PE %d bmSize %d \n", nPlatformEntrySize,
+ m_out_bm_count);
+
+ /*
+ * Memory for output side involves the following:
+ * 1. Array of Buffer Headers
+ * 2. Platform specific information List
+ * 3. Platform specific Entry List
+ * 4. PMem Information entries
+ * 5. Bitmask array to hold the buffer allocation details
+ * In order to minimize the memory management entire allocation
+ * is done in one step.
+ */
+ /*m_out_mem_ptr = (char *)calloc(nBufHdrSize +
+ nPlatformListSize +
+ nPlatformEntrySize +
+ nPMEMInfoSize +m_out_bm_count, 1); */
+ // Alloc mem for out buffer headers
+ m_out_mem_ptr = (char *)calloc(nBufHdrSize, 1);
+ // Alloc mem for platform specific info
+ char *pPtr = NULL;
+ pPtr = (char *)calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize, 1);
+ m_vdec_cfg.outputBuffer =
+ (struct vdec_frame *)malloc(sizeof(struct vdec_frame) *
+ m_out_buf_count);
+ if (m_out_mem_ptr && pPtr && m_vdec_cfg.outputBuffer) {
+ bufHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ m_platform_list =
+ (OMX_QCOM_PLATFORM_PRIVATE_LIST *) pPtr;
+ m_platform_entry = (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *)m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *)m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+ //m_out_bm_ptr = (((char *) pPMEMInfo) + nPMEMInfoSize);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::Memory Allocation Succeeded for OUT port%p\n",
+ m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "UOB::bHdr %p OutMem %p PE %p pmem[%p]\n",
+ bufHdr, m_out_mem_ptr, pPlatformEntry,
+ pPMEMInfo);
+ for (i = 0; i < m_out_buf_count; i++) {
+ memset(bufHdr, 0, sizeof(OMX_BUFFERHEADERTYPE));
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = get_output_buffer_size();
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex =
+ OMX_CORE_OUTPUT_PORT_INDEX;
+ // Platform specific PMEM Information
+ // Initialize the Platform Entry
+ pPlatformEntry->type =
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+
+ // Assign the buffer space to the bufHdr
+ bufHdr->pBuffer = (OMX_U8*)eglImage;
+ // Keep this NULL till vdec_open is done
+ bufHdr->pOutputPortPrivate = NULL;
+ pPMEMInfo->offset = 0;
+ bufHdr->pPlatformPrivate = pPlatformList;
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ *bufferHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ output_buf = (vdec_frame *) &m_vdec_cfg.outputBuffer[0];
+ output_buf[0].buffer.pmem_id = fd;
+ output_buf[0].buffer.pmem_offset = offset;
+ output_buf[0].buffer.bufferSize = get_output_buffer_size();
+ output_buf[0].buffer.base = (OMX_U8*)eglImage;
+ output_buf[0].buffer.state = VDEC_BUFFER_WITH_APP_FLUSHED;
+ BITMASK_SET(m_out_bm_count, 0x0);
+ } else {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Output buf mem alloc failed[0x%x][0x%x][0x%x]\n",
+ m_out_mem_ptr, m_loc_use_buf_hdr, pPtr);
+ eRet = OMX_ErrorInsufficientResources;
+ return eRet;
+ }
+ } else {
+ for (i = 0; i < m_out_buf_count; i++) {
+ if (BITMASK_ABSENT(m_out_bm_count, i)) {
+ break;
+ }
+ }
+ if (i < m_out_buf_count) {
+ // found an empty buffer at i
+ *bufferHdr =
+ ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr) + i;
+ (*bufferHdr)->pAppPrivate = appData;
+ (*bufferHdr)->pBuffer = (OMX_U8*)eglImage;
+ output_buf = (vdec_frame *) &m_vdec_cfg.outputBuffer[0] ;
+ output_buf[i].buffer.pmem_id = fd;
+ output_buf[i].buffer.pmem_offset = offset;
+ output_buf[i].buffer.bufferSize = get_output_buffer_size();
+ output_buf[i].buffer.base = (OMX_U8*)eglImage;
+ output_buf[i].buffer.state = VDEC_BUFFER_WITH_APP_FLUSHED;
+ BITMASK_SET(m_out_bm_count, i);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "All Output Buf Allocated:\n");
+ eRet = OMX_ErrorInsufficientResources;
+ return eRet;
+ }
+ }
+ if (allocate_done()) {
+ omx_vdec_display_in_buf_hdrs();
+ omx_vdec_display_out_buf_hdrs();
+ //omx_vdec_dup_use_buf_hdrs();
+ //omx_vdec_display_out_use_buf_hdrs();
+
+ // If use buffer and pmem alloc buffers
+ // then dont make any local copies of use buf headers
+ omx_vdec_set_use_egl_buf_flg();
+ }
+ return eRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseEGLImage
+
+DESCRIPTION
+ OMX Use EGL Image method implementation <TBD>.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Not Implemented error.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN void *eglImage) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "use_EGL_image: Begin \n");
+
+ if (m_state == OMX_StateInvalid) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Use Buffer in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ eRet =
+ use_egl_output_buffer(hComp, bufferHdr, port, appData, eglImage);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: Invalid Port Index received %d\n",
+ (int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ if (allocate_done()) {
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_IDLE_PENDING)) {
+ // Send the callback now
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if (port == OMX_CORE_OUTPUT_PORT_INDEX
+ && m_out_bPopulated) {
+ if (BITMASK_PRESENT
+ (m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
+ if (m_event_port_settings_sent) {
+ if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! vdec_commit_memory failed\n");
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,
+ OMX_EventError,
+ OMX_ErrorInsufficientResources, 0,
+ NULL);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ // Populate the Buffer Headers
+ omx_vdec_get_out_buf_hdrs();
+ BITMASK_CLEAR((m_flags),
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentRoleEnum
+
+DESCRIPTION
+ OMX Component Role Enum method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything is successful.
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_U8 * role,
+ OMX_IN OMX_U32 index) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ eRet = OMX_ErrorNoMore;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.divx",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.vc1",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.vp",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else
+ if (!strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strncpy((char *)role, "video_decoder.spark",
+ OMX_MAX_STRINGNAME_SIZE);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "component_role_enum: role %s\n", role);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "\n Querying Role on Unknown Component\n");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateInputDone
+
+DESCRIPTION
+ Checks if I/P buffer pool is allocated by IL Client or not.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_vdec::allocate_input_done(void) {
+ bool bRet = false;
+ unsigned i = 0;
+
+ if (m_inp_mem_ptr == NULL) {
+ return bRet;
+ }
+ if (m_inp_mem_ptr) {
+ for (; i < m_inp_buf_count; i++) {
+ if (BITMASK_ABSENT(m_inp_bm_count, i)) {
+ break;
+ }
+ }
+ }
+ if (i == m_inp_buf_count) {
+ bRet = true;
+ }
+ if (i == m_inp_buf_count && m_inp_bEnabled) {
+ m_inp_bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateOutputDone
+
+DESCRIPTION
+ Checks if entire O/P buffer pool is allocated by IL Client or not.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_vdec::allocate_output_done(void) {
+ bool bRet = false;
+ unsigned j = 0;
+
+ if (m_out_mem_ptr == NULL) {
+ return bRet;
+ }
+
+ if (m_out_mem_ptr) {
+ for (; j < m_out_buf_count; j++) {
+ if (BITMASK_ABSENT(m_out_bm_count, j)) {
+ break;
+ }
+ }
+ }
+
+ if (j == m_out_buf_count) {
+ bRet = true;
+ }
+
+ if (j == m_out_buf_count && m_out_bEnabled) {
+ m_out_bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateDone
+
+DESCRIPTION
+ Checks if entire buffer pool is allocated by IL Client or not.
+ Need this to move to IDLE state.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_vdec::allocate_done(void) {
+ bool bRet = false;
+ bool bRet_In = false;
+ bool bRet_Out = false;
+
+ bRet_In = allocate_input_done();
+ bRet_Out = allocate_output_done();
+
+ if (bRet_In && bRet_Out) {
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ReleaseDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::release_done(void) {
+ bool bRet = false;
+
+ if (release_input_done()) {
+ if (release_output_done()) {
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ReleaseInputDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::release_input_done(void) {
+ bool bRet = false;
+ unsigned i = 0, j = 0;
+
+ if (m_inp_mem_ptr) {
+ for (; j < m_inp_buf_count; j++) {
+ if (BITMASK_PRESENT(m_inp_bm_count, j)) {
+ break;
+ }
+ }
+ if (j == m_inp_buf_count) {
+ bRet = true;
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: Invalid Inp/OutMem pointers \n");
+ bRet = true;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ReleaseOutputDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::release_output_done(void) {
+ bool bRet = false;
+ unsigned i = 0, j = 0;
+ if (m_out_mem_ptr) {
+ for (; j < m_out_buf_count; j++) {
+ if (BITMASK_PRESENT(m_out_bm_count, j)) {
+ break;
+ }
+ }
+ if (j == m_out_buf_count) {
+ bRet = true;
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error: Invalid Inp/OutMem pointers \n");
+ bRet = true;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_get_out_buf_hdrs
+
+DESCRIPTION
+ Get the PMEM area from video decoder
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+void omx_vdec::omx_vdec_get_out_buf_hdrs() {
+ OMX_BUFFERHEADERTYPE *bufHdr;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = m_pmem_info;
+
+ bufHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ vdec_frame *base_frame = (vdec_frame *) & m_vdec_cfg.outputBuffer[0];
+ m_out_buf_count = m_vdec_cfg.numOutputBuffers;
+
+ if (base_frame) {
+ for (unsigned int i = 0; i < m_out_buf_count; i++) {
+ bufHdr->nAllocLen = m_vdec_cfg.nOutBufAllocLen; //get_output_buffer_size();
+ //bufHdr->nFilledLen= get_output_buffer_size();
+ bufHdr->nFilledLen = 0;
+ bufHdr->pBuffer =
+ (OMX_U8 *) (base_frame[i].buffer.base);
+ bufHdr->pOutputPortPrivate = (void *)&base_frame[i];
+
+ pPMEMInfo->offset = base_frame[i].buffer.pmem_offset;
+ pPMEMInfo->pmem_fd = base_frame[i].buffer.pmem_id;
+ QTV_MSG_PRIO5(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "Output Buffer param: Index [%d]: \
+ fd 0x%x output 0x%x base 0x%x off 0x%x\n", i,
+ (unsigned)pPMEMInfo->pmem_fd, &base_frame[i], (unsigned)base_frame[i].buffer.base, (unsigned)pPMEMInfo->offset);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Output [%d]: buf %x \n", i,
+ (unsigned)bufHdr->pBuffer);
+ bufHdr++;
+ pPMEMInfo++;
+ }
+ }
+ return;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_get_out_use_buf_hdrs
+
+DESCRIPTION
+ Maintain a local copy of the output use buffers
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+void omx_vdec::omx_vdec_get_out_use_buf_hdrs() {
+ OMX_BUFFERHEADERTYPE *bufHdr;
+ int nBufHdrSize = 0;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "GET OUTPUT USE BUF\n");
+
+ bufHdr = (OMX_BUFFERHEADERTYPE *) m_loc_use_buf_hdr;
+
+ vdec_frame *base_frame = (vdec_frame *) & m_vdec_cfg.outputBuffer[0];
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+ if (base_frame) {
+ for (unsigned int i = 0; i < m_out_buf_count; i++) {
+ bufHdr->nAllocLen = get_output_buffer_size();
+ //bufHdr->nFilledLen= get_output_buffer_size();
+ bufHdr->nFilledLen = 0;
+
+ bufHdr->pBuffer =
+ (OMX_U8 *) (base_frame[i].buffer.base);
+ bufHdr->pOutputPortPrivate = (void *)&base_frame[i];
+ // just the offset instead of physical address
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OutputBuffer[%d]: buf[0x%x]: pmem[0x%x] \n",
+ i, (unsigned)bufHdr->pBuffer,
+ (OMX_U8 *) (base_frame[i].buffer.base));
+ bufHdr++;
+ }
+ }
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_check_port_settings
+
+DESCRIPTION
+ Parser to check the HxW param
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::omx_vdec_check_port_settings(OMX_BUFFERHEADERTYPE *
+ buffer, unsigned &height,
+ unsigned &width,
+ bool & bInterlace,
+ unsigned &cropx,
+ unsigned &cropy,
+ unsigned &cropdx,
+ unsigned &cropdy) {
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ OMX_U8 *buf;
+ OMX_U32 buf_len;
+ OMX_U32 mult_fact = 16;
+
+ if (m_vendor_config.pData) {
+ buf = m_vendor_config.pData;
+ buf_len = m_vendor_config.nDataSize;
+ } else {
+ buf = buffer->pBuffer;
+ buf_len = buffer->nFilledLen;
+ }
+
+ if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc")) {
+ if (false ==
+ m_h264_utils->parseHeader(buf, buf_len, m_nalu_bytes,
+ height, width, bInterlace, cropx,
+ cropy, cropdx, cropdy)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Parsing Error unsupported profile or level\n");
+ return OMX_ErrorStreamCorrupt;
+ }
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Parsing Done height[%d] width[%d]\n", height,
+ width);
+ } else if ((!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4"))
+ || (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263"))
+ || (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx") &&
+ m_codec_format != QOMX_VIDEO_DIVXFormat311) ) {
+ mp4StreamType dataStream;
+ dataStream.data = (unsigned char *)buf;
+ dataStream.numBytes = (unsigned long int)buf_len;
+ if (false == m_mp4_utils->parseHeader(&dataStream)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "VOL header parsing failure, aborting playback\n");
+ return OMX_ErrorStreamCorrupt;
+ }
+ cropx = cropy = 0;
+ cropdy = height = m_mp4_utils->SrcHeight();
+ cropdx = width = m_mp4_utils->SrcWidth();
+ bInterlace = false;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "MPEG4/H263 ht[%d] wdth[%d]\n", height, width);
+ } else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark")) {
+ mp4StreamType dataStream;
+ dataStream.data = (unsigned char *)buf;
+ dataStream.numBytes = (unsigned long int)buf_len;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Parsing Spark bit stream\n");
+ if (false == m_mp4_utils->parseSparkHeader(&dataStream)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Parsing Error unsupported profile or level\n");
+ return OMX_ErrorStreamCorrupt;
+ }
+ cropx = cropy = 0;
+ cropdy = height = m_mp4_utils->SrcHeight();
+ cropdx = width = m_mp4_utils->SrcWidth();
+ bInterlace = false;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "SPARK ht[%d] wdth[%d]\n", height, width);
+ } else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx") &&
+ m_codec_format == QOMX_VIDEO_DIVXFormat311) {
+ bInterlace = false;
+ cropx = cropy = 0;
+ cropdy = height = m_crop_dy;
+ cropdx = width = m_crop_dx;
+
+ } else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp")) {
+ // TODO FOR VP6
+ OMX_U8 *pBuf;
+ if (buf_len <= 8)
+ return OMX_ErrorStreamCorrupt;
+
+ pBuf = buf;
+ /* Skip the first 4 bytes to start reading the Height and Width*/
+ pBuf += 4;
+
+ cropx = cropy = 0;
+ cropdy = height = ( ((OMX_U32) (*pBuf++)) * 16);
+ cropdx = width = ( ((OMX_U32) (*pBuf)) * 16);
+ bInterlace = false;
+ } else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1")) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "omx_vdec_check_port_settings - start code in seq header %x\n", ((*((OMX_U32 *) buf)))); // & VC1_SP_MP_START_CODE_MASK));
+ if ((((*((OMX_U32 *) buf)) & VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE)
+ || (((*((OMX_U32 *) buf)) & VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1)
+ ) {
+ OMX_U32 *pBuf32, num_frames = 0;
+ OMX_U8 *pBuf8;
+
+ pBuf32 = (OMX_U32 *) buf;
+
+ /* get the number of frames from the sequence header */
+ num_frames = *pBuf32 & 0x00FFFFFF;
+
+ /* size of struct C appears right after the number of frames information in the sequence header */
+ m_vdec_cfg.sequenceHeaderLen = *(++pBuf32);
+
+ /* advance the pointer by the size of struct C in order to get the height and width */
+ pBuf8 = (OMX_U8 *) (++pBuf32);
+ pBuf8 += m_vdec_cfg.sequenceHeaderLen;
+
+ /* read the height and width information which are each 4 bytes */
+ pBuf32 = (OMX_U32 *) pBuf8;
+ height = *pBuf32;
+ width = *(++pBuf32);
+ bInterlace = false;
+ m_bAccumulate_subframe = false;
+
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec_check_port_settings - VC1 Simple/Main profile, %d x %d %x x %x\n",
+ width, height, width, height);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec_check_port_settings - VC1 sequence header length %d\n",
+ m_vdec_cfg.sequenceHeaderLen);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec_check_port_settings - num_frames %d\n",
+ num_frames);
+ } else if (*((OMX_U32 *) buf) == 0x0F010000) {
+ OMX_U16 temp_dimension =
+ ((OMX_U16) (buf[6]) << 4) | ((OMX_U16) (buf[7]) >>
+ 4);
+ width = 2 * (temp_dimension + 1);
+
+ temp_dimension =
+ ((OMX_U16) (buf[7] & 0x0F) << 8) |
+ (OMX_U16) (buf[8]);
+ height = 2 * (temp_dimension + 1);
+
+ bInterlace = ((buf[9] & 0x40) ? true : false);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "omx_vdec_check_port_settings - VC1 Advance profile Width:%d x Height:%d\n",
+ width, height);
+ } else if(m_vendor_config.nDataSize == VC1_STRUCT_C_LEN) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,
+ "QC_DEBUG :: omx_vdec_check_port_settings - VC1 height and width, %d x %d\n",
+ width, height);
+ height = m_height;
+ width = m_width;
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "omx_vdec_check_port_settings - ERROR: Unknown VC1 profile. Couldn't find height and width\n");
+ return OMX_ErrorStreamCorrupt;
+ }
+ cropdy = height;
+ cropdx = width;
+ cropx = cropy = 0;
+ }
+ if( m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka)
+ mult_fact = 32;
+
+ if ((height % mult_fact) != 0) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Height %d is not a multiple of %d",
+ height, mult_fact);
+ height = (height / mult_fact + 1) * mult_fact;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Height adjusted to %d \n", height);
+ }
+ if ((width % mult_fact) != 0) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Width %d is not a multiple of %d",
+ width, mult_fact);
+ width = (width / mult_fact + 1) * mult_fact;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n Width adjusted to %d \n", width);
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_validate_port_param
+
+DESCRIPTION
+ Get the PMEM area from video decoder
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::omx_vdec_validate_port_param(int height, int width) {
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ long hxw = height * width;
+
+ if (hxw > (OMX_CORE_720P_HEIGHT * OMX_CORE_720P_WIDTH)) {
+ ret = OMX_ErrorNotImplemented;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Invalid Ht[%d] wdth[%d]\n", height, width);
+ }
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_add_entries
+
+DESCRIPTION
+ Add the buf header entries to the container
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+void omx_vdec::omx_vdec_add_entries() {
+ OMX_BUFFERHEADERTYPE *pOmxHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ OMX_BUFFERHEADERTYPE *pOmxOutHdr = m_loc_use_buf_hdr;
+ for (unsigned int i = 0; i < 8; i++, pOmxHdr++, pOmxOutHdr++) {
+ m_use_buf_hdrs.insert(pOmxOutHdr, pOmxHdr);
+ m_use_buf_hdrs.insert(pOmxHdr, pOmxOutHdr);
+ }
+
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_dup_use_buf_hdrs
+
+DESCRIPTION
+ Populate the copy buffer [ use buffer ]
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::omx_vdec_dup_use_buf_hdrs() {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
+ OMX_BUFFERHEADERTYPE *pHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
+ int nBufHdrSize = 0;
+
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+ memcpy(m_loc_use_buf_hdr, pHdr, nBufHdrSize);
+ omx_vdec_display_out_use_buf_hdrs();
+
+ return OMX_ErrorNone;
+}
+
+void omx_vdec::omx_vdec_cpy_user_buf(OMX_BUFFERHEADERTYPE * pBufHdr) {
+ OMX_BUFFERHEADERTYPE *bufHdr;
+ bufHdr = m_use_buf_hdrs.find(pBufHdr);
+ if (bufHdr) {
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "CPY::Found bufHdr[0x%x]0x%x-->[0x%x]0x%x\n",
+ pBufHdr->pBuffer, pBufHdr, bufHdr,
+ bufHdr->pBuffer);
+ // Map the local buff address to the user space address.
+ // Basically pMEM -->pBuf translation
+
+ // DO A MEMCPY from pMEM are to the user defined add
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "CPY::[bufferHdr]pBuffer maps[0x%x]0x%x-->[0x%x]0x%x\n",
+ pBufHdr->pBuffer, pBufHdr, bufHdr,
+ bufHdr->pBuffer);
+ // first buffer points to user defined add, sec one to PMEM area
+ memcpy(pBufHdr->pBuffer, bufHdr->pBuffer,
+ get_output_buffer_size());
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "CPY::No match found bufHdr[0x%x] \n", pBufHdr);
+ omx_vdec_display_out_use_buf_hdrs();
+ }
+}
+
+void omx_vdec::omx_vdec_display_in_buf_hdrs() {
+ OMX_BUFFERHEADERTYPE *omxhdr = ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^INPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+ for (unsigned int i = 0; i < 2; i++) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "hdr[0x%x] buffer[0x%x]\n", omxhdr + i,
+ (omxhdr + i)->pBuffer);
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^INPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+}
+
+void omx_vdec::omx_vdec_display_out_buf_hdrs() {
+ OMX_BUFFERHEADERTYPE *omxhdr = ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^^OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+ for (unsigned int i = 0; i < 8; i++) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "hdr[0x%x] buffer[0x%x]\n", omxhdr + i,
+ (omxhdr + i)->pBuffer);
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^^^OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+
+}
+
+void omx_vdec::omx_vdec_display_out_use_buf_hdrs() {
+ OMX_BUFFERHEADERTYPE *omxhdr = m_loc_use_buf_hdr;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^^^USE OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+ for (unsigned int i = 0; i < 8; i++) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "hdr[0x%x] buffer[0x%x]\n", omxhdr + i,
+ (omxhdr + i)->pBuffer);
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^^^^^USE OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^^^^USE BUF HDRS MAPPING^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+ m_use_buf_hdrs.show();
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_create_native_decoder
+
+DESCRIPTION
+ Native decoder creation
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX_ErrorNone if successful
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ omx_vdec_create_native_decoder(OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_U32 codec_type;
+ // if NALU is zero assume START CODE
+ m_vdec_cfg.height = m_port_height;
+ m_vdec_cfg.width = m_port_width;
+ m_vdec_cfg.size_of_nal_length_field = m_nalu_bytes;
+ m_vdec_cfg.vc1Rowbase = 0;
+ m_vdec_cfg.postProc = 0;
+ m_vdec_cfg.color_format = m_color_format;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "m_vdec_cfg.kind %s\n",
+ m_vdec_cfg.kind);
+
+ if (!m_vendor_config.pData) {
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4", 28)
+ == 0 ) {
+ m_vdec_cfg.sequenceHeader =
+ (byte *) malloc(buffer->nFilledLen);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Mpeg4 clip \n");
+ m_vdec_cfg.sequenceHeaderLen = buffer->nFilledLen;
+ memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
+ m_vdec_cfg.sequenceHeaderLen);
+ } else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx", 27)
+ == 0 ) {
+ if(m_codec_format == QOMX_VIDEO_DIVXFormat311) {
+ m_vdec_cfg.sequenceHeader = NULL;
+ m_vdec_cfg.sequenceHeaderLen = 0;
+ m_vdec_cfg.fourcc = MAKEFOURCC('D', 'I', 'V', '3');
+ }else {
+ m_vdec_cfg.sequenceHeader =
+ (byte *) malloc(buffer->nFilledLen);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Divx clip \n");
+ m_vdec_cfg.sequenceHeaderLen = buffer->nFilledLen;
+ memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
+ m_vdec_cfg.sequenceHeaderLen);
+ m_vdec_cfg.fourcc = MAKEFOURCC('D', 'I', 'V', 'X');
+ }
+ }else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
+ 26) == 0) {
+ m_vdec_cfg.sequenceHeader =
+ (byte *) malloc(buffer->nFilledLen);
+ m_vdec_cfg.sequenceHeaderLen =
+ m_h264_utils->parse_first_h264_input_buffer(buffer,
+ m_vdec_cfg.
+ size_of_nal_length_field);
+ memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
+ m_vdec_cfg.sequenceHeaderLen);
+ buffer->nFilledLen -= m_vdec_cfg.sequenceHeaderLen;
+ memmove(buffer->pBuffer,
+ &buffer->pBuffer[m_vdec_cfg.sequenceHeaderLen],
+ buffer->nFilledLen);
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
+ 28) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "SPARK clip \n");
+ m_vdec_cfg.sequenceHeaderLen = 0;
+ m_vdec_cfg.sequenceHeader = NULL;
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
+ 27) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "H263 clip \n");
+ m_vdec_cfg.sequenceHeaderLen = 0;
+ m_vdec_cfg.sequenceHeader = NULL;
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",
+ 25) == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "VP6 clip \n");
+ m_vdec_cfg.sequenceHeaderLen = 0;
+ m_vdec_cfg.sequenceHeader = NULL;
+ } else
+ if (strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ 26) == 0) {
+ m_vdec_cfg.sequenceHeader =
+ (byte *) malloc(buffer->nFilledLen);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "VC1 clip \n");
+ if ((((*((OMX_U32 *) buffer->pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE)
+ ||
+ (((*((OMX_U32 *) buffer->pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1)
+ )
+ {
+
+ OMX_U32 pos_sequence_header =
+ 0, sequence_layer_len = 0;
+
+ OMX_U32 *pBuf32, num_frames;
+ OMX_U8 *pBuf8;
+
+ pBuf32 = (OMX_U32 *) buffer->pBuffer;
+
+ /* get the number of frames from the sequence header */
+ num_frames = *pBuf32 & 0x00FFFFFF;
+
+ /* size of struct C appears right after the number of frames information in the sequence header */
+ m_vdec_cfg.sequenceHeaderLen = *(++pBuf32);
+
+ /* advance the pointer by the size of struct C in order to get the height and width */
+ pBuf8 = (OMX_U8 *) (++pBuf32);
+ pBuf8 += m_vdec_cfg.sequenceHeaderLen;
+
+ /* read the height and width information which are each 4 bytes */
+ pBuf32 = (OMX_U32 *) pBuf8;
+ m_vdec_cfg.height = *pBuf32;
+ m_vdec_cfg.width = *(++pBuf32);
+
+ /* get the position of struct C or sequence header */
+ pos_sequence_header = OMX_VC1_POS_STRUCT_C;
+
+ if (((*((OMX_U32 *) buffer->pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE) {
+ sequence_layer_len =
+ OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC
+ + m_vdec_cfg.sequenceHeaderLen;
+ } else
+ if (((*((OMX_U32 *) buffer->pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1) {
+ sequence_layer_len =
+ OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC
+ + m_vdec_cfg.sequenceHeaderLen;
+ }
+
+ /* copy the sequence header information to be sent to vdec core */
+ memcpy(m_vdec_cfg.sequenceHeader,
+ &buffer->pBuffer[pos_sequence_header],
+ m_vdec_cfg.sequenceHeaderLen);
+
+ for (int i = 0;
+ i < m_vdec_cfg.sequenceHeaderLen; i++) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "seq header: %x",
+ m_vdec_cfg.
+ sequenceHeader[i]);
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "\n");
+
+ /* update the nFilledLen based on the number of bytes of the sequence layer */
+ buffer->nFilledLen -= sequence_layer_len;
+ memmove(buffer->pBuffer,
+ &buffer->pBuffer[sequence_layer_len],
+ buffer->nFilledLen);
+ }
+
+ else if (*((OMX_U32 *) buffer->pBuffer) == 0x0F010000) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "VC1 Advance profile\n");
+ // Skip the start code. With the start code (first byte is 0x00),
+ // then Q6 will think it is a simple profile
+ m_vdec_cfg.sequenceHeaderLen =
+ buffer->nFilledLen - 4;
+ memcpy(m_vdec_cfg.sequenceHeader,
+ buffer->pBuffer + 4,
+ m_vdec_cfg.sequenceHeaderLen);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error: Unknown VC1 profile\n");
+ }
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR: Not supported codec. But let's try it anyway\n");
+ m_vdec_cfg.sequenceHeaderLen = buffer->nFilledLen;
+ memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
+ m_vdec_cfg.sequenceHeaderLen);
+ }
+ } else {
+ m_vdec_cfg.sequenceHeader =
+ (byte *) malloc(m_vendor_config.nDataSize);
+
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4", 28)
+ == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Mpeg4 clip \n");
+ memcpy(m_vdec_cfg.sequenceHeader, m_vendor_config.pData,
+ m_vendor_config.nDataSize);
+ m_vdec_cfg.sequenceHeaderLen =
+ m_vendor_config.nDataSize;
+#if 1 // temporary until q6 can decode without VOL header
+ memmove(buffer->pBuffer + buffer->nOffset +
+ m_vendor_config.nDataSize,
+ buffer->pBuffer + buffer->nOffset,
+ buffer->nFilledLen);
+ memcpy(buffer->pBuffer + buffer->nOffset,
+ m_vendor_config.pData,
+ m_vendor_config.nDataSize);
+ buffer->nFilledLen += m_vendor_config.nDataSize;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "size %d\n", buffer->nFilledLen);
+#endif
+ } else
+ if ((strncmp
+ (m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
+ 26) == 0)
+ &&
+ ((((*((OMX_U32 *) m_vendor_config.pData)) &
+ VC1_SP_MP_START_CODE_MASK) == VC1_SP_MP_START_CODE)
+ ||
+ (((*((OMX_U32 *) m_vendor_config.pData)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1)
+
+ )) {
+
+ OMX_U32 pos_sequence_header = 0, sequence_layer_len = 0;
+
+ OMX_U32 *pBuf32, num_frames = 0;
+ OMX_U8 *pBuf8;
+
+ pBuf32 = (OMX_U32 *) m_vendor_config.pData;
+
+ /* get the number of frames from the sequence header */
+ num_frames = *pBuf32 & 0x00FFFFFF;
+
+ /* size of struct C appears right after the number of frames information in the sequence header */
+ m_vdec_cfg.sequenceHeaderLen = *(++pBuf32);
+
+ /* advance the pointer by the size of struct C in order to get the height and width */
+ pBuf8 = (OMX_U8 *) (++pBuf32);
+ pBuf8 += m_vdec_cfg.sequenceHeaderLen;
+
+ /* read the height and width information which are each 4 bytes */
+ pBuf32 = (OMX_U32 *) pBuf8;
+ m_vdec_cfg.height = *pBuf32;
+ m_vdec_cfg.width = *(++pBuf32);
+
+ /* the struct C / sequence header starts at position 8 in the sequence header */
+ pos_sequence_header = OMX_VC1_POS_STRUCT_C;
+
+ if (((*((OMX_U32 *) m_current_frame->pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE) {
+ m_vendor_config.nDataSize =
+ OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC +
+ m_vdec_cfg.sequenceHeaderLen;
+ } else
+ if (((*((OMX_U32 *) m_current_frame->pBuffer)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE_RCV_V1) {
+ m_vendor_config.nDataSize =
+ OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC +
+ m_vdec_cfg.sequenceHeaderLen;
+ }
+
+ /* copy the sequence header information to be sent to vdec core */
+ memcpy(m_vdec_cfg.sequenceHeader,
+ &m_vendor_config.pData[pos_sequence_header],
+ m_vdec_cfg.sequenceHeaderLen);
+ } else {
+ memcpy(m_vdec_cfg.sequenceHeader, m_vendor_config.pData,
+ m_vendor_config.nDataSize);
+ m_vdec_cfg.sequenceHeaderLen =
+ m_vendor_config.nDataSize;
+ }
+ }
+
+#if 1
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "OMX - header, length %d\n",
+ m_vdec_cfg.sequenceHeaderLen);
+ for (OMX_U32 i = 0; i < m_vdec_cfg.sequenceHeaderLen; i++) {
+ printf("0x%.2x ", m_vdec_cfg.sequenceHeader[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+
+ m_vdec = vdec_open(&m_vdec_cfg);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "vdec_open[%p]\n",
+ m_vdec);
+ if (!m_vdec) {
+ m_bInvalidState = true;
+ m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
+ OMX_ErrorInsufficientResources, 0, NULL);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! vdec_open failed\n");
+ if (m_vdec_cfg.sequenceHeader) {
+ free(m_vdec_cfg.sequenceHeader);
+ }
+ return OMX_ErrorHardware;
+ }
+
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0) {
+ if (m_h264_utils != NULL) {
+ m_h264_utils->allocate_rbsp_buffer(OMX_CORE_INPUT_BUFFER_SIZE);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR!!! m_h264_utils exist\n");
+ }
+ }
+
+ if (m_vdec_cfg.sequenceHeader) {
+ free(m_vdec_cfg.sequenceHeader);
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_free_output_port_memory
+
+DESCRIPTION
+ Free output port memory
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+void omx_vdec::omx_vdec_free_output_port_memory(void) {
+ if (m_out_mem_ptr) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the Output Memory\n");
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if (m_platform_list) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the platform list\n");
+ free(m_platform_list);
+ m_platform_list = NULL;
+ }
+ if (m_platform_entry) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the platform entry\n");
+ m_platform_entry = NULL;
+ }
+ if (m_pmem_info) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the pmem info\n");
+ m_pmem_info = NULL;
+ }
+ if(omx_vdec_get_use_egl_buf_flg() && m_vdec_cfg.outputBuffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Freeing the output buf info egl \n");
+ if (m_vdec_cfg.outputBuffer) {
+ free(m_vdec_cfg.outputBuffer);
+ m_vdec_cfg.outputBuffer = NULL;
+ }
+ }
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::get_free_input_buffer
+
+DESCRIPTION
+ get a free input buffer
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ pointer to input buffer header
+ NULL if couldn't find
+========================================================================== */
+OMX_BUFFERHEADERTYPE *omx_vdec::get_free_input_buffer() {
+ int i;
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (m_input_buff_info[i].bfree_input) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "get_free_input_buffer_index - Find free input buffer %d\n",
+ i);
+ m_input_buff_info[i].bfree_input = false;
+ return input[i];
+ }
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "get_free_input_buffer_index - Couldn't find free extra buffer\n");
+ return NULL;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::find_input_buffer_index
+
+DESCRIPTION
+ find input buffer index
+
+PARAMETERS
+ OMX_U8* buffer
+
+RETURN VALUE
+ index of extra buffer
+ -1 if couldn't find
+========================================================================== */
+OMX_S8 omx_vdec::find_input_buffer_index(OMX_BUFFERHEADERTYPE * pBuffer) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "find_input_buffer_index %p\n", pBuffer);
+ OMX_S8 i;
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (pBuffer == input[i]) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "find_input_buffer_index %d\n", i);
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::free_input_buffer
+
+DESCRIPTION
+ free input buffer that is passed
+
+PARAMETERS
+ OMX_BUFFERHEADERTYPE *pBuffer
+
+RETURN VALUE
+ true if successfull
+ false if buffer is not part extra buffer
+========================================================================== */
+bool omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE * pBuffer) {
+ int i;
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (pBuffer == input[i]) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "free_input_buffer input %p\n", input);
+ if (m_input_buff_info[i].pArbitrary_bytes_freed) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "free_input_buffer - EmptyBufferDone!!\n");
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ m_input_buff_info[i].
+ pArbitrary_bytes_freed);
+ m_input_buff_info[i].pArbitrary_bytes_freed =
+ NULL;
+ }
+ m_input_buff_info[i].bfree_input = true;
+ m_bWaitForResource = false;
+ return true;
+ }
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "free_input_buffer - Error: Couldn't find input %p\n",
+ input);
+ return false;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::get_free_extra_buffer_index
+
+DESCRIPTION
+ get an extra buffer that's been already allocated
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ index of extra buffer
+ -1 if couldn't find
+========================================================================== */
+OMX_S8 omx_vdec::get_free_extra_buffer_index() {
+ int i;
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (!m_extra_buf_info[i].bExtra_pBuffer_in_use) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "get_free_extra_buffer - Find free extra buffer %d\n",
+ i);
+ m_extra_buf_info[i].bExtra_pBuffer_in_use = true;
+ return i;
+ }
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "ERROR: get_free_extra_buffer - Couldn't find free extra buffer\n");
+ return -1;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::find_extra_buffer_index
+
+DESCRIPTION
+ determine if buffer is belong to an extra buffer
+
+PARAMETERS
+ OMX_U8* buffer
+
+RETURN VALUE
+ index of extra buffer
+ -1 if couldn't find
+========================================================================== */
+OMX_S8 omx_vdec::find_extra_buffer_index(OMX_U8 * buffer) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "find_extra_buffer_index %p\n", buffer);
+ OMX_S8 i;
+ for (i = 0; i < m_inp_buf_count; i++) {
+ if (m_extra_buf_info[i].bExtra_pBuffer_in_use
+ && (buffer == m_extra_buf_info[i].extra_pBuffer)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "find_extra_buffer_index - Find used extra buffer %d\n",
+ i);
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::free_extra_buffer
+
+DESCRIPTION
+ free extra buffer that is passed
+
+PARAMETERS
+ OMX_S8 index
+
+RETURN VALUE
+ true if successfull
+ false if buffer is not part extra buffer
+========================================================================== */
+bool omx_vdec::free_extra_buffer(OMX_S8 index) {
+ if (index < 0 || index > OMX_CORE_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "free_extra_buffer - Error: Invalid index \n");
+ return false;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "free_extra_buffer index %d\n", index);
+ m_extra_buf_info[index].bExtra_pBuffer_in_use = false;
+
+ return true;
+}
+
+/* ======================================================================
+FUNCTION
+ initialize_arbitrary_bytes_environment
+
+DESCRIPTION
+ Initialize some member variables used for arbitrary bytes input packing format
+ This function is used before parsing arbitrary input buffer or
+ after doing flush to parse the next I frame (seek, fast forward, fast rewind, etc).
+
+PARAMETERS
+ none
+
+RETURN VALUE
+ true if success
+ false otherwise
+========================================================================== */
+void omx_vdec::initialize_arbitrary_bytes_environment() {
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "initialize_arbitrary_bytes_environment \n");
+ if (m_bStartCode) {
+ m_arbitrary_bytes_info.start_code.m_last_4byte = 0xFFFFFFFF;
+ m_arbitrary_bytes_info.start_code.m_last_start_code = 0;
+ } else {
+ m_arbitrary_bytes_info.frame_size.m_size_byte_left = 0;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
+ m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left = 0;
+ }
+
+ m_is_copy_truncated = false;
+
+ m_current_frame = NULL;
+ m_current_arbitrary_bytes_input = NULL;
+ m_pcurrent_frame = NULL;
+ m_bPartialFrame = false;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::get_one_complete_frame
+
+DESCRIPTION
+ Try to get one complete frame
+
+PARAMETERS
+ OMX_OUT OMX_BUFFERHEADERTYPE* dest
+
+RETURN VALUE
+ true if get one complete frame
+ false if get partial frame or failed
+========================================================================== */
+bool omx_vdec::get_one_complete_frame(OMX_OUT OMX_BUFFERHEADERTYPE * dest) {
+ if (m_current_arbitrary_bytes_input == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - m_current_arbitrary_bytes_input is NULL \n");
+ return false;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Start of get_one_complete_frame - flags %d\n",
+ m_current_arbitrary_bytes_input->nFlags);
+
+ get_one_frame(dest, m_current_arbitrary_bytes_input, &m_bPartialFrame);
+ while (m_bPartialFrame) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_complete_frame got partial frame dest->pBuffer %p\n",
+ dest->pBuffer);
+ unsigned p1; // Parameter - 1
+ unsigned p2; // Parameter - 2
+ unsigned ident = 0;
+
+ mutex_lock();
+ if (m_etb_arbitrarybytes_q.m_size) {
+ m_etb_arbitrarybytes_q.delete_entry(&p1, &p2, &ident);
+ }
+ mutex_unlock();
+ if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES) {
+ m_current_arbitrary_bytes_input =
+ (OMX_BUFFERHEADERTYPE *) p2;
+
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_complete_frame - partial frame continue to get one frame %p %p offset %d flags %d\n",
+ m_current_arbitrary_bytes_input,
+ m_current_arbitrary_bytes_input->pBuffer,
+ m_current_arbitrary_bytes_input->nOffset,
+ m_current_arbitrary_bytes_input->nFlags);
+ get_one_frame(dest, m_current_arbitrary_bytes_input,
+ &m_bPartialFrame);
+ } else {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_complete_frame - No buffer available. Try again later\n",
+ p2, ident);
+ m_current_arbitrary_bytes_input = NULL;
+ break;
+ }
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "After get_one_complete_frame - m_current_frame %p %p\n",
+ dest, dest->pBuffer);
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "After get_one_complete_frame - nFilledLen %d nOffset %d nFlags %d partial %d\n",
+ dest->nFilledLen, dest->nOffset, dest->nFlags,
+ m_bPartialFrame);
+
+ if (!m_bPartialFrame) {
+ dest->nOffset = 0;
+#if DEBUG_ON
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_complete_frame buffer, length %d %x\n",
+ dest->nFilledLen, dest->nFilledLen);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", dest->pBuffer[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ if (dest->nFilledLen > 64) {
+ printf(".....\n");
+ for (OMX_U32 i = dest->nFilledLen - 32;
+ i < dest->nFilledLen; i++) {
+ printf("0x%.2x ", dest->pBuffer[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ }
+ printf("\n");
+#endif
+
+ return true;
+ } else {
+ //m_current_frame = dest;
+ return false;
+ }
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::get_one_frame
+
+DESCRIPTION
+ - strore one frame from source to dest
+ - set the dest->offset to indicate the beginning of the new frame
+ - set the source->offset for the next frame
+ - update the remaining source->nFilledLen
+
+PARAMETERS
+ OMX_OUT OMX_BUFFERHEADERTYPE* dest,
+ OMX_IN OMX_BUFFERHEADERTYPE* source,
+ OMX_INOUT bool *isPartialFrame
+
+RETURN VALUE
+ OMX_ERRORTYPE
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_one_frame(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
+ OMX_IN OMX_BUFFERHEADERTYPE * source,
+ OMX_INOUT bool * isPartialFrame) {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame dest %p source %p isPartialFrame %d\n",
+ dest, source, *isPartialFrame);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Before get_one_frame\n");
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "dest pBuf %p len %d offset %d flags %d\n", dest->pBuffer,
+ dest->nFilledLen, dest->nOffset, dest->nFlags);
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "source pBuf %p len %d offset %d flags %d\n",
+ source->pBuffer, source->nFilledLen, source->nOffset,
+ source->nFlags);
+
+#if DEBUG_ON
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame source, length %d\n", source->nFilledLen);
+ for (OMX_U32 i = 0; (i < 32) && (i < source->nFilledLen); i++) {
+ printf("0x%.2x ", source->pBuffer[source->nOffset + i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+
+ if (m_bStartCode) {
+ get_one_frame_using_start_code(dest, source, isPartialFrame);
+ } else {
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26)
+ == 0) {
+ get_one_frame_h264_size_nal(dest, source,
+ isPartialFrame);
+ } else {
+ get_one_frame_sp_mp_vc1(dest, source, isPartialFrame);
+ }
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "After get_one_frame\n");
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "dest pBuf %p len %d offset %d flags %d\n", dest->pBuffer,
+ dest->nFilledLen, dest->nOffset, dest->nFlags);
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "source pBuf %p len %d offset %d flags %d\n",
+ source->pBuffer, source->nFilledLen, source->nOffset,
+ source->nFlags);
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::get_one_frame_using_start_code
+
+DESCRIPTION
+
+PARAMETERS
+ OMX_OUT OMX_BUFFERHEADERTYPE* dest,
+ OMX_IN OMX_BUFFERHEADERTYPE* source,
+ OMX_IN OMX_U32 start_code,
+ OMX_INOUT OMX_U32 *current_position,
+ OMX_INOUT bool *isPartialFrame
+
+RETURN VALUE
+ OMX_ERRORTYPE
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ get_one_frame_using_start_code(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
+ OMX_IN OMX_BUFFERHEADERTYPE * source,
+ OMX_INOUT bool * isPartialFrame) {
+ OMX_U32 code = m_arbitrary_bytes_info.start_code.m_last_4byte;
+ OMX_U32 readSize = 0;
+ OMX_U32 copy_size = 0;
+ OMX_U32 pos = 0;
+ OMX_U32 in_len = source->nFilledLen;
+ OMX_U8 *inputBitStream = source->pBuffer + source->nOffset;
+ OMX_U8 scl = 4; // by default start code length is 4
+ bool bH264 = false;
+
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0)
+ {
+ scl = 3; // h264 uses 3 bytes start code
+ bH264 = true;
+ }
+
+ // To concatenate with previous frame if there is
+ if (*isPartialFrame == false) {
+ dest->nOffset = dest->nFilledLen;
+ }
+
+ while (pos < in_len) {
+ code <<= 8;
+ code |= (0x000000FF & *inputBitStream);
+ if ((code & m_arbitrary_bytes_info.start_code.
+ m_start_code_mask) ==
+ m_arbitrary_bytes_info.start_code.m_start_code) {
+ scl = 4;
+ if (bH264 && (code>>24))
+ scl = 3;
+ if (readSize > scl -1 ) {
+ // in this case, this start code is the beyond
+ // the buffer boundary, fully inside inputBitStream buffer
+ readSize = readSize - scl + 1;
+ copy_size = readSize;
+ if ((m_arbitrary_bytes_info.start_code.
+ m_last_start_code & m_arbitrary_bytes_info.
+ start_code.m_start_code_mask)
+ == m_arbitrary_bytes_info.start_code.
+ m_start_code) {
+ // we have a start code left over from the previous frame
+ scl = 4;
+ if (bH264 &&
+ (m_arbitrary_bytes_info.start_code.m_last_start_code >> 24))
+ scl = 3; // only 2 zeros are in the start code
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "source->nOffset = %d start_code %x %x\n",
+ source->nOffset, code,
+ m_arbitrary_bytes_info.
+ start_code.
+ m_last_start_code);
+ if (find_extra_buffer_index
+ (dest->pBuffer) == -1) {
+ OMX_S8 index =
+ get_free_extra_buffer_index
+ ();
+ if (index != -1) {
+ OMX_U8 *temp_buffer =
+ dest->pBuffer;
+ OMX_U32 temp_size =
+ dest->nFilledLen;
+ dest->pBuffer =
+ m_extra_buf_info
+ [index].
+ extra_pBuffer;
+ if(dest->nAllocLen < dest->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Not enough memory %d \n",
+ __LINE__);
+ temp_size = dest->nAllocLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer,
+ temp_buffer,
+ temp_size);
+ } else {
+ QTV_MSG_PRIO
+ (QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Couldn't find extra buffer\n");
+ return
+ OMX_ErrorHardware;
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Copy the start_code %d %x\n",
+ dest->nFilledLen,
+ m_arbitrary_bytes_info.
+ start_code.
+ m_last_start_code);
+ for (OMX_S8 i = 0; i < scl; i++) {
+ *(dest->pBuffer +
+ dest->nFilledLen) =
+ (OMX_U8) ((m_arbitrary_bytes_info.
+ start_code.
+ m_last_start_code & 0xFF
+ << (8 * (scl - 1 - i))) >> (8 *
+ (scl - 1 - i)));
+ dest->nFilledLen++;
+ }
+ }
+ if(!m_is_copy_truncated) {
+ copy_size = readSize;
+ if((dest->nAllocLen - dest->nFilledLen)
+ < readSize) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR -- memcpy failed at line %d \n",
+ __LINE__);
+ copy_size = dest->nAllocLen - dest->nFilledLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer +
+ source->nOffset, copy_size);
+ }
+ } else
+ if (find_extra_buffer_index(dest->pBuffer)
+ != -1) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_MED,
+ "Concatenate to extra buffer\n");
+ if(!m_is_copy_truncated) {
+ copy_size = readSize;
+ if((dest->nAllocLen - dest->nFilledLen)
+ < readSize) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR -- memcpy failed at line %d \n",
+ __LINE__);
+ copy_size = dest->nAllocLen - dest->nFilledLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer +
+ source->nOffset, copy_size);
+ }
+ }
+ dest->nFilledLen += copy_size;
+ dest->nFlags = source->nFlags;
+ dest->nTimeStamp = source->nTimeStamp;
+ *isPartialFrame = false;
+ m_is_copy_truncated = false;
+ m_arbitrary_bytes_info.start_code.
+ m_last_start_code = 0x00;
+ break;
+ } else if (*isPartialFrame) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Start code boundary = %x %d\n",
+ code, readSize);
+ m_arbitrary_bytes_info.start_code.
+ m_last_start_code = code;
+ dest->nFilledLen -= (scl - 1 - readSize);
+ dest->nFlags = source->nFlags;
+ *isPartialFrame = false;
+ m_is_copy_truncated = false;
+ readSize++;
+ break;
+ } else {
+ m_arbitrary_bytes_info.start_code.
+ m_last_start_code = 0x00;
+ }
+ }
+ inputBitStream++;
+ pos++;
+ readSize++;
+ }
+ m_arbitrary_bytes_info.start_code.m_last_4byte = code;
+
+ if (pos == source->nFilledLen) {
+ OMX_S8 index;
+ if (*isPartialFrame == false) {
+ index = get_free_extra_buffer_index();
+ if (index != -1) {
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "With free extra buffer used %p %p %d %d\n",
+ m_extra_buf_info[index].
+ extra_pBuffer, dest->pBuffer,
+ dest->nOffset, dest->nFilledLen);
+ OMX_U8 *temp_buffer = dest->pBuffer;
+ OMX_U32 temp_size = dest->nOffset;
+ dest->pBuffer =
+ m_extra_buf_info[index].extra_pBuffer;
+ if(dest->nAllocLen < dest->nOffset) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Not enough memory %d \n",
+ __LINE__);
+ temp_size = dest->nAllocLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer, temp_buffer,
+ temp_size);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error - couldn't get free extra buffer %p",
+ dest->pBuffer);
+ return OMX_ErrorHardware;
+ }
+
+ if (m_extra_buf_info[index].arbitrarybytesInput) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Previous arbitrary bytes input hasn't been freed");
+ }
+ m_extra_buf_info[index].arbitrarybytesInput = source;
+ }
+
+ if ((m_arbitrary_bytes_info.start_code.
+ m_last_start_code & m_arbitrary_bytes_info.start_code.
+ m_start_code_mask)
+ == m_arbitrary_bytes_info.start_code.m_start_code) {
+ scl = 4;
+ if (bH264 &&
+ (m_arbitrary_bytes_info.start_code.m_last_start_code>>24))
+ scl = 3;
+ for (OMX_S8 i = 0; i < scl; i++) {
+ *(dest->pBuffer + dest->nFilledLen) =
+ (OMX_U8) ((m_arbitrary_bytes_info.
+ start_code.
+ m_last_start_code & 0xFF << (8 *
+ (scl - 1 - i)))
+ >> (8 * (scl - 1 - i)));
+ dest->nFilledLen++;
+ }
+ m_arbitrary_bytes_info.start_code.m_last_start_code =
+ 0x00;
+ }
+ if(!m_is_copy_truncated) {
+ copy_size = readSize;
+ if((dest->nAllocLen - dest->nFilledLen)
+ < readSize) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR -- memcpy failed at line %d \n",
+ __LINE__);
+ copy_size = dest->nAllocLen - dest->nFilledLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer + source->nOffset, copy_size);
+ }
+ dest->nFilledLen += copy_size;
+ dest->nFlags = source->nFlags;
+ dest->nTimeStamp = source->nTimeStamp;
+
+ if (*isPartialFrame == true) {
+ unsigned int nPortIndex =
+ source -
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "get_one_frame - EmptyBufferDone %p\n",
+ source);
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ source);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR!! Incorrect arbitrary bytes buffer %p\n",
+ source);
+ }
+ } else {
+ *isPartialFrame = true;
+ source->nFilledLen -= readSize;
+ source->nOffset += readSize;
+ }
+ m_current_arbitrary_bytes_input = NULL;
+
+ if (dest->nFlags & OMX_BUFFERFLAG_EOS) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "EOS observed\n");
+ *isPartialFrame = false;
+ }
+#if DEBUG_ON
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame partial buffer, length %d\n",
+ dest->nFilledLen);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", dest->pBuffer[dest->nOffset + i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+ } else {
+ source->nFilledLen -= readSize;
+ source->nOffset += readSize;
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ get_one_frame_h264_size_nal
+
+DESCRIPTION
+ get one nal from size nal length clip
+
+PARAMETERS
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer.
+
+RETURN VALUE
+ true if success
+ false otherwise
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::
+ get_one_frame_h264_size_nal(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
+ OMX_IN OMX_BUFFERHEADERTYPE * source,
+ OMX_INOUT bool * isPartialFrame) {
+ int i = 0;
+ int j = 0;
+ OMX_U8 temp_size[4];
+ OMX_U32 sizeofNAL = 0;
+
+ if ((source->nFilledLen == 0) && (source->nFlags & OMX_BUFFERFLAG_EOS)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "EOS observed\n");
+ dest->nFlags = source->nFlags;
+ m_current_arbitrary_bytes_input = NULL;
+ if (*isPartialFrame == true) {
+ unsigned int nPortIndex =
+ source -
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "get_one_frame_h264_size_nal - EmptyBufferDone %p\n",
+ source);
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ source);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR!! Incorrect arbitrary bytes buffer %p\n",
+ source);
+ }
+ }
+ *isPartialFrame = false;
+ return OMX_ErrorNone;
+ }
+
+ if (*isPartialFrame == false) {
+ dest->nOffset = dest->nFilledLen;
+
+ if (source->nFilledLen < m_nalu_bytes) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - get_free_extra_buffer_index\n");
+ OMX_S8 index = get_free_extra_buffer_index();
+ if (index != -1) {
+ OMX_U8 *temp_buffer = dest->pBuffer;
+ dest->pBuffer =
+ m_extra_buf_info[index].extra_pBuffer;
+ memcpy(dest->pBuffer, temp_buffer,
+ dest->nFilledLen);
+
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer + source->nOffset,
+ source->nFilledLen);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error - Couldn't find extra buffer\n");
+ return OMX_ErrorHardware;
+ }
+
+ if (m_extra_buf_info[index].arbitrarybytesInput) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Previous arbitrary bytes input hasn't been freed");
+ }
+ m_extra_buf_info[index].arbitrarybytesInput = source;
+ }
+
+ sizeofNAL = m_nalu_bytes;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
+ while (source->nFilledLen && sizeofNAL) {
+ sizeofNAL--;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining |=
+ source->pBuffer[source->
+ nOffset] << (sizeofNAL << 3);
+ source->nOffset++;
+ dest->nFilledLen++;
+ source->nFilledLen--;
+ }
+ m_arbitrary_bytes_info.frame_size.m_size_byte_left = sizeofNAL;
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - m_size_remaining %d %x m_size_byte_left %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_size_remaining,
+ m_arbitrary_bytes_info.frame_size.
+ m_size_remaining,
+ m_arbitrary_bytes_info.frame_size.
+ m_size_byte_left);
+ if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - partialFrame at size nal length %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_size_byte_left);
+ *isPartialFrame = true;
+ m_current_arbitrary_bytes_input = NULL;
+ return OMX_ErrorNone;
+ }
+ dest->nTimeStamp = source->nTimeStamp;
+ } else if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - find the frame size %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_size_byte_left);
+
+ sizeofNAL = m_arbitrary_bytes_info.frame_size.m_size_byte_left;
+
+ while (source->nFilledLen && sizeofNAL) {
+ sizeofNAL--;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining |=
+ source->pBuffer[source->
+ nOffset] << (sizeofNAL << 3);
+ dest->pBuffer[dest->nFilledLen] =
+ source->pBuffer[source->nOffset];
+ source->nOffset++;
+ dest->nFilledLen++;
+ source->nFilledLen--;
+ }
+
+ m_arbitrary_bytes_info.frame_size.m_size_byte_left = sizeofNAL;
+ if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - Never go here, unless input buffer is extremely small\n");
+ }
+ dest->nTimeStamp = source->nTimeStamp;
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - get the frame remaining size %d, dest size %d\n",
+ m_arbitrary_bytes_info.frame_size.m_size_remaining,
+ dest->nFilledLen);
+
+ OMX_S8 extra_buffer_index = find_extra_buffer_index(dest->pBuffer);
+ if (m_arbitrary_bytes_info.frame_size.m_size_remaining >=
+ source->nFilledLen) {
+ bool complete_nal = false;
+ if (m_arbitrary_bytes_info.frame_size.m_size_remaining ==
+ source->nFilledLen) {
+ complete_nal = true;
+ }
+ if (extra_buffer_index == -1 && (!m_is_copy_truncated)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - get_free_extra_buffer_index\n");
+ OMX_S8 index = get_free_extra_buffer_index();
+ if (index != -1) {
+ OMX_U8 *temp_buffer = dest->pBuffer;
+ unsigned int tmp_size = dest->nFilledLen;
+ dest->pBuffer =
+ m_extra_buf_info[index].extra_pBuffer;
+ if (dest->nAllocLen < dest->nFilledLen) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Not enough memory - \n");
+ tmp_size = dest->nAllocLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer, temp_buffer, tmp_size);
+
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_FATAL,
+ "Error - Couldn't find extra buffer\n");
+ return OMX_ErrorHardware;
+ }
+
+ if (m_extra_buf_info[index].arbitrarybytesInput) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Previous arbitrary bytes input hasn't been freed");
+ }
+ m_extra_buf_info[index].arbitrarybytesInput = source;
+ }
+ if (!m_is_copy_truncated) {
+ unsigned int copy_size = source->nFilledLen;
+ if ((dest->nAllocLen - dest->nFilledLen) <
+ source->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - we should never reach here memcpy failed at line %d",
+ __LINE__);
+ copy_size = dest->nAllocLen - dest->nFilledLen;
+ m_is_copy_truncated = true;
+ }
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer + source->nOffset, copy_size);
+ dest->nFilledLen += copy_size;
+ }
+
+ m_arbitrary_bytes_info.frame_size.m_size_remaining -=
+ source->nFilledLen;
+ source->nOffset += source->nFilledLen;
+ source->nFilledLen = 0;
+
+ if (*isPartialFrame == true) {
+ unsigned int nPortIndex =
+ source -
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "get_one_frame_h264_size_nal - EmptyBufferDone %p\n",
+ source);
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ source);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR!! Incorrect arbitrary bytes buffer %p\n",
+ source);
+ }
+ }
+
+ if (complete_nal) {
+ *isPartialFrame = false;
+ m_is_copy_truncated = false;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
+ } else {
+ *isPartialFrame = true;
+ }
+ m_current_arbitrary_bytes_input = NULL;
+ } else {
+ unsigned int copy_size =
+ m_arbitrary_bytes_info.frame_size.m_size_remaining;
+ if (extra_buffer_index != -1 && (false == m_is_copy_truncated)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Concatenate to extra buffer\n");
+ if ((dest->nAllocLen - dest->nFilledLen) <
+ m_arbitrary_bytes_info.frame_size.
+ m_size_remaining) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Not enough memory - %d \n",
+ __LINE__);
+ copy_size =
+ (dest->nAllocLen - dest->nFilledLen);
+ m_is_copy_truncated = true;
+ dest->nFilledLen += copy_size;
+
+ }
+
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer + source->nOffset, copy_size);
+
+ }
+ if (false == m_is_copy_truncated)
+ dest->nFilledLen += copy_size;
+
+ source->nOffset +=
+ m_arbitrary_bytes_info.frame_size.m_size_remaining;
+ source->nFilledLen -=
+ m_arbitrary_bytes_info.frame_size.m_size_remaining;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
+ m_is_copy_truncated = false;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal - dest size %d\n",
+ dest->nFilledLen);
+ dest->nFlags = source->nFlags;
+
+ if (source->nFilledLen == 0) {
+ m_current_arbitrary_bytes_input = NULL;
+ if (*isPartialFrame == false) {
+ OMX_S8 input_index =
+ find_input_buffer_index(dest);
+ if ((input_index == -1)
+ || m_input_buff_info[input_index].
+ pArbitrary_bytes_freed) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Couldn't find input index %d or Previous arbitrary bytes input hasn't been freed",
+ input_index);
+ }
+ m_input_buff_info[input_index].
+ pArbitrary_bytes_freed = source;
+ }
+ }
+ *isPartialFrame = false;
+
+#if DEBUG_ON
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_h264_size_nal partial buffer, length %d\n",
+ dest->nFilledLen);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", dest->pBuffer[dest->nOffset + i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ get_one_frame_sp_mp_vc1
+
+DESCRIPTION
+ get one nal from size nal length clip
+
+PARAMETERS
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer.
+
+RETURN VALUE
+ true if success
+ false otherwise
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_one_frame_sp_mp_vc1(OMX_OUT OMX_BUFFERHEADERTYPE *
+ dest,
+ OMX_IN OMX_BUFFERHEADERTYPE *
+ source,
+ OMX_INOUT bool *
+ isPartialFrame) {
+ int i = 0;
+ int j = 0;
+ OMX_U8 temp_size[4];
+ OMX_U8 temp_timestamp[4];
+ OMX_U32 timestamp = 0;
+ OMX_U32 frameSizeBytes = 0;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "get_one_frame_sp_mp_vc1 - timestamp field present: %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_field_present);
+
+ if ((source->nFilledLen == 0) && (source->nFlags & OMX_BUFFERFLAG_EOS)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "EOS observed\n");
+ dest->nFlags = source->nFlags;
+ m_current_arbitrary_bytes_input = NULL;
+ if (*isPartialFrame == true) {
+ unsigned int nPortIndex =
+ source -
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "get_one_frame_sp_mp_vc1 - EmptyBufferDone %p\n",
+ source);
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ source);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR!! Incorrect arbitrary bytes buffer %p\n",
+ source);
+ }
+ }
+ *isPartialFrame = false;
+ return OMX_ErrorNone;
+ }
+ // Frame size
+ if (*isPartialFrame == false) {
+ dest->nOffset = dest->nFilledLen;
+ /* for RCV V1 format, there is no timestamp field, so this should not be parsed */
+ if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_field_present == 1) {
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left = 5;
+ }
+
+ if (source->nFilledLen < 8) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - get_free_extra_buffer_index\n");
+ OMX_S8 index = get_free_extra_buffer_index();
+ if (index != -1) {
+ dest->pBuffer =
+ m_extra_buf_info[index].extra_pBuffer;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error - Couldn't find extra buffer\n");
+ return OMX_ErrorHardware;
+ }
+
+ if (m_extra_buf_info[index].arbitrarybytesInput) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Previous arbitrary bytes input hasn't been freed");
+ }
+ m_extra_buf_info[index].arbitrarybytesInput = source;
+ }
+
+ frameSizeBytes = 3;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
+ while (source->nFilledLen && frameSizeBytes) {
+ frameSizeBytes--;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining |=
+ source->pBuffer[source->
+ nOffset] << ((2 -
+ frameSizeBytes) << 3);
+ source->nOffset++;
+ source->nFilledLen--;
+ }
+
+ m_arbitrary_bytes_info.frame_size.m_size_byte_left =
+ frameSizeBytes;
+
+ if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - partialFrame at size nal length %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_size_byte_left);
+ *isPartialFrame = true;
+ m_current_arbitrary_bytes_input = NULL;
+ return OMX_ErrorNone;
+ } else {
+ /* in the case of RCV V1 format, there is no timestamp field left, but increment byte for key field */
+ if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_field_present == 0
+ && source->nFilledLen > 0) {
+ source->nFilledLen--;
+ source->nOffset++;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "RCV V1- source filled len: %d, source offset: %d \n",
+ source->nFilledLen,
+ source->nOffset);
+ }
+ }
+ } else if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - find the frame size %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_size_byte_left);
+
+ frameSizeBytes =
+ m_arbitrary_bytes_info.frame_size.m_size_byte_left;
+
+ while (source->nFilledLen && frameSizeBytes) {
+ frameSizeBytes--;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining |=
+ source->pBuffer[source->
+ nOffset] << ((2 -
+ frameSizeBytes) << 3);
+ source->nOffset++;
+ source->nFilledLen--;
+ }
+
+ m_arbitrary_bytes_info.frame_size.m_size_byte_left =
+ frameSizeBytes;
+
+ if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - Never go here, unless input buffer is extremely small\n");
+ } else {
+ /* in the case of RCV V1, no timestamp field, but increment the byte for key field */
+ if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_field_present == 0
+ && source->nFilledLen > 0) {
+ source->nFilledLen--;
+ source->nOffset++;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "RCV V1- source filled len: %d, source offset: %d \n",
+ source->nFilledLen,
+ source->nOffset);
+ }
+
+ }
+ }
+
+ OMX_S8 extra_buffer_index = find_extra_buffer_index(dest->pBuffer);
+ // Time stamp
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - partialFrame at time stamp byte left %d, nFilledLen %d\n",
+ m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left,
+ source->nFilledLen);
+ if (m_arbitrary_bytes_info.frame_size.m_timestamp_field_present == 1) {
+
+ if ((m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left >
+ 0) && (source->nFilledLen < 5)) {
+ if (source->nFilledLen != 0) {
+ if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left == 5) {
+ source->nFilledLen--; // for KEY and RES
+ source->nOffset++;
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left--;
+ }
+ frameSizeBytes =
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left;
+ timestamp = 0;
+
+ while (source->nFilledLen && frameSizeBytes) {
+ frameSizeBytes--;
+ timestamp |=
+ source->pBuffer[source->
+ nOffset] << ((3 -
+ frameSizeBytes)
+ << 3);
+ source->nOffset++;
+ source->nFilledLen--;
+ }
+ dest->nTimeStamp = (OMX_TICKS) timestamp;
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left = frameSizeBytes;
+ }
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - partialFrame at time stamp %d %d %x %x\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left, dest->nTimeStamp,
+ dest->nTimeStamp, timestamp);
+ *isPartialFrame = true;
+ m_current_arbitrary_bytes_input = NULL;
+ return OMX_ErrorNone;
+ } else if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left > 0) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - find the time stamp %d\n",
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left);
+
+ if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left == 5) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left == 5\n");
+ source->nFilledLen--; // for KEY and RES
+ source->nOffset++;
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left--;
+ dest->nTimeStamp = 0;
+ }
+
+ frameSizeBytes =
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left;
+ timestamp = dest->nTimeStamp;
+
+ while (source->nFilledLen && frameSizeBytes) {
+ frameSizeBytes--;
+ timestamp |=
+ source->pBuffer[source->
+ nOffset] << ((3 -
+ frameSizeBytes)
+ << 3);
+ source->nOffset++;
+ source->nFilledLen--;
+ }
+
+ dest->nTimeStamp = (OMX_TICKS) timestamp;
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "timeStamp %x dest timestamp %x, temp_timestamp %x\n",
+ timestamp, dest->nTimeStamp,
+ temp_timestamp);
+ m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left = frameSizeBytes;
+
+ if (extra_buffer_index == -1) {
+ dest->pBuffer += 8;
+ }
+
+ if (m_arbitrary_bytes_info.frame_size.
+ m_timestamp_byte_left > 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "Error - Never go here, unless input buffer is extremely small\n");
+ }
+ }
+ }
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - get the frame remaining size %d, dest size %d, dest ts %x %d\n",
+ m_arbitrary_bytes_info.frame_size.m_size_remaining,
+ dest->nFilledLen, dest->nTimeStamp, dest->nTimeStamp);
+
+ if (m_arbitrary_bytes_info.frame_size.m_size_remaining >=
+ source->nFilledLen) {
+ bool complete_frame = false;
+ if (m_arbitrary_bytes_info.frame_size.m_size_remaining ==
+ source->nFilledLen) {
+ complete_frame = true;
+ }
+ if (extra_buffer_index == -1 && (!m_is_copy_truncated)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - get_free_extra_buffer_index\n");
+ OMX_S8 index = get_free_extra_buffer_index();
+ if (index != -1) {
+ OMX_U8 *temp_buffer = dest->pBuffer;
+ unsigned int tmp_size = dest->nFilledLen;
+ dest->pBuffer =
+ m_extra_buf_info[index].extra_pBuffer;
+ if (dest->nAllocLen < dest->nFilledLen) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Not enough memory - \n");
+ tmp_size = dest->nAllocLen;
+ m_is_copy_truncated = true;
+ }
+
+ memcpy(dest->pBuffer, temp_buffer, tmp_size);
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_FATAL,
+ "Error - Couldn't find extra buffer\n");
+ return OMX_ErrorHardware;
+ }
+
+ if (m_extra_buf_info[index].arbitrarybytesInput) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Previous arbitrary bytes input hasn't been freed");
+ }
+ m_extra_buf_info[index].arbitrarybytesInput = source;
+ }
+ if (!m_is_copy_truncated) {
+ unsigned int copy_size = source->nFilledLen;
+ if ((dest->nAllocLen - dest->nFilledLen) <
+ source->nFilledLen) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - we should never reach here memcpy failed at line %d",
+ __LINE__);
+ copy_size = dest->nAllocLen - dest->nFilledLen;
+ m_is_copy_truncated = true;
+ }
+
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer + source->nOffset, copy_size);
+ dest->nFilledLen += copy_size;
+ }
+
+ m_arbitrary_bytes_info.frame_size.m_size_remaining -=
+ source->nFilledLen;
+ source->nOffset += source->nFilledLen;
+ source->nFilledLen = 0;
+
+ if (*isPartialFrame == true) {
+ unsigned int nPortIndex =
+ source -
+ (OMX_BUFFERHEADERTYPE *)
+ m_arbitrary_bytes_input_mem_ptr;
+ if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "get_one_frame_sp_mp_vc1 - EmptyBufferDone %p\n",
+ source);
+ m_cb.EmptyBufferDone(&m_cmp, m_app_data,
+ source);
+ } else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR!! Incorrect arbitrary bytes buffer %p\n",
+ source);
+ }
+ }
+ if (complete_frame) {
+ *isPartialFrame = false;
+ } else {
+ *isPartialFrame = true;
+ }
+ m_current_arbitrary_bytes_input = NULL;
+ } else {
+ unsigned int copy_size =
+ m_arbitrary_bytes_info.frame_size.m_size_remaining;
+ if (extra_buffer_index != -1 && (false == m_is_copy_truncated)) {
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "Concatenate to extra buffer\n");
+ if ((dest->nAllocLen - dest->nFilledLen) <
+ m_arbitrary_bytes_info.frame_size.
+ m_size_remaining) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "Not enough memory - %d \n",
+ __LINE__);
+ copy_size =
+ (dest->nAllocLen - dest->nFilledLen);
+ m_is_copy_truncated = true;
+ dest->nFilledLen += copy_size;
+ }
+ memcpy(dest->pBuffer + dest->nFilledLen,
+ source->pBuffer + source->nOffset, copy_size);
+ }
+ if (false == m_is_copy_truncated)
+ dest->nFilledLen += copy_size;
+ source->nOffset +=
+ m_arbitrary_bytes_info.frame_size.m_size_remaining;
+ source->nFilledLen -=
+ m_arbitrary_bytes_info.frame_size.m_size_remaining;
+ m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
+ m_is_copy_truncated = false;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 - dest size %d\n",
+ dest->nFilledLen);
+ dest->nFlags = source->nFlags;
+
+ if (source->nFilledLen == 0) {
+ m_current_arbitrary_bytes_input = NULL;
+ if (*isPartialFrame == false) {
+ OMX_S8 input_index =
+ find_input_buffer_index(dest);
+ if ((input_index == -1)
+ || m_input_buff_info[input_index].
+ pArbitrary_bytes_freed) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "ERROR - Couldn't find input index %d or Previous arbitrary bytes input hasn't been freed",
+ input_index);
+ }
+ m_input_buff_info[input_index].
+ pArbitrary_bytes_freed = source;
+ }
+ }
+ *isPartialFrame = false;
+
+#if DEBUG_ON
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "get_one_frame_sp_mp_vc1 partial buffer, length %d\n",
+ dest->nFilledLen);
+ for (OMX_U32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", dest->pBuffer[dest->nOffset + i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+ }
+
+ return OMX_ErrorNone;
+}
+
+void omx_vdec::fill_extradata(OMX_INOUT OMX_BUFFERHEADERTYPE * pBufHdr,
+ OMX_IN vdec_frame * frame) {
+ int n = 0;
+ Vdec_FrameDetailsType *frameDetails = &frame->frameDetails;
+ uint32 addr = 0;
+ uint32 end = (uint32) (pBufHdr->pBuffer + pBufHdr->nAllocLen);
+ OMX_OTHER_EXTRADATATYPE *pExtraData = 0;
+ OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0;
+ OMX_QCOM_EXTRADATA_FRAMEDIMENSION *pExtraFrameDimension = 0;
+ OMX_QCOM_EXTRADATA_CODEC_DATA *pExtraCodecData = 0;
+ uint32 size = 0;
+ pBufHdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
+
+ m_dec_width = frameDetails->nDecPicWidth;
+ m_dec_height = frameDetails->nDecPicHeight;
+
+ pBufHdr->nFilledLen = m_dec_width * m_dec_height * 3 / 2;
+ addr = (uint32) (pBufHdr->pBuffer + pBufHdr->nFilledLen);
+ // align to a 4 byte boundary
+ addr = (addr + 3) & (~3);
+
+ // read to the end of existing extra data sections
+ pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
+ if (m_vdec_cfg.postProc) {
+ while (addr < end && pExtraData->eType != OMX_ExtraDataNone) {
+ addr += pExtraData->nSize;
+ pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
+ }
+ }
+ // append the common frame info extra data
+ size =
+ (OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO) +
+ 3) & (~3);
+ pExtraData->nSize = size;
+ pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
+ pExtraData->nPortIndex = 1;
+ pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataFrameInfo; /* Extra Data type */
+ pExtraData->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); /* Size of the supporting data to follow */
+ pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *) pExtraData->data;
+ pBufHdr->nFlags &= (~OMX_BUFFERFLAG_SYNCFRAME);
+ if (frameDetails->ePicType[0] == VDEC_PICTURE_TYPE_I) {
+ pBufHdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+ }
+ if (frameDetails->ePicFormat == VDEC_PROGRESSIVE_FRAME)
+ pExtraFrameInfo->interlaceType =
+ OMX_QCOM_InterlaceFrameProgressive;
+ else if (frameDetails->ePicFormat = VDEC_INTERLACED_FRAME) {
+ if (frameDetails->bTopFieldFirst)
+ pExtraFrameInfo->interlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
+ else
+ pExtraFrameInfo->interlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
+ }
+ pExtraFrameInfo->panScan.numWindows = frameDetails->panScan.numWindows;
+ for (n = 0; n < frameDetails->panScan.numWindows; n++) {
+ pExtraFrameInfo->panScan.window[n].x =
+ frameDetails->panScan.winHorOffset[n];
+ pExtraFrameInfo->panScan.window[n].y =
+ frameDetails->panScan.winVerOffset[n];
+ pExtraFrameInfo->panScan.window[n].dx =
+ frameDetails->panScan.winWidth[n];
+ pExtraFrameInfo->panScan.window[n].dy =
+ frameDetails->panScan.winHeight[n];
+ }
+ pExtraFrameInfo->nConcealedMacroblocks =
+ frameDetails->nPercentConcealedMacroblocks;
+
+ // append the derived timestamp or YUV range mapping
+ addr += size;
+ pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
+ size =
+ (OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_CODEC_DATA) +
+ 3) & (~3);
+ pExtraData->nSize = size;
+ pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
+ pExtraData->nPortIndex = 1;
+ pExtraCodecData = (OMX_QCOM_EXTRADATA_CODEC_DATA *) pExtraData->data;
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0) {
+ pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataH264; /* Extra Data type */
+ pExtraData->nDataSize = sizeof(OMX_QCOM_H264EXTRADATA); /* Size of the supporting data to follow */
+ pExtraCodecData->h264ExtraData.seiTimeStamp =
+ frameDetails->calculatedTimeStamp;
+ } else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) ==
+ 0) {
+ pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVC1; /* Extra Data type */
+ pExtraData->nDataSize = sizeof(OMX_QCOM_VC1EXTRADATA); /* Size of the supporting data to follow */
+ pExtraCodecData->vc1ExtraData.nVC1RangeY =
+ frameDetails->nVC1RangeY;
+ pExtraCodecData->vc1ExtraData.nVC1RangeUV =
+ frameDetails->nVC1RangeUV;
+ pExtraCodecData->vc1ExtraData.eVC1PicResolution =
+ (OMX_QCOM_VC1RESOLUTIONTYPE) frameDetails->ePicResolution;
+ }
+
+ // append the Height and Width adjusted to multiple of 16 and Actual Height and Width
+ addr += size;
+ pExtraData = (OMX_OTHER_EXTRADATATYPE *)addr;
+ size = (OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION) + 3 ) & (~3);
+ pExtraData->nSize = size;
+ pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
+ pExtraData->nPortIndex = 1;
+ if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0)
+ {
+ pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataFrameDimension;
+ pExtraData->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION); /* Size of the supporting data to follow */
+ pExtraFrameDimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)pExtraData->data;
+ pExtraFrameDimension->nDecWidth = frameDetails->nDecPicWidth;
+ pExtraFrameDimension->nDecHeight = frameDetails->nDecPicHeight;
+ pExtraFrameDimension->nActualWidth = frameDetails->cwin.x2 - frameDetails->cwin.x1;
+ pExtraFrameDimension->nActualHeight= frameDetails->cwin.y2 - frameDetails->cwin.y1;
+ }
+
+ // append extradata terminator
+ addr += size;
+ pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
+ pExtraData->nSize = OMX_EXTRADATA_HEADER_SIZE;
+ pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
+ pExtraData->nPortIndex = 1;
+ pExtraData->eType = OMX_ExtraDataNone;
+ pExtraData->nDataSize = 0;
+
+ pBufHdr->nOffset = 0;
+ if (frameDetails->cwin.x1 || frameDetails->cwin.y1)
+ {
+ pBufHdr->nOffset = frameDetails->cwin.y1 * frameDetails->nDecPicWidth + frameDetails->cwin.x1;
+ }
+}
+
+/* ======================================================================
+FUNCTION
+ find_new_frame_ap_vc1
+
+DESCRIPTION
+ finds whether the BDU belongs to previous frame
+
+PARAMETERS
+ OMX_IN OMX_U8* buffer.
+ OMX_IN OMX_U32 buffer_length
+ OMX_OUT OMX_BOOL isNewFrame
+
+RETURN VALUE
+ true if success
+ false otherwise
+========================================================================== */
+bool omx_vdec::find_new_frame_ap_vc1(OMX_IN OMX_U8 * buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_OUT OMX_BOOL & isNewFrame) {
+ uint32 code = 0xFFFFFFFF;
+ isNewFrame = OMX_TRUE;
+ for (uint32 i = 0; i < buffer_length; i++) {
+ code <<= 8;
+ code |= *buffer++;
+
+ if ((code & VC1_AP_SLICE_START_CODE_MASK) ==
+ VC1_AP_SLICE_START_CODE) {
+ isNewFrame = OMX_FALSE;
+ break;
+ }
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "find_new_frame_ap_vc1 %d\n", isNewFrame);
+ return true;
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/omx_vdec.h b/omx/mm-video/qdsp6/vdec/src/omx_vdec.h
new file mode 100755
index 0000000..22a2be2
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/omx_vdec.h
@@ -0,0 +1,733 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef __OMX_VDEC_H__
+#define __OMX_VDEC_H__
+/*============================================================================
+ O p e n M A X Component
+ Video Decoder
+
+*//** @file comx_vdec.h
+ This module contains the class definition for openMAX decoder component.
+
+*//*========================================================================*/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+/* Uncomment out below line
+#define LOG_NDEBUG 0 if we want to see all LOGV messaging */
+
+#include<stdlib.h>
+#define LOG_TAG "QCvdec"
+
+#include <stdio.h>
+#ifdef _ANDROID_
+#include "cutils/log.h"
+#include <binder/MemoryHeapBase.h>
+#define LOG_NDEBUG 0
+#endif // _ANDROID_
+
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+#include "vdec.h"
+#include "qc_omx_component.h"
+#include "Map.h"
+#include <omx_vdec_inpbuf.h>
+#include "qtv_msg.h"
+#include "OMX_QCOMExtns.h"
+#include "H264_Utils.h"
+#include "MP4_Utils.h"
+
+extern "C" {
+ void *get_omx_component_factory_fn(void);
+}
+#ifdef _ANDROID_
+using namespace android;
+ // local pmem heap object
+class VideoHeap:public MemoryHeapBase {
+ public:
+ VideoHeap(int fd, size_t size, void *base);
+ virtual ~ VideoHeap() {
+}};
+#endif // _ANDROID_
+//////////////////////////////////////////////////////////////////////////////
+// Module specific globals
+//////////////////////////////////////////////////////////////////////////////
+#define OMX_SPEC_VERSION 0x00000101
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros
+//////////////////////////////////////////////////////////////////////////////
+#define PrintFrameHdr(bufHdr) QTV_MSG_PRIO4(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,\
+ "bufHdr %x buf %x size %d TS %d\n",\
+ (unsigned) bufHdr,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp)
+
+// BitMask Management logic
+#define BITS_PER_BYTE 0x08
+#define BITMASK_SIZE(mIndex) \
+ (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE)
+#define BITMASK_OFFSET(mIndex) \
+ ((mIndex)/BITS_PER_BYTE)
+#define BITMASK_FLAG(mIndex) \
+ (1 << ((mIndex) % BITS_PER_BYTE))
+#define BITMASK_CLEAR(mArray,mIndex) \
+ (mArray)[BITMASK_OFFSET(mIndex)] &= ~(BITMASK_FLAG(mIndex))
+#define BITMASK_SET(mArray,mIndex) \
+ (mArray)[BITMASK_OFFSET(mIndex)] |= BITMASK_FLAG(mIndex)
+#define BITMASK_PRESENT(mArray,mIndex) \
+ ((mArray)[BITMASK_OFFSET(mIndex)] & BITMASK_FLAG(mIndex))
+#define BITMASK_ABSENT(mArray,mIndex) \
+ (((mArray)[BITMASK_OFFSET(mIndex)] & BITMASK_FLAG(mIndex)) == 0x0)
+
+#define OMX_CORE_NUM_INPUT_BUFFERS MAX_NUM_INPUT_BUFFERS
+#define OMX_CORE_NUM_OUTPUT_BUFFERS 32 //changed from 32 - 8
+#define OMX_CORE_NUM_OUTPUT_BUFFERS_H264 8
+#define OMX_CORE_NUM_OUTPUT_BUFFERS_MP4 6
+#define OMX_CORE_NUM_OUTPUT_BUFFERS_VC1 6
+#define OMX_CORE_INPUT_BUFFER_SIZE (450 * 1024)
+#define OMX_CORE_CONTROL_CMDQ_SIZE 100
+#define OMX_CORE_QCIF_HEIGHT 144
+#define OMX_CORE_QCIF_WIDTH 176
+#define OMX_CORE_VGA_HEIGHT 480
+#define OMX_CORE_VGA_WIDTH 640
+#define OMX_CORE_WVGA_HEIGHT 480
+#define OMX_CORE_WVGA_WIDTH 800
+#define OMX_CORE_720P_HEIGHT 720
+#define OMX_CORE_720P_WIDTH 1280
+#define OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32
+#define OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16
+#define OMX_VC1_POS_STRUCT_C 8
+
+class genericQueue {
+ private:
+ struct node {
+ void *data;
+ node *next;
+ };
+ node *head;
+ node *tail;
+ int numElements;
+ //pthread_mutex_t queue_protector;
+ public:
+
+ genericQueue();
+
+ int Enqueue(void *data);
+ void *Dequeue();
+ int GetSize();
+ void *checkHead();
+ void *checkTail();
+
+ ~genericQueue();
+};
+
+// OMX video decoder class
+class omx_vdec:public qc_omx_component, public omx_vdec_inpbuf {
+ public:
+ // video decoder input structure
+ struct vdec_context m_vdec_cfg; // video decoder input structure
+
+ omx_vdec(); // constructor
+ virtual ~ omx_vdec(); // destructor
+
+ virtual OMX_ERRORTYPE create_msg_thread() = 0;
+ virtual void post_message(unsigned char id) = 0;
+ virtual void mutex_lock() = 0;
+ virtual void mutex_unlock() = 0;
+ virtual void semaphore_wait() = 0;
+ virtual void semaphore_post() = 0;
+
+ virtual OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData, OMX_U32 bytes);
+
+ virtual OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp);
+
+ virtual OMX_ERRORTYPE component_init(OMX_STRING role);
+
+ virtual OMX_ERRORTYPE component_role_enum(OMX_HANDLETYPE hComp,
+ OMX_U8 * role, OMX_U32 index);
+
+ virtual OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE hComp,
+ OMX_U32 port,
+ OMX_HANDLETYPE
+ peerComponent,
+ OMX_U32 peerPort,
+ OMX_TUNNELSETUPTYPE *
+ tunnelSetup);
+
+ virtual OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+
+ virtual OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+
+ void cancel_ftb_entry(OMX_BUFFERHEADERTYPE * buffer);
+ virtual OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE hComp,
+ OMX_U32 port,
+ OMX_BUFFERHEADERTYPE * buffer);
+
+ virtual OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE hComp,
+ OMX_STRING componentName,
+ OMX_VERSIONTYPE *
+ componentVersion,
+ OMX_VERSIONTYPE *
+ specVersion,
+ OMX_UUIDTYPE *
+ componentUUID);
+
+ virtual OMX_ERRORTYPE get_config(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData);
+
+ virtual OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE hComp,
+ OMX_STRING paramName,
+ OMX_INDEXTYPE * indexType);
+
+ virtual OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData);
+
+ virtual OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp,
+ OMX_STATETYPE * state);
+
+ virtual OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param1, OMX_PTR cmdData);
+
+ virtual OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp,
+ OMX_CALLBACKTYPE * callbacks,
+ OMX_PTR appData);
+
+ virtual OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData);
+
+ virtual OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData);
+
+ virtual OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes, OMX_U8 * buffer);
+
+ virtual OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData, void *eglImage);
+
+ static void buffer_done_cb(struct vdec_context *ctxt, void *cookie);
+
+ static void buffer_done_cb_stub(struct vdec_context *ctxt,
+ void *cookie);
+
+ static void frame_done_cb_stub(struct vdec_context *ctxt,
+ struct vdec_frame *frame);
+
+ static void frame_done_cb(struct vdec_context *ctxt,
+ struct vdec_frame *frame);
+ static void frame_done_display_order_cb(struct vdec_context *ctxt,
+ struct vdec_frame *frame);
+
+ static void process_event_cb(struct vdec_context *ctxt,
+ unsigned char id);
+ protected:
+ // Bit Positions
+ enum flags_bit_positions {
+ // Defer transition to IDLE
+ OMX_COMPONENT_IDLE_PENDING = 0x1,
+ // Defer transition to LOADING
+ OMX_COMPONENT_LOADING_PENDING = 0x2,
+ // First Buffer Pending
+ OMX_COMPONENT_FIRST_BUFFER_PENDING = 0x3,
+ // Second Buffer Pending
+ OMX_COMPONENT_SECOND_BUFFER_PENDING = 0x4,
+ // Defer transition to Enable
+ OMX_COMPONENT_INPUT_ENABLE_PENDING = 0x5,
+ // Defer transition to Enable
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING = 0x6,
+ // Defer transition to Disable
+ OMX_COMPONENT_INPUT_DISABLE_PENDING = 0x7,
+ // Defer transition to Disable
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING = 0x8,
+ };
+
+ // Deferred callback identifiers
+ enum {
+ //Event Callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_EVENT = 0x1,
+ //Buffer Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2,
+ //Frame Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_FRAME_DONE = 0x3,
+ //Buffer Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_FTB = 0x4,
+ //Empty This Buffer event
+ OMX_COMPONENT_GENERATE_ETB = 0x5,
+ //Command
+ OMX_COMPONENT_GENERATE_COMMAND = 0x6,
+ //Push-Pending Buffers
+ OMX_COMPONENT_PUSH_PENDING_BUFS = 0x7,
+ //Empty This Buffer event for arbitrary bytes
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES = 0x8,
+ OMX_COMPONENT_GENERATE_EVENT_FLUSH = 0x9
+ };
+
+ enum header_state {
+ HEADER_STATE_RECEIVED_NONE = 0x00,
+ HEADER_STATE_RECEIVED_PARTIAL = 0x01,
+ HEADER_STATE_RECEIVED_COMPLETE = 0x02
+ };
+
+ enum port_state {
+ PORT_STATE_DISABLED = 0x00,
+ PORT_STATE_ENABLED = 0x01,
+ PORT_STATE_INVALID = 0x02,
+ }; // PORT_SETTING
+
+ enum port_indexes {
+ OMX_CORE_INPUT_PORT_INDEX = 0,
+ OMX_CORE_OUTPUT_PORT_INDEX = 1
+ };
+
+ struct omx_event {
+ unsigned param1;
+ unsigned param2;
+ unsigned id;
+ bool canceled;
+ };
+
+ struct omx_cmd_queue {
+ omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE];
+ unsigned m_read;
+ unsigned m_write;
+ unsigned m_size;
+
+ omx_cmd_queue();
+ ~omx_cmd_queue();
+ bool insert_entry(unsigned p1, unsigned p2, unsigned id);
+ bool delete_entry(unsigned *p1, unsigned *p2, unsigned *id,
+ bool * canceled = 0);
+
+ };
+ // Store buf Header mapping between OMX client and
+ // PMEM allocated.
+ typedef Map < OMX_BUFFERHEADERTYPE *, OMX_BUFFERHEADERTYPE * >
+ use_buffer_map;
+ // Get the pMem area from Video decoder
+ void omx_vdec_get_out_buf_hdrs();
+ // Get the pMem area from video decoder and copy to local use buf hdrs
+ void omx_vdec_get_out_use_buf_hdrs();
+ // Copy the decoded frame to the user defined buffer area
+ void omx_vdec_cpy_user_buf(OMX_BUFFERHEADERTYPE * pBufHdr);
+
+ void omx_vdec_add_entries();
+
+ // Make a copy of the buf headers --> use buf only
+ OMX_ERRORTYPE omx_vdec_dup_use_buf_hdrs();
+
+ OMX_ERRORTYPE omx_vdec_check_port_settings(OMX_BUFFERHEADERTYPE *
+ buffer, unsigned &height,
+ unsigned &width,
+ bool & bInterlace,
+ unsigned &cropx,
+ unsigned &cropy,
+ unsigned &cropdx,
+ unsigned &cropdy);
+ OMX_ERRORTYPE omx_vdec_validate_port_param(int height, int width);
+
+ void omx_vdec_display_in_buf_hdrs();
+ void omx_vdec_display_out_buf_hdrs();
+ void omx_vdec_display_out_use_buf_hdrs();
+
+ bool allocate_done(void);
+ bool allocate_input_done(void);
+ bool allocate_output_done(void);
+
+ OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData, OMX_U32 bytes);
+
+ OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port, OMX_PTR appData,
+ OMX_U32 bytes);
+
+ OMX_ERRORTYPE use_input_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes, OMX_U8 * buffer);
+
+ OMX_ERRORTYPE use_output_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE ** bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes, OMX_U8 * buffer);
+ bool execute_omx_flush(OMX_U32);
+ bool execute_output_flush(void);
+ bool execute_input_flush(void);
+
+ unsigned push_one_input_buffer(OMX_BUFFERHEADERTYPE * buffer);
+ unsigned push_pending_buffers(void);
+ unsigned push_pending_buffers_proxy(void);
+
+ OMX_ERRORTYPE add_entry_subframe_stitching(OMX_IN OMX_BUFFERHEADERTYPE *
+ buffer);
+
+ OMX_ERRORTYPE empty_this_buffer_proxy_arbitrary_bytes(OMX_HANDLETYPE
+ hComp,
+ OMX_BUFFERHEADERTYPE
+ * buffer);
+
+ OMX_ERRORTYPE empty_this_buffer_proxy_frame_based(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *
+ buffer);
+
+ OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+
+ OMX_ERRORTYPE
+ empty_this_buffer_proxy_subframe_stitching(OMX_BUFFERHEADERTYPE *
+ buffer);
+ bool find_new_frame_ap_vc1(OMX_IN OMX_U8 * buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_OUT OMX_BOOL & isNewFrame);
+
+ OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+ bool release_done();
+
+ bool release_output_done();
+
+ bool release_input_done();
+
+ OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param1, OMX_PTR cmdData);
+
+ inline unsigned int get_output_buffer_size() {
+ OMX_U32 buffer_size, chroma_height, chroma_width;
+ if (m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka) {
+ buffer_size = (m_port_height * m_port_width + 4095) & ~4095;
+ chroma_height = ((m_port_height >> 1) + 31) & ~31;
+ chroma_width = 2 * ((m_port_width >> 1) + 31) & ~31;
+ buffer_size += (chroma_height * chroma_width) + get_extradata_size();
+ } else {
+ buffer_size = m_port_height * m_port_width * 3/2 + get_extradata_size();
+ }
+ return buffer_size;
+ } inline void omx_vdec_set_use_buf_flg() {
+ m_is_use_buffer = true;
+ }
+ inline void omx_vdec_reset_use_buf_flg() {
+ m_is_use_buffer = false;
+ }
+ inline bool omx_vdec_get_use_buf_flg() {
+ return m_is_use_buffer;
+ }
+ inline void omx_vdec_set_use_egl_buf_flg() {
+ m_is_use_egl_buffer = true;
+ }
+ inline void omx_vdec_reset_use_elg_buf_flg() {
+ m_is_use_egl_buffer = false;
+ }
+ inline bool omx_vdec_get_use_egl_buf_flg() {
+ return m_is_use_egl_buffer;
+ }
+ inline void omx_vdec_set_input_use_buf_flg() {
+ m_is_input_use_buffer = true;
+ }
+ inline void omx_vdec_reset_input_use_buf_flg() {
+ m_is_input_use_buffer = false;
+ }
+ inline bool omx_vdec_get_input_use_buf_flg() {
+ return m_is_input_use_buffer;
+ }
+ bool post_event(unsigned int p1, unsigned int p2, unsigned int id);
+
+ static void buffer_done_cb_arbitrarybytes(struct vdec_context *ctxt,
+ void *cookie);
+
+ // Native decoder creation
+ OMX_ERRORTYPE omx_vdec_create_native_decoder(OMX_IN OMX_BUFFERHEADERTYPE
+ * buffer);
+ // Free output port memory
+ void omx_vdec_free_output_port_memory(void);
+ OMX_BUFFERHEADERTYPE *get_free_input_buffer();
+ OMX_S8 find_input_buffer_index(OMX_BUFFERHEADERTYPE * pBuffer);
+ bool free_input_buffer(OMX_BUFFERHEADERTYPE * pBuffer);
+ OMX_S8 get_free_extra_buffer_index();
+ OMX_S8 find_extra_buffer_index(OMX_U8 * buffer);
+ bool free_extra_buffer(OMX_S8 index);
+ void initialize_arbitrary_bytes_environment();
+ bool get_one_complete_frame(OMX_OUT OMX_BUFFERHEADERTYPE * dest);
+ OMX_ERRORTYPE get_one_frame(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
+ OMX_IN OMX_BUFFERHEADERTYPE * source,
+ OMX_OUT bool * isPartialNal);
+ OMX_ERRORTYPE get_one_frame_using_start_code(OMX_OUT
+ OMX_BUFFERHEADERTYPE *
+ dest,
+ OMX_IN OMX_BUFFERHEADERTYPE
+ * source,
+ OMX_INOUT bool *
+ isPartialFrame);
+ OMX_ERRORTYPE get_one_frame_h264_size_nal(OMX_OUT OMX_BUFFERHEADERTYPE *
+ dest,
+ OMX_IN OMX_BUFFERHEADERTYPE *
+ source,
+ OMX_INOUT bool *
+ isPartialFrame);
+ OMX_ERRORTYPE get_one_frame_sp_mp_vc1(OMX_OUT OMX_BUFFERHEADERTYPE *
+ dest,
+ OMX_IN OMX_BUFFERHEADERTYPE *
+ source,
+ OMX_INOUT bool * isPartialFrame);
+ OMX_ERRORTYPE use_egl_output_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE **
+ bufferHdr, OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN void *eglImage);
+
+ int get_extradata_size(void)
+ {
+ return ((OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO)+3) & (~3))+((OMX_EXTRADATA_HEADER_SIZE+sizeof(OMX_QCOM_EXTRADATA_CODEC_DATA)+3) & (~3))+((OMX_EXTRADATA_HEADER_SIZE+sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION) + 3) & (~3))+(OMX_EXTRADATA_HEADER_SIZE + 4); }
+
+ void fill_extradata(OMX_INOUT OMX_BUFFERHEADERTYPE * pBufHdr,
+ OMX_IN vdec_frame * frame);
+
+ //*************************************************************
+ //*******************MEMBER VARIABLES *************************
+ //*************************************************************
+ // OMX State
+ OMX_STATETYPE m_state;
+ // Application data
+ OMX_PTR m_app_data;
+ // Application callbacks
+ OMX_CALLBACKTYPE m_cb;
+ OMX_COLOR_FORMATTYPE m_color_format;
+ OMX_PRIORITYMGMTTYPE m_priority_mgm;
+ OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier;
+ OMX_BUFFERHEADERTYPE *m_pcurrent_frame;
+ OMX_BUFFERHEADERTYPE *input[OMX_CORE_NUM_INPUT_BUFFERS];
+ OMX_BUFFERHEADERTYPE *m_loc_use_buf_hdr;
+ /*************************************************/
+ // used by arbitrary bytes
+ struct omx_start_code_based_info {
+ OMX_U32 m_start_code;
+ OMX_U32 m_start_code_mask;
+ OMX_U32 m_last_4byte;
+ OMX_U32 m_last_start_code;
+ };
+
+ struct omx_frame_size_based_info {
+ OMX_U32 m_size_remaining;
+ OMX_U32 m_size_byte_left;
+ OMX_U32 m_timestamp_byte_left;
+ OMX_U32 m_timestamp_field_present;
+ };
+
+ union omx_arbitrary_bytes_info {
+ struct omx_start_code_based_info start_code;
+ struct omx_frame_size_based_info frame_size;
+ } m_arbitrary_bytes_info;
+
+ OMX_BUFFERHEADERTYPE *m_current_frame;
+ OMX_BUFFERHEADERTYPE *m_current_arbitrary_bytes_input;
+ OMX_BUFFERHEADERTYPE
+ *m_arbitrary_bytes_input[OMX_CORE_NUM_INPUT_BUFFERS];
+ bool m_is_copy_truncated;
+
+ struct omx_extra_input_buff_info {
+ OMX_BUFFERHEADERTYPE *pArbitrary_bytes_freed; // pointer to arbitrary byte input need to be freed
+ bool bfree_input;
+ };
+ struct omx_extra_input_buff_info
+ m_input_buff_info[OMX_CORE_NUM_INPUT_BUFFERS];
+ struct omx_extra_arbitrarybytes_buff_info {
+ OMX_U8 *extra_pBuffer;
+ bool bExtra_pBuffer_in_use;
+ OMX_BUFFERHEADERTYPE *arbitrarybytesInput;
+ };
+ struct omx_extra_arbitrarybytes_buff_info
+ m_extra_buf_info[OMX_CORE_NUM_INPUT_BUFFERS];
+
+ // flag for reaching partialFrame for arbitrary bytes
+ bool m_bPartialFrame;
+
+ /*************************************************/
+
+ // video decoder context
+ struct VDecoder *m_vdec;
+ // fill this buffer queue
+ omx_cmd_queue m_ftb_q;
+ // Command Q for rest of the events
+ omx_cmd_queue m_cmd_q;
+ // empty this buffer queue for arbitrary bytes
+ omx_cmd_queue m_etb_arbitrarybytes_q;
+ // Input memory pointer
+ char *m_inp_mem_ptr;
+ // arbitrary bytes input memory pointer
+ char *m_arbitrary_bytes_input_mem_ptr;
+ // Output memory pointer
+ char *m_out_mem_ptr;
+
+ int m_first_pending_buf_idx;
+ int m_outstanding_frames;
+ // EOS Timestamp
+ signed long long m_eos_timestamp;
+ // bitmask array size for output side
+ unsigned char m_out_bm_count[(OMX_CORE_NUM_OUTPUT_BUFFERS + 7) / 8];
+ // Number of Output Buffers
+ unsigned int m_out_buf_count;
+ // Number of Input Buffers
+ unsigned int m_inp_buf_count;
+ // Size of Input Buffers
+ unsigned int m_inp_buf_size;
+ // bitmask array size for input side
+ unsigned char m_inp_bm_count[(MAX_NUM_INPUT_BUFFERS + 7) / 8];
+ //Input port Populated
+ OMX_BOOL m_inp_bPopulated;
+ //Output port Populated
+ OMX_BOOL m_out_bPopulated;
+ //Height
+ unsigned int m_height;
+ // Width
+ unsigned int m_width;
+
+ unsigned int m_dec_width; // the decoder width with padding
+ unsigned int m_dec_height; // the decoder height with padding
+ bool m_bInterlaced; // Indicate whether the content has interlace
+
+ // Storage of HxW during dynamic port reconfig
+ unsigned int m_port_height;
+ unsigned int m_port_width;
+ unsigned int m_crop_x;
+ unsigned int m_crop_y;
+ unsigned int m_crop_dx;
+ unsigned int m_crop_dy;
+ // encapsulate the waiting states.
+ unsigned char m_flags[4];
+ // size of NAL length
+ unsigned int m_nalu_bytes;
+ genericQueue *flush_before_vdec_op_q;
+ unsigned int m_use_pmem;
+
+#ifdef _ANDROID_
+ // Heap pointer to frame buffers
+ sp < MemoryHeapBase > m_heap_ptr;
+#endif //_ANDROID_
+ unsigned char m_out_flags[(OMX_CORE_NUM_OUTPUT_BUFFERS + 7) / 8];
+ // message count
+ unsigned m_msg_cnt;
+ // command count
+ unsigned m_cmd_cnt;
+ // Empty This Buffer count
+ unsigned m_etb_cnt;
+ // Empty Buffer Done Count
+ unsigned m_ebd_cnt;
+ // Fill This Buffer count
+ unsigned m_ftb_cnt;
+ // Fill Buffer done count
+ unsigned m_fbd_cnt;
+ // store I/P PORT state
+ OMX_BOOL m_inp_bEnabled;
+ // store O/P PORT state
+ OMX_BOOL m_out_bEnabled;
+ OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE];
+
+ // default members for pre-defined system properties
+ bool m_default_arbitrary_bytes;
+ bool m_default_arbitrary_bytes_vc1;
+ bool m_default_accumulate_subframe;
+
+ // to know whether Event Port Settings change has been triggered or not.
+ bool m_event_port_settings_sent;
+ // is USE Buffer in use
+ bool m_is_use_buffer;
+ bool m_is_input_use_buffer;
+ bool m_is_use_egl_buffer;
+ //bool m_is_use_pmem_buffer;
+ // EOS notify pending to the IL client
+ bool m_bEoSNotifyPending;
+ // NAL stitching required
+ bool m_bAccumulate_subframe;
+ // flag if input is arbitrary bytes
+ bool m_bArbitraryBytes;
+ // flag to indicate if the buffer use start code
+ bool m_bStartCode;
+
+ // wait for resource, (buffer done from Q6 to free buffers)
+ bool m_bWaitForResource;
+
+ use_buffer_map m_use_buf_hdrs;
+
+ H264_Utils *m_h264_utils;
+
+ // Input frame details
+ struct video_input_frame_info m_frame_info;
+ // Platform specific details
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *m_platform_list;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *m_platform_entry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *m_pmem_info;
+ // SPS+PPS sent as part of set_config
+ OMX_VENDOR_EXTRADATATYPE m_vendor_config;
+ header_state m_header_state;
+ bool m_bInvalidState;
+ bool m_b_divX_parser;
+ MP4_Utils *m_mp4_utils;
+ uint64 m_timestamp_interval;
+ uint64 m_prev_timestamp;
+ bool m_b_display_order;
+ struct vdec_frame *m_pPrevFrame;
+
+ typedef struct
+ {
+ mp4_frame_info_type frame_info[MAX_FRAMES_IN_CHUNK];
+ uint32 nFrames;
+ uint32 last_decoded_index;
+ bool parsing_required;
+ } omx_mp4_divX_buffer_info;
+
+ omx_mp4_divX_buffer_info m_divX_buffer_info;
+ uint32 m_codec_format;
+ uint32 m_codec_profile;
+ OMX_NATIVE_WINDOWTYPE m_display_id;
+};
+
+#endif // __OMX_VDEC_H__
diff --git a/omx/mm-video/qdsp6/vdec/src/omx_vdec_inpbuf.cpp b/omx/mm-video/qdsp6/vdec/src/omx_vdec_inpbuf.cpp
new file mode 100644
index 0000000..d9c0dbf
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/omx_vdec_inpbuf.cpp
@@ -0,0 +1,262 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ O p e n M A X Component
+ Video Decoder Input buffer class
+
+*//** @file omx_vdec_inpbuf.cpp
+ This module contains the class definition for openMAX input buffer related logic.
+
+*//*========================================================================*/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include <string.h>
+#include <omx_vdec.h>
+
+/* ======================================================================
+FUNCTION
+ omx_vdec_inpbuf constructor
+
+DESCRIPTION
+ Constructor.
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None
+
+========================================================================== */
+omx_vdec_inpbuf::omx_vdec_inpbuf():m_read(0), m_write(0), m_last(-1),
+ m_size(0)
+{
+ memset(m_pend_q, 0, sizeof(m_pend_q));
+ memset(m_flags, 0, sizeof(m_flags));
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec_inpbuf destructor
+
+DESCRIPTION
+ Destructor.
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None
+
+========================================================================== */
+omx_vdec_inpbuf::~omx_vdec_inpbuf()
+{
+ // empty due to the lack of dynamic members
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::add_entry
+
+DESCRIPTION
+ Add new entry to the pending queue.
+
+PARAMETERS
+ 1. index -- Input buffer index to be added.
+
+RETURN VALUE
+ true/false depending on whether the entry is successfully added or not?
+
+========================================================================== */
+bool omx_vdec_inpbuf::add_entry(unsigned int index)
+{
+ bool ret = false;
+ if (m_size < MAX_NUM_INPUT_BUFFERS)
+ {
+ m_size++;
+ ret = true;
+ m_pend_q[m_write] = index;
+ m_write = (m_write + 1) % MAX_NUM_INPUT_BUFFERS;
+ BITMASK_SET(m_flags, index);
+ }
+ return ret;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::push_back_entry
+
+DESCRIPTION
+ Push back the last entry deleted back to the pending queue.
+
+PARAMETERS
+ 1.index - Index of the entry which needs to be re-inserted at the top
+
+RETURN VALUE
+ true/false depending on the situation.
+
+========================================================================== */
+bool omx_vdec_inpbuf::push_back_entry(unsigned int index)
+{
+ bool ret = false;
+ if (m_size == 0)
+ {
+
+ // If the queue is empty execute the add_entry
+ ret = add_entry(index);
+ }
+ // Make sure that last entry deleted is same
+ else if ((m_size > 0) && (m_size < MAX_NUM_INPUT_BUFFERS) &&
+ (m_last >= 0) && (m_last == index))
+ {
+ m_size++;
+ ret = true;
+ // Read index need to go back here
+ if (m_read > 0)
+ {
+ m_read--;
+ }
+ else
+ {
+ m_read = MAX_NUM_INPUT_BUFFERS - 1;
+ }
+ m_pend_q[m_read] = index;
+ BITMASK_SET(m_flags, index);
+ }
+ else
+ {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - push_back_entry didn't push anything m_size %d, m_last %d, index %d\n",
+ m_size, m_last, index);
+ }
+ return ret;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::remove_top_entry
+
+DESCRIPTION
+ Knock off the top entry from the pending queue.
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. cookie(I) -- Context information related to the specific input buffer
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+int omx_vdec_inpbuf::remove_top_entry(void)
+{
+ int ret = -1;
+ if (m_size > 0)
+ {
+ m_size--;
+ ret = m_pend_q[m_read];
+ m_read = (m_read + 1) % MAX_NUM_INPUT_BUFFERS;
+ BITMASK_CLEAR(m_flags, ret);
+ m_last = ret;
+ }
+ return ret;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlBufferDoneCb
+
+DESCRIPTION
+ Buffer done callback from the decoder.
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. cookie(I) -- Context information related to the specific input buffer
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec_inpbuf::is_pending(void)
+{
+ return (m_size > 0);
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlBufferDoneCb
+
+DESCRIPTION
+ Buffer done callback from the decoder.
+
+PARAMETERS
+ 1. ctxt(I) -- Context information to the self.
+ 2. cookie(I) -- Context information related to the specific input buffer
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec_inpbuf::is_pending(unsigned int index)
+{
+ return (BITMASK_PRESENT(m_flags, index) > 0);
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::get_first_pending_index
+
+DESCRIPTION
+ Get first pending index from the queue. Peek the first entry in
+ the queue if there is any.
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ Returns the top input buffer index
+
+========================================================================== */
+int omx_vdec_inpbuf::get_first_pending_index(void)
+{
+ int ret = -1;
+ if (m_size > 0)
+ {
+ ret = m_pend_q[m_read];
+ }
+ return ret;
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/omx_vdec_inpbuf.h b/omx/mm-video/qdsp6/vdec/src/omx_vdec_inpbuf.h
new file mode 100644
index 0000000..f433957
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/omx_vdec_inpbuf.h
@@ -0,0 +1,75 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef __OMX_VDEC_INPBUF_H__
+#define __OMX_VDEC_INPBUF_H__
+/*============================================================================
+ O p e n M A X Component
+ Video Decoder
+
+*//** @file omx_vdec_inpbuf.h
+ This module contains the class definition for openMAX input buffer related logic.
+
+*//*========================================================================*/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+// Number of input buffers defined at one place
+#define MAX_NUM_INPUT_BUFFERS 8
+#define MAX_INPUT_BUFFERS_BITMASK_SIZE ((MAX_NUM_INPUT_BUFFERS/8) + 1)
+
+// OMX video decoder input buffer class
+class omx_vdec_inpbuf {
+ public:
+ omx_vdec_inpbuf(); // constructor
+ virtual ~ omx_vdec_inpbuf(); // destructor
+
+ bool add_entry(unsigned int index);
+ int remove_top_entry();
+
+ // Any buffer pending?
+ bool is_pending();
+ // Is buffer with particular index pending?
+ bool is_pending(unsigned int index);
+ int get_first_pending_index(void);
+ bool push_back_entry(unsigned int index);
+
+ private:
+ unsigned int m_pend_q[MAX_NUM_INPUT_BUFFERS];
+ unsigned int m_read; // read pointer
+ unsigned int m_write; // write pointer
+ int m_size; // size
+ int m_last; // last entry deleted
+ unsigned char m_flags[MAX_INPUT_BUFFERS_BITMASK_SIZE];
+
+};
+
+#endif // __OMX_VDEC_H__
diff --git a/omx/mm-video/qdsp6/vdec/src/omx_vdec_linux.cpp b/omx/mm-video/qdsp6/vdec/src/omx_vdec_linux.cpp
new file mode 100644
index 0000000..36ba415
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/omx_vdec_linux.cpp
@@ -0,0 +1,168 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ O p e n M A X w r a p p e r s
+ O p e n M A X C o r e
+
+*//** @file omx_vdec.c
+ This module contains the implementation of the OpenMAX core & component.
+
+*//*========================================================================*/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include "omx_vdec_linux.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+void *get_omx_component_factory_fn(void)
+{
+ return (new omx_vdec_linux);
+}
+
+void *message_thread(void *input)
+{
+ unsigned char id;
+ int n;
+ omx_vdec_linux *omx = reinterpret_cast < omx_vdec_linux * >(input);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec: message thread start\n");
+ while (1) {
+ n = read(omx->m_pipe_in, &id, 1);
+ if (0 == n)
+ break;
+ if (1 == n) {
+ omx->process_event_cb(&(omx->m_vdec_cfg), id);
+ }
+#ifdef QLE_BUILD
+ if (n < 0)
+ break;
+#else
+ if ((n < 0) && (errno != EINTR))
+ break;
+#endif
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec: message thread stop\n");
+ return 0;
+}
+
+omx_vdec_linux::omx_vdec_linux()
+{
+ m_pipe_in = -1;
+ m_pipe_out = -1;
+ is_thread_created = false;
+ pthread_mutexattr_init(&m_lock_attr);
+ pthread_mutex_init(&m_lock, &m_lock_attr);
+ sem_init(&m_cmd_lock, 0, 0);
+}
+
+omx_vdec_linux::~omx_vdec_linux()
+{
+ if (m_pipe_in) {
+ close(m_pipe_in);
+ m_pipe_in = -1;
+ }
+
+ if (m_pipe_out) {
+ close(m_pipe_out);
+ m_pipe_out = -1;
+ }
+ if (is_thread_created) {
+ pthread_join(msg_thread_id,NULL);
+ is_thread_created = false;
+ }
+
+ pthread_mutexattr_destroy(&m_lock_attr);
+ pthread_mutex_destroy(&m_lock);
+ sem_destroy(&m_cmd_lock);
+}
+
+OMX_ERRORTYPE omx_vdec_linux::create_msg_thread()
+{
+ int fds[2];
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if (fds == NULL || pipe(fds)) {
+ //QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"pipe creation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ } else {
+ m_pipe_in = fds[0];
+ m_pipe_out = fds[1];
+ if (fcntl(m_pipe_out, F_SETFL, O_NONBLOCK) == -1) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Error - Set pipe out to NONBLOCK is failed\n");
+ }
+ if (pthread_create(&msg_thread_id, 0, message_thread, this) < 0)
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ if (eRet == OMX_ErrorNone)
+ is_thread_created = true;
+ return eRet;
+}
+
+void omx_vdec_linux::post_message(unsigned char id)
+{
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "omx_vdec: post_message %d\n", id);
+ int eRet = 0;
+
+ eRet = write(m_pipe_out, &id, 1);
+
+ if (eRet == -1) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "errno %d - %s\n", errno, strerror(errno));
+ }
+
+}
+
+void omx_vdec_linux::mutex_lock()
+{
+ pthread_mutex_lock(&m_lock);
+}
+
+void omx_vdec_linux::mutex_unlock()
+{
+ pthread_mutex_unlock(&m_lock);
+}
+
+void omx_vdec_linux::semaphore_wait()
+{
+ sem_wait(&m_cmd_lock);
+}
+
+void omx_vdec_linux::semaphore_post()
+{
+ sem_post(&m_cmd_lock);
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/omx_vdec_linux.h b/omx/mm-video/qdsp6/vdec/src/omx_vdec_linux.h
new file mode 100644
index 0000000..e480c52
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/omx_vdec_linux.h
@@ -0,0 +1,78 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef __OMX_VDEC_LINUX_H__
+#define __OMX_VDEC_LINUX_H__
+/*============================================================================
+ O p e n M A X Component
+ Video Decoder
+
+*//** @file comx_vdec.h
+ This module contains the class definition for openMAX decoder component.
+
+*//*========================================================================*/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+/* Uncomment out below line
+#define LOG_NDEBUG 0 if we want to see all LOG Verbose messaging */
+
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include "omx_vdec.h"
+
+class omx_vdec_linux:public omx_vdec {
+ public:
+ omx_vdec_linux(); // constructor
+ virtual ~ omx_vdec_linux(); // destructor
+ virtual OMX_ERRORTYPE create_msg_thread();
+ virtual void post_message(unsigned char id);
+ virtual void mutex_lock();
+ virtual void mutex_unlock();
+ virtual void semaphore_wait();
+ virtual void semaphore_post();
+
+ int m_pipe_in; // for communicating with the message thread
+ int m_pipe_out; // for communicating with the message thread
+ pthread_t msg_thread_id;
+
+ private:
+ pthread_mutex_t m_lock;
+ pthread_mutexattr_t m_lock_attr;
+ bool is_thread_created;
+ //sem to handle the minimum procesing of commands
+ sem_t m_cmd_lock;
+};
+
+#endif // __OMX_VDEC_LINUX_H__
diff --git a/omx/mm-video/qdsp6/vdec/src/pmem.c b/omx/mm-video/qdsp6/vdec/src/pmem.c
new file mode 100644
index 0000000..ba3464e
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/pmem.c
@@ -0,0 +1,200 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifdef QLE_BUILD
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "pmem2.h"
+#include "pmem.h"
+#include "../../../../../modules/pmem/inc-user/pmem_module.h"
+
+static int pmem_fd;
+
+int pmem_alloc(struct pmem *pMem, unsigned nSize)
+{
+ printf("pmem_alloc : Size - [%d]\n", nSize);
+
+ if (!pMem)
+ return -1;
+
+ struct pmem_region_info sRegion;
+ const int nFlags = 5; // bit 0 disable write through cache
+ // bit 1 1 MB aligned
+ // bit 2 attach region
+ nSize = (nSize + 4095) & (~4095);
+ pMem->fd = (int)pmem2_malloc(nSize, PMEM_EBI1, nFlags, &pMem->data);
+ if ((pMem->data == NULL) || (pMem->fd < 0)) {
+ printf("error could not allocate pmem");
+ return -1;
+ }
+ pmem2_get_region_info(pMem->fd, &sRegion);
+ pMem->phys = (void *)sRegion.paddr;
+ pMem->size = nSize;
+
+ printf("PMEM ALLOC: Allocation succesfull\n");
+
+ return 0;
+}
+
+void pmem_free(struct pmem *pmem)
+{
+ close(pmem->fd);
+ pmem->fd = -1;
+ munmap(pmem->data, pmem->size);
+}
+
+#else
+#include <stdio.h>
+#include <fcntl.h>
+#include "pmem.h"
+#include "qutility.h"
+
+#ifndef T_WINNT
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+struct file;
+#include <linux/android_pmem.h>
+#endif
+
+#define USE_SMI 0 /* do NOT enable if you're running the full system */
+
+int pmem_alloc(struct pmem *pmem, unsigned sz)
+{
+#ifdef T_WINNT
+ sz = (sz + 4095) & (~4095);
+ pmem->size = sz;
+ pmem->fd = 0;
+ pmem->data = (void *)malloc(sz);
+ pmem->phys = (unsigned)pmem->data;
+ return 0;
+#else
+ struct pmem_region region;
+
+#if USE_SMI
+ pmem->fd = open("/dev/pmem_gpu0", O_RDWR);
+#elif defined(USE_PMEM_ADSP_CACHED)
+ pmem->fd = open("/dev/pmem_adsp", O_RDWR);
+#else
+ //uncached behavior
+ pmem->fd = open("/dev/pmem_adsp", O_RDWR|O_SYNC);
+#endif
+
+ if (pmem->fd < 0) {
+ perror("cannot open pmem device");
+ return -1;
+ }
+ //sz = (sz + 4095) & (~4095);
+ pmem->size = sz;
+ pmem->data = mmap(NULL, sz, PROT_READ | PROT_WRITE,
+ MAP_SHARED, pmem->fd, 0);
+
+ if (pmem->data == MAP_FAILED) {
+ perror("pmem mmap failed");
+ close(pmem->fd);
+ pmem->fd = -1;
+ return -1;
+ }
+
+ if (ioctl(pmem->fd, PMEM_GET_PHYS, ®ion)) {
+ perror("pmem phys lookup failed");
+ close(pmem->fd);
+ munmap(pmem->data, pmem->size);
+ return -1;
+ }
+ pmem->phys = region.offset;
+ printx("PMEM %p (phys=%08x)\n", pmem->data, pmem->phys);
+ return 0;
+#endif
+}
+
+void pmem_free(struct pmem *pmem)
+{
+#ifdef T_WINNT
+ pmem->fd = 0;
+ pmem->phys = 0;
+ pmem->size = 0;
+ free(pmem->data);
+ pmem->data = 0;
+#else
+ if(pmem->fd >= 0) {
+ close(pmem->fd);
+ pmem->fd = -1;
+ munmap(pmem->data, pmem->size);
+ }
+#endif
+}
+
+#ifdef USE_PMEM_ADSP_CACHED
+void pmem_cachemaint(int pmem_id, void *addr, unsigned size, PMEM_CACHE_OP op)
+{
+ struct pmem_addr pmem_addr;
+ pmem_addr.vaddr = (unsigned long)addr;
+ pmem_addr.offset = 0;
+ pmem_addr.length = size;
+ int errno_pmem = 0;
+
+ switch(op) {
+ case PMEM_CACHE_FLUSH: //Cache clean/flush operation
+ {
+ if (errno_pmem = ioctl(pmem_id, PMEM_CLEAN_CACHES, &pmem_addr)) {
+ printf("pmem_cleancache Error !!!! errno=%d\n", errno_pmem);
+ }
+ break;
+ }
+
+ case PMEM_CACHE_INVALIDATE: //Cache invalidate operation
+ {
+ if (errno_pmem = ioctl(pmem_id, PMEM_INV_CACHES, &pmem_addr)) {
+ printf("pmem_invcache Error !!!! errno=%d\n", errno_pmem);
+ }
+ break;
+ }
+
+ case PMEM_CACHE_FLUSH_INVALIDATE: //Cache clean+invalidate operation
+ {
+ if (errno_pmem = ioctl(pmem_id, PMEM_CLEAN_INV_CACHES, &pmem_addr)) {
+ printf("pmem_clean_inv_cache Error !!!! errno=%d\n", errno_pmem);
+ }
+ break;
+ }
+
+ default:
+ printf("pmem_cachemaint: Invalid cache operation.!!!!\n");
+ break;
+ }
+}
+#endif
+#endif //QLE_BUILD
diff --git a/omx/mm-video/qdsp6/vdec/src/pmem.h b/omx/mm-video/qdsp6/vdec/src/pmem.h
new file mode 100644
index 0000000..d4f5f28
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/pmem.h
@@ -0,0 +1,75 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _PMEM_SIMPLE_H_
+#define _PMEM_SIMPLE_H_
+
+#define pmem_alloc vdec_pmem_alloc
+#define pmem_free vdec_pmem_free
+
+struct pmem {
+ void *data;
+ int fd;
+
+ unsigned phys;
+ unsigned size;
+};
+
+int pmem_alloc(struct pmem *out, unsigned sz);
+void pmem_free(struct pmem *pmem);
+
+#ifdef USE_PMEM_ADSP_CACHED
+
+//Cache operation to perform on the pmem region
+typedef enum {
+ PMEM_CACHE_FLUSH = 0,
+ PMEM_CACHE_INVALIDATE,
+ PMEM_CACHE_FLUSH_INVALIDATE,
+ PMEM_CACHE_INVALID_OP
+} PMEM_CACHE_OP;
+
+/**
+ * This method is used to perform cache operations on the pmem regoin
+ * in the decoder.
+ *
+ * Prerequisite: pmem_alloc should have been called.
+ *
+ * @param[in] pmem_id
+ * id of the pmem region to use.
+ *
+ * @param[in] addr
+ * The virtual addr of the pmem region
+ *
+ * @param[in] size
+ * The size of the region
+ *
+ * @param[in] op
+ * Cache operation to perform as defined by PMEM_CACHE_OP
+ */
+void pmem_cachemaint(int pmem_id, void *addr, unsigned size, PMEM_CACHE_OP op);
+#endif
+#endif
diff --git a/omx/mm-video/qdsp6/vdec/src/qtv_msg.h b/omx/mm-video/qdsp6/vdec/src/qtv_msg.h
new file mode 100644
index 0000000..e354ce0
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/qtv_msg.h
@@ -0,0 +1,184 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef QTV_MSG_H
+#define QTV_MSG_H
+
+#include <string.h>
+#include <stdio.h>
+
+#define LOG_NDEBUG 1
+/* LOG_NDEBUG is log no debug
+ * If need to debug, please put #define LOG_NDEBUG 0 at the beginning line of .c/.cpp file that you are working on
+ * before #include <utils/Log.h>
+ *
+ * To enable all LOGV at all files, put #define LOG_NDEBUG 0 at this file (qtv_msg.h)
+ *
+ * #define LOG_NDEBUG 1 will disable LOGV
+ * #define LOG_NDEBUG 0 will enable LOGV
+ */
+//#define LOG_NDEBUG 0
+
+#ifdef _ANDROID_
+#ifndef LOG_TAG
+#define LOG_TAG "QCvdec"
+#include <utils/Log.h>
+#endif
+#endif
+
+#if 1
+/* Usage of QTV_MSG, QTV_MSG_PRIO, etc
+ * QTV_MSG(<QTV Message Sub-Group Id>, <message>)
+ * QTV_MSG_PRIOx(<QTV Message Sub-Group Id>, <QTV Message Priorities>, <message>, args)
+ */
+
+/* QTV Message Sub-Group Ids */
+#define QTVDIAG_GENERAL 0
+#define QTVDIAG_DEBUG 1
+#define QTVDIAG_STATISTICS 2
+#define QTVDIAG_UI_TASK 3
+#define QTVDIAG_MP4_PLAYER 4
+#define QTVDIAG_AUDIO_TASK 5
+#define QTVDIAG_VIDEO_TASK 6
+#define QTVDIAG_STREAMING 7
+#define QTVDIAG_MPEG4_TASK 8
+#define QTVDIAG_FILE_OPS 9
+#define QTVDIAG_RTP 10
+#define QTVDIAG_RTCP 11
+#define QTVDIAG_RTSP 12
+#define QTVDIAG_SDP_PARSE 13
+#define QTVDIAG_ATOM_PARSE 14
+#define QTVDIAG_TEXT_TASK 15
+#define QTVDIAG_DEC_DSP_IF 16
+#define QTVDIAG_STREAM_RECORDING 17
+#define QTVDIAG_CONFIGURATION 18
+#define QTVDIAG_BCAST_FLO 19
+#define QTVDIAG_GENERIC_BCAST 20
+
+/* QTV Message Priorities */
+#define QTVDIAG_PRIO_LOW
+#define QTVDIAG_PRIO_MED
+#define QTVDIAG_PRIO_HIGH
+#define QTVDIAG_PRIO_ERROR
+#define QTVDIAG_PRIO_FATAL
+#define QTVDIAG_PRIO_DEBUG
+#endif
+
+#if (defined _ANDROID_) || (LOG_NDEBUG==1)
+#define QTV_MSG_PRIO(a,b,c) LOG_##b(c)
+#define QTV_MSG_PRIO1(a,b,c,d) LOG_##b((c),(d))
+#define QTV_MSG_PRIO2(a,b,c,d,e) LOG_##b((c),(d),(e))
+#define QTV_MSG_PRIO3(a,b,c,d,e,f) LOG_##b((c),(d),(e),(f))
+#define QTV_MSG_PRIO4(a,b,c,d,e,f,g) LOG_##b((c),(d),(e),(f),(g))
+#define QTV_MSG_PRIO5(a,b,c,d,e,f,g,h) LOG_##b((c),(d),(e),(f),(g),(h))
+#define QTV_MSG_PRIO6(a,b,c,d,e,f,g,h,i) LOG_##b((c),(d),(e),(f),(g),(h),(i))
+#define QTV_MSG_PRIO7(a,b,c,d,e,f,g,h,i,j) LOG_##b((c),(d),(e),(f),(g),(h),(i),(j))
+#define QTV_MSG_PRIO8(a,b,c,d,e,f,g,h,i,j,k) LOG_##b((c),(d),(e),(f),(g),(h),(i),(j),(k))
+#else
+#define QTV_MSG_PRIO(a,b,c) {LOG_##b(c); printf("\n");}
+#define QTV_MSG_PRIO1(a,b,c,d) {LOG_##b((c),(d)); printf("\n");}
+#define QTV_MSG_PRIO2(a,b,c,d,e) {LOG_##b((c),(d),(e)); printf("\n");}
+#define QTV_MSG_PRIO3(a,b,c,d,e,f) {LOG_##b((c),(d),(e),(f)); printf("\n");}
+#define QTV_MSG_PRIO4(a,b,c,d,e,f,g) {LOG_##b((c),(d),(e),(f),(g)); printf("\n");}
+#define QTV_MSG_PRIO5(a,b,c,d,e,f,g,h) {LOG_##b((c),(d),(e),(f),(g),(h)); printf("\n");}
+#define QTV_MSG_PRIO6(a,b,c,d,e,f,g,h,i) {LOG_##b((c),(d),(e),(f),(g),(h),(i)); printf("\n");}
+#define QTV_MSG_PRIO7(a,b,c,d,e,f,g,h,i,j) {LOG_##b((c),(d),(e),(f),(g),(h),(i),(j)); printf("\n");}
+#define QTV_MSG_PRIO8(a,b,c,d,e,f,g,h,i,j,k) {LOG_##b((c),(d),(e),(f),(g),(h),(i),(j),(k)); printf("\n");}
+#endif
+
+#if (defined _ANDROID_)
+#define QTV_MSG_SPRINTF(a,b) LOGE(b)
+#define QTV_MSG_SPRINTF_1(a,b,c) LOGE((b),(c))
+#define QTV_MSG_SPRINTF_2(a,b,c,d) LOGE((b),(c),(d))
+#define QTV_MSG_SPRINTF_3(a,b,c,d,e) LOGE((b),(c),(d),(e))
+#define QTV_MSG_SPRINTF_4(a,b,c,d,e,f) LOGE((b),(c),(d),(e),(f))
+#else
+#define QTV_MSG_SPRINTF(a,b) {LOGE(b); printf("\n");}
+#define QTV_MSG_SPRINTF_1(a,b,c) {LOGE((b),(c)); printf("\n");}
+#define QTV_MSG_SPRINTF_2(a,b,c,d) {LOGE((b),(c),(d)); printf("\n");}
+#define QTV_MSG_SPRINTF_3(a,b,c,d,e) {LOGE((b),(c),(d),(e)); printf("\n");}
+#define QTV_MSG_SPRINTF_4(a,b,c,d,e,f) {LOGE((b),(c),(d),(e),(f)); printf("\n");}
+#endif
+
+#if (defined _ANDROID_) || (LOG_NDEBUG==1)
+#define QTV_MSG(a,b) LOGV(b)
+#define QTV_MSG1(a,b,c) LOGV((b),(c))
+#define QTV_MSG2(a,b,c,d) LOGV((b),(c),(d))
+#define QTV_MSG3(a,b,c,d,e) LOGV((b),(c),(d),(e))
+#define QTV_MSG4(a,b,c,d,e,f) LOGV((b),(c),(d),(e),(f))
+#else
+#define QTV_MSG(a,b) {LOGV(b); printf("\n");}
+#define QTV_MSG1(a,b,c) {LOGV((b),(c)); printf("\n");}
+#define QTV_MSG2(a,b,c,d) {LOGV((b),(c),(d)); printf("\n");}
+#define QTV_MSG3(a,b,c,d,e) {LOGV((b),(c),(d),(e)); printf("\n");}
+#define QTV_MSG4(a,b,c,d,e,f) {LOGV((b),(c),(d),(e),(f)); printf("\n");}
+#endif
+
+#define LOG_QTVDIAG_PRIO_FATAL LOGE
+#define LOG_QTVDIAG_PRIO_ERROR LOGW
+#define LOG_QTVDIAG_PRIO_HIGH LOGV
+#define LOG_QTVDIAG_PRIO_MED LOGV
+#define LOG_QTVDIAG_PRIO_LOW LOGV
+#define LOG_QTVDIAG_PRIO_DEBUG LOGV
+
+#ifdef PROFILE_DECODER
+#define QTV_PERF(a)
+#define QTV_PERF_MSG_PRIO(a,b,c) LOGE((c))
+#define QTV_PERF_MSG_PRIO1(a,b,c,d) LOGE((c),(d))
+#define QTV_PERF_MSG_PRIO2(a,b,c,d,e) LOGE((c),(d),(e))
+#define QTV_PERF_MSG_PRIO3(a,b,c,d,e,f) LOGE((c),(d),(e),(f))
+#else
+#define QTV_PERF(a)
+#define QTV_PERF_MSG_PRIO(a,b,c) //FARF(ALWAYS,(&F, c))
+#define QTV_PERF_MSG_PRIO1(a,b,c,d) //FARF(ALWAYS,(&F, c,d))
+#define QTV_PERF_MSG_PRIO2(a,b,c,d,e) //FARF(ALWAYS,(&F, c,d,e))
+#define QTV_PERF_MSG_PRIO3(a,b,c,d,e,f) //FARF(ALWAYS,(&F, c,d,e,f))
+#endif
+
+#define ERR(a, b, c, d) //FARF(ALWAYS,(&F, a, b, c, d))
+#define ERR_FATAL(a, b, c, d) //FARF(ALWAYS, (&F, a, b, c, d))
+
+#define MSG_ERROR(a, b) //FARF(ALWAYS, (&F, a, b))
+#define MSG_ERROR4(a, b, c, d) //FARF(ALWAYS, (&F, a, b, c, d))
+
+//#define ASSERT(x) if (!(x)) {char *pp=0; LOGE("%s:%d *** ERROR ASSERT(0)\n", __FILE__, __LINE__); *pp=0;}
+#if !defined(ASSERT)
+#define ASSERT(x) if (!(x)) {LOGE("%s:%d *** ERROR ASSERT(0)\n", __FILE__, __LINE__);}
+#endif
+
+#ifndef _ANDROID_
+#define LOGE printf
+#define LOGW printf
+#if (LOG_NDEBUG==1)
+#define LOGV(...)
+#else
+#define LOGV printf
+#endif
+#endif // _ANDROID_
+
+#endif // QTV_MSG_H
diff --git a/omx/mm-video/qdsp6/vdec/src/qtypes.h b/omx/mm-video/qdsp6/vdec/src/qtypes.h
new file mode 100644
index 0000000..4f17f3e
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/qtypes.h
@@ -0,0 +1,86 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef QTYPES_H
+#define QTYPES_H
+/*===========================================================================
+
+ Data Declarations
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------------------------------------------------------------------
+** Constants
+** ------------------------------------------------------------------------ */
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define TRUE 1 /* Boolean true value. */
+#define FALSE 0 /* Boolean false value. */
+
+/* -----------------------------------------------------------------------
+** Standard Types
+** ----------------------------------------------------------------------- */
+
+/* The following definitions are the same accross platforms. This first
+** group are the sanctioned types.
+*/
+
+ typedef unsigned char boolean; /* Boolean value type. */
+
+ typedef unsigned long int uint32; /* Unsigned 32 bit value */
+ typedef unsigned short uint16; /* Unsigned 16 bit value */
+ typedef unsigned char uint8; /* Unsigned 8 bit value */
+
+ typedef signed long int int32; /* Signed 32 bit value */
+ typedef signed short int16; /* Signed 16 bit value */
+ typedef signed char int8; /* Signed 8 bit value */
+
+/* This group are the deprecated types. Their use should be
+** discontinued and new code should use the types above
+*/
+ typedef unsigned char byte; /* Unsigned 8 bit value type. */
+ typedef unsigned short word; /* Unsinged 16 bit value type. */
+ typedef unsigned long dword; /* Unsigned 32 bit value type. */
+
+ typedef long long int64;
+ typedef unsigned long long uint64;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* QTYPES_H */
diff --git a/omx/mm-video/qdsp6/vdec/src/qutility.c b/omx/mm-video/qdsp6/vdec/src/qutility.c
new file mode 100644
index 0000000..8a9c724
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/qutility.c
@@ -0,0 +1,92 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#include "qutility.h"
+
+#ifdef T_WINNT
+#include <errno.h>
+/*
+ * Number of micro-seconds between the beginning of the Windows epoch
+ * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
+ *
+ * This assumes all Win32 compilers have 64-bit support.
+ */
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
+#define DELTA_EPOCH_IN_USEC 11644473600000000Ui64
+#else
+#define DELTA_EPOCH_IN_USEC 11644473600000000ULL
+#endif
+
+static usecs_t filetime_to_unix_epoch(const FILETIME * ft)
+{
+ usecs_t res = (usecs_t) ft->dwHighDateTime << 32;
+
+ res |= ft->dwLowDateTime;
+ res /= 10; /* from 100 nano-sec periods to usec */
+ res -= DELTA_EPOCH_IN_USEC; /* from Win epoch to Unix epoch */
+ return (res);
+}
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+ FILETIME ft;
+ usecs_t tim;
+
+ if (!tv) {
+ errno = EINVAL;
+ return (-1);
+ }
+ GetSystemTimeAsFileTime(&ft);
+ tim = filetime_to_unix_epoch(&ft);
+ tv->tv_sec = (long)(tim / 1000000L);
+ tv->tv_usec = (long)(tim % 1000000L);
+ return (0);
+}
+#endif //T_WINNT
+
+int fwritex(const void *ptr, int count, FILE * stream)
+{
+ char *ptr1 = (char *)ptr;
+ int bytes, total_bytes = 0;
+ printx("\nfwritex(), count: %d, remainder: %d\n", count, count % 1024);
+ do {
+ if (count >= 1024) {
+ bytes = fwrite(ptr1, 1, 1024, stream);
+ //printx("fwritex: %d\n", bytes);
+ ptr1 += 1024;
+ count -= 1024;
+ total_bytes += bytes;
+ } else {
+ bytes = fwrite(ptr1, 1, count, stream);
+ printx("\nfwritex: %d\n", bytes);
+ count = 0;
+ total_bytes += bytes;
+ }
+ } while (count);
+ return total_bytes;
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/qutility.h b/omx/mm-video/qdsp6/vdec/src/qutility.h
new file mode 100644
index 0000000..63e05b8
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/qutility.h
@@ -0,0 +1,139 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _QUTILITY_H_
+#define _QUTILITY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdio.h>
+#include "qtv_msg.h"
+
+#ifndef T_WINNT
+#include <sys/time.h>
+#ifdef _ANDROID_
+//#include "cutils/log.h"
+#endif //_ANDROID_
+#else
+#include <Windows.h>
+ extern int gettimeofday(struct timeval *tv, void *tz);
+#endif //T_WINNT
+
+//#define LOG_YUV_SLICES 0
+//#define LOG_YUV_FRAMES 0
+
+ typedef unsigned long long usecs_t;
+
+#if 0
+#define printp(x...) LOGV(x)
+
+#ifdef PROFILE_DECODER
+#define printx(x...) do {} while (0)
+#else
+#ifdef USE_LOGE_FOR_DECODER
+#define printx(x...) LOGV(x)
+#else
+#define printx(x...) fprintf(stderr, x)
+#endif
+#endif
+#else
+#ifndef T_WINNT
+#define printx(x...) do {} while (0)
+#else
+#define printx(...) do {} while (0)
+#endif //T_WINNT
+#endif
+
+ int fwritex(const void *ptr, int count, FILE * stream);
+
+// To enable profiling on CBSP2 please add "CPPFLAGS += -DPROFILE_DECODER" in
+// vdec-omxmp4.mk and vdec_omxh264.mk
+
+#ifdef PROFILE_DECODER
+
+#define QPERF_INIT(PREFIX) \
+usecs_t PREFIX ## _total_time_us = 0;\
+int PREFIX ## _n_running_timer = 0;\
+struct timeval PREFIX ## _tv1, PREFIX ## _tv2;\
+struct timezone PREFIX ## _tz1, PREFIX ## _tz2;\
+int PREFIX ## _total_iterations = 0
+
+#define QPERF_RESET(PREFIX) \
+PREFIX ## _total_time_us = 0;\
+PREFIX ## _total_iterations = 0
+
+#define QPERF_START(PREFIX) \
+ if (PREFIX ## _n_running_timer == 0) gettimeofday(&PREFIX ## _tv1, &PREFIX ## _tz1);\
+ PREFIX ## _n_running_timer++
+
+#define QPERF_END(PREFIX) \
+ gettimeofday(&PREFIX ## _tv2, &PREFIX ## _tz2);\
+ PREFIX ## _total_time_us += ((PREFIX ## _tv2.tv_sec - PREFIX ## _tv1.tv_sec) * 1000000 + (PREFIX ## _tv2.tv_usec - PREFIX ## _tv1.tv_usec));\
+ PREFIX ## _total_iterations++;\
+ PREFIX ## _n_running_timer--
+
+#define QPERF_END_AND_START(PREFIX) \
+ gettimeofday(&PREFIX ## _tv2, &PREFIX ## _tz2);\
+ PREFIX ## _total_time_us += ((PREFIX ## _tv2.tv_sec - PREFIX ## _tv1.tv_sec) * 1000000 + (PREFIX ## _tv2.tv_usec - PREFIX ## _tv1.tv_usec));\
+ PREFIX ## _total_iterations++;\
+ PREFIX ## _tv1 = PREFIX ## _tv2;\
+ PREFIX ## _tz1 = PREFIX ## _tz2;\
+ PREFIX ## _n_running_timer--
+
+#define QPERF_TIME(PREFIX, FN)\
+ QPERF_START(PREFIX); \
+ FN; \
+ QPERF_END(PREFIX)
+
+#define QPERF_SET_ITERATION(PREFIX, N) \
+ PREFIX ## _total_iterations = N
+
+#define QPERF_TERMINATE(PREFIX) \
+ QTV_PERF_MSG_PRIO1(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "Statistic of %s\n", #PREFIX);\
+ QTV_PERF_MSG_PRIO(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "============================================================\n");\
+ QTV_PERF_MSG_PRIO1(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "Total number of iteration %d\n", PREFIX ## _total_iterations);\
+ QTV_PERF_MSG_PRIO2(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "%s total_time(us): %30lld\n",#PREFIX, (PREFIX ## _total_time_us));\
+ if (0 != PREFIX ## _total_iterations) {QTV_PERF_MSG_PRIO2(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "%s average_time/iteration(us): %30lld\n",#PREFIX, (PREFIX ## _total_time_us)/(PREFIX ## _total_iterations));}\
+ if (0 != PREFIX ## _total_time_us) {QTV_PERF_MSG_PRIO2(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "%s frame per second: %.2f\n",#PREFIX, (double)(PREFIX ## _total_iterations)/(PREFIX ## _total_time_us)*1000000);}\
+ QTV_PERF_MSG_PRIO(QTVDIAG_STATISTICS, QTVDIAG_PRIO_DEBUG, "============================================================\n");
+
+#else
+#define QPERF_INIT(PREFIX)
+#define QPERF_RESET(PREFIX) do {} while (0)
+#define QPERF_START(PREFIX) do {} while (0)
+#define QPERF_END(PREFIX) do {} while (0)
+#define QPERF_TIME(PREFIX, FN) FN
+#define QPERF_END_AND_START(PREFIX) do {} while (0)
+#define QPERF_SET_ITERATION(PREFIX, N) do {} while (0)
+#define QPERF_TERMINATE(PREFIX) do {} while (0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _QUTILITY_H_ */
diff --git a/omx/mm-video/qdsp6/vdec/src/vdec.cpp b/omx/mm-video/qdsp6/vdec/src/vdec.cpp
new file mode 100644
index 0000000..283b337
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/vdec.cpp
@@ -0,0 +1,1253 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include "semaphore.h"
+#include "OMX_QCOMExtns.h"
+
+extern "C" {
+#include "pmem.h"
+#include <linux/msm_q6vdec.h>
+#include "adsp.h"
+}
+#include "qtv_msg.h"
+#include "qutility.h"
+#include "vdec.h"
+#ifdef T_WINNT
+#define LOG_YUV_FRAMES 1
+#define LOG_INPUT_BUFFERS 1
+#else
+#define LOG_YUV_FRAMES 0
+#define LOG_INPUT_BUFFERS 0
+#endif
+
+#define DEBUG_ON 0
+#define Q6_VDEC_PAGE_SIZE 0x1000
+#define Q6_VDEC_PAGE_MASK (~(Q6_VDEC_PAGE_SIZE-1))
+#define Q6_VDEC_PAGE_ALIGN(addr) (((addr) + Q6_VDEC_PAGE_SIZE - 1) & Q6_VDEC_PAGE_MASK)
+#define MAKEFOURCC(ch0,ch1,ch2,ch3) ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
+static void vdec_frame_cb_handler(void *vdec_context,
+ struct Vdec_FrameDetailsType *pFrame);
+static void vdec_reuse_input_cb_handler(void *vdec_context, void *buffer_id);
+
+#define VDEC_INPUT_BUFFER_SIZE 450 * 1024
+#define VDEC_NUM_INPUT_BUFFERS 8
+#define VDEC_MAX_SEQ_HEADER_SIZE 300
+
+struct Vdec_pthread_info {
+ pthread_mutex_t in_buf_lock;
+ pthread_mutex_t out_buf_lock;
+ sem_t flush_sem;
+} Vdec_pthread_info;
+
+QPERF_INIT(arm_decode);
+
+#if LOG_YUV_FRAMES
+FILE *pYUVFile=NULL;
+#endif /* LOG_YUV_FRAMES */
+
+#if LOG_INPUT_BUFFERS
+FILE *pInputFile=NULL;
+static int counter = 0;
+#endif /* LOG_INPUT_BUFFERS */
+
+int timestamp = 0;
+
+static int getExtraDataSize()
+{
+ int extraSize =
+ ((OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO)+3) & (~3)) + ((OMX_EXTRADATA_HEADER_SIZE+sizeof(OMX_QCOM_EXTRADATA_CODEC_DATA)+3) & (~3)) + ((OMX_EXTRADATA_HEADER_SIZE+sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION)+3) & (~3))+(OMX_EXTRADATA_HEADER_SIZE + 4); return extraSize;
+}
+
+void vdec_frame_cb_handler(void *vdec_context,
+ struct Vdec_FrameDetailsType *pFrame,
+ unsigned int fd, unsigned int offset)
+{
+ int index;
+ struct VDecoder *dec;
+ static unsigned int nFrameDoneCnt = 0;
+ static unsigned int nGoodFrameCnt = 0;
+ struct Vdec_pthread_info *pthread_info;
+
+ dec = (struct VDecoder *)vdec_context;
+
+ if (NULL == pFrame || dec == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: pFrame or dec parameter is NULL, dropping frame\n");
+ return;
+ }
+
+ if (NULL == dec->ctxt || NULL == dec->ctxt->outputBuffer
+ || NULL == dec->ctxt->frame_done) {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: dec_output or context corrupted dec_output %x, ctxt %x, "
+ "frame_done %x, dropping frame\n", dec->ctxt,
+ dec->ctxt->outputBuffer, dec->ctxt->frame_done);
+ return;
+ }
+
+ pthread_info = (struct Vdec_pthread_info *)dec->thread_specific_info;
+ ++nFrameDoneCnt;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: frame done cb cnt: %d", nFrameDoneCnt);
+ switch (pFrame->status) {
+ case VDEC_FRAME_DECODE_SUCCESS:
+ {
+
+ //Iterate through the output frame array to locate corresponding index
+ for (index = 0; index < dec->ctxt->numOutputBuffers;
+ index++) {
+ if (fd ==
+ dec->ctxt->outputBuffer[index].buffer.
+ pmem_id
+ && offset ==
+ dec->ctxt->outputBuffer[index].buffer.
+ pmem_offset) {
+ break;
+ }
+ }
+ if (dec->ctxt->numOutputBuffers == index) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "vdec: error: unable to map offset to address %x, and fd %d dropping frame\n",
+ offset, fd);
+ return;
+ } else {
+ ++nGoodFrameCnt;
+ dec->ctxt->outputBuffer[index].flags = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: callback status good frame, cnt: %d\n",
+ nGoodFrameCnt);
+
+#if LOG_YUV_FRAMES
+ if (pYUVFile) {
+ int size =
+ dec->ctxt->width *
+ dec->ctxt->height * 1.5;
+ fwritex(dec->ctxt->outputBuffer[index].
+ buffer.base, size, pYUVFile);
+ }
+#endif
+ memcpy(&dec->ctxt->outputBuffer[index].
+ frameDetails, pFrame,
+ sizeof(struct Vdec_FrameDetailsType));
+ dec->ctxt->outputBuffer[index].timestamp =
+ pFrame->timestamp;
+ pthread_mutex_lock(&pthread_info->out_buf_lock);
+ dec->ctxt->outputBuffer[index].buffer.state =
+ VDEC_BUFFER_WITH_APP;
+ pthread_mutex_unlock(&pthread_info->
+ out_buf_lock);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_HIGH,
+ "****** vdec: got the frame_done, call the frame done callback %x\n",
+ pFrame->userData1);
+ dec->ctxt->frame_done(dec->ctxt,
+ &dec->ctxt->
+ outputBuffer[index]);
+ }
+ break;
+ }
+
+ case VDEC_FLUSH_DONE:
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: callback status flush Done\n");
+ if (-1 == sem_post(&pthread_info->flush_sem)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "[readframe] - sem_post failed %d\n",
+ errno);;
+ }
+ break;
+ }
+
+ case VDEC_FRAME_DECODE_ERROR:
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: callback status decode error\n");
+ break;
+ }
+
+ case VDEC_FATAL_ERROR:
+ {
+ static struct vdec_frame vdecFrame;
+ memset(&vdecFrame, 0, sizeof(vdecFrame));
+ vdecFrame.flags |= FRAME_FATAL_ERROR;
+ dec->ctxt->frame_done(dec->ctxt, &vdecFrame);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_FATAL,
+ "vdec: callback status error fatal\n");
+ break;
+ }
+
+ case VDEC_END_OF_STREAM:
+ {
+ static struct vdec_frame vdecFrame;
+ memset(&vdecFrame, 0, sizeof(vdecFrame));
+ vdecFrame.flags |= FRAME_FLAG_EOS;
+ dec->ctxt->frame_done(dec->ctxt, &vdecFrame);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: callback status EOS\n");
+ break;
+ }
+
+ default:
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: callback status unknown status\n");
+ break;
+ }
+
+ return;
+
+}
+void vdec_reuse_input_cb_handler(void *vdec_context, void *buffer_id)
+{
+ struct VDecoder *dec;
+ struct Vdec_pthread_info *pthread_info;
+ dec = (struct VDecoder *)vdec_context;
+ if (NULL == dec || NULL == dec->ctxt || NULL == dec->ctxt->buffer_done) {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: dec_output or context corrupted dec_output %x, ctxt %x, "
+ "buffer_done %x, dropping reuse input buffer\n",
+ dec, dec->ctxt, dec->ctxt->buffer_done);
+ return;
+ }
+ pthread_info = (struct Vdec_pthread_info *)dec->thread_specific_info;
+ for (int i = 0; i < dec->ctxt->numInputBuffers; i++) {
+ if (dec->ctxt->inputBuffer[i].omx_cookie == buffer_id) {
+ pthread_mutex_lock(&pthread_info->in_buf_lock);
+ dec->ctxt->inputBuffer[i].state =
+ VDEC_BUFFER_WITH_VDEC_CORE;
+ pthread_mutex_unlock(&pthread_info->in_buf_lock);
+ dec->ctxt->buffer_done(dec->ctxt,
+ dec->ctxt->inputBuffer[i].
+ omx_cookie);
+ break;
+ }
+
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: got reuse input buffer\n");
+}
+
+Vdec_ReturnType vdec_close(struct VDecoder *dec)
+{
+ unsigned int i = 0;
+ struct Vdec_pthread_info *pthread_info;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "vdec: vdec_close()\n");
+
+ if (dec == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: dec parameter is NULL, bailing out\n");
+ return VDEC_EFAILED;
+ }
+
+ pthread_info = (struct Vdec_pthread_info *)dec->thread_specific_info;
+
+#if LOG_YUV_FRAMES
+ if (pYUVFile) {
+ fclose(pYUVFile);
+ pYUVFile = NULL;
+ }
+#endif
+#if LOG_INPUT_BUFFERS
+ if (pInputFile) {
+ fclose(pInputFile);
+ pInputFile=NULL;
+ }
+#endif
+ dec->is_commit_memory = 0;
+ adsp_close((struct adsp_module *)dec->adsp_module);
+ free(dec->ctxt->inputBuffer);
+ free(dec->ctxt->outputBuffer);
+ dec->ctxt->outputBuffer =NULL;
+ dec->ctxt->inputBuffer =NULL;
+ if (-1 == sem_destroy(&pthread_info->flush_sem)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "[vdec_close] - sem_destroy failed %d\n", errno);
+ }
+ pthread_mutex_destroy(&pthread_info->in_buf_lock);
+ pthread_mutex_destroy(&pthread_info->out_buf_lock);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "vdec: Free pmem\n");
+ for (i = 0; i < dec->pmem_buffers; i++) {
+ pmem_free(&dec->arena[i]);
+ }
+ free(dec->arena);
+ free(dec->thread_specific_info);
+ free(dec);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "vdec: closed\n");
+ return VDEC_SUCCESS;
+}
+
+Vdec_ReturnType vdec_get_input_buf_requirements(struct VDecoder_buf_info *
+ buf_req)
+{
+ if (NULL == buf_req) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec_get_input_buf_requirements: Null parameter\n");
+ return VDEC_EFAILED;
+ }
+
+ buf_req->buffer_size = VDEC_INPUT_BUFFER_SIZE;
+ buf_req->numbuf = VDEC_NUM_INPUT_BUFFERS;
+ return VDEC_SUCCESS;
+}
+
+Vdec_ReturnType vdec_allocate_input_buffer(unsigned int size,
+ Vdec_BufferInfo * buf, int is_pmem)
+{
+ int bufin_size, bufout_size, in_offset, out_offset, total_size;
+ unsigned off;
+ byte *ipBuffer;
+ int n;
+ int page_size = sysconf(_SC_PAGESIZE);
+ if (buf == NULL || size <= 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Invalid argument allocate buffer\n");
+ return VDEC_EFAILED;
+ }
+ if (is_pmem) {
+ struct pmem pmem_data;
+
+ pmem_data.fd = -1;
+ pmem_data.size = (size + page_size - 1) & (~(page_size - 1));;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Allocating input buffer from pmem\n");
+ if (-1 == pmem_alloc(&pmem_data, pmem_data.size)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "pmem allocation failed\n");
+ return VDEC_EFAILED;
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Allocated input buffer from pmem size %d\n",
+ pmem_data.size);
+
+ buf->base = (byte *) pmem_data.data;
+ buf->pmem_id = pmem_data.fd;
+ buf->bufferSize = pmem_data.size;
+ buf->pmem_offset = 0;
+ buf->state = VDEC_BUFFER_WITH_APP;
+ } else {
+ byte *data = NULL;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Allocating input buffer from heap\n");
+ data = (byte *) malloc(size * sizeof(byte));
+ if (data == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "heap allocation failed\n");
+ return VDEC_EFAILED;
+ }
+ buf->base = data;
+ buf->bufferSize = size;
+ buf->state = VDEC_BUFFER_WITH_APP;
+
+ }
+ return VDEC_SUCCESS;
+}
+
+Vdec_ReturnType vdec_free_input_buffer(Vdec_BufferInfo * buf_info, int is_pmem)
+{
+ int i;
+ if (NULL == buf_info || buf_info->base == NULL) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Invalid buffer to free\n");
+ return VDEC_EFAILED;
+ }
+ if (is_pmem) {
+ struct pmem pmem_data;
+ pmem_data.data = buf_info->base;
+ pmem_data.fd = buf_info->pmem_id;
+ pmem_data.size = buf_info->bufferSize;
+ pmem_free(&pmem_data);
+ } else {
+ free(buf_info->base);
+ }
+ return VDEC_SUCCESS;
+
+}
+
+Vdec_ReturnType vdec_commit_memory(struct VDecoder * dec)
+{
+ unsigned off;
+ int n;
+ int r;
+ int pmemid, pmembuf_cnt;
+ void *pmem_buf;
+ int bufnum, bufsize, total_out_size = 0, extraSize = 0, total_set_buffers =
+ 0;
+ int bufin_size, bufout_size = 0, bufdec1_size, bufdec2_size, in_offset,
+ out_offset, dec1_offset, total_size, dec2_offset;
+ struct adsp_buffer_info adsp_buf_info;
+ struct pmem arena;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec commit memory 0x%x\n", dec);
+
+ int page_size = sysconf(_SC_PAGESIZE);
+
+ if (dec->ctxt->inputBuffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec commit memory OMC allocated input buffer\n");
+ dec->ctxt->outputBuffer =
+ (struct vdec_frame *)malloc(sizeof(struct vdec_frame) *
+ dec->ctxt->outputReq.
+ numMinBuffers);
+
+ if (NULL == dec->ctxt->outputBuffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate output buffers\n");
+ return VDEC_EFAILED;
+ }
+
+ dec->pmem_buffers = 1;
+
+ dec->arena =
+ (struct pmem *)malloc(sizeof(struct pmem) *
+ dec->pmem_buffers);
+ if (NULL == dec->arena) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate output buffers\n");
+ free(dec->ctxt->outputBuffer);
+ return VDEC_EFAILED;
+ }
+
+ pmembuf_cnt = 0;
+
+ extraSize = getExtraDataSize();
+
+ dec->ctxt->nOutBufAllocLen =
+ dec->ctxt->outputReq.bufferSize + extraSize;
+ //dec->ctxt->nOutBufAllocLen = dec->ctxt->outputReq.bufferSize ;
+ bufout_size =
+ Q6_VDEC_PAGE_ALIGN(dec->ctxt->outputReq.bufferSize +
+ extraSize);
+ total_out_size =
+ Q6_VDEC_PAGE_ALIGN(bufout_size *
+ dec->ctxt->outputReq.numMinBuffers);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: Commit: out buf size %d and tot out size %d\n", bufout_size, total_out_size);
+ bufdec1_size = 0;
+ if (dec->decReq1.numMinBuffers) {
+ bufdec1_size =
+ dec->decReq1.numMinBuffers *
+ dec->decReq1.bufferSize;
+ }
+
+ bufdec2_size = 0;
+ if (dec->decReq2.numMinBuffers) {
+ bufdec2_size =
+ dec->decReq2.numMinBuffers *
+ dec->decReq2.bufferSize;
+ }
+
+ out_offset = 0;
+ dec1_offset = Q6_VDEC_PAGE_ALIGN(out_offset + total_out_size);
+ dec2_offset = Q6_VDEC_PAGE_ALIGN(dec1_offset + bufdec1_size);
+ total_size = dec2_offset + bufdec2_size;
+ total_size = (total_size + page_size - 1) & (~(page_size - 1));
+
+ if (pmem_alloc(&arena, total_size)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate input pmem arena (%d bytes)\n",
+ total_size);
+ return VDEC_EFAILED;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: allocated %d bytes of input pmem\n",
+ total_size);
+ dec->arena[pmembuf_cnt].data = arena.data;
+ dec->arena[pmembuf_cnt].fd = arena.fd;
+ dec->arena[pmembuf_cnt].phys = arena.phys;
+ dec->arena[pmembuf_cnt].size = arena.size;
+
+ for (n = 0; n < dec->ctxt->numInputBuffers; n++) {
+ struct Vdec_BufferInfo *fr = dec->ctxt->inputBuffer + n;
+ adsp_buf_info.buf.pmem_id = fr->pmem_id;
+ adsp_buf_info.buf.offset = fr->pmem_offset;
+ adsp_buf_info.buf.size = fr->bufferSize;
+ adsp_buf_info.buf_type = ADSP_BUFFER_TYPE_INPUT;
+ adsp_buf_info.numbuf = 1;
+ adsp_buf_info.is_last =
+ (n == (dec->ctxt->numInputBuffers - 1));
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ " input[%d] base=%p off=0x%08x id=%d\n",
+ n, fr->base, fr->pmem_offset,
+ fr->pmem_id);
+ if (adsp_set_buffers
+ ((struct adsp_module *)dec->adsp_module,
+ adsp_buf_info)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,
+ QTVDIAG_PRIO_ERROR,
+ "vdec: failed to set adsp buffers");
+ return VDEC_EFAILED;
+ }
+ }
+
+ } else {
+ dec->ctxt->inputBuffer =
+ (struct Vdec_BufferInfo *)
+ malloc(sizeof(struct Vdec_BufferInfo) *
+ dec->ctxt->inputReq.numMinBuffers);
+ if (NULL == dec->ctxt->inputBuffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate Input buffers\n");
+ return VDEC_EFAILED;
+ }
+
+ dec->pmem_buffers = 1;
+
+ dec->arena =
+ (struct pmem *)malloc(sizeof(struct pmem) *
+ dec->pmem_buffers);
+ if (NULL == dec->arena) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate output buffers\n");
+ free(dec->ctxt->inputBuffer);
+ return VDEC_EFAILED;
+ }
+ extraSize = getExtraDataSize();
+
+ if(NULL == dec->ctxt->outputBuffer ) {
+ dec->ctxt->outputBuffer =
+ (struct vdec_frame *)malloc(sizeof(struct vdec_frame) *
+ dec->ctxt->outputReq.
+ numMinBuffers);
+
+ if (NULL == dec->ctxt->outputBuffer) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate output buffers\n");
+ free(dec->ctxt->inputBuffer);
+ free(dec->arena);
+ return VDEC_EFAILED;
+ }
+ bufout_size =
+ Q6_VDEC_PAGE_ALIGN(dec->ctxt->outputReq.bufferSize +
+ extraSize);
+ total_out_size =
+ Q6_VDEC_PAGE_ALIGN(bufout_size *
+ dec->ctxt->outputReq.numMinBuffers);
+ }
+
+ bufin_size =
+ dec->ctxt->inputReq.numMinBuffers *
+ dec->ctxt->inputReq.bufferSize;
+ pmembuf_cnt = 0;
+ dec->ctxt->numInputBuffers = dec->ctxt->inputReq.numMinBuffers;
+
+
+ dec->ctxt->nOutBufAllocLen =
+ dec->ctxt->outputReq.bufferSize + extraSize;
+ //dec->ctxt->nOutBufAllocLen = dec->ctxt->outputReq.bufferSize ;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: Commit: out buf size %d and tot out size %d\n", bufout_size, total_out_size);
+
+ bufdec1_size = 0;
+ if (dec->decReq1.numMinBuffers) {
+ bufdec1_size =
+ dec->decReq1.numMinBuffers *
+ dec->decReq1.bufferSize;
+ }
+
+ bufdec2_size = 0;
+ if (dec->decReq2.numMinBuffers) {
+ bufdec2_size =
+ dec->decReq2.numMinBuffers *
+ dec->decReq2.bufferSize;
+ }
+
+ out_offset = bufin_size;
+ out_offset = Q6_VDEC_PAGE_ALIGN(out_offset);
+ dec1_offset = Q6_VDEC_PAGE_ALIGN(out_offset + total_out_size);
+ dec2_offset = Q6_VDEC_PAGE_ALIGN(dec1_offset + bufdec1_size);
+ total_size = dec2_offset + bufdec2_size;
+ total_size = (total_size + page_size - 1) & (~(page_size - 1));
+ if (pmem_alloc(&arena, total_size)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to allocate input pmem arena (%d bytes)\n",
+ total_size);
+ return VDEC_EFAILED;
+ }
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: allocated %d bytes of input pmem\n",
+ total_size);
+ dec->arena[pmembuf_cnt].data = arena.data;
+ dec->arena[pmembuf_cnt].fd = arena.fd;
+ dec->arena[pmembuf_cnt].phys = arena.phys;
+ dec->arena[pmembuf_cnt].size = arena.size;
+
+ off = 0;
+ for (n = 0; n < dec->ctxt->inputReq.numMinBuffers; n++) {
+ struct Vdec_BufferInfo *fr = dec->ctxt->inputBuffer + n;
+ fr->pmem_id = dec->arena[pmembuf_cnt].fd;
+ fr->pmem_offset = off;
+ fr->base =
+ ((byte *) dec->arena[pmembuf_cnt].data) + off;
+ fr->bufferSize = dec->ctxt->inputReq.bufferSize;
+ off += dec->ctxt->inputReq.bufferSize;
+ fr->state = VDEC_BUFFER_WITH_VDEC_CORE;
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ " input[%d] base=%p off=0x%08x id=%d\n",
+ n, fr->base, fr->pmem_offset,
+ fr->pmem_id);
+ }
+ adsp_buf_info.buf.pmem_id = dec->arena[pmembuf_cnt].fd;
+ adsp_buf_info.buf.offset = 0;
+ adsp_buf_info.buf.size = bufin_size;
+ adsp_buf_info.buf_type = ADSP_BUFFER_TYPE_INPUT;
+ adsp_buf_info.numbuf = dec->ctxt->inputReq.numMinBuffers;
+ adsp_buf_info.is_last = 1;
+
+ if (adsp_set_buffers
+ ((struct adsp_module *)dec->adsp_module, adsp_buf_info)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to set adsp buffers");
+ return VDEC_EFAILED;
+ }
+ }
+
+ off = out_offset;
+ for (n = 0; n < dec->ctxt->outputReq.numMinBuffers; n++) {
+ struct vdec_frame *fr = NULL;
+ fr = dec->ctxt->outputBuffer + n;
+ if(bufout_size > 0) {
+ fr->buffer.pmem_id = dec->arena[pmembuf_cnt].fd;
+ fr->buffer.pmem_offset = off;
+ fr->buffer.base = ((byte *) dec->arena[pmembuf_cnt].data) + off;
+ fr->buffer.state = VDEC_BUFFER_WITH_APP_FLUSHED;
+ off += bufout_size;
+ }
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ " output[%d] base=%p off=0x%08x id=%d\n", n,
+ fr->buffer.base, fr->buffer.pmem_offset,
+ fr->buffer.pmem_id);
+
+ adsp_buf_info.buf.pmem_id = fr->buffer.pmem_id;
+ adsp_buf_info.buf.offset = fr->buffer.pmem_offset;
+ adsp_buf_info.buf.size = dec->ctxt->outputReq.bufferSize;
+ adsp_buf_info.buf_type = ADSP_BUFFER_TYPE_OUTPUT;
+ adsp_buf_info.numbuf = 1;
+ adsp_buf_info.is_last =
+ ((n == (dec->ctxt->outputReq.numMinBuffers - 1)) ? 1 : 0);
+ if (adsp_set_buffers
+ ((struct adsp_module *)dec->adsp_module, adsp_buf_info)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to set adsp buffers");
+ return VDEC_EFAILED;
+ }
+ }
+
+ if (dec->decReq1.numMinBuffers) {
+ adsp_buf_info.buf.pmem_id = dec->arena[pmembuf_cnt].fd;
+ adsp_buf_info.buf.offset = dec1_offset;
+ adsp_buf_info.buf.size = bufdec1_size;
+ adsp_buf_info.buf_type = ADSP_BUFFER_TYPE_INTERNAL1;
+ adsp_buf_info.numbuf = dec->decReq1.numMinBuffers;
+ adsp_buf_info.is_last = 1;
+
+ if (adsp_set_buffers
+ ((struct adsp_module *)dec->adsp_module, adsp_buf_info)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to set adsp buffers");
+ return VDEC_EFAILED;
+ }
+ }
+
+ if (dec->decReq2.numMinBuffers) {
+ adsp_buf_info.buf.pmem_id = dec->arena[pmembuf_cnt].fd;
+ adsp_buf_info.buf.offset = dec2_offset;
+ adsp_buf_info.buf.size = bufdec2_size;
+ adsp_buf_info.buf_type = ADSP_BUFFER_TYPE_INTERNAL2;
+ adsp_buf_info.numbuf = dec->decReq2.numMinBuffers;
+ adsp_buf_info.is_last = 1;
+ if (adsp_set_buffers
+ ((struct adsp_module *)dec->adsp_module, adsp_buf_info)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: failed to set adsp buffers");
+ return VDEC_EFAILED;
+ }
+ }
+ dec->is_commit_memory = 1;
+ return VDEC_SUCCESS;
+}
+struct VDecoder *vdec_open(struct vdec_context *ctxt)
+{
+
+ struct VDecoder *dec;
+ int r;
+ int fd;
+ struct adsp_open_info openinfo;
+ struct adsp_init init;
+ struct adsp_buf_req buf;
+ struct Vdec_pthread_info *pthread_info;
+ dec = (VDecoder *) calloc(1, sizeof(struct VDecoder));
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "vdec_open\n");
+ if (!dec)
+ return 0;
+
+ pthread_info =
+ (struct Vdec_pthread_info *)
+ malloc(sizeof(struct Vdec_pthread_info));
+
+ if (!pthread_info) {
+ free(dec);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec_open failed while allocating memory for pthread_info\n");
+ return 0;
+ }
+ sem_init(&pthread_info->flush_sem, 0, 0);
+ pthread_mutex_init(&pthread_info->in_buf_lock, 0);
+ pthread_mutex_init(&pthread_info->out_buf_lock, 0);
+
+ dec->thread_specific_info = (void *)pthread_info;
+ dec->ctxt = ctxt;
+ dec->is_commit_memory = 0;
+
+ openinfo.frame_done = vdec_frame_cb_handler;
+ openinfo.buffer_done = vdec_reuse_input_cb_handler;
+
+ dec->adsp_module =
+ (void *)adsp_open("/dev/vdec", openinfo, (void *)dec, dec->ctxt->vdec_fd );
+
+ if (NULL == dec->adsp_module) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Adsp Open Failed\n");
+ goto fail_open;
+ }
+
+ init.seq_header = dec->ctxt->sequenceHeader;
+ init.seq_len = dec->ctxt->sequenceHeaderLen;
+ if(init.seq_len > VDEC_MAX_SEQ_HEADER_SIZE)
+ init.seq_len = VDEC_MAX_SEQ_HEADER_SIZE;
+ init.width = dec->ctxt->width;
+
+ init.height = dec->ctxt->height;
+ init.order = 1;
+ init.fourcc = dec->ctxt->fourcc;
+ init.notify_enable = 1;
+ init.h264_nal_len_size = dec->ctxt->size_of_nal_length_field;
+ init.h264_startcode_detect = 0;
+ if (!dec->ctxt->size_of_nal_length_field) {
+ init.h264_startcode_detect = 1;
+ }
+ init.postproc_flag = dec->ctxt->postProc;
+ init.vc1_rowbase = dec->ctxt->vc1Rowbase;
+ init.fruc_enable = 0;
+ init.color_format = 0;
+ if (dec->ctxt->color_format ==
+ QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Open setting color format to yamato \n");
+ init.color_format = ADSP_COLOR_FORMAT_NV21_YAMATO;
+ }
+ init.buf_req = &buf;
+
+ if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.avc")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening H264 Decoder \n");
+ init.order = 0;
+ } else if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.mpeg4")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening MPEG4 Decoder \n");
+ init.order = 0;
+ } else if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.divx")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening Divx Decoder \n");
+ init.order = 1;
+ }else if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.h263")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening H263 Decoder \n");
+ init.order = 0;
+ } else if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.vc1")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening VC1 Decoder \n");
+ init.order = 0;
+ }else if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.vp")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening VP6 Decoder \n");
+ init.order = 0;
+ } else if (!strcmp(dec->ctxt->kind, "OMX.qcom.video.decoder.spark")) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: Opening Spark Decoder \n");
+ init.order = 0;
+ } else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Incorrect codec kind\n");
+ goto fail_initialize;
+ }
+
+ if (adsp_init((struct adsp_module *)dec->adsp_module, &init) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Adsp Open Failed\n");
+ goto fail_initialize;
+ }
+
+ QPERF_RESET(arm_decode);
+
+ timestamp = 0;
+
+ dec->ctxt->inputReq.numMinBuffers = init.buf_req->input.bufnum_min;
+ dec->ctxt->inputReq.numMaxBuffers = init.buf_req->input.bufnum_max;
+ dec->ctxt->inputReq.bufferSize = init.buf_req->input.bufsize;
+
+ dec->ctxt->outputReq.numMinBuffers = init.buf_req->output.bufnum_min;
+ dec->ctxt->outputReq.numMaxBuffers = init.buf_req->output.bufnum_max;
+ dec->ctxt->outputReq.bufferSize = init.buf_req->output.bufsize;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_open input numbuf= %d and bufsize= %d\n",
+ dec->ctxt->inputReq.numMinBuffers,
+ dec->ctxt->inputReq.bufferSize);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_open output numbuf= %d and bufsize= %d\n",
+ dec->ctxt->outputReq.numMinBuffers,
+ dec->ctxt->outputReq.bufferSize);
+ dec->decReq1.numMinBuffers = init.buf_req->dec_req1.bufnum_min;
+ dec->decReq1.numMaxBuffers = init.buf_req->dec_req1.bufnum_max;
+ dec->decReq1.bufferSize = init.buf_req->dec_req1.bufsize;
+ dec->decReq2.numMinBuffers = init.buf_req->dec_req2.bufnum_min;
+ dec->decReq2.numMaxBuffers = init.buf_req->dec_req2.bufnum_max;
+ dec->decReq2.bufferSize = init.buf_req->dec_req2.bufsize;
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_open decoder1 numbuf= %d and bufsize= %d\n",
+ dec->decReq1.numMinBuffers, dec->decReq1.bufferSize);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_open ointernal 2 numbuf= %d and bufsize= %d\n",
+ dec->decReq2.numMinBuffers,
+ dec->decReq2.bufferSize);
+ dec->ctxt->numOutputBuffers =
+ dec->ctxt->outputReq.numMinBuffers;
+
+#if LOG_YUV_FRAMES
+#ifdef T_WINNT
+ pYUVFile = fopen("../debug/yuvframes.yuv", "wb");
+#elif _ANDROID_
+ pYUVFile = fopen("/data/yuvframes.yuv", "wb");
+#else
+ pYUVFile = fopen("yuvframes.yuv", "wb");
+#endif
+ if(!pYUVFile) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: error: Unable to open file to log YUV frames.");
+ }
+#endif /* LOG_YUV_FRAMES */
+
+#if LOG_INPUT_BUFFERS
+#ifdef T_WINNT
+ pInputFile = fopen("../debug/inputbuffers.264", "wb");
+#elif _ANDROID_
+ pInputFile = fopen("/data/inputbuffers.264", "wb");
+#else
+ pInputFile = fopen("inputbuffers.264", "wb");
+#endif
+ if(!pInputFile) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: error: Unable to open file to log Input buffers.");
+ }
+
+#endif /* LOG_INPUT_BUFFERS */
+
+ return dec;
+
+fail_initialize:
+ adsp_close((struct adsp_module *)dec->adsp_module);
+fail_open:
+ free(dec);
+ free(pthread_info);
+ return 0;
+}
+
+Vdec_ReturnType vdec_post_input_buffer(struct VDecoder * dec,
+ video_input_frame_info * frame,
+ void *cookie, int is_pmem)
+{
+ QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: post_input data=%p len=%d %x cookie=%p\n",
+ frame->data, frame->len, frame->len, cookie);
+
+#if DEBUG_ON
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_post_input_buffer, length %d\n", frame->len);
+ for (uint32 i = 0; i < 32; i++) {
+ printf("0x%.2x ", ((uint8 *) (frame->data))[i]);
+ if (i % 16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+
+ adsp_input_buf input;
+ int buf_index, i;
+ struct Vdec_pthread_info *pthread_info;
+ unsigned int copy_size;
+
+ buf_index = -1;
+
+ if (NULL == dec || NULL == frame || NULL == frame->data) {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: error: encountered NULL parameter dec: 0x%x frame: 0x%x data: 0x%x\n",
+ (unsigned int)dec, (unsigned int)frame,
+ (unsigned int)frame->data);
+ return VDEC_EFAILED;
+ }
+
+ if (dec->ctxt->outputBuffer) {
+ for (i = 0; i < dec->ctxt->numOutputBuffers; i++) {
+ if (dec->ctxt->outputBuffer[i].buffer.state ==
+ VDEC_BUFFER_WITH_HW) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_post available free output buffer %d\n",
+ i);
+ break;
+ }
+ }
+ if (i >= dec->ctxt->numOutputBuffers) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_post output buffer not avilable for decode \n");
+ return VDEC_EOUTOFBUFFERS;
+ }
+ }
+
+ pthread_info = (struct Vdec_pthread_info *)dec->thread_specific_info;
+
+ if (is_pmem == 0) {
+ if (dec->ctxt->inputBuffer) {
+ for (i = 0; i < dec->ctxt->inputReq.numMinBuffers; i++) {
+ if (dec->ctxt->inputBuffer[i].state ==
+ VDEC_BUFFER_WITH_VDEC_CORE) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: got input buffer index %d\n",
+ i);
+ pthread_mutex_lock(&pthread_info->in_buf_lock);
+ dec->ctxt->inputBuffer[i].state =
+ VDEC_BUFFER_WITH_HW;
+ pthread_mutex_unlock(&pthread_info->
+ in_buf_lock);
+ buf_index = i;
+ break;
+ }
+ }
+ }
+ } else {
+ for (i = 0; i < dec->ctxt->numInputBuffers; i++) {
+ if ((frame->data >= dec->ctxt->inputBuffer[i].base) &&
+ (frame->data <
+ (dec->ctxt->inputBuffer[i].base +
+ dec->ctxt->inputBuffer[i].bufferSize))) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: got input buffer index %d\n",
+ i);
+ pthread_mutex_lock(&pthread_info->in_buf_lock);
+ dec->ctxt->inputBuffer[i].state =
+ VDEC_BUFFER_WITH_HW;
+ pthread_mutex_unlock(&pthread_info->
+ in_buf_lock);
+ buf_index = i;
+ break;
+ }
+ }
+
+ }
+
+ if (buf_index < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "Wrong Input buffer and not able to get the buffer Index\n");
+ return VDEC_EOUTOFBUFFERS;
+ }
+#if LOG_INPUT_BUFFERS
+ if(pInputFile) {
+ fwritex((uint8 *) frame->data, frame->len, pInputFile);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: input buffer %d len %d\n", counter++, frame->len);
+ }
+
+#endif
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: inputBuffer[].base %x, buffer size %d\n",
+ dec->ctxt->inputBuffer[buf_index].base,
+ dec->ctxt->inputBuffer[buf_index].bufferSize);
+ copy_size = frame->len;
+ if (!is_pmem) {
+ copy_size =
+ ((dec->ctxt->inputBuffer[buf_index].bufferSize >=
+ frame->len) ? frame->len : dec->ctxt->
+ inputBuffer[buf_index].bufferSize);
+ memcpy(dec->ctxt->inputBuffer[buf_index].base,
+ (uint8 *) frame->data, (uint32) copy_size);
+ input.offset = dec->ctxt->inputBuffer[buf_index].pmem_offset;
+ } else {
+ input.offset =
+ (byte *) frame->data -
+ dec->ctxt->inputBuffer[buf_index].base;
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "cookie %d\tbuf_index %d\n", (int)cookie, buf_index);
+ dec->ctxt->inputBuffer[buf_index].omx_cookie = cookie;
+ input.pmem_id = dec->ctxt->inputBuffer[buf_index].pmem_id;
+ input.timestamp_lo = (int32) (frame->timestamp & 0x00000000FFFFFFFFLL);
+ input.timestamp_hi =
+ (int32) ((frame->timestamp & 0xFFFFFFFF00000000LL) >> 32);
+ input.size = (uint32) copy_size;
+ input.data = (uint32) (dec->ctxt->inputBuffer[buf_index].omx_cookie);
+ input.flags = frame->flags;
+ //RAJESH: TBD below
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: input->size %d, input->offset %x\n", input.size,
+ input.offset);
+ //input.avsync_state
+
+#ifdef USE_PMEM_ADSP_CACHED
+ //Flush/clean the cache (bit-stream data sent to driver)
+ vdec_cachemaint(input.pmem_id, dec->ctxt->inputBuffer[buf_index].base, copy_size, PMEM_CACHE_FLUSH);
+#endif
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: received ts: %lld",
+ frame->timestamp);
+ if (frame->timestamp < timestamp) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: error: out of order stamp! %d < %d\n",
+ (int)(frame->timestamp & 0xFFFFFFFF), timestamp);
+ }
+ timestamp = (int)frame->timestamp;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec: vdec_core_post_input. buffer_size[0]: %ld frame->flags: 0x%x\n",
+ input.size, frame->flags);
+
+ if (input.size == 0 && frame->flags & FRAME_FLAG_EOS) {
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: Zero-length buffer with EOS bit set\n");
+
+ pthread_mutex_lock(&pthread_info->in_buf_lock);
+ dec->ctxt->inputBuffer[i].state = VDEC_BUFFER_WITH_VDEC_CORE;
+ pthread_mutex_unlock(&pthread_info->in_buf_lock);
+
+ if (adsp_post_input_buffer
+ ((struct adsp_module *)dec->adsp_module, input, 1) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: Post Input Buffer Failed\n");
+ return VDEC_EFAILED;
+ }
+ dec->ctxt->buffer_done(dec->ctxt, cookie);
+ return VDEC_SUCCESS;
+
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: vdec_core_post_input\n");
+
+ QPERF_START(arm_decode);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
+ "vdec: queue frame (ioctl) \n");
+
+ if (adsp_post_input_buffer
+ ((struct adsp_module *)dec->adsp_module, input, 0) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: Post Input Buffer Failed\n");
+ pthread_mutex_lock(&pthread_info->in_buf_lock);
+ dec->ctxt->inputBuffer[i].state = VDEC_BUFFER_WITH_VDEC_CORE;
+ pthread_mutex_unlock(&pthread_info->in_buf_lock);
+ dec->ctxt->buffer_done(dec->ctxt,cookie);
+ return VDEC_EFAILED;
+ }
+
+ if (frame->flags & FRAME_FLAG_EOS) {
+ if (adsp_post_input_buffer
+ ((struct adsp_module *)dec->adsp_module, input, 1) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: Post Input Buffer EOS Failed\n");
+ return VDEC_EFAILED;
+ }
+
+ }
+
+ return VDEC_SUCCESS;
+}
+
+Vdec_ReturnType vdec_release_frame(struct VDecoder * dec,
+ struct vdec_frame * frame)
+{
+ unsigned int buf, i;
+ struct Vdec_pthread_info *pthread_info;
+ int buf_index = -1;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: release_frame %p\n", frame);
+ if (NULL == dec || NULL == frame) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: ERROR: encountered NULL parameter vdec: 0x%x frame: 0x%x",
+ (unsigned int)dec, (unsigned int)frame);
+ return VDEC_EFAILED;
+ }
+ pthread_info = (struct Vdec_pthread_info *)dec->thread_specific_info;
+ for (i = 0; i < dec->ctxt->numOutputBuffers; i++) {
+ if (dec->ctxt->outputBuffer[i].buffer.base ==
+ frame->buffer.base) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: got output buffer index %d\n", i);
+ buf_index = i;
+ break;
+ }
+ }
+ if (buf_index < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec_release_frame: Wrong Output buffer and not able to get the buffer Index\n");
+ return VDEC_EFAILED;
+ }
+
+ if (dec->ctxt->outputBuffer[buf_index].buffer.state ==
+ VDEC_BUFFER_WITH_APP) {
+ pthread_mutex_lock(&pthread_info->out_buf_lock);
+ dec->ctxt->outputBuffer[buf_index].buffer.state =
+ VDEC_BUFFER_WITH_HW;
+ pthread_mutex_unlock(&pthread_info->out_buf_lock);
+ buf = frame->frameDetails.userData1;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: release_frame userData1 %d\n", buf);
+
+ if (adsp_release_frame
+ ((struct adsp_module *)dec->adsp_module, &buf) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Adsp release frame failed\n");
+ return VDEC_EFAILED;
+ }
+ } else {
+ pthread_mutex_lock(&pthread_info->out_buf_lock);
+ dec->ctxt->outputBuffer[buf_index].buffer.state =
+ VDEC_BUFFER_WITH_HW;
+ pthread_mutex_unlock(&pthread_info->out_buf_lock);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: release_frame called for Buffer not with OMX: %d",
+ dec->ctxt->outputBuffer[buf_index].buffer.state);
+ }
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
+ "vdec: released_frame with ptr: %d", buf);
+ return VDEC_SUCCESS;
+}
+
+#ifdef USE_PMEM_ADSP_CACHED
+void vdec_cachemaint(int pmem_id, void *addr, unsigned size, PMEM_CACHE_OP op)
+{
+ pmem_cachemaint(pmem_id,addr,size, op);
+}
+#endif
+
+Vdec_ReturnType vdec_flush_port(struct VDecoder * dec, int *nFlushedFrames,
+ Vdec_PortType port)
+{
+ struct Vdec_pthread_info *pthread_info;
+ int i = 0;
+ Vdec_ReturnType retVal=VDEC_SUCCESS;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "vdec: flush \n");
+ if (NULL == dec || NULL == dec->ctxt || !dec->is_commit_memory) {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "vdec: error: encountered NULL parameter vdec: 0x%x or commit memroy not called %d \n",
+ (unsigned int)dec, dec->is_commit_memory);
+ return VDEC_EFAILED;
+ }
+ pthread_info = (struct Vdec_pthread_info *)dec->thread_specific_info;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "[vdec_flush] - calling IoCTL \n");;
+
+ if (adsp_flush
+ ((struct adsp_module *)dec->adsp_module, (unsigned int)port) < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
+ "Adsp Flush failed\n");
+ retVal = VDEC_EFAILED;
+ }else{
+ /* this is to make flush a sync call*/
+ if (-1 == sem_wait(&pthread_info->flush_sem)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "[vdec_flush] - sem_wait failed %d\n", errno);;
+ }
+ }
+ /*Now release all the Input as well as Frame buffers */
+ if (dec->ctxt->inputBuffer) {
+ for (i = 0; i < dec->ctxt->inputReq.numMinBuffers; i++) {
+ if (dec->ctxt->inputBuffer[i].state ==
+ VDEC_BUFFER_WITH_HW) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_flush Flushing input buffer %d\n",
+ i);
+ pthread_mutex_lock(&pthread_info->in_buf_lock);
+ dec->ctxt->inputBuffer[i].state =
+ VDEC_BUFFER_WITH_VDEC_CORE;
+ pthread_mutex_unlock(&pthread_info->
+ in_buf_lock);
+ dec->ctxt->buffer_done(dec->ctxt,
+ dec->ctxt->
+ inputBuffer[i].
+ omx_cookie);
+
+ }
+ }
+ }
+ if (dec->ctxt->outputBuffer) {
+ for (i = 0; i < dec->ctxt->numOutputBuffers; i++) {
+ if (dec->ctxt->outputBuffer[i].buffer.state ==
+ VDEC_BUFFER_WITH_HW) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
+ "vdec_flush Flushing output buffer %d\n",
+ i);
+ pthread_mutex_lock(&pthread_info->out_buf_lock);
+ dec->ctxt->outputBuffer[i].buffer.state =
+ VDEC_BUFFER_WITH_APP_FLUSHED;
+ pthread_mutex_unlock(&pthread_info->
+ out_buf_lock);
+ dec->ctxt->outputBuffer[i].flags =
+ FRAME_FLAG_FLUSHED;
+ dec->ctxt->frame_done(dec->ctxt,
+ &dec->ctxt->
+ outputBuffer[i]);
+
+ }
+ }
+ }
+ return retVal;
+}
diff --git a/omx/mm-video/qdsp6/vdec/src/vdec.h b/omx/mm-video/qdsp6/vdec/src/vdec.h
new file mode 100644
index 0000000..902980d
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/src/vdec.h
@@ -0,0 +1,507 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*========================================================================
+
+ Video Decoder interface
+
+ *//** @file vdec.h
+ This file defines the Video decoder interface.
+
+*//*====================================================================== */
+
+#ifndef _SIMPLE_VDEC_H_
+#define _SIMPLE_VDEC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "qtypes.h"
+#include "pmem.h"
+
+/**
+ * The following are fourcc hex representations of the video
+ * codecs currently supported by the vdec core
+ */
+#define H264_FOURCC 0x61766331
+#define MPEG4_FOURCC 0x646D3476
+
+/**
+ * The following frame flags are used to provide additional
+ * input/output frame properties
+ */
+#define FRAME_FLAG_EOS 0x00000001
+#define FRAME_FLAG_FLUSHED 0x00000002
+#define FRAME_FLAGS_DECODE_ERROR 0x00000004
+#define FRAME_FATAL_ERROR 0x00000010
+
+// Post processing flags for for the ConfigParametersType */
+#define POST_PROC_QUANTIZATION 0x1
+
+ typedef enum Vdec_ReturnType {
+ VDEC_SUCCESS = 0, /* no error */
+ VDEC_EFAILED = 1, /* general failure */
+ VDEC_EOUTOFBUFFERS = 2 /* buffer not available for decode */
+ } Vdec_ReturnType;
+
+ typedef enum Vdec_PortType {
+ VDEC_FLUSH_INPUT_PORT,
+ VDEC_FLUSH_OUTPUT_PORT,
+ VDEC_FLUSH_ALL_PORT
+ } Vdec_PortType;
+/**
+ * This lists the possible status codes of the output frame.
+ */
+ typedef enum Vdec_StatusType {
+ VDEC_FRAME_DECODE_SUCCESS,
+ VDEC_FRAME_DECODE_ERROR,
+ VDEC_FATAL_ERROR,
+ VDEC_FLUSH_DONE,
+ VDEC_END_OF_STREAM,
+ VDEC_FRAME_FLUSHED, //!< Frame is flushed
+ VDEC_STREAM_SWITCHED, //!< Stream has switched
+ VDEC_SUSPEND_DONE //!< Suspend operation finished
+ } Vdec_StatusType;
+
+ typedef enum Vdec_BufferOwnerType {
+ VDEC_BUFFER_WITH_HW,
+ VDEC_BUFFER_WITH_APP,
+ VDEC_BUFFER_WITH_VDEC_CORE,
+ VDEC_BUFFER_WITH_APP_FLUSHED,
+ } Vdec_BufferOwnerType;
+
+/**
+ * This lists all the possible encoded frame types
+ */
+ typedef enum Vdec_PictureType {
+ VDEC_PICTURE_TYPE_I,
+ VDEC_PICTURE_TYPE_P,
+ VDEC_PICTURE_TYPE_B,
+ VDEC_PICTURE_TYPE_BI,
+ VDEC_PICTURE_TYPE_SKIP,
+ VDEC_PICTURE_TYPE_UNKNOWN
+ } Vdec_PictureType;
+
+/**
+ * This lists all the possible frame types
+ */
+ typedef enum Vdec_PictureFormat {
+ VDEC_PROGRESSIVE_FRAME,
+ VDEC_INTERLACED_FRAME,
+ VDEC_INTERLACED_FIELD
+ } Vdec_PictureFormat;
+
+/**
+ * This lists all the possible picture resolutions
+ */
+ typedef enum Vdec_PictureRes {
+ VDEC_PICTURE_RES_1x1,
+ VDEC_PICTURE_RES_2x1,
+ VDEC_PICTURE_RES_1x2,
+ VDEC_PICTURE_RES_2x2
+ } Vdec_PictureRes;
+
+/**
+ * This defines the structure of the pan scan parameters used in
+ * Advanced Profile Frame display
+ */
+#define MAX_VC1_PAN_SCAN_WINDOWS 4
+ typedef struct Vdec_VC1PanScanRegions {
+ int32 numWindows;
+ int32 winWidth[MAX_VC1_PAN_SCAN_WINDOWS];
+ int32 winHeight[MAX_VC1_PAN_SCAN_WINDOWS];
+ int32 winHorOffset[MAX_VC1_PAN_SCAN_WINDOWS];
+ int32 winVerOffset[MAX_VC1_PAN_SCAN_WINDOWS];
+ } Vdec_VC1PanScanRegions;
+
+ typedef struct Vdec_CroppingWindow {
+ uint32 x1; //!< Left offset
+ uint32 y1; //!< Top Offset
+ uint32 x2; //!< Right Offset
+ uint32 y2; //!< Bottom Offset
+ } Vdec_CroppingWindow;
+
+/**
+ * This structure specifies the detials of the
+ * output frame.
+ *
+ * status - Status code of the frame
+ * userData1 - User data, used internally by the decoder
+ * userData2 - uint32 representation of the associated input cookie
+ * nDecPicWidth - Width of the decoded picture
+ * nDecPicHeigh - Height of the decoded picture
+ * nDispPicWidth - Width of the picture to display
+ * nDispPicHeight - Height of the picture to display
+ * ePicType[2] - Coding type of the decoded frame (both fields)
+ * ePicFormat - Picture coding format
+ * nVC1RangeY - Scale factor for Luma Range Mapping
+ * nVC1RangeUV - Scale factor for Chroma Range Mapping
+ * ePicResolution - Scaling factor for frame wrt full resolution frame
+ * nRepeatProgFrames - Number of times frame may be repeated by display
+ * bRepeatFirstField - 1st field can be repeated after 2nd in a pair
+ * bTopFieldFirst - Field closer to top to be displayed before bottom
+ * bFrameInterpFlag - Data not suitable for inter-frame interpolation
+ * panScan - Pan scan window regions
+ * reserved1 - reserved field, should be set to 0
+ * reserved2 - reserved field, should be set to 0
+ */
+#define MAX_FIELDS 2
+ typedef struct Vdec_FrameDetailsType {
+ Vdec_StatusType status;
+ uint32 userData1;
+ uint32 userData2;
+ uint64 timestamp;
+ uint64 calculatedTimeStamp;
+ uint32 nDecPicWidth;
+ uint32 nDecPicHeight;
+ Vdec_CroppingWindow cwin;
+ Vdec_PictureType ePicType[MAX_FIELDS];
+ Vdec_PictureFormat ePicFormat;
+ uint32 nVC1RangeY;
+ uint32 nVC1RangeUV;
+ Vdec_PictureRes ePicResolution;
+ uint32 nRepeatProgFrames;
+ uint32 bRepeatFirstField;
+ uint32 bTopFieldFirst;
+ uint32 bFrameInterpFlag;
+ Vdec_VC1PanScanRegions panScan;
+ uint32 nPercentConcealedMacroblocks;
+ uint32 flags;
+ uint32 performanceStats; //!< Performance statistics returned by the decoder
+ } Vdec_FrameDetailsType;
+
+/**
+ * This structure specifies the buffer requirements of the
+ * decoder.
+ */
+ typedef struct Vdec_BufferRequirements {
+ uint32 bufferSize; /* Buffer size, in bytes */
+ uint32 numMinBuffers; //!< The minimum number of buffers required for functionality.
+ uint32 numMaxBuffers; //!< The maximum number of buffers for good performance.
+ } Vdec_BufferRequirements;
+
+/**
+ * This structure specifies information about the input and output allocated
+ * buffers.
+ */
+ typedef struct Vdec_BufferInfo {
+ byte *base; /* Starting virtual address */
+ int pmem_id;
+ unsigned pmem_offset;
+ uint32 bufferSize; /* Buffer size */
+ Vdec_BufferOwnerType state;
+ void *omx_cookie;
+ } Vdec_BufferInfo;
+
+/**
+ * This structure specifies a decoder (input or output) frame.
+ */
+ typedef struct vdec_frame {
+ int64 timestamp; /* frame timestamp */
+ uint32 flags; /* holds frame flags properties */
+ Vdec_FrameDetailsType frameDetails; /* Details on decoded frame */
+ Vdec_BufferInfo buffer;
+ } vdec_frame;
+
+/**
+ * This structure defines an input video frame sent to decoder
+ */
+ typedef struct video_input_frame_info {
+ void *data; /* Pointer to the input data */
+ unsigned int len; /* Input frame length in bytess */
+ signed long long timestamp; /* Timestamp,forwarded from i/p to o/p */
+ unsigned int flags; /* Flag to indicate EOS */
+ uint32 userData; /* User data associated with the frame */
+ int32 avSyncState; /* AV sync state */
+ } video_input_frame_info;
+
+/**
+ * This structure is a decoder context that should be filled up by the client
+ * before calling vdec_open
+ */
+ typedef struct vdec_context {
+ /* The following fields are to be filled up by the client if it
+ * has the corresponding information.
+ */
+ uint32 width; /* Width of the image */
+ uint32 height; /* Height of the image */
+ uint32 fourcc; /* 4cc for type of decoder */
+ byte *sequenceHeader; /* parameter set */
+ uint32 sequenceHeaderLen; /* length of parameter set */
+ boolean bRenderDecodeOrder; /* Render decode order */
+ unsigned int size_of_nal_length_field;
+ uint32 vc1Rowbase;
+ uint32 postProc;
+ int32 vdec_fd;
+ uint32 color_format;
+
+ /////////////////////////////////To be removed in future.
+ char kind[128]; // new code to pass the role from omx vdec.
+ // This has to be replaced with fourcc in future
+ void (*process_message) (struct vdec_context * ctxt,
+ unsigned char id);
+ void *extra;
+ //////////////////////////////////
+ /* The following fields are to be filled up by the vdec (decoder)
+ * if it has the corresponding information.
+ */
+
+ /* Input Output Buffer requirements
+ * This might be filled in by vdec if the vdec decides on the
+ * buffer requirements.
+ */
+ Vdec_BufferRequirements inputReq;
+ Vdec_BufferRequirements outputReq;
+
+ /* Input/Ouput Buffers
+ * These hold the location and size of the input and output
+ * buffers. This might be filled up by the vdec after a call
+ * to vdec_commit_memory.
+ */
+ Vdec_BufferInfo *inputBuffer;
+ uint32 nInpBufAllocLen;
+ uint32 numInputBuffers;
+
+ vdec_frame *outputBuffer;
+ uint32 nOutBufAllocLen;
+ uint32 numOutputBuffers;
+
+ /*
+ * Callback function that will be called when output frame is complete
+ * call vdec_release_frame() when you are done with it
+ */
+ void (*frame_done) (struct vdec_context * ctxt,
+ struct vdec_frame * frame);
+
+ /**
+ * Callback function that will be called when input buffer is no longer in
+ * use
+ */
+ void (*buffer_done) (struct vdec_context * ctxt, void *cookie);
+ } vdec_context;
+
+ struct Vdec_Input_BufferInfo {
+ Vdec_BufferInfo *input;
+ unsigned int numbuf;
+ };
+ struct VDecoder_buf_info {
+ uint32 buffer_size;
+ unsigned numbuf;
+ };
+
+/**
+ * A structure which identifies the decoder.
+ * The stucture is returned when the decoder
+ * is opened and used in subsequent calls
+ * to identify the decoder.
+ */
+ struct VDecoder {
+ unsigned pmem_buffers;
+ struct pmem *arena;
+
+ void *adsp_module;
+ struct vdec_context *ctxt;
+ void *thread_specific_info;
+ Vdec_BufferRequirements decReq1;
+ Vdec_BufferRequirements decReq2;
+ boolean is_commit_memory;
+ };
+
+/**
+ * This method is to be used to get the input buffer
+ * requirements from the Decoder.
+ *
+ * @param[inout] buf_req
+ * Video decoder buffer requirements. The client of the
+ * decoder should should pass the appropriate pointer to
+ * the buffer requirements structure and the Decoder will
+ * fill this with the required input buffer requirement
+ * fields.
+ *
+ * @return
+ * 0 success
+ * -1 failure
+ */
+ Vdec_ReturnType vdec_get_input_buf_requirements(struct VDecoder_buf_info
+ *buf_req);
+
+/**
+ * This method is to be used to get the input buffer
+ * requirements from the Decoder.
+ *
+ * @param[in] unsigned int size
+ * The size of the input buffer that need to be allocated
+ *
+ * @return
+ * NULL if the buffer allocation failures
+ * pointer to virtual address of input buffer allocated
+ */
+ Vdec_ReturnType vdec_allocate_input_buffer(unsigned int size,
+ Vdec_BufferInfo * buf,
+ int is_pmem);
+/**
+ * This method is to be used to get the input buffer
+ * requirements from the Decoder.
+ *
+ * @param[in] Vdec_BufferInfo
+ * the pointer to the input buffer allocated by the call to
+ * vdec_allocate_one_input_buffer
+ *
+ * @return
+ * 0 success
+ * -1 failure
+ */
+ Vdec_ReturnType vdec_free_input_buffer(Vdec_BufferInfo * buf_info,
+ int is_pmem);
+
+/**
+ * This method is to be used to open the decoder.
+ *
+ * @param[inout] ctxt
+ * Video decoder context. The client of the decoder should
+ * fill in the appropriate fields in the structure.After
+ * the return from the call, the decoder will fill up
+ * certain fields in the structure.
+ *
+ * @return
+ * Video decoder strucure. This value has to be passed as
+ * the first argument in further calls. A NULL return value
+ * indicates that the decoder could not be opened.
+ */
+ struct VDecoder *vdec_open(struct vdec_context *ctxt);
+
+/**
+ * This method is to be used to allocate the memory needed by decoder.
+ * This method needs to be called before decoding can begin. Also,
+ * vdec_open should have been called before this.
+ *
+ * Prerequisite: vdec_open should have been called.
+ *
+ * @param[in] dec
+ * Pointer to the Video decoder.
+ *
+ * @return
+ *
+ * 0 - success. Memory is allocated successfully.
+ *
+ * -1 - Failure. Memory allocation failed.
+ *
+ */
+ Vdec_ReturnType vdec_commit_memory(struct VDecoder *dec);
+
+/**
+ * This method is to be used to close a video decoder.
+ *
+ * Prerequisite: vdec_open should have been called.
+ *
+ * @param[in] dec
+ * Pointer to the Video decoder.
+ */
+ Vdec_ReturnType vdec_close(struct VDecoder *dec);
+
+/**
+ * This method is to be used to post an input buffer.
+ *
+ * Prerequisite: vdec_open should have been called.
+ *
+ * @param[in] dec
+ * Pointer to the Video decoder.
+ *
+ * @param[in] frame
+ * The input frame to be decoded. The frame should point to an area in
+ * shared memory for WinMo solution.
+ *
+ * @param[in] cookie
+ * A cookie for the input frame. The cookie is used to
+ * identify the frame when the buffer_done callback
+ * function is called.The cookie is unused by the decoder
+ * otherwise.
+ *
+ * @return
+ * 0 if the input buffer is posted successfully.
+ * -1 if the input buffer could not be sent to the decoder.
+ */
+ Vdec_ReturnType vdec_post_input_buffer(struct VDecoder *dec,
+ struct video_input_frame_info
+ *frame, void *cookie,
+ int is_pmem);
+
+/**
+ * This method is used to release an output frame back to the decoder.
+ *
+ * Prerequisite: vdec_open should have been called.
+ *
+ * @param[in] dec
+ * Pointer to the Video decoder.
+ *
+ * @param[in] frame
+ * The released output frame.
+ */
+ Vdec_ReturnType vdec_release_frame(struct VDecoder *dec,
+ struct vdec_frame *frame);
+
+/**
+ * This method is used to flush the frames in the decoder.
+ *
+ * Prerequisite: vdec_open should have been called.
+ *
+ * @param[in] dec
+ * Pointer to the Video decoder.
+ *
+ * @param[in] nFlushedFrames
+ * The number of flushed frames. A value of -1 indicates that n
+ * information is available on number of flushed frames.
+ */
+ Vdec_ReturnType vdec_flush_port(struct VDecoder *dec,
+ int *nFlushedFrames,
+ Vdec_PortType port);
+
+#ifdef USE_PMEM_ADSP_CACHED
+/**
+ * This method is used to perform cache operations on the pmem region in the decoder.
+ *
+ * Prerequisite: vdec_open should have been called.
+ *
+ * @param[in] pmem_id
+ * id of the pmem region to use
+ *
+ * @param[in] addr
+ * The virtual addr of the pmem region
+ *
+ * @param[in] size
+ * The size of the region
+ *
+ * @param[in] op
+ * Cache operation to perform as defined by PMEM_CACHE_OP
+ */
+ void vdec_cachemaint(int pmem_id, void *addr, unsigned size, PMEM_CACHE_OP op);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/omx/mm-video/qdsp6/vdec/test/omx_vdec_property_mgr.cpp b/omx/mm-video/qdsp6/vdec/test/omx_vdec_property_mgr.cpp
new file mode 100644
index 0000000..5913def
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/test/omx_vdec_property_mgr.cpp
@@ -0,0 +1,254 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*
+ * An OMX Video Decoder Property Manager application ....
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "cutils/properties.h"
+
+const char *prop_arb_bytes = "persist.omxvideo.arb-bytes";
+const char *prop_acc_subframe = "persist.omxvideo.accsubframe";
+const char *prop_profile_chk = "persist.omxvideo.profilecheck";
+const char *prop_level_chk = "persist.omxvideo.levelcheck";
+const char *prop_arb_bytes_vc1 = "persist.omxvideo.arb-bytes-vc1";
+
+const char *key_arbitrary = "arbitrarybytes";
+const char *key_arbitrary_vc1 = "vc1-arbitrarybytes";
+const char *key_accumulate = "accumulatesubframe";
+const char *key_profile = "profilecheck";
+const char *key_level = "levelcheck";
+
+/* Function which parses the keyword & returns a matching Android property */
+const char* parse_property_key ( char* key )
+{
+ const char* property_name = NULL;
+ int error = 0;
+
+ if(key == NULL)
+ {
+ printf("\nInvalid key[0x0]\n");
+ return NULL;
+ }
+
+ printf("\n Input key [%s]\n", key);
+
+ switch(key[0])
+ {
+ case 'a':
+ if(strstr(key_arbitrary, key) == key_arbitrary)
+ {
+ property_name = prop_arb_bytes;
+ }
+ else if(strstr(key_accumulate, key) == key_accumulate)
+ {
+ property_name = prop_acc_subframe;
+ }
+ else
+ {
+ error = 1;
+ }
+ break;
+
+ case 'p':
+ if(strstr(key_profile, key) == key_profile)
+ {
+ property_name = prop_profile_chk;
+ }
+ else
+ {
+ error = 1;
+ }
+ break;
+
+ case 'l':
+ if(strstr(key_level, key) == key_level)
+ {
+ property_name = prop_level_chk;
+ }
+ else
+ {
+ error = 1;
+ }
+ break;
+
+ case 'v':
+ if(strstr(key_arbitrary_vc1, key) == key_arbitrary_vc1)
+ {
+ property_name = prop_arb_bytes_vc1;
+ }
+ else
+ {
+ error = 1;
+ }
+ break;
+
+ default:
+ error = 1;
+ break;
+ }
+
+ if(error)
+ {
+ printf("\n INVALID key given as input \n");
+ }
+ return property_name;
+}
+
+int main ( int argc, char** argv )
+{
+ const char *property = NULL;
+ const char *str_value_true = "true";
+ const char *str_value_false = "false";
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+ int count = argc;
+ int i = 1, ret = -1;
+
+ if(count <= 2 || count >= 12)
+ {
+ printf("\nError: Invalid number of arguments[%d]!\n", count);
+ printf("\nOnly 3 to 11 arguments can be given\n");
+ printf("\nUsage: ./mm-vdec-omx-property-mgr <property1 name or");
+ printf(" key-prefix> <value to set> \n<property2 name or key-prefix>");
+ printf(" <value to set> .... upto 5 properties currently\n");
+ printf("\n Ex: ./mm-vdec-omx-property-mgr ac true ar 1 p 0\n");
+ return -1;
+ }
+
+ if(count%2 == 0)
+ {
+ printf("\nError: Even no. of arguments! Last property has no value\n");
+ property = parse_property_key( argv[count-1] );
+ if(property == NULL)
+ {
+ printf("\nInvalid property given at the end\n");
+ }
+ else
+ {
+ printf("\n Key [%s] corresponding to property [%s]", argv[count-1],
+ property);
+ printf("\n has no value in input");
+ printf("\n Property [%s] will be ignored \n", property);
+ count--;
+ }
+ }
+
+ while(i < count)
+ {
+ property = parse_property_key( argv[i] );
+
+ if(property)
+ {
+ printf("\n Valid property[%s] at argument [%d]\n", property, i);
+
+ if(!strcmp(argv[i+1], "true") || !strcmp(argv[i+1], "1"))
+ {
+ ret = property_set(property, str_value_true);
+ }
+ else if(!strcmp(argv[i+1], "false") || !strcmp(argv[i+1], "0"))
+ {
+ ret = property_set(property, str_value_false);
+ }
+ else
+ {
+ printf("\nError: Invalid value{%s} for property [%s]\n", \
+ argv[i+1], property);
+ i += 2;
+ continue;
+ }
+
+ if(ret != 0)
+ {
+ printf("\nError: property_set failed for \"%s\"\n", property);
+ }
+ }
+ else
+ {
+ printf("\nError: Invalid key [%s] given at argument [%d]\n",
+ argv[i], i);
+ }
+
+ i += 2;
+ }
+
+ sleep(1);
+ /* Read and print the values of all properties */
+ printf("\n PROPERTY : VALUE\n");
+
+ if(0 != property_get(prop_arb_bytes, property_value, NULL))
+ {
+ printf("\n %s : %s", prop_arb_bytes, property_value);
+ }
+ else
+ {
+ printf("\n %s : [READ ERROR]", prop_arb_bytes);
+ }
+
+ if(0 != property_get(prop_arb_bytes_vc1, property_value, NULL))
+ {
+ printf("\n %s : %s", prop_arb_bytes_vc1, property_value);
+ }
+ else
+ {
+ printf("\n %s : [READ ERROR]", prop_arb_bytes_vc1);
+ }
+
+ if(0 != property_get(prop_acc_subframe, property_value, NULL))
+ {
+ printf("\n %s : %s", prop_acc_subframe, property_value);
+ }
+ else
+ {
+ printf("\n %s : [READ ERROR]", prop_acc_subframe);
+ }
+
+ if(0 != property_get(prop_profile_chk, property_value, NULL))
+ {
+ printf("\n %s : %s", prop_profile_chk, property_value);
+ }
+ else
+ {
+ printf("\n %s : [READ ERROR]", prop_profile_chk);
+ }
+
+ if(0 != property_get(prop_level_chk, property_value, NULL))
+ {
+ printf("\n %s : %s", prop_level_chk, property_value);
+ }
+ else
+ {
+ printf("\n %s : [READ ERROR]", prop_level_chk);
+ }
+
+ printf("\n****************************************************\n");
+ printf("\n***********OMX VDEC PROPERTIES TEST COMPLETE********\n");
+ printf("\n****************************************************\n");
+}
+
diff --git a/omx/mm-video/qdsp6/vdec/test/omx_vdec_test.cpp b/omx/mm-video/qdsp6/vdec/test/omx_vdec_test.cpp
new file mode 100644
index 0000000..090d9c3
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/test/omx_vdec_test.cpp
@@ -0,0 +1,2558 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*
+ An Open max test application ....
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdint.h>
+
+#ifdef _ANDROID_
+#include <binder/MemoryHeapBase.h>
+#endif
+#include "OMX_Core.h"
+#include "OMX_Component.h"
+#include "OMX_QCOMExtns.h"
+#include "qtv_msg.h"
+extern "C" {
+#include "queue.h"
+#include "pmem.h"
+}
+
+
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+#include "qutility.h"
+
+
+/************************************************************************/
+/* #DEFINES */
+/************************************************************************/
+#define DELAY 66
+#define false 0
+#define true 1
+#define VOP_START_CODE 0x000001B6
+#define SHORT_HEADER_START_CODE 0x00008000
+#define SPARK1_START_CODE 0x00008400
+#define VC1_START_CODE 0x00000100
+#define NUMBER_OF_ARBITRARYBYTES_READ (4 * 1024)
+#define VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32
+#define VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16
+
+#define CONFIG_VERSION_SIZE(param) \
+ param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\
+ param.nSize = sizeof(param);
+
+#define FAILED(result) (result != OMX_ErrorNone)
+
+#define SUCCEEDED(result) (result == OMX_ErrorNone)
+#define SWAPBYTES(ptrA, ptrB) { char t = *ptrA; *ptrA = *ptrB; *ptrB = t;}
+#define SIZE_NAL_FIELD_MAX 4
+#define MDP_DEINTERLACE 0x80000000
+
+/************************************************************************/
+/* GLOBAL DECLARATIONS */
+/************************************************************************/
+#ifdef _ANDROID_
+using namespace android;
+#endif
+
+typedef enum {
+ CODEC_FORMAT_H264 = 1,
+ CODEC_FORMAT_MP4,
+ CODEC_FORMAT_H263,
+ CODEC_FORMAT_VC1,
+ CODEC_FORMAT_DIVX,
+ CODEC_FORMAT_VP,
+ CODEC_FORMAT_SPARK0,
+ CODEC_FORMAT_SPARK1,
+ CODEC_FORMAT_MAX = CODEC_FORMAT_SPARK1
+} codec_format;
+
+typedef enum {
+ FILE_TYPE_DAT_PER_AU = 1,
+ FILE_TYPE_ARBITRARY_BYTES,
+ FILE_TYPE_COMMON_CODEC_MAX,
+
+ FILE_TYPE_START_OF_H264_SPECIFIC = 10,
+ FILE_TYPE_264_NAL_SIZE_LENGTH = FILE_TYPE_START_OF_H264_SPECIFIC,
+
+ FILE_TYPE_START_OF_MP4_SPECIFIC = 20,
+ FILE_TYPE_PICTURE_START_CODE = FILE_TYPE_START_OF_MP4_SPECIFIC,
+
+ FILE_TYPE_START_OF_VC1_SPECIFIC = 30,
+ FILE_TYPE_RCV = FILE_TYPE_START_OF_VC1_SPECIFIC,
+ FILE_TYPE_VC1,
+
+ FILE_TYPE_START_OF_DIVX_SPECIFIC = 40,
+ FILE_TYPE_DIVX_4_5_6 = FILE_TYPE_START_OF_DIVX_SPECIFIC,
+ FILE_TYPE_DIVX_311,
+
+ FILE_TYPE_START_OF_VP_SPECIFIC = 50,
+ FILE_TYPE_VP_6 = FILE_TYPE_START_OF_VP_SPECIFIC,
+} file_type;
+
+typedef enum {
+ GOOD_STATE = 0,
+ PORT_SETTING_CHANGE_STATE,
+ ERROR_STATE,
+ INVALID_STATE
+} test_status;
+
+typedef enum {
+ FREE_HANDLE_AT_LOADED = 1,
+ FREE_HANDLE_AT_IDLE,
+ FREE_HANDLE_AT_EXECUTING,
+ FREE_HANDLE_AT_PAUSE
+} freeHandle_test;
+
+struct use_egl_id {
+ int pmem_fd;
+ int offset;
+};
+
+static int (*Read_Buffer)(OMX_BUFFERHEADERTYPE *pBufHdr );
+
+struct use_egl_id *egl_id = NULL;
+int is_use_egl_image = 0;
+
+FILE * inputBufferFile;
+FILE * outputBufferFile;
+int takeYuvLog = 0;
+int displayYuv = 0;
+int displayWindow = 0;
+int is_yamato = 0;
+
+Queue *etb_queue = NULL;
+Queue *fbd_queue = NULL;
+
+pthread_t ebd_thread_id;
+pthread_t fbd_thread_id;
+void* ebd_thread(void*);
+void* fbd_thread(void*);
+
+pthread_mutex_t etb_lock;
+pthread_mutex_t fbd_lock;
+pthread_mutex_t lock;
+pthread_cond_t cond;
+pthread_mutex_t elock;
+pthread_cond_t econd;
+pthread_cond_t fcond;
+pthread_mutex_t eos_lock;
+pthread_cond_t eos_cond;
+
+sem_t etb_sem;
+sem_t fbd_sem;
+
+OMX_PARAM_PORTDEFINITIONTYPE portFmt;
+OMX_PORT_PARAM_TYPE portParam;
+OMX_ERRORTYPE error;
+
+static int fb_fd = -1;
+static struct fb_var_screeninfo vinfo;
+static struct fb_fix_screeninfo finfo;
+void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr);
+
+/************************************************************************/
+/* GLOBAL INIT */
+/************************************************************************/
+int input_buf_cnt = 0;
+int height =0, width =0;
+int used_ip_buf_cnt = 0;
+volatile int event_is_done = 0;
+int ebd_cnt, fbd_cnt;
+int bInputEosReached = 0;
+int bOutputEosReached = 0;
+char in_filename[512];
+
+int timeStampLfile = 0;
+int timestampInterval = 100;
+codec_format codec_format_option;
+file_type file_type_option;
+freeHandle_test freeHandle_option;
+int nalSize;
+int sent_disabled = 0;
+int waitForPortSettingsChanged = 1;
+test_status currentStatus = GOOD_STATE;
+
+//* OMX Spec Version supported by the wrappers. Version = 1.1 */
+const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101;
+OMX_COMPONENTTYPE* dec_handle = 0;
+
+OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL;
+OMX_BUFFERHEADERTYPE **pOutYUVBufHdrs= NULL;
+
+int rcv_v1=0;
+
+/* Performance related variable*/
+QPERF_INIT(render_fb);
+QPERF_INIT(client_decode);
+
+/************************************************************************/
+/* GLOBAL FUNC DECL */
+/************************************************************************/
+int Init_Decoder();
+int Play_Decoder();
+int run_tests();
+
+/**************************************************************************/
+/* STATIC DECLARATIONS */
+/**************************************************************************/
+static int video_playback_count = 1;
+static int open_video_file ();
+static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr );
+static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_FrameSize_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+
+static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle,
+ OMX_BUFFERHEADERTYPE ***pBufHdrs,
+ OMX_U32 nPortIndex,
+ long bufCntMin, long bufSize);
+static OMX_ERRORTYPE Use_EGL_Buffer ( OMX_COMPONENTTYPE *dec_handle,
+ OMX_BUFFERHEADERTYPE ***pBufHdrs,
+ OMX_U32 nPortIndex,
+ long bufCntMin, long bufSize,
+ struct use_egl_id **egl);
+
+
+static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+static OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+
+static void do_freeHandle_and_clean_up(bool isDueToError);
+
+/*static usecs_t get_time(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return ((usecs_t)tv.tv_usec) +
+ (((usecs_t)tv.tv_sec) * ((usecs_t)1000000));
+}*/
+
+
+void wait_for_event(void)
+{
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Waiting for event\n");
+ pthread_mutex_lock(&lock);
+ while (event_is_done == 0) {
+ pthread_cond_wait(&cond, &lock);
+ }
+ event_is_done = 0;
+ pthread_mutex_unlock(&lock);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Running .... get the event\n");
+}
+
+void event_complete(void )
+{
+ pthread_mutex_lock(&lock);
+ if (event_is_done == 0) {
+ event_is_done = 1;
+ pthread_cond_broadcast(&cond);
+ }
+ pthread_mutex_unlock(&lock);
+}
+
+void* ebd_thread(void* pArg)
+{
+ while(currentStatus != INVALID_STATE)
+ {
+ int readBytes =0;
+ OMX_BUFFERHEADERTYPE* pBuffer = NULL;
+
+ sem_wait(&etb_sem);
+ pthread_mutex_lock(&etb_lock);
+ pBuffer = (OMX_BUFFERHEADERTYPE *) pop(etb_queue);
+ pthread_mutex_unlock(&etb_lock);
+ if(pBuffer == NULL)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - No etb pBuffer to dequeue\n");
+ continue;
+ }
+ pBuffer->nOffset = 0;
+ if((readBytes = Read_Buffer(pBuffer)) > 0) {
+ pBuffer->nFilledLen = readBytes;
+ OMX_EmptyThisBuffer(dec_handle,pBuffer);
+ }
+ else
+ {
+ pBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
+ bInputEosReached = true;
+ pBuffer->nFilledLen = readBytes;
+ OMX_EmptyThisBuffer(dec_handle,pBuffer);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,
+ "EBD::Either EOS or Some Error while reading file\n");
+ break;
+ }
+ }
+ return NULL;
+}
+
+void* fbd_thread(void* pArg)
+{
+ while(currentStatus != INVALID_STATE)
+ {
+ int bytes_written = 0;
+ OMX_BUFFERHEADERTYPE *pBuffer;
+ sem_wait(&fbd_sem);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s fbd_cnt[%d] \n", __FUNCTION__, fbd_cnt);
+
+ fbd_cnt++;
+ pthread_mutex_lock(&fbd_lock);
+ pBuffer = (OMX_BUFFERHEADERTYPE *) pop(fbd_queue);
+ pthread_mutex_unlock(&fbd_lock);
+ if (pBuffer == NULL)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Error - No pBuffer to dequeue\n");
+ continue;
+ }
+
+ /*********************************************
+ Write the output of the decoder to the file.
+ *********************************************/
+
+ if (sent_disabled)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Ignoring FillBufferDone\n");
+ continue;
+ }
+
+ if (displayYuv && pBuffer->nFilledLen > 0)
+ {
+ QPERF_TIME(render_fb, render_fb(pBuffer));
+ }
+
+ if (takeYuvLog) {
+ bytes_written = fwrite((const char *)pBuffer->pBuffer,
+ pBuffer->nFilledLen,1,outputBufferFile);
+ if (bytes_written < 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "\nFillBufferDone: Failed to write to the file\n");
+ }
+ else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "\nFillBufferDone: Wrote %d YUV bytes to the file\n",
+ bytes_written);
+ }
+ }
+
+ /********************************************************************/
+ /* De-Initializing the open max and relasing the buffers and */
+ /* closing the files.*/
+ /********************************************************************/
+ if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS ) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "***************************************************\n");
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "FillBufferDone: End Of Stream Reached\n");
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "***************************************************\n");
+ pthread_mutex_lock(&eos_lock);
+ bOutputEosReached = true;
+ pthread_cond_broadcast(&eos_cond);
+ pthread_mutex_unlock(&eos_lock);
+ QPERF_END(client_decode);
+ QPERF_SET_ITERATION(client_decode, fbd_cnt);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "***************************************************\n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"FBD_THREAD bOutputEosReached %d\n",bOutputEosReached);
+ break;
+ }
+ OMX_FillThisBuffer(dec_handle, pBuffer);
+ }
+ return NULL;
+}
+
+OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Function %s \n", __FUNCTION__);
+
+ switch(eEvent) {
+ case OMX_EventCmdComplete:
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\n OMX_EventCmdComplete \n");
+ // check nData1 for DISABLE event
+ if(OMX_CommandPortDisable == (OMX_COMMANDTYPE)nData1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "*********************************************\n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Recieved DISABLE Event Command Complete[%d]\n",nData2);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "*********************************************\n");
+ sent_disabled = 0;
+ }
+ else if(OMX_CommandPortEnable == (OMX_COMMANDTYPE)nData1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "*********************************************\n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Recieved ENABLE Event Command Complete[%d]\n",nData2);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "*********************************************\n");
+ }
+ currentStatus = GOOD_STATE;
+ event_complete();
+ break;
+
+ case OMX_EventError:
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_EventError \n");
+ currentStatus = INVALID_STATE;
+ if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)nData1)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Invalid State \n");
+ if(event_is_done == 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Event error in the middle of Decode \n");
+ pthread_mutex_lock(&eos_lock);
+ bOutputEosReached = true;
+ pthread_cond_broadcast(&eos_cond);
+ pthread_mutex_unlock(&eos_lock);
+
+ }
+ }
+
+ event_complete();
+ break;
+ case OMX_EventPortSettingsChanged:
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_EventPortSettingsChanged port[%d]\n",nData1);
+ waitForPortSettingsChanged = 0;
+ currentStatus = PORT_SETTING_CHANGE_STATE;
+ // reset the event
+ event_complete();
+ break;
+
+ default:
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"ERROR - Unknown Event \n");
+ break;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ int readBytes =0; int bufCnt=0;
+ OMX_ERRORTYPE result;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Function %s cnt[%d]\n", __FUNCTION__, ebd_cnt);
+ ebd_cnt++;
+
+
+ if(bInputEosReached) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "*****EBD:Input EoS Reached************\n");
+ return OMX_ErrorNone;
+ }
+
+ pthread_mutex_lock(&etb_lock);
+ if(push(etb_queue, (void *) pBuffer) < 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Error in enqueue ebd data\n");
+ return OMX_ErrorUndefined;
+ }
+ pthread_mutex_unlock(&etb_lock);
+ sem_post(&etb_sem);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Inside %s callback_count[%d] \n", __FUNCTION__, fbd_cnt);
+
+ /* Test app will assume there is a dynamic port setting
+ * In case that there is no dynamic port setting, OMX will not call event cb,
+ * instead OMX will send empty this buffer directly and we need to clear an event here
+ */
+ if(waitForPortSettingsChanged && currentStatus != INVALID_STATE)
+ {
+ currentStatus = GOOD_STATE;
+ waitForPortSettingsChanged = 0;
+ event_complete();
+ }
+
+ if(!sent_disabled)
+ {
+ pthread_mutex_lock(&fbd_lock);
+ if(push(fbd_queue, (void *)pBuffer) < 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"Error in enqueueing fbd_data\n");
+ return OMX_ErrorUndefined;
+ }
+ pthread_mutex_unlock(&fbd_lock);
+ sem_post(&fbd_sem);
+ }
+ return OMX_ErrorNone;
+}
+
+int main(int argc, char **argv)
+{
+ int i=0;
+ int bufCnt=0;
+ int num=0;
+ int outputOption = 0;
+ int test_option = 0;
+ OMX_ERRORTYPE result;
+
+ strncpy(in_filename, argv[1], strlen(argv[1])+1);
+
+ if(argc > 5)
+ {
+ codec_format_option = (codec_format)atoi(argv[2]);
+ file_type_option = (file_type)atoi(argv[3]);
+ }
+ else
+ {
+ printf("Command line argument is available\n");
+ printf("To use it: ./mm-vdec-omx-test <clip location> <codec_type> \n");
+ printf(" <input_type: 1. per AU(.dat), 2. arbitrary, 3.per NAL/frame>\n");
+ printf(" <output_type> <test_case> <size_nal if H264>\n\n\n");
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1--> H264\n");
+ printf(" 2--> MP4\n");
+ printf(" 3--> H263\n");
+ printf(" 4--> VC1\n");
+ printf(" 5--> DIVX\n");
+ printf(" 6--> VP6\n");
+ printf(" 7--> Spark0\n");
+ printf(" 8--> Spark1\n");
+ fflush(stdin);
+ scanf("%d", &codec_format_option);
+ fflush(stdin);
+
+ if (codec_format_option > CODEC_FORMAT_MAX)
+ {
+ printf(" Wrong test case...[%d] \n", codec_format_option);
+ return -1;
+ }
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ if (codec_format_option != CODEC_FORMAT_DIVX && codec_format_option != CODEC_FORMAT_VP) {
+ printf(" 1--> PER ACCESS UNIT CLIP (.dat). Clip only available for H264 and Mpeg4\n");
+ printf(" 2--> ARBITRARY BYTES (need .264/.264c/.mv4/.263/.rcv/.vc1)\n");
+ }
+ if (codec_format_option == CODEC_FORMAT_H264)
+ {
+ printf(" 3--> NAL LENGTH SIZE CLIP (.264c)\n");
+ }
+ else if ( (codec_format_option == CODEC_FORMAT_MP4) || (codec_format_option == CODEC_FORMAT_H263) )
+ {
+ printf(" 3--> MP4 VOP or H263 P0 SHORT HEADER START CODE CLIP or DIVX (.m4v or .263)\n");
+ }
+ else if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ printf(" 3--> VC1 clip Simple/Main Profile (.rcv)\n");
+ printf(" 4--> VC1 clip Advance Profile (.vc1)\n");
+ }
+ else if (codec_format_option == CODEC_FORMAT_DIVX) {
+ printf(" 3--> Divx clip 4, 5, 6 format\n");
+ printf(" 4--> Divx clip 311 format\n");
+ }
+ else if (codec_format_option == CODEC_FORMAT_VP)
+ {
+ printf(" 3--> VP6 raw bit stream (.vp)\n");
+ }
+ else if (codec_format_option == CODEC_FORMAT_SPARK0 || codec_format_option == CODEC_FORMAT_SPARK1)
+ {
+ printf(" 3--> SPARK start code based clip\n");
+ }
+ fflush(stdin);
+ scanf("%d", &file_type_option);
+ fflush(stdin);
+ }
+
+ if (file_type_option >= FILE_TYPE_COMMON_CODEC_MAX)
+ {
+ switch (codec_format_option)
+ {
+ case CODEC_FORMAT_H264:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_H264_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ case CODEC_FORMAT_MP4:
+ case CODEC_FORMAT_H263:
+ case CODEC_FORMAT_SPARK0:
+ case CODEC_FORMAT_SPARK1:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_MP4_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ case CODEC_FORMAT_VC1:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_VC1_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ case CODEC_FORMAT_DIVX:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_DIVX_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ case CODEC_FORMAT_VP:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_VP_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ default:
+ printf("Error: Unknown code %d\n", codec_format_option);
+ }
+ }
+
+ if(argc > 5)
+ {
+ outputOption = atoi(argv[4]);
+ test_option = atoi(argv[5]);
+ if (argc > 6)
+ {
+ nalSize = atoi(argv[6]);
+ }
+ else
+ {
+ nalSize = 0;
+ }
+
+ if(argc > 7)
+ {
+ displayWindow = atoi(argv[7]);
+ if(displayWindow > 4)
+ {
+ printf(" display window 0-4 only supported forcing it to 0 \n");
+ displayWindow = 0;
+ }
+ }
+ else
+ {
+ displayWindow = 0;
+ }
+
+ }
+ else
+ {
+ switch(file_type_option)
+ {
+ case FILE_TYPE_DAT_PER_AU:
+ case FILE_TYPE_ARBITRARY_BYTES:
+ case FILE_TYPE_264_NAL_SIZE_LENGTH:
+ case FILE_TYPE_PICTURE_START_CODE:
+ case FILE_TYPE_RCV:
+ case FILE_TYPE_VC1:
+ case FILE_TYPE_DIVX_4_5_6:
+ case FILE_TYPE_DIVX_311:
+ case FILE_TYPE_VP_6:
+ {
+ nalSize = 0;
+ if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) ||
+ ((codec_format_option == CODEC_FORMAT_H264) && (file_type_option == FILE_TYPE_ARBITRARY_BYTES)))
+ {
+ printf(" Enter Nal length size [2 or 4] \n");
+ if (file_type_option == FILE_TYPE_ARBITRARY_BYTES)
+ {
+ printf(" Enter 0 if it is a start code based clip\n");
+ }
+ scanf("%d", &nalSize);
+ if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) &&
+ (nalSize == 0))
+ {
+ printf("Error - Can't pass NAL length size = 0\n");
+ return -1;
+ }
+ }
+
+ height=144;width=176; // Assume Default as QCIF
+ printf("Executing DynPortReconfig QCIF 144 x 176 \n");
+ break;
+ }
+
+ default:
+ {
+ printf(" Wrong test case...[%d] \n",file_type_option);
+ return -1;
+ }
+ }
+
+ printf(" *********************************************\n");
+ printf(" Output buffer option:\n");
+ printf(" *********************************************\n");
+ printf(" 0 --> No display and no YUV log\n");
+ printf(" 1 --> Diplay YUV\n");
+ printf(" 2 --> Take YUV log\n");
+ printf(" 3 --> Display YUV and take YUV log\n");
+ fflush(stdin);
+ scanf("%d", &outputOption);
+ fflush(stdin);
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1 --> Play the clip till the end\n");
+ printf(" 2 --> Run compliance test. Do NOT expect any display for most option. \n");
+ printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n");
+ fflush(stdin);
+ scanf("%d", &test_option);
+ fflush(stdin);
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE PORTION OF DISPLAY TO USE\n");
+ printf(" *********************************************\n");
+ printf(" 0 --> Entire Screen\n");
+ printf(" 1 --> 1/4 th of the screen starting from top left corner to middle \n");
+ printf(" 2 --> 1/4 th of the screen starting from middle to top right corner \n");
+ printf(" 3 --> 1/4 th of the screen starting from middle to bottom left \n");
+ printf(" 4 --> 1/4 th of the screen starting from middle to bottom right \n");
+ printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n");
+ fflush(stdin);
+ scanf("%d", &displayWindow);
+ fflush(stdin);
+
+ }
+
+
+ if (outputOption == 0)
+ {
+ displayYuv = 0;
+ takeYuvLog = 0;
+ }
+ else if (outputOption == 1)
+ {
+ displayYuv = 1;
+ }
+ else if (outputOption == 2)
+ {
+ takeYuvLog = 1;
+ }
+ else if (outputOption == 3)
+ {
+ displayYuv = 1;
+ takeYuvLog = 1;
+ }
+ else
+ {
+ printf("Wrong option. Assume you want to see the YUV display\n");
+ displayYuv = 1;
+ }
+
+ if (test_option == 2)
+ {
+ printf(" *********************************************\n");
+ printf(" ENTER THE COMPLIANCE TEST YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1 --> Call Free Handle at the OMX_StateLoaded\n");
+ printf(" 2 --> Call Free Handle at the OMX_StateIdle\n");
+ printf(" 3 --> Call Free Handle at the OMX_StateExecuting\n");
+ printf(" 4 --> Call Free Handle at the OMX_StatePause\n");
+ fflush(stdin);
+ scanf("%d", &freeHandle_option);
+ fflush(stdin);
+ }
+ else
+ {
+ freeHandle_option = (freeHandle_test)0;
+ }
+
+ printf("Input values: inputfilename[%s]\n", in_filename);
+ printf("*******************************************************\n");
+ pthread_cond_init(&cond, 0);
+ pthread_cond_init(&eos_cond, 0);
+ pthread_mutex_init(&eos_lock, 0);
+ pthread_mutex_init(&lock, 0);
+ pthread_mutex_init(&etb_lock, 0);
+ pthread_mutex_init(&fbd_lock, 0);
+ if (-1 == sem_init(&etb_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+ if (-1 == sem_init(&fbd_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+
+ etb_queue = alloc_queue();
+ if (etb_queue == NULL)
+ {
+ printf("\n Error in Creating etb_queue\n");
+ return -1;
+ }
+
+ fbd_queue = alloc_queue();
+ if (fbd_queue == NULL)
+ {
+ printf("\n Error in Creating fbd_queue\n");
+ free_queue(etb_queue);
+ return -1;
+ }
+
+ if(0 != pthread_create(&fbd_thread_id, NULL, fbd_thread, NULL))
+ {
+ printf("\n Error in Creating fbd_thread \n");
+ free_queue(etb_queue);
+ free_queue(fbd_queue);
+ return -1;
+ }
+
+ if (displayYuv)
+ {
+ QPERF_RESET(render_fb);
+#ifdef _ANDROID_
+ fb_fd = open("/dev/graphics/fb0", O_RDWR);
+#else
+ fb_fd = open("/dev/fb0", O_RDWR);
+#endif
+ if (fb_fd < 0) {
+ printf("[omx_vdec_test] - ERROR - can't open framebuffer!\n");
+ return -1;
+ }
+
+ if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
+ printf("[omx_vdec_test] - ERROR - can't retrieve vscreenInfo!\n");
+ close(fb_fd);
+ return -1;
+ }
+ if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
+ printf("[omx_vdec_test] - ERROR - can't retrieve fscreenInfo!\n");
+ close(fb_fd);
+ return -1;
+ }
+ }
+
+ run_tests();
+ pthread_cond_destroy(&cond);
+ pthread_mutex_destroy(&lock);
+ pthread_mutex_destroy(&etb_lock);
+ pthread_mutex_destroy(&fbd_lock);
+ pthread_cond_destroy(&eos_cond);
+ pthread_mutex_destroy(&eos_lock);
+ if (-1 == sem_destroy(&etb_sem))
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - sem_destroy failed %d\n", errno);
+ }
+ if (-1 == sem_destroy(&fbd_sem))
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - sem_destroy failed %d\n", errno);
+ }
+
+ if (displayYuv)
+ {
+ close(fb_fd);
+ fb_fd = -1;
+ QPERF_TERMINATE(render_fb);
+ }
+ QPERF_TERMINATE(client_decode);
+ return 0;
+}
+
+int run_tests()
+{
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s\n", __FUNCTION__);
+ waitForPortSettingsChanged = 1;
+ currentStatus = GOOD_STATE;
+
+ if(file_type_option == FILE_TYPE_DAT_PER_AU) {
+ Read_Buffer = Read_Buffer_From_DAT_File;
+ }
+ else if(file_type_option == FILE_TYPE_ARBITRARY_BYTES) {
+ Read_Buffer = Read_Buffer_ArbitraryBytes;
+ }
+ else if(codec_format_option == CODEC_FORMAT_H264) {
+ Read_Buffer = Read_Buffer_From_Size_Nal;
+ }
+ else if((codec_format_option == CODEC_FORMAT_H263) ||
+ (codec_format_option == CODEC_FORMAT_MP4) ||
+ (codec_format_option == CODEC_FORMAT_SPARK0) ||
+ (codec_format_option == CODEC_FORMAT_SPARK1) ||
+ (file_type_option == FILE_TYPE_DIVX_4_5_6)) {
+ Read_Buffer = Read_Buffer_From_Vop_Start_Code_File;
+ }
+ else if(file_type_option == FILE_TYPE_RCV) {
+ Read_Buffer = Read_Buffer_From_RCV_File;
+ }
+ else if(file_type_option == FILE_TYPE_VC1) {
+ Read_Buffer = Read_Buffer_From_VC1_File;
+ }
+ else if (file_type_option == FILE_TYPE_DIVX_311) {
+ Read_Buffer = Read_Buffer_From_FrameSize_File;
+ }
+ else if (file_type_option == FILE_TYPE_VP_6) {
+ Read_Buffer = Read_Buffer_From_FrameSize_File;
+ }
+
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"file_type_option %d!\n", file_type_option);
+
+ switch(file_type_option)
+ {
+ case FILE_TYPE_DAT_PER_AU:
+ case FILE_TYPE_ARBITRARY_BYTES:
+ case FILE_TYPE_264_NAL_SIZE_LENGTH:
+ case FILE_TYPE_PICTURE_START_CODE:
+ case FILE_TYPE_RCV:
+ case FILE_TYPE_VC1:
+ case FILE_TYPE_DIVX_4_5_6:
+ case FILE_TYPE_DIVX_311:
+ case FILE_TYPE_VP_6:
+ if(Init_Decoder()!= 0x00)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"Error - Decoder Init failed\n");
+ return -1;
+ }
+ if(Play_Decoder() != 0x00)
+ {
+ return -1;
+ }
+ break;
+ default:
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - Invalid Entry...%d\n",file_type_option);
+ break;
+ }
+
+ pthread_mutex_lock(&eos_lock);
+ while (bOutputEosReached == false)
+ {
+ pthread_cond_wait(&eos_cond, &eos_lock);
+ }
+ pthread_mutex_unlock(&eos_lock);
+
+ // Wait till EOS is reached...
+ if(bOutputEosReached)
+ {
+ int bufCnt = 0;
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Moving the decoder to idle state \n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0);
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return 0;
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Moving the decoder to loaded state \n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateLoaded,0);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "[OMX Vdec Test] - Deallocating i/p and o/p buffers \n");
+ for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]);
+ }
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountMin; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]);
+ }
+
+ fbd_cnt = 0; ebd_cnt=0;
+ bInputEosReached = false;
+ bOutputEosReached = false;
+
+ wait_for_event();
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - Free handle decoder\n");
+ OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle);
+ if (result != OMX_ErrorNone)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "[OMX Vdec Test] - Terminate: OMX_FreeHandle error. Error code: %d\n", result);
+ }
+ dec_handle = NULL;
+
+ /* Deinit OpenMAX */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - Terminate: De-initializing OMX \n");
+ OMX_Deinit();
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - Terminate: closing all files\n");
+ if(inputBufferFile)
+ {
+ fclose(inputBufferFile);
+ inputBufferFile = NULL;
+ }
+
+
+ if (takeYuvLog && outputBufferFile) {
+ fclose(outputBufferFile);
+ outputBufferFile = NULL;
+ }
+
+ if(etb_queue)
+ {
+ free_queue(etb_queue);
+ etb_queue = NULL;
+ }
+ if(fbd_queue)
+ {
+ free_queue(fbd_queue);
+ fbd_queue = NULL;
+ }
+
+ printf("*****************************************\n");
+ printf("******...TEST SUCCESSFULL...*******\n");
+ printf("*****************************************\n");
+
+ }
+
+ return 0;
+}
+
+int Init_Decoder()
+{
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE omxresult;
+ OMX_U32 total = 0;
+ char vdecCompNames[50];
+ typedef OMX_U8* OMX_U8_PTR;
+ char *role ="video_decoder";
+
+ static OMX_CALLBACKTYPE call_back = {&EventHandler, &EmptyBufferDone, &FillBufferDone};
+
+ int i = 0;
+ long bufCnt = 0;
+
+ /* Init. the OpenMAX Core */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nInitializing OpenMAX Core....\n");
+ omxresult = OMX_Init();
+
+ if(OMX_ErrorNone != omxresult) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "\n Failed to Init OpenMAX core");
+ return -1;
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "\nOpenMAX Core Init Done\n");
+ }
+
+ /* Query for video decoders*/
+ OMX_GetComponentsOfRole(role, &total, 0);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nTotal components of role=%s :%d", role, total);
+
+ if(total)
+ {
+ /* Allocate memory for pointers to component name */
+ OMX_U8** vidCompNames = (OMX_U8**)malloc((sizeof(OMX_U8*))*total);
+
+ for (i = 0; i < total; ++i) {
+ vidCompNames[i] = (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_MAX_STRINGNAME_SIZE);
+ }
+ OMX_GetComponentsOfRole(role, &total, vidCompNames);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nComponents of Role:%s\n", role);
+ for (i = 0; i < total; ++i) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nComponent Name [%s]\n",vidCompNames[i]);
+ free(vidCompNames[i]);
+ }
+ free(vidCompNames);
+ }
+ else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "No components found with Role:%s", role);
+ }
+
+ if (codec_format_option == CODEC_FORMAT_H264)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.avc", 27);
+ }
+ else if (codec_format_option == CODEC_FORMAT_MP4)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg4", 29);
+ }
+ else if (codec_format_option == CODEC_FORMAT_H263)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.h263", 28);
+ }
+ else if (codec_format_option == CODEC_FORMAT_SPARK0 || codec_format_option == CODEC_FORMAT_SPARK1)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.spark", 29);
+ }
+ else if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.vc1", 27);
+ }
+ else if (codec_format_option == CODEC_FORMAT_DIVX)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.divx", 28);
+ }
+ else if (codec_format_option == CODEC_FORMAT_VP)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.vp", 26);
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error: Unsupported codec %d\n", codec_format_option);
+ return -1;
+ }
+
+ omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&dec_handle),
+ (OMX_STRING)vdecCompNames, NULL, &call_back);
+ if (FAILED(omxresult)) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "\nFailed to Load the component:%s\n", vdecCompNames);
+ return -1;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nComponent %s is in LOADED state\n", vdecCompNames);
+ }
+
+ /* Get the port information */
+ CONFIG_VERSION_SIZE(portParam);
+ omxresult = OMX_GetParameter(dec_handle, OMX_IndexParamVideoInit,
+ (OMX_PTR)&portParam);
+
+ if(FAILED(omxresult)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "ERROR - Failed to get Port Param\n");
+ return -1;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "portParam.nPorts:%d\n", portParam.nPorts);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "portParam.nStartPortNumber:%d\n", portParam.nStartPortNumber);
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Set parameter immediately followed by getparameter");
+ if(is_use_egl_image) {
+ portFmt.format.video.pNativeWindow = (void *)0xDEADBEAF;
+ }
+ omxresult = OMX_SetParameter(dec_handle,
+ OMX_IndexParamPortDefinition,
+ &portFmt);
+
+ if(OMX_ErrorNone != omxresult)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "ERROR - Set parameter failed");
+ }
+
+ /* Set the compression format on i/p port */
+ if (codec_format_option == CODEC_FORMAT_H264)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ }
+ else if (codec_format_option == CODEC_FORMAT_MP4)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ }
+ else if (codec_format_option == CODEC_FORMAT_H263)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
+ }
+ else if (codec_format_option == CODEC_FORMAT_SPARK0 || codec_format_option == CODEC_FORMAT_SPARK1)
+ {
+ //portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingSpark;
+ portFmt.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingSpark;
+ }
+ else if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
+ }
+ else if (codec_format_option == CODEC_FORMAT_DIVX)
+ {
+ portFmt.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+ }
+ else if (codec_format_option == CODEC_FORMAT_VP)
+ {
+ portFmt.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingVp;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error: Unsupported codec %d\n", codec_format_option);
+ }
+
+
+ return 0;
+}
+
+int Play_Decoder()
+{
+ int i, bufCnt;
+ int frameSize=0;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE ret;
+
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE));
+
+ /* open the i/p and o/p files based on the video file format passed */
+ if(open_video_file()) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error in opening video file\n");
+ return -1;
+ }
+
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE inputPortFmt;
+ memset(&inputPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE));
+ CONFIG_VERSION_SIZE(inputPortFmt);
+ inputPortFmt.nPortIndex = 0; // input port
+ switch (file_type_option)
+ {
+ case FILE_TYPE_DAT_PER_AU:
+ case FILE_TYPE_PICTURE_START_CODE:
+ case FILE_TYPE_RCV:
+ case FILE_TYPE_DIVX_4_5_6:
+ case FILE_TYPE_DIVX_311:
+ case FILE_TYPE_VP_6:
+ {
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame;
+ break;
+ }
+
+ case FILE_TYPE_ARBITRARY_BYTES:
+ {
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary;
+ break;
+ }
+
+ case FILE_TYPE_264_NAL_SIZE_LENGTH:
+ case FILE_TYPE_VC1:
+ {
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteSubFrame;
+ break;
+ }
+
+ default:
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Unspecified;
+ }
+ OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn,
+ (OMX_PTR)&inputPortFmt);
+
+ OMX_VIDEO_PARAM_PORTFORMATTYPE colorFormat;
+ memset(&colorFormat,0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
+ CONFIG_VERSION_SIZE(colorFormat);
+ colorFormat.nPortIndex = 1;
+ if (!is_yamato) {
+ colorFormat.eColorFormat = (OMX_COLOR_FORMATTYPE) OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
+ printf("color format nv21 %d\n", colorFormat.eColorFormat);
+ }
+ else {
+ colorFormat.eColorFormat = (OMX_COLOR_FORMATTYPE) QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka;
+ printf("color format nv21 yamato %d\n", colorFormat.eColorFormat);
+ }
+ OMX_SetParameter(dec_handle, (OMX_INDEXTYPE)OMX_IndexParamVideoPortFormat,
+ (OMX_PTR)&colorFormat);
+
+ /* Query the decoder outport's min buf requirements */
+ CONFIG_VERSION_SIZE(portFmt);
+
+ /* Port for which the Client needs to obtain info */
+ portFmt.nPortIndex = portParam.nStartPortNumber;
+
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nDec: Min Buffer Count %d\n", portFmt.nBufferCountMin);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nDec: Buffer Size %d\n", portFmt.nBufferSize);
+
+ if(OMX_DirInput != portFmt.eDir) {
+ printf ("\nDec: Expect Input Port\n");
+ return -1;
+ }
+
+ if(codec_format_option == CODEC_FORMAT_DIVX) {
+ QOMX_VIDEO_PARAM_DIVXTYPE paramDivx;
+ CONFIG_VERSION_SIZE(paramDivx);
+ paramDivx.nPortIndex = 0;
+ if(file_type_option == FILE_TYPE_DIVX_311) {
+ int off;
+ paramDivx.eFormat = QOMX_VIDEO_DIVXFormat311;
+ off = fread(&width, 1, 4, inputBufferFile);
+ if (off == 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "Failed to read width for divx\n");
+ return -1;
+ }
+ off = fread(&height, 1, 4, inputBufferFile);
+ if (off == 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "Failed to read wodth for divx\n");
+ return -1;
+ }
+
+ }
+ else if (file_type_option == FILE_TYPE_DIVX_4_5_6) {
+ paramDivx.eFormat = QOMX_VIDEO_DIVXFormat4;
+ }
+ paramDivx.eProfile = QOMX_VIDEO_DivXProfileqMobile;
+ OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamVideoDivx,
+ (OMX_PTR)¶mDivx);
+ }
+ else if(codec_format_option == CODEC_FORMAT_VP) {
+ QOMX_VIDEO_PARAM_VPTYPE paramVp;
+ CONFIG_VERSION_SIZE(paramVp);
+ paramVp.nPortIndex = 0;
+ if(file_type_option == FILE_TYPE_VP_6) {
+ paramVp.eFormat = QOMX_VIDEO_VPFormat6;
+ }
+ paramVp.eProfile = QOMX_VIDEO_VPProfileAdvanced;
+ OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamVideoVp,
+ (OMX_PTR)¶mVp);
+ } else
+ if(codec_format_option == CODEC_FORMAT_SPARK0 || codec_format_option == CODEC_FORMAT_SPARK1) {
+ QOMX_VIDEO_PARAM_SPARKTYPE paramSpark;
+ CONFIG_VERSION_SIZE(paramSpark);
+ paramSpark.nPortIndex = 0;
+ if( codec_format_option == CODEC_FORMAT_SPARK1 ) {
+
+ paramSpark.eFormat = QOMX_VIDEO_SparkFormat1;
+ }
+ else if (codec_format_option == CODEC_FORMAT_SPARK0 ) {
+
+ paramSpark.eFormat = QOMX_VIDEO_SparkFormat0;
+ }
+ OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamVideoSpark,
+ (OMX_PTR)¶mSpark);
+ }
+
+
+ bufCnt = 0;
+ portFmt.format.video.nFrameHeight = height;
+ portFmt.format.video.nFrameWidth = width;
+ if(is_use_egl_image) {
+ portFmt.format.video.pNativeWindow = (void *)0xDEADBEAF;
+ }
+ OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition,
+ (OMX_PTR)&portFmt);
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,
+ &portFmt);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nDec: New Min Buffer Count %d", portFmt.nBufferCountMin);
+
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nVideo format, height = %d", portFmt.format.video.nFrameHeight);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nVideo format, height = %d\n", portFmt.format.video.nFrameWidth);
+ if(codec_format_option == CODEC_FORMAT_H264)
+ {
+ OMX_VIDEO_CONFIG_NALSIZE naluSize;
+ naluSize.nNaluBytes = nalSize;
+ OMX_SetConfig(dec_handle,OMX_IndexConfigVideoNalSize,(OMX_PTR)&naluSize);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"SETTING THE NAL SIZE to %d\n",naluSize.nNaluBytes);
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nOMX_SendCommand Decoder -> IDLE\n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0);
+
+ input_buf_cnt = portFmt.nBufferCountMin;
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Transition to Idle State succesful...\n");
+ /* Allocate buffer on decoder's i/p port */
+ error = Allocate_Buffer(dec_handle, &pInputBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountMin, portFmt.nBufferSize);
+ if (error != OMX_ErrorNone) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - OMX_AllocateBuffer Input buffer error\n");
+ return -1;
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\nOMX_AllocateBuffer Input buffer success\n");
+ }
+
+ portFmt.nPortIndex = portParam.nStartPortNumber+1;
+ /* Port for which the Client needs to obtain info */
+
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"nMin Buffer Count=%d", portFmt.nBufferCountMin);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"nBuffer Size=%d", portFmt.nBufferSize);
+ if(OMX_DirOutput != portFmt.eDir) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - Expect Output Port\n");
+ return -1;
+ }
+
+ if(!is_use_egl_image) {
+ /* Allocate buffer on decoder's o/p port */
+ error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountMin, portFmt.nBufferSize);
+ }
+ else {
+ error = Use_EGL_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountMin, portFmt.nBufferSize, &egl_id);
+ }
+
+ if (error != OMX_ErrorNone) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - OMX_AllocateBuffer Output buffer error\n");
+ return -1;
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"OMX_AllocateBuffer Output buffer success\n");
+ }
+
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+
+ if (freeHandle_option == FREE_HANDLE_AT_IDLE)
+ {
+ OMX_STATETYPE state = OMX_StateInvalid;
+ OMX_GetState(dec_handle, &state);
+ if (state == OMX_StateIdle)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Decoder is in OMX_StateIdle and trying to call OMX_FreeHandle \n");
+ do_freeHandle_and_clean_up(false);
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state);
+ do_freeHandle_and_clean_up(true);
+ }
+ return -1;
+ }
+
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_SendCommand Decoder -> Executing\n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0);
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountMin; ++bufCnt) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_FillThisBuffer on output buf no.%d\n",bufCnt);
+ pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1;
+ pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]);
+ if (OMX_ErrorNone != ret) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - OMX_FillThisBuffer failed with result %d\n", ret);
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_FillThisBuffer success!\n");
+ }
+ }
+
+ used_ip_buf_cnt = input_buf_cnt;
+
+ rcv_v1 = 0;
+
+ QPERF_START(client_decode);
+ if ((codec_format_option == CODEC_FORMAT_VC1) && (file_type_option == FILE_TYPE_RCV))
+ {
+ pInputBufHdrs[0]->nOffset = 0;
+ frameSize = Read_Buffer_From_RCV_File_Seq_Layer(pInputBufHdrs[0]);
+ pInputBufHdrs[0]->nFilledLen = frameSize;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "After Read_Buffer_From_RCV_File_Seq_Layer frameSize %d\n", frameSize);
+ pInputBufHdrs[0]->nInputPortIndex = 0;
+ pInputBufHdrs[0]->nOffset = 0;
+ pInputBufHdrs[0]->nFlags = 0;
+ //pBufHdr[bufCnt]->pAppPrivate = this;
+ ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[0]);
+ if (OMX_ErrorNone != ret) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret);
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_EmptyThisBuffer success!\n");
+ }
+ i = 1;
+ }
+ else
+ {
+ i = 0;
+ }
+
+ for (i; i < used_ip_buf_cnt;i++) {
+ pInputBufHdrs[i]->nInputPortIndex = 0;
+ pInputBufHdrs[i]->nOffset = 0;
+ if((frameSize = Read_Buffer(pInputBufHdrs[i])) <= 0 ){
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,"NO FRAME READ\n");
+ pInputBufHdrs[i]->nFilledLen = frameSize;
+ pInputBufHdrs[i]->nInputPortIndex = 0;
+ pInputBufHdrs[i]->nFlags |= OMX_BUFFERFLAG_EOS;;
+ bInputEosReached = true;
+
+ OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]);
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,
+ "File is small::Either EOS or Some Error while reading file\n");
+ break;
+ }
+ pInputBufHdrs[i]->nFilledLen = frameSize;
+ pInputBufHdrs[i]->nInputPortIndex = 0;
+ pInputBufHdrs[i]->nFlags = 0;
+//pBufHdr[bufCnt]->pAppPrivate = this;
+ ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]);
+ if (OMX_ErrorNone != ret) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret);
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_EmptyThisBuffer success!\n");
+ }
+ }
+
+ if(0 != pthread_create(&ebd_thread_id, NULL, ebd_thread, NULL))
+ {
+ printf("\n Error in Creating fbd_thread \n");
+ free_queue(etb_queue);
+ free_queue(fbd_queue);
+ return -1;
+ }
+
+ // wait for event port settings changed event
+ wait_for_event();
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "RECIEVED EVENT PORT TO DETERMINE IF DYN PORT RECONFIGURATION NEEDED, currentStatus %d\n",
+ currentStatus);
+ if (currentStatus == INVALID_STATE)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - INVALID_STATE\n");
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ else if (currentStatus == PORT_SETTING_CHANGE_STATE)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "PORT_SETTING_CHANGE_STATE\n");
+ // Send DISABLE command
+ sent_disabled = 1;
+ OMX_SendCommand(dec_handle, OMX_CommandPortDisable, 1, 0);
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"FREEING BUFFERS\n");
+ // Free output Buffer
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountMin; ++bufCnt) {
+ OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]);
+ if(is_use_egl_image && egl_id) {
+ struct pmem arena;
+ arena.fd = egl_id[bufCnt].pmem_fd;
+ arena.size = pOutYUVBufHdrs[bufCnt]->nAllocLen;
+ pmem_free(&arena);
+ }
+ }
+
+ if(egl_id) {
+ free(egl_id);
+ egl_id = NULL;
+ }
+
+ // wait for Disable event to come back
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"DISABLE EVENT RECD\n");
+ // GetParam and SetParam
+
+ // Send Enable command
+ OMX_SendCommand(dec_handle, OMX_CommandPortEnable, 1, 0);
+ // AllocateBuffers
+ /* Allocate buffer on decoder's o/p port */
+
+ portFmt.nPortIndex = 1;
+ /* Port for which the Client needs to obtain info */
+
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Min Buffer Count=%d", portFmt.nBufferCountMin);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Buffer Size=%d", portFmt.nBufferSize);
+ if(OMX_DirOutput != portFmt.eDir) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - Expect Output Port\n");
+ return -1;
+ }
+
+ if(!is_use_egl_image) {
+ /* Allocate buffer on decoder's o/p port */
+ error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountMin, portFmt.nBufferSize);
+ }
+ else {
+ error = Use_EGL_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountMin, portFmt.nBufferSize, &egl_id);
+ }
+
+ if (error != OMX_ErrorNone) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - OMX_AllocateBuffer Output buffer error\n");
+ return -1;
+ }
+ else
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "OMX_AllocateBuffer Output buffer success\n");
+ }
+
+ // wait for enable event to come back
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"ENABLE EVENT HANDLER RECD\n");
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountMin; ++bufCnt) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"OMX_FillThisBuffer on output buf no.%d\n",bufCnt);
+ pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1;
+ pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]);
+ if (OMX_ErrorNone != ret) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "ERROR - OMX_FillThisBuffer failed with result %d\n", ret);
+ }
+ else {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"OMX_FillThisBuffer success!\n");
+ }
+ }
+ }
+
+ if (freeHandle_option == FREE_HANDLE_AT_EXECUTING)
+ {
+ OMX_STATETYPE state = OMX_StateInvalid;
+ OMX_GetState(dec_handle, &state);
+ if (state == OMX_StateExecuting)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Decoder is in OMX_StateExecuting and trying to call OMX_FreeHandle \n");
+ do_freeHandle_and_clean_up(false);
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state);
+ do_freeHandle_and_clean_up(true);
+ }
+ return -1;
+ }
+ else if (freeHandle_option == FREE_HANDLE_AT_PAUSE)
+ {
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0);
+ wait_for_event();
+
+ OMX_STATETYPE state = OMX_StateInvalid;
+ OMX_GetState(dec_handle, &state);
+ if (state == OMX_StatePause)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Decoder is in OMX_StatePause and trying to call OMX_FreeHandle \n");
+ do_freeHandle_and_clean_up(false);
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state);
+ do_freeHandle_and_clean_up(true);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle,
+ OMX_BUFFERHEADERTYPE ***pBufHdrs,
+ OMX_U32 nPortIndex,
+ long bufCntMin, long bufSize)
+{
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE error=OMX_ErrorNone;
+ long bufCnt=0;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"pBufHdrs = %x,bufCntMin = %d\n", pBufHdrs, bufCntMin);
+ *pBufHdrs= (OMX_BUFFERHEADERTYPE **)
+ malloc(sizeof(OMX_BUFFERHEADERTYPE)*bufCntMin);
+
+ for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"OMX_AllocateBuffer No %d \n", bufCnt);
+ error = OMX_AllocateBuffer(dec_handle, &((*pBufHdrs)[bufCnt]),
+ nPortIndex, NULL, bufSize);
+ }
+
+ return error;
+}
+
+static OMX_ERRORTYPE Use_EGL_Buffer ( OMX_COMPONENTTYPE *dec_handle,
+ OMX_BUFFERHEADERTYPE ***pBufHdrs,
+ OMX_U32 nPortIndex,
+ long bufCntMin, long bufSize,
+ struct use_egl_id **egl)
+{
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE error=OMX_ErrorNone;
+ long bufCnt=0;
+ struct use_egl_id *egl_info;
+ struct pmem arena;
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"pBufHdrs = %x,bufCntMin = %d\n", pBufHdrs, bufCntMin);
+ *pBufHdrs= (OMX_BUFFERHEADERTYPE **)
+ malloc(sizeof(OMX_BUFFERHEADERTYPE)*bufCntMin);
+ *egl = (struct use_egl_id *)
+ malloc(sizeof(struct use_egl_id) * bufCntMin);
+
+ for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) {
+ egl_info = *egl+bufCnt;
+ if (pmem_alloc (&arena, bufSize))
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"OMX_Use_EGL_Buffer No pmem %d \n", bufSize);
+ return OMX_ErrorInsufficientResources;
+ }
+ egl_info->pmem_fd = arena.fd;
+ egl_info->offset = 0;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"OMX_AllocateBuffer No %d \n", bufCnt);
+ error = OMX_UseEGLImage(dec_handle, &((*pBufHdrs)[bufCnt]),
+ nPortIndex, NULL, (void *) egl_info);
+ }
+
+ return error;
+}
+
+static void do_freeHandle_and_clean_up(bool isDueToError)
+{
+ int bufCnt = 0;
+
+ for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]);
+ }
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountMin; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]);
+ if(is_use_egl_image && egl_id) {
+ struct pmem arena;
+ arena.fd = egl_id[bufCnt].pmem_fd;
+ arena.size = pOutYUVBufHdrs[bufCnt]->nAllocLen;
+ pmem_free(&arena);
+ }
+ }
+ if(egl_id) {
+ free(egl_id);
+ egl_id = NULL;
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - Free handle decoder\n");
+ OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle);
+ if (result != OMX_ErrorNone)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "[OMX Vdec Test] - OMX_FreeHandle error. Error code: %d\n", result);
+ }
+ dec_handle = NULL;
+
+ /* Deinit OpenMAX */
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - De-initializing OMX \n");
+ OMX_Deinit();
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - closing all files\n");
+ if(inputBufferFile)
+ {
+ fclose(inputBufferFile);
+ inputBufferFile = NULL;
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - after free inputfile\n");
+
+ if (takeYuvLog && outputBufferFile) {
+ fclose(outputBufferFile);
+ outputBufferFile = NULL;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - after free outputfile\n");
+
+ if(etb_queue)
+ {
+ free_queue(etb_queue);
+ etb_queue = NULL;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - after free etb_queue \n");
+ if(fbd_queue)
+ {
+ free_queue(fbd_queue);
+ fbd_queue = NULL;
+ }
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"[OMX Vdec Test] - after free iftb_queue\n");
+
+
+ printf("*****************************************\n");
+ if (isDueToError)
+ {
+ printf("************...TEST FAILED...************\n");
+ }
+ else
+ {
+ printf("**********...TEST SUCCESSFULL...*********\n");
+ }
+ printf("*****************************************\n");
+}
+
+static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ long frameSize=0;
+ char temp_buffer[10];
+ char temp_byte;
+ int bytes_read=0;
+ int i=0;
+ unsigned char *read_buffer=NULL;
+ char c = '1'; //initialize to anything except '\0'(0)
+ char inputFrameSize[10];
+ int count =0; char cnt =0;
+ memset(temp_buffer, 0, sizeof(temp_buffer));
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Inside %s \n", __FUNCTION__);
+
+ while (cnt < 10)
+ /* Check the input file format, may result in infinite loop */
+ {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"loop[%d] count[%d]\n",cnt,count);
+ count = fread(&inputFrameSize[cnt], 1, 1, inputBufferFile);
+ if(inputFrameSize[cnt] == '\0' )
+ break;
+ cnt++;
+ }
+ inputFrameSize[cnt]='\0';
+ frameSize = atoi(inputFrameSize);
+ pBufHdr->nFilledLen = 0;
+
+ /* get the frame length */
+ fseek(inputBufferFile, -1, SEEK_CUR);
+ bytes_read = fread(pBufHdr->pBuffer, 1, frameSize, inputBufferFile);
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Actual frame Size [%d] bytes_read using fread[%d]\n",
+ frameSize, bytes_read);
+
+ if(bytes_read == 0 || bytes_read < frameSize ) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Bytes read Zero After Read frame Size \n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Checking VideoPlayback Count:video_playback_count is:%d\n",
+ video_playback_count);
+ return 0;
+ }
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ return bytes_read;
+}
+
+static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ char temp_buffer[10];
+ char temp_byte;
+ int bytes_read=0;
+ int i=0;
+ unsigned char *read_buffer=NULL;
+ char c = '1'; //initialize to anything except '\0'(0)
+ char inputFrameSize[10];
+ int count =0; char cnt =0;
+ memset(temp_buffer, 0, sizeof(temp_buffer));
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+
+ bytes_read = fread(pBufHdr->pBuffer, 1, NUMBER_OF_ARBITRARYBYTES_READ, inputBufferFile);
+
+ if(bytes_read == 0) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Bytes read Zero After Read frame Size \n");
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Checking VideoPlayback Count:video_playback_count is:%d\n",
+ video_playback_count);
+ return 0;
+ }
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ return bytes_read;
+}
+
+static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int readOffset = 0;
+ unsigned int ret = 0;
+ int bytes_read = 0;
+ unsigned int code = 0;
+ pBufHdr->nFilledLen = 0;
+ static unsigned int header_code = 0;
+ unsigned char data;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+
+ do
+ {
+ //Start codes are always byte aligned.
+ if(readOffset <= pBufHdr->nAllocLen) {
+ bytes_read = fread(&pBufHdr->pBuffer[readOffset],1, 1,inputBufferFile);
+ data = pBufHdr->pBuffer[readOffset];
+ }
+ else {
+ bytes_read = fread(&data,1, 1,inputBufferFile);
+ }
+ if(!bytes_read)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Bytes read Zero \n");
+ break;
+ }
+ code <<= 8;
+ code |= (0x000000FF & data);
+ //VOP start code comparision
+ if (readOffset>3)
+ {
+ if(!header_code ){
+ if( VOP_START_CODE == code)
+ {
+ header_code = VOP_START_CODE;
+ }
+ else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE )
+ {
+ header_code = SHORT_HEADER_START_CODE;
+ }
+ else if ( (0xFFFFFC00 & code) == SPARK1_START_CODE )
+ {
+ header_code = SPARK1_START_CODE;
+ }
+ }
+ if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=3;
+ break;
+
+ }
+ else if ( (( header_code == SHORT_HEADER_START_CODE ) && ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) ||
+ (( header_code == SPARK1_START_CODE ) && ( SPARK1_START_CODE == (code & 0xFFFFFC00))) )
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=3;
+ break;
+ }
+ }
+ readOffset++;
+ }while (1);
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ ret = ((readOffset > pBufHdr->nAllocLen)?pBufHdr->nAllocLen:readOffset);
+ return ret;
+}
+
+static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ // NAL unit stream processing
+ char temp_size[SIZE_NAL_FIELD_MAX];
+ int i = 0;
+ int j = 0;
+ unsigned int size = 0, readSize = 0; // Need to make sure that uint32 has SIZE_NAL_FIELD_MAX (4) bytes
+ int bytes_read = 0;
+
+ // read the "size_nal_field"-byte size field
+ bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset, 1, nalSize, inputBufferFile);
+ if (bytes_read == 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "Failed to read frame or it might be EOF\n");
+ return 0;
+ }
+
+ for (i=0; i<SIZE_NAL_FIELD_MAX-nalSize; i++)
+ {
+ temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = 0;
+ }
+
+ /* Due to little endiannes, Reorder the size based on size_nal_field */
+ for (j=0; i<SIZE_NAL_FIELD_MAX; i++, j++)
+ {
+ temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = pBufHdr->pBuffer[pBufHdr->nOffset + j];
+ }
+ size = (unsigned int)(*((unsigned int *)(temp_size)));
+
+ readSize =( (size > pBufHdr->nAllocLen)?pBufHdr->nAllocLen:size);
+
+ // now read the data
+ bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset + nalSize, 1, readSize, inputBufferFile);
+ if (bytes_read != readSize)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "Failed to read frame\n");
+ }
+ if(readSize < size)
+ {
+ /* reseek to beginning of sequence header */
+ fseek(inputBufferFile, size-bytes_read, SEEK_CUR);
+ }
+
+ return bytes_read + nalSize;
+}
+
+static int Read_Buffer_From_FrameSize_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int size = 0, readSize =0;
+ unsigned int readOffset = 0;
+ unsigned char* pBuf = pBufHdr->pBuffer + pBufHdr->nOffset;
+
+ // read the vop size bytes
+ readOffset = fread(&size, 1, 4, inputBufferFile);
+ if (readOffset != 4)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,"ReadBufferUsingVopSize failed to read vop size bytes\n");
+ return 0;
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"vop Size=%d bytes_read=%d \n",size,readOffset);
+
+ readSize =( (size > pBufHdr->nAllocLen)?pBufHdr->nAllocLen:size);
+ // read the vop
+ readOffset = fread(pBuf, 1, readSize, inputBufferFile);
+ if (readOffset != readSize)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,"ReadBufferUsingVopSize failed to read vop %d bytes\n", size);
+ return 0;
+ }
+ if(readSize < size)
+ {
+ /* reseek to beginning of next frame */
+ fseek(inputBufferFile, size-readOffset, SEEK_CUR);
+ }
+
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;;
+ return readOffset;
+}
+static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int readOffset = 0, size_struct_C = 0;
+ unsigned int startcode = 0;
+ pBufHdr->nFilledLen = 0;
+ pBufHdr->nFlags = 0;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+
+ fread(&startcode, 4, 1, inputBufferFile);
+
+ /* read size of struct C as it need not be 4 always*/
+ fread(&size_struct_C, 1, 4, inputBufferFile);
+
+ /* reseek to beginning of sequence header */
+ fseek(inputBufferFile, -8, SEEK_CUR);
+
+ if ((startcode & 0xFF000000) == 0xC5000000)
+ {
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C);
+
+ readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC + size_struct_C, inputBufferFile);
+ }
+ else if((startcode & 0xFF000000) == 0x85000000)
+ {
+ // .RCV V1 file
+
+ rcv_v1 = 1;
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C);
+
+ readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC + size_struct_C, inputBufferFile);
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error: Unknown VC1 clip format %x\n", startcode);
+ }
+
+#if 0
+ {
+ int i=0;
+ printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", readOffset, readOffset);
+ for (i=0; i<36; i++)
+ {
+ printf("0x%.2x ", pBufHdr->pBuffer[i]);
+ if (i%16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+ return readOffset;
+}
+
+static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int readOffset = 0;
+ unsigned int len = 0;
+ unsigned int key = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File - nOffset %d\n", pBufHdr->nOffset);
+ if(rcv_v1)
+ {
+ /* for the case of RCV V1 format, the frame header is only of 4 bytes and has
+ only the frame size information */
+ readOffset = fread(&len, 1, 4, inputBufferFile);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File - framesize %d %x\n", len, len);
+
+ }
+ else
+ {
+ /* for a regular RCV file, 3 bytes comprise the frame size and 1 byte for key*/
+ readOffset = fread(&len, 1, 3, inputBufferFile);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File - framesize %d %x\n", len, len);
+
+ readOffset = fread(&key, 1, 1, inputBufferFile);
+ if ( (key & 0x80) == false)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File - Non IDR frame key %x\n", key);
+ }
+
+ }
+
+ if(!rcv_v1)
+ {
+ /* There is timestamp field only for regular RCV format and not for RCV V1 format*/
+ readOffset = fread(&pBufHdr->nTimeStamp, 1, 4, inputBufferFile);
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Read_Buffer_From_RCV_File - timeStamp %d\n", pBufHdr->nTimeStamp);
+ }
+
+ if(len > pBufHdr->nAllocLen)
+ {
+ QTV_MSG_PRIO3(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"Error in sufficient buffer framesize %d, allocalen %d noffset %d\n",len,pBufHdr->nAllocLen, pBufHdr->nOffset);
+ readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, pBufHdr->nAllocLen - pBufHdr->nOffset , inputBufferFile);
+ fseek(inputBufferFile, len - readOffset,SEEK_CUR);
+ return readOffset;
+ }
+ else
+ readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, len, inputBufferFile);
+ if (readOffset != len)
+ {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "EOS reach or Reading error %d, %s \n", readOffset, strerror( errno ));
+ return 0;
+ }
+
+#if 0
+ {
+ int i=0;
+ printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", len, readOffset);
+ for (i=0; i<64; i++)
+ {
+ printf("0x%.2x ", pBufHdr->pBuffer[i]);
+ if (i%16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+
+ return readOffset;
+}
+
+static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ static int timeStampLfile = 0;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Inside %s \n", __FUNCTION__);
+
+ unsigned int readOffset = 0;
+ int bytes_read = 0;
+ unsigned int code = 0;
+ pBufHdr->nFilledLen = 0;
+
+ do
+ {
+ //Start codes are always byte aligned.
+ bytes_read = fread(&pBufHdr->pBuffer[readOffset],1, 1,inputBufferFile);
+ if(!bytes_read)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"\n Bytes read Zero \n");
+ break;
+ }
+ code <<= 8;
+ code |= (0x000000FF & pBufHdr->pBuffer[readOffset]);
+ //VOP start code comparision
+ if (readOffset>3)
+ {
+ if (VC1_START_CODE == (code & 0xFFFFFF00))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=3;
+
+ while(pBufHdr->pBuffer[readOffset-1] == 0)
+ readOffset--;
+
+ break;
+ }
+ }
+ readOffset++;
+ }while (1);
+
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += 100;
+
+#if 0
+ {
+ int i=0;
+ printf("Read_Buffer_From_VC1_File, readOffset %d\n", readOffset);
+ for (i=0; i<64; i++)
+ {
+ printf("0x%.2x ", pBufHdr->pBuffer[i]);
+ if (i%16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+
+ return readOffset;
+}
+
+static int open_video_file ()
+{
+ int error_code = 0;
+ char outputfilename[512];
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "Inside %s filename=%s\n", __FUNCTION__, in_filename);
+
+ inputBufferFile = fopen (in_filename, "rb");
+ if (inputBufferFile == NULL) {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Error - i/p file %s could NOT be opened\n",
+ in_filename);
+ error_code = -1;
+ }
+ else {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"I/p file %s is opened \n", in_filename);
+ }
+
+ if (takeYuvLog) {
+ strncpy(outputfilename, "yuvframes.yuv", 14);
+ outputBufferFile = fopen (outputfilename, "ab");
+ if (outputBufferFile == NULL)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "ERROR - o/p file %s could NOT be opened\n", outputfilename);
+ error_code = -1;
+ }
+ else
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,
+ "O/p file %s is opened \n", outputfilename);
+ }
+ }
+ return error_code;
+}
+
+void swap_byte(char *pByte, int nbyte)
+{
+ int i=0;
+
+ for (i=0; i<nbyte/2; i++)
+ {
+ pByte[i] ^= pByte[nbyte-i-1];
+ pByte[nbyte-i-1] ^= pByte[i];
+ pByte[i] ^= pByte[nbyte-i-1];
+ }
+}
+
+void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int addr = 0;
+ OMX_OTHER_EXTRADATATYPE *pExtraData = 0;
+ OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0;
+ OMX_QCOM_EXTRADATA_FRAMEDIMENSION *pExtraFrameDimension = 0;
+ OMX_QCOM_EXTRADATA_CODEC_DATA *pExtraCodecData = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
+ unsigned int destx, desty,destW, destH;
+ struct use_egl_id *egl_info = NULL;
+#ifdef _ANDROID_
+ MemoryHeapBase *vheap = NULL;
+#endif
+
+ unsigned int end = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nAllocLen);
+
+ struct mdp_blit_req *e;
+ union {
+ char dummy[sizeof(struct mdp_blit_req_list) +
+ sizeof(struct mdp_blit_req) * 1];
+ struct mdp_blit_req_list list;
+ } img;
+
+ if (fb_fd < 0)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Warning: /dev/fb0 is not opened!\n");
+ return;
+ }
+
+ if(is_use_egl_image) {
+ egl_info = (struct use_egl_id *)pBufHdr->pBuffer;
+ }
+
+ img.list.count = 1;
+ e = &img.list.req[0];
+
+
+ if(!is_use_egl_image) {
+ addr = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nFilledLen);
+ // align to a 4 byte boundary
+ addr = (addr + 3) & (~3);
+
+ // read to the end of existing extra data sections
+ pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr;
+
+ while (addr < end && pExtraData->eType != OMX_ExtraDataNone)
+ {
+ if (pExtraData->eType == OMX_ExtraDataFrameInfo)
+ {
+ pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtraData->data;
+ }
+ if (pExtraData->eType == OMX_ExtraDataFrameDimension)
+ {
+ pExtraFrameDimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)pExtraData->data;
+ }
+
+ if (pExtraData->eType == OMX_ExtraDataH264)
+ {
+ pExtraCodecData = (OMX_QCOM_EXTRADATA_CODEC_DATA *)pExtraData->data;
+ }
+
+ addr += pExtraData->nSize;
+ pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr;
+ }
+
+ if (pExtraData->eType == OMX_ExtraDataNone)
+ {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "pExtraData->eType %d pExtraData->nSize %d\n",pExtraData->eType,pExtraData->nSize);
+ }
+
+ if (pExtraCodecData)
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"Extra Data Codec Data TimeStamp %d\n",pExtraCodecData->h264ExtraData.seiTimeStamp);
+
+ if (pExtraFrameDimension)
+ {
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Extra Data FrameDimension DecWidth %d DecHeight %d\n",pExtraFrameDimension->nDecWidth,pExtraFrameDimension->nDecHeight);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "Extra Data FrameDimension CropWidth %d CropHeight %d\n",pExtraFrameDimension->nActualWidth,pExtraFrameDimension->nActualHeight);
+ }
+
+ }
+ if (pBufHdr->nOffset)
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"pBufHdr->nOffset = %d \n",pBufHdr->nOffset);
+
+
+ pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
+ pBufHdr->pPlatformPrivate)->entryList->entry;
+#ifdef _ANDROID_
+ vheap = (MemoryHeapBase *)pPMEMInfo->pmem_fd;
+#endif
+
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "DecWidth %d DecHeight %d\n",portFmt.format.video.nStride,portFmt.format.video.nSliceHeight);
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "DispWidth %d DispHeight %d\n",portFmt.format.video.nFrameWidth,portFmt.format.video.nFrameHeight);
+
+
+ if(pExtraFrameDimension)
+ {
+ e->src.width = pExtraFrameDimension->nDecWidth;
+ e->src.height = pExtraFrameDimension->nDecHeight;
+ }else{
+ e->src.width = portFmt.format.video.nStride;
+ e->src.height = portFmt.format.video.nSliceHeight;
+ }
+
+ e->src.format = MDP_Y_CBCR_H2V2;
+ if(is_use_egl_image) {
+ e->src.offset = egl_info->offset;
+ e->src.memory_id = egl_info->pmem_fd;
+ }
+ else {
+ e->src.offset = pPMEMInfo->offset;
+#ifdef _ANDROID_
+ e->src.memory_id = vheap->getHeapID();
+#else
+ e->src.memory_id = pPMEMInfo->pmem_fd;
+#endif
+ }
+
+ QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "pmemOffset %d pmemID %d\n",e->src.offset,e->src.memory_id);
+
+ e->dst.width = finfo.line_length/2;
+ e->dst.height = vinfo.yres;
+ e->dst.format = MDP_RGB_565;
+ e->dst.offset = 0;
+ e->dst.memory_id = fb_fd;
+
+ e->transp_mask = 0xffffffff;
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,
+ "Frame interlace type %d!\n", pExtraFrameInfo->interlaceType);
+ if(pExtraFrameInfo && pExtraFrameInfo->interlaceType != OMX_QCOM_InterlaceFrameProgressive)
+ {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,
+ "Intrelaced Frame!\n");
+ e->flags = MDP_DEINTERLACE;
+ }
+ else
+ e->flags = 0;
+ e->alpha = 0xff;
+
+ switch(displayWindow)
+ {
+ case 1: destx = 0;
+ desty = 0;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+ case 2: destx = vinfo.xres/2;
+ desty = 0;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+
+ case 3: destx = 0;
+ desty = vinfo.yres/2;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+ case 4: destx = vinfo.xres/2;
+ desty = vinfo.yres/2;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+ case 0:
+ default:
+ destx = 0;
+ desty = 0;
+ destW = finfo.line_length;
+ destH = vinfo.yres;
+ }
+
+ if(portFmt.format.video.nFrameWidth < destW)
+ {
+ if(pExtraFrameDimension)
+ destW=pExtraFrameDimension->nActualWidth;
+ else
+ destW = portFmt.format.video.nFrameWidth ;
+ }
+
+ if(portFmt.format.video.nFrameHeight < destH)
+ {
+ if(pExtraFrameDimension)
+ destH=pExtraFrameDimension->nActualHeight;
+ else
+ destH = portFmt.format.video.nFrameHeight;
+ }
+
+ e->dst_rect.x = destx;
+ e->dst_rect.y = desty;
+ e->dst_rect.w = destW;
+ e->dst_rect.h = destH;
+
+ //e->dst_rect.w = 800;
+ //e->dst_rect.h = 480;
+
+ e->src_rect.x = 0;
+ e->src_rect.y = 0;
+
+ if(pExtraFrameDimension)
+ {
+ e->src_rect.w = pExtraFrameDimension->nActualWidth;
+ e->src_rect.h = pExtraFrameDimension->nActualHeight;
+ }else{
+ e->src_rect.w = portFmt.format.video.nFrameWidth;
+ e->src_rect.h = portFmt.format.video.nFrameHeight;
+ }
+
+ //e->src_rect.w = portFmt.format.video.nStride;
+ //e->src_rect.h = portFmt.format.video.nSliceHeight;
+
+ if (ioctl(fb_fd, MSMFB_BLIT, &img)) {
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"MSMFB_BLIT ioctl failed!\n");
+ return;
+ }
+
+ if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0)
+ {
+ QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,
+ "FBIOPAN_DISPLAY failed! line=%d\n", __LINE__);
+ return;
+ }
+
+ QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"render_fb complete!\n");
+}
+
diff --git a/omx/mm-video/qdsp6/vdec/test/queue.c b/omx/mm-video/qdsp6/vdec/test/queue.c
new file mode 100644
index 0000000..3940e40
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/test/queue.c
@@ -0,0 +1,127 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*
+ Queue with Linked list
+*/
+
+#include "queue.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct Node
+{
+ void *element;
+ struct Node *next;
+} Node;
+
+struct Queue
+{
+ Node *head;
+ Node *tail;
+ int current_size;
+};
+
+Queue *alloc_queue()
+{
+ Queue *q = (Queue *) malloc(sizeof(Queue));
+ if (q)
+ {
+ q->head = q->tail = NULL;
+ q->current_size = 0;
+ }
+ return q;
+}
+
+void free_queue(Queue *q)
+{
+ while (q->current_size)
+ {
+ pop(q);
+ }
+}
+
+void free_queue_and_qelement(Queue *q)
+{
+ while (q->current_size)
+ {
+ void *element = pop(q);
+ if (element)
+ free(element);
+ }
+}
+
+int push(Queue *q, void * element)
+{
+ Node *new_node = (Node *) malloc(sizeof(Node));
+
+ if (new_node == NULL)
+ return -1;
+
+ new_node->element = element;
+ new_node->next = NULL;
+
+ if (q->current_size == 0)
+ {
+ q->head = new_node;
+ }
+ else
+ {
+ q->tail->next = new_node;
+ }
+
+ q->tail = new_node;
+ q->current_size++;
+
+ return 0;
+}
+
+void *pop(Queue *q)
+{
+ Node *temp;
+ void *element;
+
+ if (q->current_size == 0)
+ return NULL;
+
+ temp = q->head;
+ element = temp->element;
+
+ if (q->current_size == 1)
+ {
+ q->head = q->tail = NULL;
+ }
+ else
+ {
+ q->head = q->head->next;
+ }
+
+ free(temp);
+ q->current_size--;
+ return element;
+}
+
diff --git a/omx/mm-video/qdsp6/vdec/test/queue.h b/omx/mm-video/qdsp6/vdec/test/queue.h
new file mode 100644
index 0000000..65f5151
--- /dev/null
+++ b/omx/mm-video/qdsp6/vdec/test/queue.h
@@ -0,0 +1,39 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef QUEUE_H
+#define QUEUE_H
+
+typedef struct Queue Queue;
+
+Queue *alloc_queue();
+void free_queue(Queue *q);
+void free_queue_and_qelement(Queue *q);
+int push(Queue *q, void * element);
+void *pop(Queue *q);
+
+#endif
diff --git a/omx/mm-video/qdsp6/venc/Android.mk b/omx/mm-video/qdsp6/venc/Android.mk
new file mode 100644
index 0000000..bb8638a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/Android.mk
@@ -0,0 +1,106 @@
+ifneq ($(BUILD_TINY_ANDROID),true)
+
+ROOT_DIR := $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_PATH:= $(ROOT_DIR)
+
+# ---------------------------------------------------------------------------------
+# Common definitons
+# ---------------------------------------------------------------------------------
+
+libmm-venc-def := -DVENC_MSG_ERROR_ENABLE
+libmm-venc-def += -DVENC_MSG_FATAL_ENABLE
+libmm-venc-def += -DQCOM_OMX_VENC_EXT
+libmm-venc-def += -O3
+libmm-venc-def += -D_ANDROID_LOG_
+libmm-venc-def += -D_ANDROID_LOG_ERROR
+libmm-venc-def += -D_ANDROID_LOG_PROFILE
+libmm-venc-def += -Du32="unsigned int"
+
+# ---------------------------------------------------------------------------------
+# Make the Shared library (libOmxVidEnc)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+libmm-venc-inc += $(LOCAL_PATH)/omx/inc
+libmm-venc-inc += $(LOCAL_PATH)/device/inc
+libmm-venc-inc += $(LOCAL_PATH)/common/inc
+libmm-venc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore
+
+LOCAL_MODULE := libOmxVidEnc
+LOCAL_CFLAGS := $(libmm-venc-def)
+LOCAL_C_INCLUDES := $(libmm-venc-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog libutils
+
+LOCAL_SRC_FILES := omx/src/OMX_Venc.cpp
+LOCAL_SRC_FILES += omx/src/OMX_VencBufferManager.cpp
+LOCAL_SRC_FILES += device/src/venc_device.c
+
+include $(BUILD_SHARED_LIBRARY)
+
+# ---------------------------------------------------------------------------------
+# Make the apps-test (mm-venc-omx-test)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+mm-venc-test-inc := $(LOCAL_PATH)/src
+mm-venc-test-inc += $(LOCAL_PATH)/test
+mm-venc-test-inc += $(LOCAL_PATH)/test/common/inc
+mm-venc-test-inc += $(LOCAL_PATH)/common/inc
+mm-venc-test-inc += $(LOCAL_PATH)/omx/inc
+mm-venc-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore
+
+LOCAL_MODULE := mm-venc-omx-test
+LOCAL_CFLAGS := $(libmm-venc-def)
+LOCAL_C_INCLUDES := $(mm-venc-test-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libdl libOmxCore libOmxVidEnc
+
+LOCAL_SRC_FILES := test/app/src/venctest_App.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Config.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Pmem.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Encoder.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Script.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_File.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_FileSink.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Mutex.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Parser.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_FileSource.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Queue.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Signal.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_SignalQueue.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Sleeper.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Thread.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_Time.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_StatsThread.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestCaseFactory.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_ITestCase.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestEncode.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestIFrameRequest.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestGetSyntaxHdr.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestEOS.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestChangeQuality.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestChangeIntraPeriod.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestStateExecutingToIdle.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestStatePause.cpp
+LOCAL_SRC_FILES += test/common/src/venctest_TestFlush.cpp
+LOCAL_SRC_FILES += common/src/venc_queue.c
+LOCAL_SRC_FILES += common/src/venc_semaphore.c
+LOCAL_SRC_FILES += common/src/venc_mutex.c
+LOCAL_SRC_FILES += common/src/venc_time.c
+LOCAL_SRC_FILES += common/src/venc_sleep.c
+LOCAL_SRC_FILES += common/src/venc_signal.c
+LOCAL_SRC_FILES += common/src/venc_file.c
+LOCAL_SRC_FILES += common/src/venc_thread.c
+
+include $(BUILD_EXECUTABLE)
+
+endif #BUILD_TINY_ANDROID
+
+# ---------------------------------------------------------------------------------
+# END
+# ---------------------------------------------------------------------------------
+
diff --git a/omx/mm-video/qdsp6/venc/Makefile b/omx/mm-video/qdsp6/venc/Makefile
new file mode 100644
index 0000000..23f9485
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/Makefile
@@ -0,0 +1,137 @@
+# ---------------------------------------------------------------------------------
+# MM-VIDEO-OSS-8K-VENC
+# ---------------------------------------------------------------------------------
+
+# cross-compiler flags
+CFLAGS += -Wall
+CFLAGS += -Wundef
+CFLAGS += -Wstrict-prototypes
+CFLAGS += -Wno-trigraphs
+#CFLAGS += -Werror
+
+# cross-compile flags specific to shared objects
+CFLAGS_SO += -fpic
+
+# required pre-processor flags
+CPPFLAGS += -D__packed__=
+CPPFLAGS += -DIMAGE_APPS_PROC
+CPPFLAGS += -DFEATURE_Q_SINGLE_LINK
+CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR
+CPPFLAGS += -DFEATURE_LINUX
+CPPFLAGS += -DFEATURE_NATIVELINUX
+CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS
+
+# venc specific defines
+CPPFLAGS += -DPROFILE_DECODER
+CPPFLAGS += -DVENC_MSG_ERROR_ENABLE
+CPPFLAGS += -DVENC_MSG_FATAL_ENABLE
+CPPFLAGS += -DQCOM_OMX_VENC_EXT
+CPPFLAGS += -Du32="unsigned int"
+
+CPPFLAGS += -Iinc
+CPPFLAGS += -Icommon/inc
+CPPFLAGS += -Idevice/inc
+CPPFLAGS += -Iomx/inc
+CPPFLAGS += -Itest/common/inc
+
+# linker flags
+LDFLAGS += -L$(SYSROOT)/usr/lib
+
+# linker flags for shared objects
+LDFLAGS_SO += -shared
+
+MM_VENC_OMX_LDLIBS := -lpthread
+MM_VENC_OMX_LDLIBS += -lrt
+MM_VENC_OMX_LDLIBS += -lstdc++
+MM_VENC_OMX_LDLIBS += -lOmxCore
+
+LDLIBS += $(MM_VENC_OMX_LDLIBS)
+
+SRCS := omx/src/OMX_Venc.cpp
+SRCS += omx/src/OMX_VencBufferManager.cpp
+SRCS += device/src/venc_device.c
+
+# defintions
+LIBMAJOR := $(basename $(basename $(LIBVER)))
+LIBINSTALLDIR := $(DESTDIR)usr/lib
+BININSTALLDIR := $(DESTDIR)usr/bin
+
+# ---------------------------------------------------------------------------------
+# BUILD
+# ---------------------------------------------------------------------------------
+all: libOmxVidEnc.so.$(LIBVER) mm-venc-omx-test
+
+install:
+ echo "installing opensource video encoder libs in $(DESTDIR)"
+ if [ ! -d $(LIBINSTALLDIR) ]; then mkdir -p $(LIBINSTALLDIR); fi
+ if [ ! -d $(BININSTALLDIR) ]; then mkdir -p $(BININSTALLDIR); fi
+ install -m 555 libOmxVidEnc.so.$(LIBVER) $(LIBINSTALLDIR)
+ cd $(LIBINSTALLDIR) && ln -s libOmxVidEnc.so.$(LIBVER) libOmxVidEnc.so.$(LIBMAJOR)
+ cd $(LIBINSTALLDIR) && ln -s libOmxVidEnc.so.$(LIBMAJOR) libOmxVidEnc.so
+ install -m 555 mm-venc-omx-test $(BININSTALLDIR)
+
+# ---------------------------------------------------------------------------------
+# COMPILE LIBRARY
+# ---------------------------------------------------------------------------------
+LDLIBS := -lpthread
+LDLIBS += -lrt
+LDLIBS += -lstdc++
+LDLIBS += -lOmxCore
+
+SRCS := omx/src/OMX_Venc.cpp
+SRCS += omx/src/OMX_VencBufferManager.cpp
+SRCS += device/src/venc_device.c
+
+libOmxVidEnc.so.$(LIBVER): $(SRCS)
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxVidEnc.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS)
+
+# ---------------------------------------------------------------------------------
+# COMPILE TEST APP
+# ---------------------------------------------------------------------------------
+TEST_LDLIBS := -lpthread
+TEST_LDLIBS += -ldl
+TEST_LDLIBS += -lOmxCore
+
+TEST_SRCS := test/app/src/venctest_App.cpp
+TEST_SRCS += test/common/src/venctest_Config.cpp
+TEST_SRCS += test/common/src/venctest_Pmem.cpp
+TEST_SRCS += test/common/src/venctest_Encoder.cpp
+TEST_SRCS += test/common/src/venctest_Script.cpp
+TEST_SRCS += test/common/src/venctest_File.cpp
+TEST_SRCS += test/common/src/venctest_FileSink.cpp
+TEST_SRCS += test/common/src/venctest_Mutex.cpp
+TEST_SRCS += test/common/src/venctest_Parser.cpp
+TEST_SRCS += test/common/src/venctest_FileSource.cpp
+TEST_SRCS += test/common/src/venctest_Queue.cpp
+TEST_SRCS += test/common/src/venctest_Signal.cpp
+TEST_SRCS += test/common/src/venctest_SignalQueue.cpp
+TEST_SRCS += test/common/src/venctest_Sleeper.cpp
+TEST_SRCS += test/common/src/venctest_Thread.cpp
+TEST_SRCS += test/common/src/venctest_Time.cpp
+TEST_SRCS += test/common/src/venctest_StatsThread.cpp
+TEST_SRCS += test/common/src/venctest_TestCaseFactory.cpp
+TEST_SRCS += test/common/src/venctest_ITestCase.cpp
+TEST_SRCS += test/common/src/venctest_TestEncode.cpp
+TEST_SRCS += test/common/src/venctest_TestIFrameRequest.cpp
+TEST_SRCS += test/common/src/venctest_TestGetSyntaxHdr.cpp
+TEST_SRCS += test/common/src/venctest_TestEOS.cpp
+TEST_SRCS += test/common/src/venctest_TestChangeQuality.cpp
+TEST_SRCS += test/common/src/venctest_TestChangeIntraPeriod.cpp
+TEST_SRCS += test/common/src/venctest_TestStateExecutingToIdle.cpp
+TEST_SRCS += test/common/src/venctest_TestStatePause.cpp
+TEST_SRCS += test/common/src/venctest_TestFlush.cpp
+TEST_SRCS += common/src/venc_queue.c
+TEST_SRCS += common/src/venc_semaphore.c
+TEST_SRCS += common/src/venc_mutex.c
+TEST_SRCS += common/src/venc_time.c
+TEST_SRCS += common/src/venc_sleep.c
+TEST_SRCS += common/src/venc_signal.c
+TEST_SRCS += common/src/venc_file.c
+TEST_SRCS += common/src/venc_thread.c
+
+mm-venc-omx-test: libOmxVidEnc.so.$(LIBVER) $(TEST_SRCS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS)
+
+# ---------------------------------------------------------------------------------
+# END
+# ---------------------------------------------------------------------------------
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_debug.h b/omx/mm-video/qdsp6/venc/common/inc/venc_debug.h
new file mode 100644
index 0000000..1ba5a2a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_debug.h
@@ -0,0 +1,98 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_DEBUG_H
+#define _VENC_DEBUG_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include <stdio.h>
+#include <string.h>
+
+#define LOG_NDEBUG 0
+
+#ifdef _ANDROID_LOG_
+#ifndef LOG_TAG
+#define LOG_TAG "VENC_ENC"
+#include <utils/Log.h>
+#endif
+#include <utils/threads.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+
+#define VENC_MSG_PROFILE(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_ERROR(fmt, ...) LOGE("VENC_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_FATAL(fmt, ...) LOGE("VENC_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+
+#ifdef _ANDROID_LOG_DEBUG
+#define VENC_MSG_LOW(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_MEDIUM(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_HIGH(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#else
+#define VENC_MSG_LOW(fmt, ...)
+#define VENC_MSG_MEDIUM(fmt, ...)
+#define VENC_MSG_HIGH(fmt, ...)
+#endif
+
+#else
+
+#define VENC_MSG_HIGH(fmt, ...) fprintf(stderr, "VENC_HIGH %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_PROFILE(fmt, ...) fprintf(stderr, "VENC_PROFILE %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_ERROR(fmt, ...) fprintf(stderr, "VENC_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_FATAL(fmt, ...) fprintf(stderr, "VENC_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+
+#ifdef VENC_MSG_LOG_DEBUG
+#define VENC_MSG_LOW(fmt, ...) fprintf(stderr, "VENC_LOW %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_MSG_MEDIUM(fmt, ...) fprintf(stderr, "VENC_MEDIUM %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#else
+#define VENC_MSG_LOW(fmt, ...)
+#define VENC_MSG_MEDIUM(fmt, ...)
+#endif
+
+/*
+#define QC_OMX_MSG_LOW(fmt, a, b, c) printf("QC_OMX (LOW): (%s::%d) "fmt"\n", __FUNCTION__, __LINE__, (a), (b), (c))
+#define QC_OMX_MSG_MEDIUM(fmt, a, b, c) printf("QC_OMX (MEDIUM): (%s::%d) "fmt"\n", __FUNCTION__, __LINE__, (a), (b), (c))
+#define QC_OMX_MSG_HIGH(fmt, a, b, c) printf("QC_OMX (HIGH): (%s::%d) "fmt"\n", __FUNCTION__, __LINE__, (a), (b), (c))
+#define QC_OMX_MSG_ERROR(fmt, a, b, c) printf("QC_OMX (ERROR): (%s::%d) "fmt"\n", __FUNCTION__, __LINE__, (a), (b), (c))
+#define QC_OMX_MSG_FATAL(fmt, a, b, c) printf("QC_OMX (FATAL): (%s::%d) "fmt"\n", __FUNCTION__, __LINE__, (a), (b), (c))
+#define QC_OMX_MSG_PROFILE(fmt, a, b, c) printf("QC_OMX (PROFILE): (%s::%d) "fmt"\n", __FUNCTION__, __LINE__, (a), (b), (c))
+*/
+
+#endif //#ifdef _ANDROID_LOG_
+
+#define QC_OMX_MSG_LOW VENC_MSG_LOW
+#define QC_OMX_MSG_MEDIUM VENC_MSG_MEDIUM
+#define QC_OMX_MSG_HIGH VENC_MSG_HIGH
+#define QC_OMX_MSG_ERROR VENC_MSG_ERROR
+#define QC_OMX_MSG_FATAL VENC_MSG_FATAL
+#define QC_OMX_MSG_PROFILE VENC_MSG_PROFILE
+
+#endif // #ifndef _VENC_DEBUG_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_file.h b/omx/mm-video/qdsp6/venc/common/inc/venc_file.h
new file mode 100644
index 0000000..56a37f8
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_file.h
@@ -0,0 +1,94 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_FILE_H
+#define _VENC_FILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+ * @brief Opens the file in read or write mode
+ *
+ * @param handle The new file handle
+ * @param filename The name of the file
+ * @param readonly Set to 1 for read access, 0 for write access.
+ */
+int venc_file_open(void** handle,
+ char* filename,
+ int readonly);
+
+/**
+ * @brief Closes the file
+ */
+int venc_file_close(void* handle);
+
+/**
+ * @brief Reads the file. Only valid in read mode.
+ *
+ * @param handle The file handle
+ * @param buffer The buffer to read into
+ * @param bytes The number of bytes to read
+ * @param bytes_read The number of bytes actually read (output)
+ */
+int venc_file_read(void* handle,
+ void* buffer,
+ int bytes);
+
+/**
+ * @brief Writes to the file. Only valid in write mode.
+ *
+ * @param handle The file handle
+ * @param buffer The buffer to write from
+ * @param bytes The number of bytes to write
+ * @param bytes_write The number of bytes actually written (output)
+ */
+int venc_file_write(void* handle,
+ void* buffer,
+ int bytes);
+
+/**
+ * @brief Reposition the file pointer.
+ *
+ * @param handle The file handle
+ * @param bytes The number of bytes from the start of file
+ */
+int venc_file_seek_start(void* handle,
+ int bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_FILE_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_mutex.h b/omx/mm-video/qdsp6/venc/common/inc/venc_mutex.h
new file mode 100644
index 0000000..5724e5b
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_mutex.h
@@ -0,0 +1,65 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_MUTEX_H
+#define _VENC_MUTEX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+ * @brief Constructor
+ */
+int venc_mutex_create(void** handle);
+
+/**
+ * @brief Destructor
+ */
+int venc_mutex_destroy(void* handle);
+
+/**
+ * @brief Locks the mutex
+ */
+int venc_mutex_lock(void* handle);
+
+/**
+ * @brief Unlocks the mutex
+ */
+int venc_mutex_unlock(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_MUTEX_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_queue.h b/omx/mm-video/qdsp6/venc/common/inc/venc_queue.h
new file mode 100644
index 0000000..e83eea4
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_queue.h
@@ -0,0 +1,106 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_QUEUE_H
+#define _VENC_QUEUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+ * @brief Constructor
+ *
+ * @param handle The queue handle
+ * @param max_queue_size Max number of items in queue (size)
+ * @param max_data_size Max data size
+ */
+int venc_queue_create(void** handle, int max_queue_size, int max_data_size);
+
+/**
+ * @brief Destructor
+ *
+ * @param handle The queue handle
+ */
+int venc_queue_destroy(void* handle);
+
+/**
+ * @brief Pushes an item onto the queue.
+ *
+ * @param handle The queue handle
+ * @param data Pointer to the data
+ * @param data_size Size of the data in bytes
+ */
+int venc_queue_push(void* handle, void* data, int data_size);
+
+/**
+ * @brief Pops an item from the queue.
+ *
+ * @param handle The queue handle
+ * @param data Pointer to the data
+ * @param data_size Size of the data buffer in bytes
+ */
+int venc_queue_pop(void* handle, void* data, int data_size);
+
+/**
+ * @brief Peeks at the item at the head of the queue
+ *
+ * Nothing will be removed from the queue
+ *
+ * @param handle The queue handle
+ * @param data Pointer to the data
+ * @param data_size Size of the data in bytes
+ *
+ * @return 0 if there is no data
+ */
+int venc_queue_peek(void* handle, void* data, int data_size);
+
+/**
+ * @brief Get the size of the queue.
+ *
+ * @param handle The queue handle
+ */
+int venc_queue_size(void* handle);
+
+/**
+ * @brief Check if the queue is full
+ *
+ * @param handle The queue handle
+ */
+int venc_queue_full(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_QUEUE_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_semaphore.h b/omx/mm-video/qdsp6/venc/common/inc/venc_semaphore.h
new file mode 100644
index 0000000..738b9c3
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_semaphore.h
@@ -0,0 +1,65 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_SEMAPHORE_H
+#define _VENC_SEMAPHORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+ * @brief Constructor
+ */
+int venc_semaphore_create(void** handle, int init_count, int max_count);
+
+/**
+ * @brief Destructor
+ */
+int venc_semaphore_destroy(void* handle);
+
+/**
+ * @brief Waits for the semaphore
+ */
+int venc_semaphore_wait(void* handle, int timeout);
+
+/**
+ * @brief Posts the semaphore
+ */
+int venc_semaphore_post(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_SEMAPHORE_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_signal.h b/omx/mm-video/qdsp6/venc/common/inc/venc_signal.h
new file mode 100644
index 0000000..66d5717
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_signal.h
@@ -0,0 +1,69 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_SIGNAL_H
+#define _VENC_SIGNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+* @brief Constructor
+*/
+int venc_signal_create(void** handle);
+
+/**
+* @brief Destructor
+*/
+int venc_signal_destroy(void* handle);
+
+/**
+* @brief Set a signal
+*/
+int venc_signal_set(void* handle);
+
+/**
+* @brief Wait for signal to be set
+*
+* @param timeout Milliseconds before timeout. Specify 0 for infinite.
+*
+* @return 0 on success, 1 on error, 2 on timeout
+*/
+int venc_signal_wait(void* handle, int timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_SIGNAL_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_sleep.h b/omx/mm-video/qdsp6/venc/common/inc/venc_sleep.h
new file mode 100644
index 0000000..93b6e3d
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_sleep.h
@@ -0,0 +1,52 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_SLEEPER_H
+#define _VENC_SLEEPER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+ * @brief Sleep for the specified time
+ *
+ * @param time_millis The time to sleep in milliseconds
+ */
+int venc_sleep(int time_millis);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_SLEEPER_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_thread.h b/omx/mm-video/qdsp6/venc/common/inc/venc_thread.h
new file mode 100644
index 0000000..8b63241
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_thread.h
@@ -0,0 +1,70 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_THREAD_H
+#define _VENC_THREAD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+/**
+ * @brief Thread start function pointer
+ */
+typedef int (*thread_fn_type) (void* thread_data);
+
+/**
+ * @brief Starts a thread at the specified function
+ *
+ * @param handle Handle to the thread
+ * @param pfn Pointer to the thread start function
+ * @param thread_data Arguments passed in to the thread (null is valid)
+ * @param priority Priority of the thread, unique to each platform.
+ */
+int venc_thread_create(void** handle,
+ thread_fn_type pfn,
+ void* thread_data,
+ int priority);
+
+/**
+ * @brief Destroys a thread. Blocks until thread exits
+ *
+ * @return The thread exit code
+ */
+int venc_thread_destroy(void* handle, int* thread_result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_THREAD_H
diff --git a/omx/mm-video/qdsp6/venc/common/inc/venc_time.h b/omx/mm-video/qdsp6/venc/common/inc/venc_time.h
new file mode 100644
index 0000000..f65b1ea
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/inc/venc_time.h
@@ -0,0 +1,51 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TIME_H
+#define _VENC_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+
+
+/**
+ * @brief Get the timestamp in microseconds
+ */
+long long venc_time_microsec();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _VENC_TIME_H
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_file.c b/omx/mm-video/qdsp6/venc/common/src/venc_file.c
new file mode 100644
index 0000000..b29359b
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_file.c
@@ -0,0 +1,166 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venc_file.h"
+#include "venc_debug.h"
+#include <stdio.h>
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_file_open(void** handle,
+ char* filename,
+ int readonly)
+{
+ int result = 0;
+ FILE* f = NULL;
+
+ if (handle != NULL && filename != NULL && (readonly == 0 || readonly == 1))
+ {
+ if (readonly == 1)
+ {
+ f = fopen(filename, "rb");
+ }
+ else
+ {
+ f = fopen(filename, "wb");
+ }
+
+ if (f == NULL)
+ {
+ VENC_MSG_ERROR("Unable to open file");
+ result = 1;
+ }
+
+ *handle = f;
+ }
+ else
+ {
+ VENC_MSG_ERROR("bad param");
+ result = 1;
+ }
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_file_close(void* handle)
+{
+ int result = 0;
+
+ if (handle != NULL)
+ {
+ fclose((FILE*) handle);
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_file_read(void* handle,
+ void* buffer,
+ int bytes)
+{
+ int result = 0;
+
+ if (buffer != NULL)
+ {
+ if (bytes > 0)
+ {
+ result = (int) fread(buffer, 1, bytes, (FILE*) handle);
+ }
+ else
+ {
+ VENC_MSG_ERROR("Bytes must be > 0");
+ result = -1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("Null param");
+ result = -1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_file_write(void* handle,
+ void* buffer,
+ int bytes)
+{
+ int result = 0;
+
+ if (buffer != NULL)
+ {
+ if (bytes > 0)
+ {
+ result = (int) fwrite(buffer, 1, bytes, (FILE*) handle);
+ /* fflush((FILE *)handle); */
+ }
+ else
+ {
+ VENC_MSG_ERROR("Bytes must be > 0");
+ result = -1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("Null param");
+ result = -1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_file_seek_start(void* handle,
+ int bytes)
+{
+ int result = 0;
+
+ if (bytes >= 0)
+ {
+ if (fseek((FILE*) handle, bytes, SEEK_SET) != 0)
+ {
+ VENC_MSG_ERROR("failed to seek");
+ result = 1;
+ }
+ }
+
+ return result;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_mutex.c b/omx/mm-video/qdsp6/venc/common/src/venc_mutex.c
new file mode 100644
index 0000000..2a14879
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_mutex.c
@@ -0,0 +1,139 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venc_mutex.h"
+#include "venc_debug.h"
+#include "venc_debug.h"
+#include <pthread.h>
+#include <stdlib.h>
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_mutex_create(void** handle)
+{
+ int result = 0;
+ pthread_mutex_t* mutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+
+ if (handle)
+ {
+ if (pthread_mutex_init(mutex, NULL) == 0)
+ {
+ *handle = mutex;
+ }
+ else
+ {
+ VENC_MSG_ERROR("init mutex failed");
+ free(mutex);
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_mutex_destroy(void* handle)
+{
+ int result = 0;
+ pthread_mutex_t* mutex = (pthread_mutex_t*) handle;
+
+ if (mutex)
+ {
+ if (pthread_mutex_destroy(mutex) == 0)
+ {
+ free(handle);
+ }
+ else
+ {
+ VENC_MSG_ERROR("destroy mutex failed");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_mutex_lock(void* handle)
+{
+ int result = 0;
+ pthread_mutex_t* mutex = (pthread_mutex_t*) handle;
+
+ if (mutex)
+ {
+ if (pthread_mutex_lock(mutex) != 0)
+ {
+ VENC_MSG_ERROR("lock mutex failed");
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_mutex_unlock(void* handle)
+{
+ int result = 0;
+ pthread_mutex_t* mutex = (pthread_mutex_t*) handle;
+
+ if (mutex)
+ {
+ if (pthread_mutex_unlock(mutex) != 0)
+ {
+ VENC_MSG_ERROR("lock mutex failed");
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_queue.c b/omx/mm-video/qdsp6/venc/common/src/venc_queue.c
new file mode 100644
index 0000000..eec1f28
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_queue.c
@@ -0,0 +1,247 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venc_debug.h"
+#include "venc_queue.h"
+#include <stdlib.h>
+
+typedef struct venc_queue_type
+{
+ int head;
+ int size;
+ unsigned char* data;
+ int max_queue_size;
+ int max_data_size;
+} venc_queue_type;
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_queue_create(void** handle, int max_queue_size, int max_data_size)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_queue_type* queue = (venc_queue_type*) malloc(sizeof(venc_queue_type));
+ *handle = (void*) queue;
+
+ queue->max_queue_size = max_queue_size;
+ queue->max_data_size = max_data_size;
+ queue->data = NULL;
+ queue->head = 0;
+ queue->size = 0;
+
+ if (queue->max_queue_size > 0)
+ {
+ if (queue->max_data_size > 0)
+ {
+ queue->data = malloc(queue->max_queue_size * queue->max_data_size);
+ if (!queue->data)
+ {
+ VENC_MSG_ERROR("error allocating data array");
+ free((void*) queue);
+ result = 1;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_queue_destroy(void* handle)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ free(handle);
+ }
+ else
+ {
+ VENC_MSG_ERROR("invalid handle");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_queue_pop(void* handle, void* data, int data_size)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_queue_type* queue = (venc_queue_type*) handle;
+ result = venc_queue_peek(handle, data, data_size);
+
+ if (result == 0)
+ {
+ --queue->size;
+ queue->head = (queue->head + 1) % queue->max_queue_size;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("invalid handle");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_queue_push(void* handle, void* data, int data_size)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_queue_type* queue = (venc_queue_type*) handle;
+
+ // see if queue is full
+ if (queue->size < queue->max_queue_size)
+ {
+ // see if data size is okay
+ if (data_size >= 0 && data_size <= queue->max_data_size)
+ {
+ // make sure we have no null data
+ if (data != NULL)
+ {
+ int index = (queue->head + queue->size) % queue->max_queue_size;
+ int byte_offset = index * queue->max_data_size;
+ memcpy(&queue->data[byte_offset], data, data_size);
+ ++queue->size;
+ }
+ else
+ {
+ VENC_MSG_ERROR("Data is null");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("Data size is wrong");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("Q is full");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("invalid handle");
+ result = 1;
+ }
+
+ return result;
+}
+
+int venc_queue_peek(void* handle, void* data, int data_size)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_queue_type* queue = (venc_queue_type*) handle;
+ // see if data size is okay
+ if (data_size >= 0 && data_size <= queue->max_data_size)
+ {
+ // make sure we have no null data
+ if (data != NULL)
+ {
+ // make sure we have something on the queue
+ if (venc_queue_size(handle) > 0)
+ {
+ int byte_offset = queue->head * queue->max_data_size;
+ memcpy(data, &queue->data[byte_offset], data_size);
+ }
+ else
+ {
+ VENC_MSG_ERROR("queue is empty");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("Data is null");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("Data size is wrong");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("invalid handle");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_queue_size(void* handle)
+{
+ int size = 0;
+
+ if (handle)
+ {
+ venc_queue_type* queue = (venc_queue_type*) handle;
+ size = queue->size;
+ }
+ else
+ {
+ VENC_MSG_ERROR("invalid handle");
+ }
+
+ return size;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_queue_full(void* handle)
+{
+ venc_queue_type* queue = (venc_queue_type*) handle;
+ return (queue && queue->size == queue->max_queue_size) ? 1 : 0;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_semaphore.c b/omx/mm-video/qdsp6/venc/common/src/venc_semaphore.c
new file mode 100644
index 0000000..bb57ce6
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_semaphore.c
@@ -0,0 +1,174 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venc_semaphore.h"
+#include "venc_debug.h"
+#include <semaphore.h>
+#include <time.h>
+#include <errno.h>
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_semaphore_create(void** handle, int init_count, int max_count)
+{
+ int result = 0;
+
+ (void) max_count;
+
+ if (handle)
+ {
+ sem_t* sem = (sem_t*) malloc(sizeof(sem_t));
+
+ if (sem)
+ {
+ if (sem_init(sem, 0, 0) == 0)
+ {
+ *handle = (void*) sem;
+ }
+ else
+ {
+ VENC_MSG_ERROR("failed to create semaphore");
+ free((void*) sem);
+ result = 1;
+ }
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_semaphore_destroy(void* handle)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ if (sem_destroy((sem_t*) handle) == 0)
+ {
+ free(handle);
+ }
+ else
+ {
+ VENC_MSG_ERROR("failed to destroy sem %s", strerror(errno));
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_semaphore_wait(void* handle, int timeout)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ if (timeout > 0)
+ {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
+ {
+ int ret;
+ // get the number of seconds in timeout (from millis)
+ ts.tv_sec = ts.tv_sec + (time_t) (timeout / 1000);
+
+ // get the number of nanoseconds left over
+ ts.tv_nsec = ts.tv_nsec + (long) ((timeout % 1000) * 1000);
+
+ if (sem_timedwait((sem_t*) handle, &ts) != 0)
+ {
+ if (errno == ETIMEDOUT)
+ {
+ result = 2;
+ }
+ else
+ {
+ VENC_MSG_ERROR("error waiting for sem");
+ result = 1;
+ }
+ }
+ }
+
+ }
+ else // no timeout
+ {
+ if (sem_wait((sem_t*) handle) != 0)
+ {
+ VENC_MSG_ERROR("error waiting for sem");
+ result = 1;
+ }
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_semaphore_post(void* handle)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ if (sem_post((sem_t*) handle) != 0)
+ {
+ VENC_MSG_ERROR("Failed to post semaphore");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_signal.c b/omx/mm-video/qdsp6/venc/common/src/venc_signal.c
new file mode 100644
index 0000000..a64d9de
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_signal.c
@@ -0,0 +1,243 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+Include Files
+==========================================================================*/
+#include "venc_signal.h"
+#include "venc_debug.h"
+#include <time.h>
+#include <pthread.h>
+#include <errno.h>
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define TRUE 1 /* Boolean true value. */
+#define FALSE 0 /* Boolean false value. */
+
+typedef struct venc_signal_type
+{
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ unsigned char m_bSignalSet ;
+} venc_signal_type;
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_signal_create(void** handle)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_signal_type* sig;
+
+ *handle = malloc(sizeof(venc_signal_type));
+ sig = (venc_signal_type*) *handle;
+ sig->m_bSignalSet = FALSE ;
+ if (*handle)
+ {
+ if (pthread_cond_init(&sig->cond,NULL) == 0)
+ {
+ if (pthread_mutex_init(&sig->mutex, NULL) != 0)
+ {
+ VENC_MSG_ERROR("failed to create mutex");
+ result = 1;
+ pthread_cond_destroy(&sig->cond);
+ free(*handle);
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("failed to create cond var");
+ result = 1;
+ free(*handle);
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("failed to alloc handle");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_signal_destroy(void* handle)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_signal_type* sig = (venc_signal_type*) handle;
+ sig->m_bSignalSet = FALSE ;
+ pthread_cond_destroy(&sig->cond);
+ pthread_mutex_destroy(&sig->mutex);
+ free(handle);
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_signal_set(void* handle)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_signal_type* sig = (venc_signal_type*) handle;
+
+ if (pthread_mutex_lock(&sig->mutex) == 0)
+ {
+ sig->m_bSignalSet = TRUE ;
+ if (pthread_cond_signal(&sig->cond) != 0)
+ {
+ VENC_MSG_ERROR("error setting signal");
+ result = 1;
+ }
+
+ if (pthread_mutex_unlock(&sig->mutex) != 0)
+ {
+ VENC_MSG_ERROR("error unlocking mutex");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("error locking mutex");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_signal_wait(void* handle, int timeout)
+{
+ int result = 0;
+
+ if (handle)
+ {
+ venc_signal_type* sig = (venc_signal_type*) handle;
+
+ if (pthread_mutex_lock(&sig->mutex) == 0)
+ {
+
+ if (timeout > 0)
+ {
+ int wait_result;
+ struct timespec time;
+ clock_gettime(CLOCK_REALTIME, &time);
+ time.tv_sec += timeout / 1000;
+ time.tv_nsec += (timeout % 1000) * 1000000;
+
+ wait_result = pthread_cond_timedwait(&sig->cond, &sig->mutex, &time);
+ if (wait_result == ETIMEDOUT)
+ {
+ result = 2;
+ }
+ else if (wait_result != 0)
+ {
+ result = 1;
+ }
+ }
+ else
+ {
+ if(sig->m_bSignalSet == TRUE)
+ {
+ struct timespec time;
+ timeout = 1 ;
+ clock_gettime(CLOCK_REALTIME, &time);
+ time.tv_sec += timeout / 1000;
+ time.tv_nsec += (timeout % 1000) * 1000000;
+ VENC_MSG_MEDIUM("error waiting for signal but its already set");
+ pthread_cond_timedwait(&sig->cond, &sig->mutex, &time) ;
+ sig->m_bSignalSet = FALSE ;
+ }
+ else
+ {
+ if (pthread_cond_wait(&sig->cond, &sig->mutex) != 0)
+ {
+ VENC_MSG_ERROR("error waiting for signal");
+ result = 1;
+ }
+ sig->m_bSignalSet = FALSE ;
+ }
+ }
+
+ if (pthread_mutex_unlock(&sig->mutex) != 0)
+ {
+ VENC_MSG_ERROR("error unlocking mutex");
+ result = 1;
+ }
+
+ }
+ else
+ {
+ VENC_MSG_ERROR("error locking mutex");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_sleep.c b/omx/mm-video/qdsp6/venc/common/src/venc_sleep.c
new file mode 100644
index 0000000..2e67c0f
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_sleep.c
@@ -0,0 +1,39 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venc_sleep.h"
+#include <unistd.h>
+
+int venc_sleep(int time_millis)
+{
+ usleep(time_millis * 1000);
+ return 0;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_thread.c b/omx/mm-video/qdsp6/venc/common/src/venc_thread.c
new file mode 100644
index 0000000..25055bc
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_thread.c
@@ -0,0 +1,111 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include <pthread.h>
+#include "venc_debug.h"
+#include "venc_thread.h"
+#include <stdlib.h>
+
+typedef struct venc_thread_type
+{
+ thread_fn_type pfn;
+ int priority;
+ pthread_t thread;
+ void* thread_data;
+} venc_thread_type;
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+static void* venc_thread_entry(void* thread_data)
+{
+ venc_thread_type* thread = (venc_thread_type*) thread_data;
+ return (void*) thread->pfn(thread->thread_data);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_thread_create(void** handle,
+ thread_fn_type pfn,
+ void* thread_data,
+ int priority)
+{
+ int result = 0;
+ venc_thread_type* thread = (venc_thread_type*) malloc(sizeof(venc_thread_type));
+ *handle = thread;
+
+ if (thread)
+ {
+ int create_result;
+ thread->pfn = pfn;
+ thread->thread_data = thread_data;
+ thread->priority = priority;
+ create_result = pthread_create(&thread->thread,
+ NULL,
+ venc_thread_entry,
+ (void*) thread);
+ if (create_result != 0)
+ {
+ VENC_MSG_ERROR("failed to create thread");
+ result = 1;
+ }
+ }
+ else
+ {
+ VENC_MSG_ERROR("failed to allocate thread");
+ result = 1;
+ }
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+int venc_thread_destroy(void* handle, int* thread_result)
+{
+ int result = 0;
+ venc_thread_type* thread = (venc_thread_type*) handle;
+
+ if (thread)
+ {
+ if (pthread_join(thread->thread, (void**) thread_result) != 0)
+ {
+ VENC_MSG_ERROR("failed to join thread");
+ result = 1;
+ }
+ free(thread);
+ }
+ else
+ {
+ VENC_MSG_ERROR("handle is null");
+ result = 1;
+ }
+ return result;
+}
diff --git a/omx/mm-video/qdsp6/venc/common/src/venc_time.c b/omx/mm-video/qdsp6/venc/common/src/venc_time.c
new file mode 100644
index 0000000..0d54871
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/common/src/venc_time.c
@@ -0,0 +1,49 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venc_time.h"
+#include <sys/time.h>
+#include <stdio.h>
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+long long venc_time_microsec()
+{
+ struct timeval time;
+ long long time_microsec = 0;
+
+ if (gettimeofday(&time, NULL) == 0)
+ {
+ time_microsec = ((long long) time.tv_sec * 1000 * 1000) + ((long long) time.tv_usec) ;
+ }
+
+ return time_microsec;
+}
diff --git a/omx/mm-video/qdsp6/venc/device/inc/venc_device.h b/omx/mm-video/qdsp6/venc/device/inc/venc_device.h
new file mode 100644
index 0000000..43c4d96
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/device/inc/venc_device.h
@@ -0,0 +1,753 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_DEVICE_H
+#define _VENC_DEVICE_H
+
+#include <linux/msm_q6venc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+
+ DEFINITIONS AND DECLARATIONS
+
+===========================================================================*/
+
+/* -----------------------------------------------------------------------
+** Constants & Macros
+** ----------------------------------------------------------------------- */
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * STATUS CODES
+ */
+
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * INTERFACE VERSION
+ *
+ * Note: Interface version changes only if existing structures are modified.
+ */
+#define VEN_INTF_VER 1
+#define VEN_FRAME_TYPE_I 1 /**< I frame type */
+#define VEN_FRAME_TYPE_P 2 /**< P frame type */
+#define VEN_FRAME_TYPE_B 3 /**< B frame type */
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Video codec types.
+ */
+#define VEN_CODEC_MPEG4 1 /**< MPEG4 Codec */
+#define VEN_CODEC_H264 2 /**< H.264 Codec */
+#define VEN_CODEC_H263 3 /**< H.263 Codec */
+
+/*
+ * Video codec profile types.
+ */
+#define VEN_PROFILE_MPEG4_SP 1 /**< 1 - MPEG4 SP profile */
+#define VEN_PROFILE_MPEG4_ASP 2 /**< 2 - MPEG4 ASP profile */
+#define VEN_PROFILE_H264_BASELINE 3 /**< 3 - H264 Baseline profile */
+#define VEN_PROFILE_H264_MAIN 4 /**< 4 - H264 Main profile */
+#define VEN_PROFILE_H264_HIGH 5 /**< 5 - H264 High profile */
+#define VEN_PROFILE_H263_BASELINE 6 /**< 6 - H263 Baseline profile */
+
+/*
+ * Video codec profile level types.
+ */
+#define VEN_LEVEL_MPEG4_0 0x1 /**< MPEG4 Level 0 */
+#define VEN_LEVEL_MPEG4_0B 0x2 /**< MPEG4 Level 0b */
+#define VEN_LEVEL_MPEG4_1 0x3 /**< MPEG4 Level 1 */
+#define VEN_LEVEL_MPEG4_2 0x4 /**< MPEG4 Level 2 */
+#define VEN_LEVEL_MPEG4_3 0x5 /**< MPEG4 Level 3 */
+#define VEN_LEVEL_MPEG4_3B 0x6 /**< MPEG4 Level 3b */
+#define VEN_LEVEL_MPEG4_4 0x7 /**< MPEG4 Level 4 */
+#define VEN_LEVEL_MPEG4_4A 0x8 /**< MPEG4 Level 4a */
+#define VEN_LEVEL_MPEG4_5 0x9 /**< MPEG4 Level 5 */
+#define VEN_LEVEL_MPEG4_6 0xA /**< MPEG4 Level 6 */
+
+#define VEN_LEVEL_H264_1 0x8 /**< H.264 Level 1 */
+#define VEN_LEVEL_H264_1B 0x9 /**< H.264 Level 1b */
+#define VEN_LEVEL_H264_1P1 0xA /**< H.264 Level 1.1 */
+#define VEN_LEVEL_H264_1P2 0xB /**< H.264 Level 1.2 */
+#define VEN_LEVEL_H264_1P3 0xC /**< H.264 Level 1.3 */
+#define VEN_LEVEL_H264_2 0xD /**< H.264 Level 2 */
+#define VEN_LEVEL_H264_2P1 0xE /**< H.264 Level 2.1 */
+#define VEN_LEVEL_H264_2P2 0xF /**< H.264 Level 2.2 */
+#define VEN_LEVEL_H264_3 0x10 /**< H.264 Level 3 */
+#define VEN_LEVEL_H264_3P1 0x11 /**< H.264 Level 3.1 */
+
+#define VEN_LEVEL_H263_10 0x12 /**< H.263 Level 10 */
+#define VEN_LEVEL_H263_20 0x13 /**< H.263 Level 20 */
+#define VEN_LEVEL_H263_30 0x14 /**< H.263 Level 30 */
+#define VEN_LEVEL_H263_40 0x15 /**< H.263 Level 40 */
+#define VEN_LEVEL_H263_45 0x16 /**< H.263 Level 45 */
+#define VEN_LEVEL_H263_50 0x17 /**< H.263 Level 50 */
+#define VEN_LEVEL_H263_60 0x18 /**< H.263 Level 60 */
+#define VEN_LEVEL_H263_70 0x19 /**< H.263 Level 70 */
+
+#define VEN_FRAME_SIZE_IN_RANGE(w1, h1, w2, h2) \
+ ((w1) * (h1) <= (w2) * (h2))
+
+#define VEN_QCIF_DX 176
+#define VEN_QCIF_DY 144
+
+#define VEN_WQVGA_DX 400
+#define VEN_WVQGA_DY 240
+
+#define VEN_CIF_DX 352
+#define VEN_CIF_DY 288
+
+#define VEN_VGA_DX 640
+#define VEN_VGA_DY 480
+
+#define VEN_PAL_DX 720
+#define VEN_PAL_DY 576
+
+#define VEN_HD720P_DX 1280
+#define VEN_HD720P_DY 720
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Entropy coding model selection for H.264 encoder.
+ */
+#define VEN_ENTROPY_MODEL_CAVLC 1 /**< Context-based Adaptive Variable
+ * Length Coding (CAVLC)
+ */
+#define VEN_ENTROPY_MODEL_CABAC 2 /**< Context-based Adaptive Binary
+ * Arithmetic Coding (CABAC)
+ */
+
+/*
+ * Cabac model number (0,1,2) for encoder.
+ */
+#define VEN_CABAC_MODEL_0 1 /**< CABAC Model 0. */
+#define VEN_CABAC_MODEL_1 2 /**< CABAC Model 1. */
+#define VEN_CABAC_MODEL_2 3 /**< CABAC Model 2. */
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Deblocking filter control type for encoder.
+ */
+#define VEN_DB_DISABLE 1 /**< 1 - Disable deblocking
+ * filter
+ */
+#define VEN_DB_ALL_BLKG_BNDRY 2 /**< 2 - All blocking boundary
+ * filtering
+ */
+#define VEN_DB_SKIP_SLICE_BNDRY 3 /**< 3 - Filtering except slice
+ * boundary
+ */
+
+/*--------------------------------------------------------------------------*/
+
+
+/*
+ * Different methods of Multi slice selection.
+ */
+#define VEN_MSLICE_OFF 1 /**< 1 - Multi slice OFF */
+#define VEN_MSLICE_CNT_MB 2 /**< 2 - Multi slice by number of MBs
+ * count per slice
+ */
+#define VEN_MSLICE_CNT_BYTE 3 /**< 3 - Multi slice by number of
+ * bytes count per slice. Required
+ * minimum byte count value is
+ * 1920. TODO: check for Q6
+ */
+#define VEN_MSLICE_GOB 4 /**< 4 - Multi slice by GOB for
+ * H.263 only.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Different modes for Rate Control.
+ */
+#define VEN_RC_OFF 1 /**< Rate Control is OFF.
+ * It is not recommended as it will
+ * not obey bitrate requirement
+ */
+#define VEN_RC_VBR_VFR 2 /**< Variable bit rate; Variable frame
+ * rate. i.e frames may be skipped.
+ * Mainly used for TODO:
+ */
+#define VEN_RC_VBR_CFR 3 /**< Variable bit rate; Constant frame
+ * rate. i.e frames are not skipped.
+ * Mainly used for higher quality
+ * expectation appliation.
+ * (e.g. camcorder)
+ */
+#define VEN_RC_CBR_VFR 4 /**< Constant bit rate; Variable frame
+ * rate. i.e frames may be skipped.
+ * Mainly used for strict rate
+ * control scenario application.
+ * (e.g. video telephony)
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Different modes for flushing buffers
+ */
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Different input formats for YUV data.
+ */
+#define VEN_INPUTFMT_NV12 1 /**< NV12 Linear */
+#define VEN_INPUTFMT_NV21 2 /**< NV21 Linear */
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Different allowed rotation modes.
+ */
+#define VEN_ROTATION_0 0 /**< 0 degrees */
+#define VEN_ROTATION_90 1 /**< 90 degrees */
+#define VEN_ROTATION_180 2 /**< 180 degrees */
+#define VEN_ROTATION_270 3 /**< 270 degrees */
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * IOCTL timeout values
+ */
+#define VEN_TIMEOUT_INFINITE 0xffffffff /**< Infinite timeout value.
+ * i.e. don't timeout.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * Different allowed intra refresh modes.
+ */
+#define VEN_IR_OFF 1 /**< Intra refresh is disabled */
+#define VEN_IR_CYCLIC 2 /**< Cyclic IR mode. Here configured
+ * no. of consecutive macroblocks
+ * are intra coded.
+ */
+#define VEN_IR_RANDOM 3 /**< Random IR mode. Here configured
+ * no. of macroblocks are randomly
+ * picked per frame by an internal
+ * algorithm for intra coding.
+ */
+
+enum q6_frame_type_enum
+{
+ VENC_IDR_FRAME,
+ VENC_I_FRAME,
+ VENC_P_FRAME
+};
+
+enum q6_rotation_angle_enum
+{
+ VENC_ROTATION_0,
+ VENC_ROTATION_90,
+ VENC_ROTATION_180,
+ VENC_ROTATION_270
+};
+
+enum q6_rate_control_enum
+{
+ VENC_RC_OFF,
+ VENC_RC_VBR_VFR,
+ VENC_RC_VBR_VFR_TIGHT,
+ VENC_RC_VBR_CFR,
+ VENC_RC_CBR_VFR
+};
+
+enum q6_codec_type_enum
+{
+ VENC_CODEC_MPEG4,
+ VENC_CODEC_H263,
+ VENC_CODEC_H264
+};
+
+enum q6_mpeg4_profile_enum
+{
+ VENC_MPEG4_PROFILE_SIMPLE
+};
+
+enum q6_mpeg4_level_enum
+{
+ VENC_MPEG4_LEVEL_0,
+ VENC_MPEG4_LEVEL_0B,
+ VENC_MPEG4_LEVEL_1,
+ VENC_MPEG4_LEVEL_2,
+ VENC_MPEG4_LEVEL_3,
+ //VENC_MPEG4_LEVEL_3B,
+ //VENC_MPEG4_LEVEL_4,
+ VENC_MPEG4_LEVEL_4A,
+ //VENC_MPEG4_LEVEL_4B,
+ VENC_MPEG4_LEVEL_5,
+ VENC_MPEG4_LEVEL_6
+};
+
+enum q6_h263_profile_enum
+{
+ VENC_H263_PROFILE_P0,
+ VENC_H263_PROFILE_P3
+};
+
+enum q6_h263_level_enum
+{
+ VENC_H263_LEVEL_10,
+ VENC_H263_LEVEL_20,
+ VENC_H263_LEVEL_30,
+ VENC_H263_LEVEL_40,
+ VENC_H263_LEVEL_45,
+ VENC_H263_LEVEL_50,
+ VENC_H263_LEVEL_60,
+ VENC_H263_LEVEL_70
+};
+
+enum q6_h264_profile_enum
+{
+ VENC_H264_PROFILE_BASELINE
+};
+
+enum q6_h264_level_enum
+{
+ VENC_H264_LEVEL_1,
+ VENC_H264_LEVEL_1B,
+ VENC_H264_LEVEL_1P1,
+ VENC_H264_LEVEL_1P2,
+ VENC_H264_LEVEL_1P3,
+ VENC_H264_LEVEL_2,
+ VENC_H264_LEVEL_2P1,
+ VENC_H264_LEVEL_2P2,
+ VENC_H264_LEVEL_3,
+ VENC_H264_LEVEL_3P1
+};
+
+enum q6_slice_mode_enum
+{
+ VENC_SLICE_MODE_DEFAULT,
+ VENC_SLICE_MODE_GOB,
+ VENC_SLICE_MODE_MB,
+ VENC_SLICE_MODE_BIT
+};
+
+
+struct ven_switch
+{
+ unsigned char status; /**< TRUE (1) if setting is enabled
+ * or ON,
+ * FALSE (0) if disabled or OFF.
+ */
+};
+
+struct ven_allocator_property
+{
+ unsigned int min_count; /**< Minimum number of buffers required. */
+ unsigned int actual_count; /**< When used in Get: \n
+ * If there hasn't been a Set yet: \n
+ * It's the recommended number of buffers
+ * to allocate for optimal performance.\n
+ * If there was a Set made: \n
+ * The value provided in last Set is
+ * returned. \n
+ *
+ * When used in Set:
+ * It should be the actual number of
+ * buffers that are allocated or are to be
+ * allocated.
+ */
+ unsigned int data_size; /**< Data size of each buffer in bytes ( i.e
+ * size excluding suffix bytes )
+ * This is the region that will contain the
+ * YUV or bitstream content.
+ */
+ unsigned int suffix_size; /**< Number of bytes as suffix;
+ * A suffix of these many bytes follows the
+ * buffer data region.
+ * This region could contain metadata.
+ */
+ unsigned int alignment; /**< Buffer's address (start of data region)
+ * would be aligned to multiple of these
+ * many bytes.
+ * The start of suffix would always be
+ * aligned to 4 bytes (32 bits)
+ */
+ unsigned int buf_pool_id; /**< Unique pool identifier which can be set
+ * for buffer allocations. This can come
+ * from driver or come from some local
+ * policy component might have.
+ */
+
+};
+
+struct ven_buffer_payload
+{
+ unsigned char* buffer; /**< Virtual pointer to buffer */
+ unsigned int size; /**< Size of buffer in bytes.
+ * Field can be ignored in few IOCTLs
+ * Refer to the individual IOCTLs for
+ * details.
+ */
+
+};
+
+struct ven_base_cfg
+{
+ unsigned int input_width; /**< Input YUV frame width */
+ unsigned int input_height; /**< Input YUV frame height */
+ unsigned int dvs_width; /**< Encoded frame width. Used only
+ * in Digital Video Stabilization (DVS).
+ * In DVS, nDVSWidth < nIpWidth &
+ * (nIpWidth - nDVSWidth) is used for
+ * DVS horizontal margin. \n
+ * If DVS is not being used, nDVSWidth should
+ * be set equal to nIpWidth. \n
+ */
+ unsigned int dvs_height; /**< Encoded frame height. Used only in
+ * Digital Video Stabilization (DVS).
+ * For DVS, nDVSHeight < nIpHeight &
+ * (nIpHeight - nDVSHeight) is used for
+ * DVS vertical margin. \n
+ * If DVS is not being used, nDVSHeight
+ * should be set equal to nIpHeight. \n
+ */
+ unsigned int codec_type; /**< Video codec type \n
+ * Refer to codec type constants in the
+ * constants section above. \n
+ * VEN_CODEC_MPEG4 - For MPEG4 simple
+ * profile is defaulted \n
+ * VEN_CODEC_H264 - H264 baseline
+ * profile is defaulted \n
+ * VEN_CODEC_H263 - H263 baseline
+ * profile is defaulted \n
+ */
+ unsigned int fps_num; /**< Numerator of frame rate */
+ unsigned int fps_den; /**< Denominator of frame rate */
+ unsigned int target_bitrate; /**< Target bit rate in bits per sec */
+ unsigned int input_format; /**< Input memory access format; \n
+ * Refer to input format constants in the
+ * constants section above.
+ */
+
+};
+
+struct ven_profile
+{
+ unsigned int profile; /**< Codec profile payload.
+ * Refer to codec profile constants in the
+ * constants section above.
+ */
+
+};
+
+struct ven_profile_level
+{
+ unsigned int level; /**< Codec-profile specific level payload */
+
+};
+
+struct ven_session_qp
+{
+ unsigned int iframe_qp; /**< QP value for the first I Frame.
+ * This value will be used for all
+ * I frames if rate control is
+ * disabled
+ */
+ unsigned int pframe_qp; /**< QP value for the first P Frame.
+ * This value will be used for all
+ * P frames if rate control is
+ * disabled.
+ */
+
+};
+
+struct ven_qp_range
+{
+ unsigned int max_qp; /**< Maximum QP value */
+ unsigned int min_qp; /**< Minimum QP value */
+
+};
+
+struct ven_intra_period
+{
+ unsigned int num_pframes; /**< No of P-Frames between 2
+ * I-Frames.
+ */
+};
+
+
+struct ven_capability
+{
+ unsigned int codec_types;
+ unsigned int max_frame_width;
+ unsigned int max_frame_height;
+ //min resoln??
+ unsigned int max_target_bitrate;
+ unsigned int max_frame_rate;
+ unsigned int input_formats;
+ unsigned char dvs;
+
+};
+
+struct ven_entropy_cfg
+{
+ unsigned int entropy_sel; /**< Set Entropy coding model selection
+ * Refer to entropy coding model constants
+ * in the constants section above.
+ */
+ unsigned int cabac_model; /**< Valid only when Entropy Selection
+ * is CABAC. This is model number for
+ * CABAC.
+ * Refer to CABAC model number constants
+ * in the constants section above.
+ */
+
+};
+
+struct ven_db_cfg
+{
+ unsigned int db_mode; /**< Deblocking Control
+ * Refer to deblocking mode constants
+ * in the constants section above.
+ */
+ unsigned int slice_alpha_offset; /**< Aplha offset value in Slice Header (
+ * slice_alpha_c0_offset_div2).
+ * This value is in 2Â’s complement form.
+ * This valueÂ’s range is -6 to 6
+ */
+ unsigned int slice_beta_offset; /**< Beta offset value in Slice Header (
+ * Slice_beta_offset_div2).
+ * This value is in 2Â’s complement form.
+ * This valueÂ’s range is -6 to 6
+ */
+};
+
+struct ven_intra_refresh
+{
+ unsigned int ir_mode; /**< Intra refresh method to be used.
+ * Refer to intra refresh mode constants
+ * in the constants section above.
+ */
+ unsigned int mb_count; /**< Number of macroblocks to be intra
+ * coded per frame.
+ */
+
+};
+
+struct ven_multi_slice_cfg
+{
+ unsigned int mslice_mode; /**< To enable/disable Multi-slice.
+ * Refer to multi slice mode constants
+ * in the constants section above.
+ */
+ unsigned int mslice_size; /**< If nMSliceMode is VEN_MSLICE_OFF or
+ * VEN_MSLICE_GOB, then this field is
+ * ignored.
+ * Otherwise, this is size of slice;
+ * if mode is MB count, then this is
+ * No of MB per slice.
+ * if mode is byte count, then this is
+ * No of bytes per slice.
+ */
+
+};
+
+
+struct ven_rate_ctrl_cfg
+{
+ unsigned int rc_mode; /**< Rate Control mode.
+ * Refer to rate control mode constants
+ * in the constants section above.
+ */
+
+};
+
+struct ven_vop_timing_cfg
+{
+ unsigned int vop_time_resolution; /**< VOP Time resolution value
+ * expressed in number of ticks
+ * per second.
+ */
+
+};
+
+struct ven_frame_rate
+{
+ unsigned int fps_denominator; /**< Denominator of frame rate */
+ unsigned int fps_numerator; /**< Numerator of frame rate */
+
+};
+
+struct ven_target_bitrate
+{
+ unsigned int target_bitrate; /**< target bitrate (bits/second) */
+
+};
+
+struct ven_rotation
+{
+ unsigned int rotation; /**< Degree of frame rotation
+ * Refer to rotation mode constants
+ * in the constants section above.
+ */
+
+};
+
+struct ven_timeout
+{
+ unsigned int millisec; /**< Time out interval in milliseconds.
+ * 0 = IOCTL will return immediately
+ * (no wait) if operation cannot
+ * be compelted at the time of call.
+ * VEN_TIMEOUT_INFINITE = infinite wait
+ * for operation to be completed.
+ *
+ * if 0 < nMilliSec < VEN_TIMEOUT_INFINITE,
+ * IOCTL will return with a timeout status
+ * if operation cannot be completed in
+ * nMilliSec amount of time.
+ */
+
+};
+
+struct ven_header_extension
+{
+ unsigned int header_extension; /**< If 0 then header extension is
+ * disabled.
+ * If > 0, then it specifies number
+ * of consecutive video packets
+ * between header extension codes
+ * i.e, header extension would be
+ * inserted every nHeaderExtension
+ * number of packets.
+ */
+};
+
+struct ven_seq_header
+{
+ unsigned char* pHdrBuf;
+ unsigned int nBufSize;
+ unsigned int nHdrLen;
+};
+
+struct ven_config_type
+{
+ struct ven_base_cfg base_config;
+ struct ven_profile profile;
+ struct ven_profile_level profile_level;
+ struct ven_rate_ctrl_cfg rate_control;
+ struct ven_multi_slice_cfg multi_slice;
+ struct ven_rotation rotation;
+ struct ven_target_bitrate bitrate;
+ struct ven_frame_rate frame_rate;
+ struct ven_intra_refresh intra_refresh;
+ struct ven_intra_period intra_period;
+ struct ven_session_qp session_qp;
+ struct ven_qp_range qp_range;
+ struct ven_vop_timing_cfg vop_timing;
+ struct ven_switch ac_prediction;
+ struct ven_switch short_header;
+ struct ven_header_extension hec_interval;
+ struct ven_switch data_partition;
+ void * callback_event;
+};
+
+struct ven_device {
+ int fd;
+ enum venc_state_type state;
+ enum venc_state_type pending_state;
+ struct ven_config_type config;
+
+ /* Attributes for input buffers */
+ struct ven_allocator_property input_attrs;
+ /* Attribute for output buffers */
+ struct ven_allocator_property output_attrs;
+
+};
+
+#define VEN_PMEM_ALIGN 4096
+#define VEN_PMEM_ALIGN_MASK 0xFFFFF000
+
+int ven_device_open(struct ven_device **ptr);
+int ven_device_close(struct ven_device *ptr);
+int ven_set_input_req(struct ven_device* dvenc, struct ven_allocator_property* pprop);
+int ven_get_input_req(struct ven_device* dvenc, struct ven_allocator_property* pprop);
+int ven_set_output_req(struct ven_device* dvenc, struct ven_allocator_property* pprop);
+int ven_get_output_req(struct ven_device* dvenc, struct ven_allocator_property* pprop);
+int ven_update_properties(struct ven_device* dvenc, struct ven_base_cfg *pcfg);
+int ven_start(struct ven_device *dvenc, struct venc_buffers *q6_bufs);
+
+int ven_get_sequence_hdr(struct ven_device *dvenc, struct venc_pmem *pseq, int *psize);
+int ven_set_session_qp(struct ven_device* dvenc, struct ven_session_qp *ptr);
+int ven_get_session_qp(struct ven_device* dvenc, struct ven_session_qp *ptr);
+int ven_set_qp_range(struct ven_device* dvenc, struct ven_qp_range *ptr);
+int ven_get_qp_range(struct ven_device* dvenc, struct ven_qp_range *ptr);
+int ven_set_ac_prediction(struct ven_device* dvenc, struct ven_switch *ptr);
+int ven_get_ac_prediction(struct ven_device* dvenc, struct ven_switch *ptr);
+int ven_set_short_hdr(struct ven_device* dvenc, struct ven_switch *ptr);
+int ven_get_short_hdr(struct ven_device* dvenc, struct ven_switch *ptr);
+int ven_set_base_cfg(struct ven_device * dvenc, struct ven_base_cfg* bcfg);
+int ven_get_base_cfg(struct ven_device * dvenc, struct ven_base_cfg* bcfg);
+int ven_set_codec_profile(struct ven_device* dvenc, struct ven_profile* prof);
+int ven_get_codec_profile(struct ven_device* dvenc, struct ven_profile* prof);
+int ven_set_profile_level(struct ven_device* dvenc, struct ven_profile_level* prof_level);
+int ven_get_profile_level(struct ven_device* dvenc, struct ven_profile_level* prof_level);
+int ven_set_intra_period(struct ven_device* dvenc, struct ven_intra_period *ptr);
+int ven_get_intra_period(struct ven_device* dvenc, struct ven_intra_period* intra_period);
+int ven_set_frame_rate(struct ven_device* dvenc, struct ven_frame_rate *ptr);
+int ven_get_frame_rate(struct ven_device* dvenc, struct ven_frame_rate* frame_rate);
+int ven_set_target_bitrate(struct ven_device* dvenc, struct ven_target_bitrate *ptr);
+int ven_get_target_bitrate(struct ven_device* dvenc, struct ven_target_bitrate *ptr);
+int ven_request_iframe(struct ven_device* dvenc);
+int ven_set_intra_refresh_rate(struct ven_device* dvenc, struct ven_intra_refresh* intra_ref);
+int ven_get_intra_refresh_rate(struct ven_device* dvenc, struct ven_intra_refresh* intra_ref);
+int ven_set_multislice_cfg(struct ven_device* dvenc, struct ven_multi_slice_cfg* multi_slice_cfg);
+int ven_get_multislice_cfg(struct ven_device* dvenc, struct ven_multi_slice_cfg* multi_slice_cfg);
+int ven_set_rate_control(struct ven_device* dvenc, struct ven_rate_ctrl_cfg* rate_ctrl);
+int ven_get_rate_control(struct ven_device* dvenc, struct ven_rate_ctrl_cfg* rate_ctrl);
+int ven_set_vop_timing(struct ven_device* dvenc, struct ven_vop_timing_cfg* vop_timing);
+int ven_get_vop_timing(struct ven_device* dvenc, struct ven_vop_timing_cfg* vop_timing);
+int ven_set_rotation(struct ven_device* dvenc, struct ven_rotation* rotation);
+int ven_get_rotation(struct ven_device* dvenc, struct ven_rotation* rotation);
+int ven_set_hec(struct ven_device* dvenc, struct ven_switch* hex);
+int ven_get_hec(struct ven_device* dvenc, struct ven_switch* hex);
+int ven_set_data_partition(struct ven_device* dvenc, struct ven_switch* dp);
+int ven_get_data_partition(struct ven_device* dvenc, struct ven_switch* dp);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _VENC_DEVICE_H_ */
diff --git a/omx/mm-video/qdsp6/venc/device/src/venc_device.c b/omx/mm-video/qdsp6/venc/device/src/venc_device.c
new file mode 100644
index 0000000..573cf6e
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/device/src/venc_device.c
@@ -0,0 +1,1300 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include <stdio.h>
+#include <linux/msm_q6venc.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <linux/android_pmem.h>
+#include <fcntl.h>
+
+#include "venc_device.h"
+#include "venc_debug.h"
+
+
+/*----------------------------------------------------------------------------
+* Type Declarations
+* -------------------------------------------------------------------------*/
+struct venc_pmem_buffer
+{
+ unsigned int phys;
+ unsigned int virt;
+ struct file *file;
+ struct venc_pmem pmem_buf;
+};
+static int ven_ref;
+
+/**************************************************************************
+ * @brief Set buffer properties based on current config
+ *************************************************************************/
+static int ven_set_default_buf_properties(struct ven_device* dvenc)
+{
+ int ret = 0;
+ struct ven_base_cfg* pcfg;
+
+ if (dvenc == NULL) {
+ QC_OMX_MSG_ERROR("%s: null driver", __func__);
+ ret = -1;
+ }
+
+ pcfg = &(dvenc->config.base_config);
+
+ QC_OMX_MSG_HIGH("Update input buffer requirements pcfg: %p\n", pcfg);
+ dvenc->input_attrs.min_count = 1;
+ dvenc->input_attrs.actual_count = 6;
+ dvenc->input_attrs.suffix_size = 0;
+ dvenc->input_attrs.data_size = pcfg->input_width * pcfg->input_height * 3 / 2;
+ dvenc->input_attrs.alignment = VEN_PMEM_ALIGN;
+
+ QC_OMX_MSG_HIGH("Update output buffer requirements pcfg:%p \n", pcfg);
+ dvenc->output_attrs.min_count = 1;
+ dvenc->output_attrs.actual_count = 4;
+ dvenc->output_attrs.suffix_size = 0;
+ dvenc->output_attrs.data_size = pcfg->input_width * pcfg->input_height * 3 / 2;
+ dvenc->output_attrs.alignment = VEN_PMEM_ALIGN;
+
+
+ return ret;
+}
+
+/**********************************************************************//**
+ * @brief Updates the output buffer size requirements
+ *************************************************************************/
+void ven_update_output_size(struct ven_device* dvenc)
+{
+
+ int width = dvenc->config.base_config.dvs_width;
+ int height = dvenc->config.base_config.dvs_height;
+
+ if (dvenc->config.base_config.codec_type == VEN_CODEC_MPEG4)
+ {
+ switch (dvenc->config.profile_level.level)
+ {
+ case VEN_LEVEL_MPEG4_0:
+ case VEN_LEVEL_MPEG4_1:
+ dvenc->output_attrs.data_size = 10 << 11;
+ break;
+ case VEN_LEVEL_MPEG4_0B:
+ dvenc->output_attrs.data_size = 20 << 11;
+ break;
+ case VEN_LEVEL_MPEG4_2:
+ case VEN_LEVEL_MPEG4_3:
+ dvenc->output_attrs.data_size = 40 << 11;
+ break;
+ case VEN_LEVEL_MPEG4_4A:
+ dvenc->output_attrs.data_size = 80 << 11;
+ break;
+ case VEN_LEVEL_MPEG4_5:
+ dvenc->output_attrs.data_size = 112 << 11;
+ break;
+ case VEN_LEVEL_MPEG4_6:
+ dvenc->output_attrs.data_size = 248 << 11;
+ break;
+ }
+ dvenc->output_attrs.data_size = dvenc->output_attrs.data_size;
+ }
+ else if (dvenc->config.base_config.codec_type == VEN_CODEC_H263)
+ {
+ if (VEN_FRAME_SIZE_IN_RANGE(width, height, VEN_QCIF_DX, VEN_QCIF_DY))
+ {
+ dvenc->output_attrs.data_size = 20 << 11;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(width, height, VEN_CIF_DX, VEN_CIF_DY))
+ {
+ dvenc->output_attrs.data_size = 40 << 11;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(width, height, VEN_VGA_DX, VEN_VGA_DY))
+ {
+ dvenc->output_attrs.data_size = 80 << 11;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(width, height, VEN_PAL_DX, VEN_PAL_DY))
+ {
+ dvenc->output_attrs.data_size = 112 << 11;
+ }
+ else
+ {
+ dvenc->output_attrs.data_size = 248 << 11;
+ }
+ }
+ else
+ {
+ // Compression of 50% of the YUV size
+ dvenc->output_attrs.data_size = (int) (width * height * 0.5) * 3 / 2;
+ }
+
+ QC_OMX_MSG_HIGH("new out buf size: %d", dvenc->output_attrs.data_size);
+}
+
+static int ven_update_buf_properties(struct ven_device *dvenc)
+{
+ int result = VENC_S_SUCCESS;
+ struct ven_base_cfg* pcfg;
+
+ if (dvenc == NULL) {
+ QC_OMX_MSG_ERROR("null driver");
+ result = VENC_S_EBADPARAM;
+ }
+
+ pcfg = &dvenc->config.base_config;
+ dvenc->input_attrs.data_size = pcfg->input_height * pcfg->input_width * 3 / 2;
+
+ ven_update_output_size(dvenc);
+
+ return result;
+}
+
+/**************************************************************************
+ * @brief Set the default driver configuration.
+ *************************************************************************/
+static int ven_set_default_config(struct ven_device *dvenc)
+{
+ int ret = 0;
+ struct ven_config_type *pconfig;
+
+ pconfig = &(dvenc->config);
+ QC_OMX_MSG_HIGH("%s: pconfig: %p base_cfg %p \n", __func__, pconfig, &(pconfig->base_config) );
+ // base configuration MPEG4 720p @ 30fps / 8Mbps
+ pconfig->base_config.input_width = 1280;
+ pconfig->base_config.input_height = 720;
+ pconfig->base_config.dvs_width = 1280;
+ pconfig->base_config.dvs_height = 720;
+ pconfig->base_config.codec_type = VEN_CODEC_MPEG4;
+ pconfig->base_config.fps_num = 24;
+ pconfig->base_config.fps_den = 1;
+ pconfig->base_config.target_bitrate = 6000000;
+ pconfig->base_config.input_format = VEN_INPUTFMT_NV21;
+
+ // profile and level setting for 720p
+ pconfig->profile.profile = VEN_PROFILE_MPEG4_SP;
+ pconfig->profile_level.level = VEN_LEVEL_MPEG4_6;
+
+ // variable bitrate with frame skip
+ pconfig->rate_control.rc_mode = VEN_RC_VBR_CFR;
+
+ // disable slicing
+ pconfig->multi_slice.mslice_mode = VENC_SLICE_MODE_DEFAULT;
+ pconfig->multi_slice.mslice_size = 0;
+
+ // no rotation
+ pconfig->rotation.rotation = VEN_ROTATION_0;
+
+ // default bitrate
+ pconfig->bitrate.target_bitrate = pconfig->base_config.target_bitrate;
+
+ // default frame rate
+ pconfig->frame_rate.fps_numerator = pconfig->base_config.fps_num;
+ pconfig->frame_rate.fps_denominator = pconfig->base_config.fps_den;
+
+ // disable int ra refresh
+ pconfig->intra_refresh.mb_count = 0;
+
+ // two second int ra period
+ pconfig->intra_period.num_pframes = pconfig->base_config.fps_num * 2 - 1;
+
+ // conservative QP setting
+ pconfig->session_qp.iframe_qp = 14;
+ pconfig->session_qp.pframe_qp = 14;
+
+ // full QP range
+ pconfig->qp_range.min_qp = 2;
+ pconfig->qp_range.max_qp = 31;
+
+ // 2 ticks per frame
+ pconfig->vop_timing.vop_time_resolution = pconfig->base_config.fps_num * 2;
+
+ // enable AC prediction
+ pconfig->ac_prediction.status = 0;
+
+ // disable error resilience
+ pconfig->short_header.status = 0;
+ pconfig->hec_interval.header_extension = 0;
+ pconfig->data_partition.status = 0;
+
+ return ret;
+}
+
+static void ven_change_codec(struct ven_device * dvenc)
+{
+ struct ven_config_type *pconfig =&(dvenc->config);
+
+ QC_OMX_MSG_HIGH("%s \n", __func__);
+ if (pconfig->base_config.codec_type == VEN_CODEC_MPEG4)
+ {
+ pconfig->qp_range.min_qp = 2;
+ pconfig->qp_range.max_qp = 31;
+
+ pconfig->multi_slice.mslice_mode = VENC_SLICE_MODE_DEFAULT;
+ pconfig->multi_slice.mslice_size = 0;
+
+ pconfig->profile.profile = VEN_PROFILE_MPEG4_SP;
+ pconfig->profile_level.level = VEN_LEVEL_MPEG4_6;
+
+ pconfig->session_qp.iframe_qp = 14;
+ pconfig->session_qp.pframe_qp = 14;
+
+ pconfig->short_header.status = 0;
+ pconfig->hec_interval.header_extension = 0;
+ pconfig->data_partition.status = 0;
+ }
+ else if (pconfig->base_config.codec_type == VEN_CODEC_H263)
+ {
+ pconfig->qp_range.min_qp = 2;
+ pconfig->qp_range.max_qp = 31;
+
+ pconfig->multi_slice.mslice_mode = VENC_SLICE_MODE_DEFAULT;
+ pconfig->multi_slice.mslice_size = 0;
+
+ pconfig->profile.profile = VEN_PROFILE_H263_BASELINE;
+ pconfig->profile_level.level = VEN_LEVEL_H263_70;
+
+ pconfig->session_qp.iframe_qp = 14;
+ pconfig->session_qp.pframe_qp = 14;
+
+ pconfig->short_header.status = 0;
+ pconfig->ac_prediction.status = 0;
+ pconfig->hec_interval.header_extension = 0;
+ pconfig->data_partition.status = 0;
+ }
+ else if (pconfig->base_config.codec_type == VEN_CODEC_H264)
+ {
+ pconfig->qp_range.min_qp = 2;
+ pconfig->qp_range.max_qp = 51;
+
+ pconfig->multi_slice.mslice_mode = VENC_SLICE_MODE_DEFAULT;
+ pconfig->multi_slice.mslice_size = 0;
+
+ pconfig->profile.profile = VEN_PROFILE_H264_BASELINE;
+ pconfig->profile_level.level = VEN_LEVEL_H264_3P1;
+
+ pconfig->session_qp.iframe_qp = 30;
+ pconfig->session_qp.pframe_qp = 30;
+
+ pconfig->short_header.status = 0;
+ pconfig->ac_prediction.status = 0;
+ pconfig->hec_interval.header_extension = 0;
+ pconfig->data_partition.status = 0;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid codec type");
+ }
+}
+
+/**************************************************************************
+ * @brief Validate the given encoder configuration
+ *************************************************************************/
+static int ven_validate_config(struct ven_config_type* pconfig)
+{
+ return 0;
+}
+
+/**************************************************************************
+ * @brief Print out configuration
+ *************************************************************************/
+static void ven_print_config(struct venc_q6_config* pconfig)
+{
+
+ QC_OMX_MSG_PROFILE("Config for video encoder \n");
+ QC_OMX_MSG_PROFILE("config standard=%d, input_frame_height=%d, input_frame_width=%d \n",
+ (int ) pconfig->config_params.standard,
+ (int ) pconfig->config_params.input_frame_height,
+ (int ) pconfig->config_params.input_frame_width);
+
+ QC_OMX_MSG_PROFILE("config output_frame_height=%d, output_frame_width=%d, rotation_angle=%d \n",
+ (int ) pconfig->config_params.output_frame_height,
+ (int ) pconfig->config_params.output_frame_width,
+ (int ) pconfig->config_params.rotation_angle);
+
+ QC_OMX_MSG_PROFILE("config intra_period=%d \n",
+ (int ) pconfig->config_params.intra_period);
+
+ QC_OMX_MSG_PROFILE("config rate_control=%d \n",
+ (int ) pconfig->config_params.rate_control);
+
+ ////////////////////////////////////////
+ //////////////////////// slice
+ QC_OMX_MSG_PROFILE("config mslice_mode=%d, slice_size=%d \n",
+ (int ) pconfig->config_params.slice_config.slice_mode,
+ (int ) pconfig->config_params.slice_config.units_per_slice);
+
+ ////////////////////////////////////////
+ //////////////////////// quality
+ QC_OMX_MSG_PROFILE("config frame_numerator=%d, fps_denominator=%d, bitrate=%d \n",
+ (int ) pconfig->config_params.frame_rate.frame_rate_num,
+ (int ) pconfig->config_params.frame_rate.frame_rate_den,
+ (int ) pconfig->config_params.bitrate);
+
+ QC_OMX_MSG_PROFILE("config iframe_qp=%d, pframe_qp=%d, min_qp=%d \n",
+ (int ) pconfig->config_params.iframe_qp,
+ (int ) pconfig->config_params.pframe_qp,
+ (int ) pconfig->config_params.qp_range.min_qp);
+
+ QC_OMX_MSG_PROFILE("config max_qp=%d",
+ (int ) pconfig->config_params.qp_range.max_qp);
+
+ ////////////////////////////////////////
+ //////////////////////// mp4
+ if (pconfig->config_params.standard == VENC_CODEC_MPEG4)
+ {
+ QC_OMX_MSG_PROFILE("config mp4 profile=%d, level=%d, time_resolution=%d \n",
+ (int ) pconfig->codec_params.mpeg4_params.profile,
+ (int ) pconfig->codec_params.mpeg4_params.level,
+ (int ) pconfig->codec_params.mpeg4_params.time_resolution);
+ QC_OMX_MSG_PROFILE("config ac_prediction=%d, hec_interval=%d, data_partition=%d \n",
+ (int ) pconfig->codec_params.mpeg4_params.ac_prediction,
+ (int ) pconfig->codec_params.mpeg4_params.hec_interval,
+ (int ) pconfig->codec_params.mpeg4_params.data_partition);
+ QC_OMX_MSG_HIGH("config short_header=%d",
+ (int ) pconfig->codec_params.mpeg4_params.short_header);
+ }
+
+ ////////////////////////////////////////
+ //////////////////////// h263
+ else if (pconfig->config_params.standard == VENC_CODEC_H263)
+ {
+ QC_OMX_MSG_PROFILE("config h263 profile=%d, level=%d \n",
+ (int ) pconfig->codec_params.h263_params.profile,
+ (int ) pconfig->codec_params.h263_params.level);
+ }
+
+ ////////////////////////////////////////
+ //////////////////////// h264
+ else if (pconfig->config_params.standard == VENC_CODEC_H264)
+ {
+ QC_OMX_MSG_PROFILE("config h264 profile=%d, level=%d \n",
+ (int ) pconfig->codec_params.h264_params.profile,
+ (int ) pconfig->codec_params.h264_params.level);
+ }
+
+}
+
+/**************************************************************************
+ * @brief Translate driver to Q6 config
+ *************************************************************************/
+static int ven_translate_config(struct ven_config_type* psrc,
+ union venc_codec_config* pcodec,
+ struct venc_common_config* pcommon)
+{
+ int ret = 0;
+
+ if (psrc == NULL ||
+ pcommon == NULL ||
+ pcodec == NULL) {
+ QC_OMX_MSG_ERROR( "%s: failed with null parameter \n", __func__);
+ }
+
+ memset(pcommon, 0, sizeof(*pcommon));
+ memset(pcodec, 0, sizeof(*pcodec));
+
+ // codec specific
+ if (psrc->base_config.codec_type == VEN_CODEC_MPEG4)
+ {
+ struct venc_mpeg4_config* pmp4 = &(pcodec->mpeg4_params);
+
+ QC_OMX_MSG_HIGH("Configuring for mpeg4... psrc = %p\n",psrc);
+ pcommon->standard = VENC_CODEC_MPEG4;
+
+ if (psrc->profile.profile == VEN_PROFILE_MPEG4_SP) {
+ pmp4->profile = VENC_MPEG4_PROFILE_SIMPLE;
+ }
+ else
+ QC_OMX_MSG_ERROR("Invalid mp4 configuration \n");
+
+ switch (psrc->profile_level.level)
+ {
+ case VEN_LEVEL_MPEG4_0:
+ pmp4->level = VENC_MPEG4_LEVEL_0;
+ break;
+ case VEN_LEVEL_MPEG4_0B:
+ pmp4->level = VENC_MPEG4_LEVEL_0B;
+ break;
+ case VEN_LEVEL_MPEG4_1:
+ pmp4->level = VENC_MPEG4_LEVEL_1;
+ break;
+ case VEN_LEVEL_MPEG4_2:
+ pmp4->level = VENC_MPEG4_LEVEL_2;
+ break;
+ case VEN_LEVEL_MPEG4_3:
+ pmp4->level = VENC_MPEG4_LEVEL_3;
+ break;
+ case VEN_LEVEL_MPEG4_4A:
+ pmp4->level = VENC_MPEG4_LEVEL_4A;
+ break;
+ case VEN_LEVEL_MPEG4_5:
+ pmp4->level = VENC_MPEG4_LEVEL_5;
+ break;
+ case VEN_LEVEL_MPEG4_6:
+ pmp4->level = VENC_MPEG4_LEVEL_6;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("invalid level specified %d",
+ (int) psrc->profile_level.level);
+ break;
+ }
+
+ pmp4->time_resolution = psrc->vop_timing.vop_time_resolution;
+ pmp4->ac_prediction = psrc->ac_prediction.status == 1 ? 1 : 0;
+ pmp4->hec_interval = psrc->hec_interval.header_extension; /// @int egrate need to have HEC int erval in driver api. also fix this hack in the OMX layer
+ pmp4->data_partition = psrc->data_partition.status == 1 ? 1 : 0;
+ pmp4->short_header = psrc->short_header.status == 1 ? 1 : 0;
+ }
+ else if (psrc->base_config.codec_type == VEN_CODEC_H263)
+ {
+ struct venc_h263_config* p263 = &(pcodec->h263_params);
+
+ QC_OMX_MSG_HIGH("Configuring for h263...");
+ pcommon->standard = VENC_CODEC_H263;
+ if (psrc->profile.profile == VEN_PROFILE_H263_BASELINE)
+ {
+ p263->profile = VENC_H263_PROFILE_P0;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid profile %d",
+ (int) psrc->profile.profile);
+ }
+
+ switch (psrc->profile_level.level)
+ {
+ case VEN_LEVEL_H263_10:
+ p263->level = VENC_H263_LEVEL_10;
+ break;
+ case VEN_LEVEL_H263_20:
+ p263->level = VENC_H263_LEVEL_20;
+ break;
+ case VEN_LEVEL_H263_30:
+ p263->level = VENC_H263_LEVEL_30;
+ break;
+ case VEN_LEVEL_H263_40:
+ p263->level = VENC_H263_LEVEL_40;
+ break;
+ case VEN_LEVEL_H263_45:
+ p263->level = VENC_H263_LEVEL_45;
+ break;
+ case VEN_LEVEL_H263_50:
+ p263->level = VENC_H263_LEVEL_50;
+ break;
+ case VEN_LEVEL_H263_60:
+ p263->level = VENC_H263_LEVEL_60;
+ break;
+ case VEN_LEVEL_H263_70:
+ p263->level = VENC_H263_LEVEL_70;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("invalid level specified %d",
+ (int) psrc->profile_level.level);
+ break;
+ }
+ }
+ else if (psrc->base_config.codec_type == VEN_CODEC_H264)
+ {
+ struct venc_h264_config* p264 = &(pcodec->h264_params);
+
+ QC_OMX_MSG_HIGH("Configuring for h264...");
+ pcommon->standard = VENC_CODEC_H264;
+
+ if (psrc->profile.profile == VEN_PROFILE_H264_BASELINE)
+ {
+ p264->profile = VENC_H264_PROFILE_BASELINE;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid profile %d",
+ (int) psrc->profile.profile);
+ }
+
+ switch (psrc->profile_level.level)
+ {
+ case VEN_LEVEL_H264_1:
+ p264->level = VENC_H264_LEVEL_1;
+ break;
+ case VEN_LEVEL_H264_1B:
+ p264->level = VENC_H264_LEVEL_1B;
+ break;
+ case VEN_LEVEL_H264_1P1:
+ p264->level = VENC_H264_LEVEL_1P1;
+ break;
+ case VEN_LEVEL_H264_1P2:
+ p264->level = VENC_H264_LEVEL_1P2;
+ break;
+ case VEN_LEVEL_H264_1P3:
+ p264->level = VENC_H264_LEVEL_1P3;
+ break;
+ case VEN_LEVEL_H264_2:
+ p264->level = VENC_H264_LEVEL_2;
+ break;
+ case VEN_LEVEL_H264_2P1:
+ p264->level = VENC_H264_LEVEL_2P1;
+ break;
+ case VEN_LEVEL_H264_2P2:
+ p264->level = VENC_H264_LEVEL_2P2;
+ break;
+ case VEN_LEVEL_H264_3:
+ p264->level = VENC_H264_LEVEL_3;
+ break;
+ case VEN_LEVEL_H264_3P1:
+ p264->level = VENC_H264_LEVEL_3P1;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("invalid level specified %d",
+ (int) psrc->profile_level.level);
+ break;
+ }
+ }
+
+ pcommon->input_frame_width = psrc->base_config.input_width;
+ pcommon->input_frame_height = psrc->base_config.input_height;
+ pcommon->output_frame_width = psrc->base_config.dvs_width;
+ pcommon->output_frame_height = psrc->base_config.dvs_height;
+
+ if (psrc->rotation.rotation == VEN_ROTATION_0)
+ {
+ pcommon->rotation_angle = VEN_ROTATION_0;
+ }
+ else if (psrc->rotation.rotation == VEN_ROTATION_90)
+ {
+ // swap width and height
+ pcommon->output_frame_width = psrc->base_config.dvs_height;
+ pcommon->output_frame_height = psrc->base_config.dvs_width;
+ pcommon->rotation_angle = VEN_ROTATION_90;
+ }
+ else if (psrc->rotation.rotation == VEN_ROTATION_180)
+ {
+ pcommon->rotation_angle = VEN_ROTATION_180;
+ }
+ else if (psrc->rotation.rotation == VEN_ROTATION_270)
+ {
+ // swap width and height
+ pcommon->output_frame_width = psrc->base_config.dvs_height;
+ pcommon->output_frame_height = psrc->base_config.dvs_width;
+ pcommon->rotation_angle = VEN_ROTATION_270;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid rotation %d", psrc->rotation.rotation);
+ }
+ pcommon->intra_period = psrc->intra_period.num_pframes;
+
+ // rate control config
+ if (psrc->rate_control.rc_mode == VEN_RC_OFF)
+ {
+ pcommon->rate_control = VEN_RC_OFF;
+ }
+ else if (psrc->rate_control.rc_mode == VEN_RC_VBR_CFR)
+ {
+ pcommon->rate_control = VEN_RC_VBR_CFR;
+ }
+ else if (psrc->rate_control.rc_mode == VEN_RC_VBR_VFR)
+ {
+ pcommon->rate_control = VEN_RC_VBR_VFR;
+ }
+ else if (psrc->rate_control.rc_mode == VEN_RC_CBR_VFR)
+ {
+ pcommon->rate_control = VEN_RC_CBR_VFR;
+ }
+
+ // quality config
+ pcommon->frame_rate.frame_rate_num = psrc->base_config.fps_num;
+ pcommon->frame_rate.frame_rate_den = psrc->base_config.fps_den;
+ pcommon->bitrate = psrc->bitrate.target_bitrate;
+
+ if (psrc->rate_control.rc_mode == VEN_RC_OFF)
+ {
+ // if rc is off, then use the client supplied qp
+ pcommon->iframe_qp = psrc->session_qp.iframe_qp;
+ pcommon->pframe_qp = psrc->session_qp.pframe_qp;
+ }
+ else
+ {
+ // if rc is on, then we have to supply the qp since driver
+ // interface qp ony applies when rc is off
+ if (psrc->base_config.codec_type == VEN_CODEC_H264)
+ {
+ pcommon->iframe_qp = 30;
+ pcommon->pframe_qp = 30;
+ }
+ else
+ {
+ pcommon->iframe_qp = 14;
+ pcommon->pframe_qp = 14;
+ }
+
+ if (pcommon->iframe_qp > psrc->qp_range.max_qp ||
+ pcommon->iframe_qp < psrc->qp_range.min_qp)
+ {
+ pcommon->iframe_qp = (psrc->qp_range.max_qp + psrc->qp_range.min_qp) / 2;
+ }
+
+ if (pcommon->pframe_qp > psrc->qp_range.max_qp ||
+ pcommon->pframe_qp < psrc->qp_range.min_qp)
+ {
+ pcommon->pframe_qp = (psrc->qp_range.max_qp + psrc->qp_range.min_qp) / 2;
+ }
+ }
+
+ pcommon->qp_range.min_qp = psrc->qp_range.min_qp;
+ pcommon->qp_range.max_qp = psrc->qp_range.max_qp;
+
+ return ret;
+}
+
+
+int ven_start(struct ven_device *dvenc,
+ struct venc_buffers *venc_bufs)
+{
+ int ret = 0;
+ struct venc_init_config vcfg;
+
+ ven_translate_config(&(dvenc->config), &(vcfg.q6_config.codec_params),
+ &(vcfg.q6_config.config_params));
+ memcpy(&(vcfg.q6_bufs), venc_bufs, sizeof(struct venc_buffers));
+
+ ven_print_config(&(vcfg.q6_config));
+ ret = ioctl(dvenc->fd, VENC_IOCTL_CMD_START,&vcfg);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ return ret;
+}
+
+int ven_get_sequence_hdr(struct ven_device *dvenc,
+ struct venc_pmem *pbuf,
+ int *psize)
+{
+ int ret = 0;
+ struct venc_seq_config vcfg;
+
+ ven_translate_config(&(dvenc->config), &(vcfg.q6_config.codec_params),
+ &(vcfg.q6_config.config_params));
+ memcpy(&(vcfg.buf), pbuf, sizeof(struct venc_pmem));
+
+ ret = ioctl(dvenc->fd, VENC_IOCTL_GET_SEQUENCE_HDR, &vcfg);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ else
+ *psize = vcfg.size;
+
+ return ret;
+}
+
+int ven_set_input_req(struct ven_device* dvenc,
+ struct ven_allocator_property* pprop)
+{
+ int ret = 0;
+ QC_OMX_MSG_HIGH("Processing ven_set_input_req...\n");
+
+ if (pprop == NULL)
+ { QC_OMX_MSG_ERROR( "null params(s)");
+ ret = -1;
+ return ret;
+ }
+
+ if (pprop->min_count == dvenc->input_attrs.min_count)
+ {
+ if (pprop->actual_count >= dvenc->input_attrs.min_count)
+ {
+ if (pprop->data_size >= dvenc->input_attrs.data_size)
+ {
+ if (pprop->alignment == dvenc->input_attrs.alignment)
+ {
+ dvenc->input_attrs = *pprop;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "alignment is read only");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "buffer is too small");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "not enough buffers");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "min buffer count is read only");
+ ret = VENC_S_EBUFFREQ;
+ }
+ return ret;
+}
+
+
+int ven_get_input_req(struct ven_device* dvenc,
+ struct ven_allocator_property* pprop)
+{
+ if(!pprop || !dvenc)
+ return -1;
+ memcpy(pprop, &dvenc->input_attrs, sizeof(struct ven_allocator_property));
+ return 0;
+}
+
+
+/**************************************************************************
+ * @brief
+ *************************************************************************/
+int ven_set_output_req(struct ven_device* dvenc,
+ struct ven_allocator_property* pprop)
+{
+ int ret = 0;
+ QC_OMX_MSG_HIGH("Processing ven_set_output_req...");
+
+ if (dvenc != NULL && pprop != NULL)
+ {
+ if (pprop->min_count == dvenc->output_attrs.min_count)
+ {
+ if (pprop->actual_count >= dvenc->output_attrs.min_count)
+ {
+ if (pprop->data_size >= dvenc->output_attrs.data_size)
+ {
+ if (pprop->alignment == dvenc->output_attrs.alignment)
+ {
+ dvenc->output_attrs = *pprop;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "alignment is read only");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "buffer is too small");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "not enough buffers");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "min buffer count is read only");
+ ret = VENC_S_EBUFFREQ;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR( "null params(s)");
+ ret = -1;
+ }
+ return ret;
+}
+int ven_get_output_req(struct ven_device* dvenc,
+ struct ven_allocator_property* pprop)
+{
+ if(!pprop || !dvenc)
+ return -1;
+ memcpy(pprop, &dvenc->output_attrs, sizeof(struct ven_allocator_property));
+ return 0;
+}
+
+/**************************************************************************
+ * @brief
+ *************************************************************************/
+int ven_set_qp_range(struct ven_device* dvenc,
+ struct ven_qp_range *ptr)
+{
+ int ret = 0;
+ struct venc_qp_range qp;
+
+ QC_OMX_MSG_HIGH("%s: SET_QP_RANGE \n", __func__);
+ memcpy(&(dvenc->config.qp_range), ptr, sizeof(struct ven_qp_range));
+
+ if (dvenc->state == VENC_STATE_START) {
+
+ qp.min_qp = (dvenc->config.qp_range).min_qp;
+ qp.max_qp = (dvenc->config.qp_range).max_qp;
+ ret = ioctl(dvenc->fd, VENC_IOCTL_SET_QP_RANGE,&qp);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+int ven_get_qp_range(struct ven_device* dvenc,
+ struct ven_qp_range *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: SET_INTRA_PERIOD \n", __func__);
+ memcpy(ptr, &(dvenc->config.session_qp),
+ sizeof(struct ven_qp_range));
+ return ret;
+}
+/**************************************************************************
+ * @brief
+ *
+ * @todo document
+ *************************************************************************/
+int ven_set_session_qp(struct ven_device* dvenc,
+ struct ven_session_qp *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: SET_SESSION_QP \n", __func__);
+ memcpy(&(dvenc->config.session_qp), ptr,
+ sizeof(struct ven_session_qp));
+ return ret;
+}
+
+int ven_get_session_qp(struct ven_device* dvenc,
+ struct ven_session_qp *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: GET_SESSION_QP \n", __func__);
+ memcpy(ptr, &(dvenc->config.session_qp),
+ sizeof(struct ven_session_qp));
+ return ret;
+}
+
+int ven_set_ac_prediction(struct ven_device* dvenc,
+ struct ven_switch *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: SET_AC_PREDICITON \n", __func__);
+ memcpy(&(dvenc->config.ac_prediction), ptr,
+ sizeof(struct ven_switch));
+ return ret;
+}
+
+int ven_get_ac_prediction(struct ven_device* dvenc,
+ struct ven_switch *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: GET_AC_PREDICTION \n", __func__);
+ memcpy(ptr, &(dvenc->config.ac_prediction),
+ sizeof(struct ven_switch));
+ return ret;
+}
+
+int ven_set_short_hdr(struct ven_device* dvenc,
+ struct ven_switch *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: SET_SHORT_HEADER \n", __func__);
+ memcpy(&(dvenc->config.short_header), ptr,
+ sizeof(struct ven_switch));
+ return ret;
+}
+
+int ven_get_short_hdr(struct ven_device* dvenc,
+ struct ven_switch *ptr)
+{
+ int ret = 0;
+
+ QC_OMX_MSG_HIGH("%s: GET_SHORT_HEADER \n", __func__);
+ memcpy(ptr, &(dvenc->config.short_header),
+ sizeof(struct ven_switch));
+ return ret;
+}
+
+/**************************************************************************
+ * @brief
+ *
+ * @todo document
+ *************************************************************************/
+int ven_set_intra_period(struct ven_device* dvenc,
+ struct ven_intra_period *ptr)
+{
+ int ret = 0;
+ unsigned int pnum=0;
+
+ QC_OMX_MSG_HIGH("%s: SET_INTRA_PERIOD \n", __func__);
+ memcpy(&(dvenc->config.intra_period), ptr, sizeof(struct ven_intra_period));
+
+ if (dvenc->state == VENC_STATE_START) {
+ pnum = (dvenc->config.intra_period).num_pframes;
+ QC_OMX_MSG_HIGH("Process intra period with pnum:%d \n", pnum);
+
+ ret = ioctl(dvenc->fd, VENC_IOCTL_SET_INTRA_PERIOD, &pnum);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+int ven_get_intra_period(struct ven_device* dvenc,
+ struct ven_intra_period* intra_period)
+{
+ if(!intra_period || !dvenc)
+ return -1;
+ memcpy(intra_period, &dvenc->config.intra_period, sizeof(struct ven_intra_period));
+ return 0;
+}
+
+/**************************************************************************
+ * @brief
+ *
+ * @todo document
+ *************************************************************************/
+int ven_set_frame_rate(struct ven_device* dvenc,
+ struct ven_frame_rate *ptr)
+{
+ int ret = 0;
+ struct venc_frame_rate pdata;
+
+ QC_OMX_MSG_HIGH("%s: SET_FRAME_RATE \n", __func__);
+ memcpy(&(dvenc->config.frame_rate), ptr, sizeof(struct ven_frame_rate));
+
+ if (dvenc->state == VENC_STATE_START)
+ {
+ ptr = &(dvenc->config.frame_rate);
+ pdata.frame_rate_den = ptr->fps_denominator;
+ pdata.frame_rate_num = ptr->fps_numerator;
+
+ ret = ioctl(dvenc->fd, VENC_IOCTL_SET_FRAME_RATE, &pdata);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+int ven_get_frame_rate(struct ven_device* dvenc,
+ struct ven_frame_rate* frame_rate)
+{
+ if(!frame_rate || !dvenc)
+ return -1;
+ memcpy(frame_rate, &dvenc->config.frame_rate, sizeof(struct ven_frame_rate));
+ return 0;
+}
+
+/**************************************************************************
+ * @brief
+ *
+ * @todo document
+ *************************************************************************/
+int ven_set_target_bitrate(struct ven_device* dvenc,
+ struct ven_target_bitrate *ptr)
+{
+ int ret = 0;
+ unsigned int pdata = 0;
+
+ memcpy(&(dvenc->config.bitrate), ptr, sizeof(struct ven_target_bitrate));
+
+ if (dvenc->state == VENC_STATE_START)
+ {
+ pdata = (dvenc->config.bitrate).target_bitrate;
+ (dvenc->config.base_config).target_bitrate = pdata;
+ ret = ioctl(dvenc->fd, VENC_IOCTL_SET_TARGET_BITRATE, &pdata);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s: remote function failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+int ven_get_target_bitrate(struct ven_device* dvenc,
+ struct ven_target_bitrate *ptr)
+{
+ if(!ptr || !dvenc)
+ return -1;
+ memcpy(ptr, &dvenc->config.bitrate, sizeof(struct ven_target_bitrate));
+ return 0;
+}
+int ven_request_iframe(struct ven_device* dvenc)
+{
+ if(!dvenc)
+ return -1;
+ int rc = ioctl(dvenc->fd, VENC_IOCTL_CMD_REQUEST_IFRAME);
+ if(rc) {
+ QC_OMX_MSG_ERROR("%s: err: %d \n", __func__, rc);
+ }
+ return rc;
+}
+
+
+int ven_set_intra_refresh_rate(struct ven_device* dvenc,
+ struct ven_intra_refresh* intra_ref)
+{
+ int ret = 0;
+ unsigned int pnum;
+ if(!intra_ref || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.intra_refresh, intra_ref, sizeof(struct ven_intra_refresh));
+ pnum = dvenc->config.intra_refresh.mb_count;
+ ret = ioctl(dvenc->fd, VENC_IOCTL_SET_INTRA_REFRESH, &pnum);
+ if (ret) {
+ QC_OMX_MSG_ERROR("%s failed (%d) \n", __func__, ret);
+ return ret;
+ }
+ return 0;
+}
+int ven_get_intra_refresh_rate(struct ven_device* dvenc,
+ struct ven_intra_refresh* intra_ref)
+{
+ if(!intra_ref || !dvenc)
+ return -1;
+ memcpy(intra_ref,&dvenc->config.intra_refresh, sizeof(struct ven_intra_refresh));
+ return 0;
+}
+
+int ven_set_multislice_cfg(struct ven_device* dvenc,
+ struct ven_multi_slice_cfg* multi_slice_cfg)
+{
+ if(!multi_slice_cfg || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.multi_slice, multi_slice_cfg, sizeof(struct ven_multi_slice_cfg));
+ return 0;
+}
+int ven_get_multislice_cfg(struct ven_device* dvenc,
+ struct ven_multi_slice_cfg* multi_slice_cfg)
+{
+ if(!multi_slice_cfg || !dvenc)
+ return -1;
+ memcpy(multi_slice_cfg, &dvenc->config.multi_slice, sizeof(struct ven_multi_slice_cfg));
+ return 0;
+}
+int ven_set_rate_control(struct ven_device* dvenc,
+ struct ven_rate_ctrl_cfg* rate_ctrl)
+{
+ if(!rate_ctrl || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.rate_control, rate_ctrl, sizeof(struct ven_rate_ctrl_cfg));
+ return 0;
+}
+int ven_get_rate_control(struct ven_device* dvenc,
+ struct ven_rate_ctrl_cfg* rate_ctrl)
+{
+ if(!rate_ctrl || !dvenc)
+ return -1;
+ memcpy(rate_ctrl, &dvenc->config.rate_control, sizeof(struct ven_rate_ctrl_cfg));
+ return 0;
+}
+int ven_set_vop_timing(struct ven_device* dvenc,
+ struct ven_vop_timing_cfg* vop_timing)
+{
+ if(!vop_timing || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.rate_control, vop_timing, sizeof(struct ven_vop_timing_cfg));
+ return 0;
+}
+int ven_get_vop_timing(struct ven_device* dvenc,
+ struct ven_vop_timing_cfg* vop_timing)
+{
+ if(!vop_timing || !dvenc)
+ return -1;
+ memcpy(vop_timing, &dvenc->config.rate_control, sizeof(struct ven_vop_timing_cfg));
+ return 0;
+}
+int ven_set_rotation(struct ven_device* dvenc,
+ struct ven_rotation* rotation)
+{
+ if(!rotation || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.rotation, rotation, sizeof(struct ven_rotation));
+ return 0;
+}
+int ven_get_rotation(struct ven_device* dvenc,
+ struct ven_rotation* rotation)
+{
+ if(!rotation || !dvenc)
+ return -1;
+ memcpy(rotation, &dvenc->config.rotation, sizeof(struct ven_rotation));
+ return 0;
+}
+int ven_set_hec(struct ven_device* dvenc,
+ struct ven_switch* hex)
+{
+ if(!hex || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.rotation, hex, sizeof(struct ven_header_extension));
+ return 0;
+}
+int ven_get_hec(struct ven_device* dvenc,
+ struct ven_switch* hex)
+{
+ if(!hex || !dvenc)
+ return -1;
+ memcpy(hex, &dvenc->config.rotation, sizeof(struct ven_header_extension));
+ return 0;
+}
+int ven_set_data_partition(struct ven_device* dvenc,
+ struct ven_switch* dp)
+{
+ if(!dp || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.rotation, dp, sizeof(struct ven_switch));
+ return 0;
+}
+int ven_get_data_partition(struct ven_device* dvenc,
+ struct ven_switch* dp)
+{
+ if(!dp || !dvenc)
+ return -1;
+ memcpy(dp, &dvenc->config.rotation, sizeof(struct ven_switch));
+ return 0;
+}
+int ven_get_base_cfg(struct ven_device * dvenc,
+ struct ven_base_cfg* bcfg)
+{
+ if(!bcfg || !dvenc)
+ return -1;
+ memcpy(bcfg, &dvenc->config.base_config, sizeof(struct ven_base_cfg));
+ return 0;
+}
+
+int ven_set_base_cfg(struct ven_device * dvenc,
+ struct ven_base_cfg* pcfg)
+{
+ struct ven_base_cfg *pconfig;
+ int new_codec;
+ int result = 0;
+
+ if (dvenc == NULL || pcfg == NULL) {
+ QC_OMX_MSG_ERROR( "null driver");
+ return -1;
+ }
+
+ new_codec = (pcfg->codec_type != dvenc->config.base_config.codec_type);
+ pconfig = &(dvenc->config.base_config);
+ memcpy(pconfig, pcfg, sizeof(struct ven_base_cfg));
+ dvenc->config.frame_rate.fps_numerator = pconfig->fps_num;
+ dvenc->config.frame_rate.fps_denominator = pconfig->fps_den;
+ dvenc->config.bitrate.target_bitrate = pconfig->target_bitrate;
+ dvenc->input_attrs.data_size = pconfig->input_width * pconfig->input_height * 3 / 2;
+ dvenc->output_attrs.data_size = pconfig->input_width * pconfig->input_height * 3 / 2;
+ dvenc->config.intra_period.num_pframes = pconfig->fps_num * 2 - 1;
+ dvenc->config.vop_timing.vop_time_resolution = pconfig->fps_num * 2;
+
+ if (new_codec)
+ {
+ ven_change_codec(dvenc);
+ }
+
+ result = ven_update_buf_properties(dvenc);
+
+ return 0;
+}
+int ven_set_codec_profile(struct ven_device* dvenc,
+ struct ven_profile* prof)
+{
+ if(!prof || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.profile, prof, sizeof(struct ven_profile));
+ return 0;
+}
+int ven_get_codec_profile(struct ven_device* dvenc,
+ struct ven_profile* prof)
+{
+ if(!prof || !dvenc)
+ return -1;
+ memcpy(prof, &dvenc->config.profile, sizeof(struct ven_profile));
+ return 0;
+}
+int ven_set_profile_level(struct ven_device* dvenc,
+ struct ven_profile_level* prof_level)
+{
+ int result = 0;
+
+ if(!prof_level || !dvenc)
+ return -1;
+ memcpy(&dvenc->config.profile_level, prof_level, sizeof(struct ven_profile_level));
+ result = ven_update_buf_properties(dvenc);
+
+ return result;
+}
+int ven_get_profile_level(struct ven_device* dvenc,
+ struct ven_profile_level* prof_level)
+{
+ if(!prof_level || !dvenc)
+ return -1;
+ memcpy(prof_level, &dvenc->config.profile_level, sizeof(struct ven_profile_level));
+ return 0;
+}
+
+
+int ven_device_open(struct ven_device** handle)
+{
+ int fd;
+
+ QC_OMX_MSG_HIGH("%s \n", __func__);
+ struct ven_device* dvenc = (struct ven_device *)malloc(sizeof(struct ven_device));
+ if (!dvenc) return -1;
+
+ *handle = dvenc;
+ QC_OMX_MSG_HIGH("%s: dvenc:%p pconfig: %p \n", __func__, dvenc, &(dvenc->config.base_config));
+ fd = open("/dev/q6venc", O_RDWR);
+ if (fd < 0)
+ {
+ QC_OMX_MSG_ERROR("Cannot open /dev/q6venc ");
+ close(fd);
+ return -1;
+ }
+ dvenc->fd = fd;
+
+ (void) ven_set_default_config(dvenc);
+ (void) ven_set_default_buf_properties(dvenc);
+ dvenc->config.callback_event = NULL;
+ dvenc->state = VENC_STATE_STOP;
+
+ // dvenc->is_active = 1;
+ QC_OMX_MSG_HIGH("%s = %d\n", __func__,fd);
+ return fd;
+}
+
+int ven_device_close(struct ven_device* handle)
+{
+ int ret = 0;
+ struct ven_device *dvenc;
+
+ QC_OMX_MSG_HIGH("%s\n", __func__);
+
+ dvenc = (struct ven_device *)handle;
+ if (dvenc) {
+ close(dvenc->fd);
+ }
+
+ free(dvenc);
+ return ret;
+}
diff --git a/omx/mm-video/qdsp6/venc/omx/inc/OMX_Venc.h b/omx/mm-video/qdsp6/venc/omx/inc/OMX_Venc.h
new file mode 100644
index 0000000..98cf4eb
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/omx/inc/OMX_Venc.h
@@ -0,0 +1,520 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef OMX_VENC_H
+#define OMX_VENC_H
+
+/*----------------------------------------------------------------------------
+ * Include Files
+ * -------------------------------------------------------------------------*/
+#include "qc_omx_component.h"
+#include "OMX_Types.h"
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+
+#include "venc_device.h"
+#include <pthread.h>
+#include <linux/msm_q6venc.h>
+#include <semaphore.h>
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+class VencBufferManager; // forward declaration
+class VencMsgQ; // forward declaration
+
+/*---------------------------------------------------------------------------
+ * Class Definitions
+ ---------------------------------------------------------------------------*/
+
+
+/**
+ * The omx mpeg4 video encoder class.
+ */
+class Venc : public qc_omx_component
+{
+ public:
+
+ /**********************************************************************//**
+ * @brief Class constructor
+ *************************************************************************/
+ static Venc* get_instance();
+ Venc();
+
+ /**********************************************************************//**
+ * @brief Class destructor
+ *************************************************************************/
+ virtual ~Venc();
+
+ /**********************************************************************//**
+ * @brief Initializes the component
+ *
+ * @return error if unsuccessful.
+ *************************************************************************/
+ virtual OMX_ERRORTYPE component_init(OMX_IN OMX_STRING pComponentName);
+
+ //////////////////////////////////////////////////////////////////////////
+ /// For the following methods refer to corresponding function descriptions
+ /// in the OMX_COMPONENTTYPE structure in OMX_Componenent.h
+ //////////////////////////////////////////////////////////////////////////
+
+ virtual OMX_ERRORTYPE get_component_version(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_STRING pComponentName,
+ OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
+ OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
+ OMX_OUT OMX_UUIDTYPE* pComponentUUID);
+
+ virtual OMX_ERRORTYPE send_command(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_COMMANDTYPE Cmd,
+ OMX_IN OMX_U32 nParam1,
+ OMX_IN OMX_PTR pCmdData);
+
+ virtual OMX_ERRORTYPE get_parameter(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nParamIndex,
+ OMX_INOUT OMX_PTR pComponentParameterStructure);
+
+
+ virtual OMX_ERRORTYPE set_parameter(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_IN OMX_PTR pComponentParameterStructure);
+
+
+ virtual OMX_ERRORTYPE get_config(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_INOUT OMX_PTR pComponentConfigStructure);
+
+
+ virtual OMX_ERRORTYPE set_config(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_IN OMX_PTR pComponentConfigStructure);
+
+
+ virtual OMX_ERRORTYPE get_extension_index(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_STRING cParameterName,
+ OMX_OUT OMX_INDEXTYPE* pIndexType);
+
+
+ virtual OMX_ERRORTYPE get_state(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_STATETYPE* pState);
+
+
+ virtual OMX_ERRORTYPE component_tunnel_request(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 nPort,
+ OMX_IN OMX_HANDLETYPE hTunneledComp,
+ OMX_IN OMX_U32 nTunneledPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup);
+
+ virtual OMX_ERRORTYPE use_buffer(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN OMX_U32 nSizeBytes,
+ OMX_IN OMX_U8* pBuffer);
+
+ virtual OMX_ERRORTYPE allocate_buffer(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN OMX_U32 nSizeBytes);
+
+ virtual OMX_ERRORTYPE free_buffer(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ virtual OMX_ERRORTYPE empty_this_buffer(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ virtual OMX_ERRORTYPE fill_this_buffer(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ virtual OMX_ERRORTYPE set_callbacks(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_CALLBACKTYPE* pCallbacks,
+ OMX_IN OMX_PTR pAppData);
+
+ virtual OMX_ERRORTYPE component_deinit(
+ OMX_IN OMX_HANDLETYPE hComponent);
+
+ virtual OMX_ERRORTYPE use_EGL_image(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN void* eglImage);
+
+ virtual OMX_ERRORTYPE component_role_enum(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_U8 *cRole,
+ OMX_IN OMX_U32 nIndex);
+
+ private:
+ static Venc* g_pVencInstance;
+
+ /// Max number of input buffers (assumed)
+ static const OMX_S32 MAX_IN_BUFFERS = 16;
+
+ /// Max number of output buffers (assumed)
+ static const OMX_S32 MAX_OUT_BUFFERS = 16;
+
+ /// Port indexes according to the OMX IL spec
+ enum PortIndexType
+ {
+ PORT_INDEX_IN = 0,
+ PORT_INDEX_OUT = 1,
+ PORT_INDEX_BOTH = -1,
+ PORT_INDEX_NONE = -2
+ };
+
+ // Bit Positions
+ enum flags_bit_positions
+ {
+ // Defer transition to IDLE
+ OMX_COMPONENT_IDLE_PENDING = 0x1,
+ // Defer transition to LOADING
+ OMX_COMPONENT_LOADING_PENDING = 0x2,
+ // Defer transition to Enable
+ OMX_COMPONENT_INPUT_ENABLE_PENDING = 0x3,
+ // Defer transition to Enable
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING = 0x4,
+ // Defer transition to Disable
+ OMX_COMPONENT_INPUT_DISABLE_PENDING = 0x5,
+ // Defer transition to Disable
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING = 0x6,
+ //Defer going to the Invalid state
+ OMX_COMPONENT_INVALID_PENDING = 0x9,
+ //Defer going to Pause state
+ OMX_COMPONENT_PAUSE_PENDING = 0xA
+ };
+ /// Private data for buffer header field pInputPortPrivate
+ struct PrivatePortData
+ {
+ OMX_BOOL bComponentAllocated; ///< Did we allocate this buffer?
+ struct venc_pmem sPmemInfo;
+ };
+
+ private:
+
+ /**********************************************************************//**
+ * @brief encode frame function.
+ *
+ * Method will check to see if there is an available input
+ * and output buffer. If so, then it will encode, otherwise it will
+ * queue the specified buffer until it receives another buffer.
+ *
+ * @param pBuffer: pointer to the input or output buffer.
+ * @return NULL (ignore)
+ *************************************************************************/
+ // void process_encode_frame(OMX_BUFFERHEADERTYPE* pBuffer);
+ OMX_ERRORTYPE encode_frame(OMX_BUFFERHEADERTYPE* pBuffer);
+ /**********************************************************************//**
+ * @brief Component thread main function.
+ *
+ * @param pClassObj: Pointer to the Venc instance.
+ * @return NULL (ignore)
+ *************************************************************************/
+ static void *component_thread(void* pClassObj);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ *************************************************************************/
+ void process_state_change(OMX_STATETYPE eState);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_FLUSH
+ *
+ * @param nPortIndex: The port index
+ *************************************************************************/
+ void process_flush(OMX_U32 nPortIndex);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ *************************************************************************/
+ void process_port_enable(OMX_U32 nPortIndex);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ *************************************************************************/
+ void process_port_disable(OMX_U32 nPortIndex);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ * @param pMarkData: The mark buffer data
+ *************************************************************************/
+ void process_mark_buffer(OMX_U32 nPortIndex,
+ const OMX_MARKTYPE* pMarkData);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ * @param pMarkData: The mark buffer data
+ *************************************************************************/
+ void process_empty_buffer(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ * @param pMarkData: The mark buffer data
+ *************************************************************************/
+ void process_fill_buffer(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**********************************************************************//**
+ * @brief Process thread message MSG_ID_STATE_CHANGE
+ *
+ * @param nPortIndex: The port index
+ * @param pMarkData: The mark buffer data
+ *************************************************************************/
+ void process_driver_msg(struct venc_msg* pMsg);
+
+ OMX_ERRORTYPE is_multi_slice_mode_supported();
+ // driver status messages
+ void process_status_input_buffer_done(void* pData, unsigned long nStatus);
+ void process_status_output_buffer_done(void* pData, unsigned long nStatus);
+ void process_status_flush_done(struct venc_buffer_flush* pData, unsigned long nStatus);
+ void process_status_start_done(unsigned long nStatus);
+ void process_status_stop_done(unsigned long nStatus);
+ void process_status_pause_done(unsigned long nStatus);
+ void process_status_resume_done(unsigned long nStatus);
+
+ static void *reader_thread_entry(void *);
+ void reader_thread();
+
+
+ OMX_ERRORTYPE translate_profile(unsigned int* pDriverProfile,
+ OMX_U32 eProfile,
+ OMX_VIDEO_CODINGTYPE eCodec);
+ OMX_ERRORTYPE translate_level(unsigned int* pDriverLevel,
+ OMX_U32 eLevel,
+ OMX_VIDEO_CODINGTYPE eCodec);
+
+ OMX_ERRORTYPE translate_driver_error(int);
+ OMX_ERRORTYPE driver_set_default_config();
+ OMX_ERRORTYPE adjust_profile_level();
+ OMX_ERRORTYPE driver_get_buffer_reqs(OMX_PARAM_PORTDEFINITIONTYPE* pPortDef, PortIndexType eIndex);
+
+ /**********************************************************************//**
+ * @brief update the port format
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_port_fmt(OMX_IN OMX_VIDEO_PARAM_PORTFORMATTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update the port definition
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_port_def(OMX_IN OMX_PARAM_PORTDEFINITIONTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update video init params
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_video_init(OMX_IN OMX_PORT_PARAM_TYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update bitrate
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_bitrate(OMX_IN OMX_VIDEO_PARAM_BITRATETYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update mpeg4 params
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_mpeg4(OMX_IN OMX_VIDEO_PARAM_MPEG4TYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update profile/level params
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_profile_level(OMX_IN OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update error correction
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_err_correct(OMX_IN OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update h263 params
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_h263(OMX_IN OMX_VIDEO_PARAM_H263TYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update avc params
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_avc(OMX_IN OMX_VIDEO_PARAM_AVCTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update quant params
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_quantization(OMX_IN OMX_VIDEO_PARAM_QUANTIZATIONTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update intra refresh
+ *************************************************************************/
+ OMX_ERRORTYPE update_param_intra_refresh(OMX_IN OMX_VIDEO_PARAM_INTRAREFRESHTYPE* pParam);
+
+ /**********************************************************************//**
+ * @brief update bitrate
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_bitrate(OMX_VIDEO_CONFIG_BITRATETYPE* pConfig);
+
+ /**********************************************************************//**
+ * @brief update frame rate
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_frame_rate(OMX_CONFIG_FRAMERATETYPE* pConfig);
+
+ /**********************************************************************//**
+ * @brief update rotation
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_rotate(OMX_CONFIG_ROTATIONTYPE* pConfig);
+
+ /**********************************************************************//**
+ * Check for the actual buffer allocate/deallocate complete
+ *
+ *************************************************************************/
+ OMX_BOOL allocate_done(void);
+ OMX_BOOL release_done();
+ /**********************************************************************//**
+ * @brief request intra vop
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_intra_vop_refresh(OMX_IN OMX_CONFIG_INTRAREFRESHVOPTYPE* pConfig);
+
+#ifdef QCOM_OMX_VENC_EXT
+ /**********************************************************************//**
+ * @brief change qp range
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_qp_range(OMX_IN QOMX_VIDEO_TEMPORALSPATIALTYPE* pConfig);
+
+ /**********************************************************************//**
+ * @brief change the intra period
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_intra_period(OMX_IN QOMX_VIDEO_INTRAPERIODTYPE* pConfig);
+#endif
+
+ /**********************************************************************//**
+ * @brief change the nal size
+ *************************************************************************/
+ OMX_ERRORTYPE update_config_nal_size(OMX_IN OMX_VIDEO_CONFIG_NALSIZE* pConfig);
+
+ OMX_ERRORTYPE allocate_q6_buffers(struct venc_buffers *);
+ OMX_ERRORTYPE free_q6_buffers(struct venc_buffers *);
+
+ OMX_ERRORTYPE pmem_alloc(struct venc_pmem *ptr, int size, int pmem_region_id);
+ OMX_ERRORTYPE pmem_free(struct venc_pmem *);
+ private:
+
+ /// thread object
+ pthread_t m_ComponentThread;
+
+ /// thread object
+ pthread_t m_ReaderThread;
+
+ /// Input buffer manager
+ VencBufferManager* m_pInBufferMgr;
+
+ /// Output buffer manager
+ VencBufferManager* m_pOutBufferMgr;
+
+ /// Message Q
+ VencMsgQ* m_pMsgQ;
+
+ /// Private input buffer data
+ PrivatePortData* m_pPrivateInPortData;
+
+ /// Private output buffer data
+ PrivatePortData* m_pPrivateOutPortData;
+
+ struct venc_buffers m_sQ6Buffers;
+ private:
+
+ OMX_STATETYPE m_eState;
+ OMX_CALLBACKTYPE m_sCallbacks;
+ OMX_PTR m_pAppData;
+ OMX_HANDLETYPE m_hSelf;
+ OMX_PORT_PARAM_TYPE m_sPortParam;
+ OMX_PARAM_PORTDEFINITIONTYPE m_sInPortDef;
+ OMX_PARAM_PORTDEFINITIONTYPE m_sOutPortDef;
+ OMX_U32 m_nFlags;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE m_sInPortFormat;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE m_sOutPortFormat;
+ OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE m_sErrorCorrection;
+ OMX_PRIORITYMGMTTYPE m_sPriorityMgmt;
+ OMX_PARAM_BUFFERSUPPLIERTYPE m_sInBufSupplier;
+ OMX_PARAM_BUFFERSUPPLIERTYPE m_sOutBufSupplier;
+ OMX_VIDEO_PARAM_MPEG4TYPE m_sParamMPEG4;
+ OMX_VIDEO_PARAM_AVCTYPE m_sParamAVC;
+ OMX_VIDEO_PARAM_BITRATETYPE m_sParamBitrate;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE m_sParamProfileLevel;
+ OMX_VIDEO_PARAM_INTRAREFRESHTYPE m_sParamIntraRefresh;
+ OMX_VIDEO_CONFIG_BITRATETYPE m_sConfigBitrate;
+ OMX_CONFIG_FRAMERATETYPE m_sConfigFramerate;
+ OMX_CONFIG_ROTATIONTYPE m_sConfigFrameRotation;
+ OMX_VIDEO_PARAM_H263TYPE m_sParamH263;
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE m_sParamQPs;
+ OMX_CONFIG_INTRAREFRESHVOPTYPE m_sConfigIntraRefreshVOP;
+#ifdef QCOM_OMX_VENC_EXT
+ QOMX_VIDEO_TEMPORALSPATIALTYPE m_sConfigQpRange;
+ QOMX_VIDEO_INTRAPERIODTYPE m_sConfigIntraPeriod;
+#endif
+ OMX_VIDEO_CONFIG_NALSIZE m_sConfigNAL;
+ OMX_BUFFERHEADERTYPE* m_pInBuffHeaders;
+ OMX_BUFFERHEADERTYPE* m_pOutBuffHeaders;
+ OMX_STRING m_pComponentName;
+ OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE];
+ struct ven_device *m_pDevice;
+ OMX_S32 m_nFd;
+
+ OMX_U32 m_nInBuffAllocated;
+ OMX_U32 m_nOutBuffAllocated;
+ sem_t m_cmd_lock;
+
+};
+
+#endif
diff --git a/omx/mm-video/qdsp6/venc/omx/src/OMX_Venc.cpp b/omx/mm-video/qdsp6/venc/omx/src/OMX_Venc.cpp
new file mode 100644
index 0000000..d3a97f4
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/omx/src/OMX_Venc.cpp
@@ -0,0 +1,4843 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ O p e n M A X w r a p p e r s
+ O p e n M A X C o r e
+
+ @file OMX_Venc.cpp
+ This module contains the implementation of the OpenMAX core & component.
+
+=========================================================================*/
+
+/*----------------------------------------------------------------------------
+* Include Files
+* -------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <linux/android_pmem.h>
+#include <fcntl.h>
+
+#include "OMX_Venc.h"
+
+#include "OMX_VencBufferManager.h"
+#include "OMX_VencMsgQ.h"
+#include "qc_omx_common.h"
+#include "venc_debug.h"
+
+// #include "Diag_LSM.h"
+
+#define DeviceIoControl ioctl
+/*----------------------------------------------------------------------------
+* Preprocessor Definitions and Constants
+* -------------------------------------------------------------------------*/
+
+#define OMX_SPEC_VERSION 0x00000101
+#define OMX_INIT_STRUCT(_s_, _name_) \
+ memset((_s_), 0x0, sizeof(_name_)); \
+ (_s_)->nSize = sizeof(_name_); \
+ (_s_)->nVersion.nVersion = OMX_SPEC_VERSION
+
+#define BITS_SHIFT(index) 1 << index
+#define BITMASK_SET(val, index) (val |= (1 << index))
+#define BITMASK_CLEAR(val, index) (val &= (OMX_U32) ~(1 << index))
+#define BITMASK_PRESENT(val, index) (val & (1 << index))
+
+static const char pRoleMPEG4[] = "video_encoder.mpeg4";
+static const char pRoleH263[] = "video_encoder.h263";
+static const char pRoleAVC[] = "video_encoder.avc";
+/*----------------------------------------------------------------------------
+* Type Declarations
+* -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+* Global Data Definitions
+* -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+* Static Variable Definitions
+* -------------------------------------------------------------------------*/
+Venc* Venc::g_pVencInstance = NULL;
+
+#define VEN_QCIF_DX 176
+#define VEN_QCIF_DY 144
+
+#define VEN_CIF_DX 352
+#define VEN_CIF_DY 288
+
+#define VEN_VGA_DX 640
+#define VEN_VGA_DY 480
+
+#define VEN_PAL_DX 720
+#define VEN_PAL_DY 576
+
+#define VEN_WQVGA_DX 400
+#define VEN_WVQGA_DY 240
+
+#define VEN_D1_DX 720
+#define VEN_D1_DY 480
+
+#define VEN_WVGA_DX 800
+#define VEN_WVGA_DY 480
+
+#define VEN_HD720P_DX 1280
+#define VEN_HD720P_DY 720
+
+#define VEN_FRAME_SIZE_IN_RANGE(w1, h1, w2, h2) \
+ ((w1) * (h1) <= (w2) * (h2))
+
+/*----------------------------------------------------------------------------
+* Static Function Declarations and Definitions
+* -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+* Externalized Function Definitions
+* -------------------------------------------------------------------------*/
+extern "C" {
+ void* get_omx_component_factory_fn(void)
+ {
+ return Venc::get_instance();
+ }
+}
+#define GetLastError() 1
+typedef struct OMXComponentCapabilityFlagsType
+{
+ ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS
+ OMX_BOOL iIsOMXComponentMultiThreaded;
+ OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc;
+ OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc;
+ OMX_BOOL iOMXComponentSupportsMovableInputBuffers;
+ OMX_BOOL iOMXComponentSupportsPartialFrames;
+ OMX_BOOL iOMXComponentUsesNALStartCodes;
+ OMX_BOOL iOMXComponentCanHandleIncompleteFrames;
+ OMX_BOOL iOMXComponentUsesFullAVCFrames;
+
+} OMXComponentCapabilityFlagsType;
+#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347
+///////////////////////////////////////////////////////////////////////////////
+// Refer to the header file for detailed method descriptions
+///////////////////////////////////////////////////////////////////////////////
+Venc::Venc() :
+ m_ComponentThread(NULL),
+ m_ReaderThread(NULL),
+ m_pInBufferMgr(NULL),
+ m_pOutBufferMgr(NULL),
+ m_pMsgQ(NULL),
+ m_pComponentName(NULL),
+ m_pDevice(NULL),
+ m_nInBuffAllocated(0),
+ m_nOutBuffAllocated(0)
+{
+
+ QC_OMX_MSG_HIGH("constructor (opening driver)");
+ memset(&m_sCallbacks, 0, sizeof(m_sCallbacks));
+
+ m_nFd = ven_device_open(&m_pDevice);
+
+ memset(&m_pPrivateInPortData, 0, sizeof(m_pPrivateInPortData));
+ memset(&m_pPrivateOutPortData, 0, sizeof(m_pPrivateOutPortData));
+ memset(&m_sErrorCorrection, 0, sizeof(m_sErrorCorrection));
+ sem_init(&m_cmd_lock,0,0);
+}
+
+Venc::~Venc()
+{
+ g_pVencInstance = NULL;
+ QC_OMX_MSG_HIGH("deconstructor (closing driver)");
+ sem_destroy(&m_cmd_lock);
+ ven_device_close(m_pDevice);
+}
+
+int roundingup( double val )
+{
+ int ret = (int) val;
+ val -= ret;
+ if(val >= 0.5)
+ return (int) ++ret;
+ else
+ return ret;
+}
+
+OMX_ERRORTYPE Venc::component_init(OMX_IN OMX_STRING pComponentName)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BOOL bCThread = OMX_FALSE;
+ OMX_BOOL bRThread = OMX_FALSE;
+ OMX_BOOL bMutex = OMX_FALSE;
+ OMX_VIDEO_CODINGTYPE eCodec;
+
+ int nNameLen = (int) strlen(pComponentName);
+
+ QC_OMX_MSG_LOW("initializing component");
+ if (pComponentName && nNameLen < OMX_MAX_STRINGNAME_SIZE)
+ {
+ if (strcmp(pComponentName, "OMX.qcom.video.encoder.mpeg4") == 0)
+ {
+ m_pComponentName = (OMX_STRING) malloc(OMX_MAX_STRINGNAME_SIZE);
+ memcpy(m_cRole, pRoleMPEG4, strlen(pRoleMPEG4) + 1);
+ memcpy(m_pComponentName, pComponentName, nNameLen);
+ eCodec = OMX_VIDEO_CodingMPEG4;
+ }
+ else if (strcmp(pComponentName, "OMX.qcom.video.encoder.h263") == 0)
+ {
+ m_pComponentName = (OMX_STRING) malloc(OMX_MAX_STRINGNAME_SIZE);
+ memcpy(m_cRole, pRoleH263, strlen(pRoleH263) + 1);
+ memcpy(m_pComponentName, pComponentName, nNameLen);
+ eCodec = OMX_VIDEO_CodingH263;
+ }
+ else if (strcmp(pComponentName, "OMX.qcom.video.encoder.avc") == 0)
+ {
+ m_pComponentName = (OMX_STRING) malloc(OMX_MAX_STRINGNAME_SIZE);
+ memcpy(m_cRole, pRoleAVC, strlen(pRoleAVC) + 1);
+ memcpy(m_pComponentName, pComponentName, nNameLen);
+ eCodec = OMX_VIDEO_CodingAVC;
+ }
+ else
+ {
+ return OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ QC_OMX_MSG_HIGH("initializing component codec=%d ", (int) m_pComponentName);
+
+ /// allocate message queue
+ m_pMsgQ = new VencMsgQ;
+ if (m_pMsgQ == NULL)
+ {
+ QC_OMX_MSG_ERROR("failed to allocate message queue");
+ result = OMX_ErrorInsufficientResources;
+ goto bail;
+ }
+ m_eState = OMX_StateLoaded;
+
+ OMX_INIT_STRUCT(&m_sPortParam, OMX_PORT_PARAM_TYPE);
+ m_sPortParam.nPorts = 0x2;
+ m_sPortParam.nStartPortNumber = (OMX_U32) PORT_INDEX_IN;
+
+ OMX_INIT_STRUCT(&m_sParamBitrate, OMX_VIDEO_PARAM_BITRATETYPE);
+ m_sParamBitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamBitrate.eControlRate = OMX_Video_ControlRateVariable;
+ m_sParamBitrate.nTargetBitrate = 64000;
+
+ OMX_INIT_STRUCT(&m_sConfigBitrate, OMX_VIDEO_CONFIG_BITRATETYPE);
+ m_sConfigBitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigBitrate.nEncodeBitrate = 64000;
+
+ OMX_INIT_STRUCT(&m_sConfigFramerate, OMX_CONFIG_FRAMERATETYPE);
+ m_sConfigFramerate.nPortIndex = (OMX_U32) PORT_INDEX_IN;
+ m_sConfigFramerate.xEncodeFramerate = 15 << 16;
+
+ OMX_INIT_STRUCT(&m_sParamProfileLevel, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
+ m_sParamProfileLevel.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ switch (eCodec)
+ {
+ case OMX_VIDEO_CodingMPEG4 :
+ m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple;
+ m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_MPEG4Level0;
+ break;
+ case OMX_VIDEO_CodingAVC :
+ m_sParamProfileLevel.eProfile = (OMX_U32)OMX_VIDEO_AVCProfileBaseline;
+ m_sParamProfileLevel.eLevel = (OMX_U32)OMX_VIDEO_AVCLevel1;
+ break;
+ case OMX_VIDEO_CodingH263 :
+ m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_H263ProfileBaseline;
+ m_sParamProfileLevel.eLevel = (OMX_U32)OMX_VIDEO_H263Level10;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("Error in CodecType");
+ break;
+ }
+
+ // Initialize the video parameters for input port
+ OMX_INIT_STRUCT(&m_sInPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
+ m_sInPortDef.nPortIndex = (OMX_U32) PORT_INDEX_IN;
+ m_sInPortDef.bEnabled = OMX_TRUE;
+ m_sInPortDef.bPopulated = OMX_FALSE;
+ m_sInPortDef.eDomain = OMX_PortDomainVideo;
+ m_sInPortDef.eDir = OMX_DirInput;
+ m_sInPortDef.format.video.cMIMEType = (OMX_STRING)"YUV420";
+ m_sInPortDef.format.video.nFrameWidth = 176;
+ m_sInPortDef.format.video.nFrameHeight = 144;
+ m_sInPortDef.format.video.nStride = 0;
+ m_sInPortDef.format.video.nSliceHeight = 0;
+ m_sInPortDef.format.video.nBitrate = 0;
+ m_sInPortDef.format.video.xFramerate = 15 << 16;
+ m_sInPortDef.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ m_sInPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+ // Initialize the video parameters for output port
+ OMX_INIT_STRUCT(&m_sOutPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
+ m_sOutPortDef.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sOutPortDef.bEnabled = OMX_TRUE;
+ m_sOutPortDef.bPopulated = OMX_FALSE;
+ m_sOutPortDef.eDomain = OMX_PortDomainVideo;
+ m_sOutPortDef.eDir = OMX_DirOutput;
+ switch (eCodec)
+ {
+ case OMX_VIDEO_CodingMPEG4:
+ m_sOutPortDef.format.video.cMIMEType = (OMX_STRING)"MPEG4";
+ break;
+ case OMX_VIDEO_CodingAVC:
+ m_sOutPortDef.format.video.cMIMEType = (OMX_STRING)"H264";
+ break;
+ case OMX_VIDEO_CodingH263:
+ m_sOutPortDef.format.video.cMIMEType = (OMX_STRING)"H263";
+ break;
+ default:
+ QC_OMX_MSG_ERROR("Error in MIME Type");
+ return OMX_ErrorBadParameter;
+ }
+
+ m_sOutPortDef.format.video.nFrameWidth = 176;
+ m_sOutPortDef.format.video.nFrameHeight = 144;
+ m_sOutPortDef.format.video.nBitrate = 64000;
+ m_sOutPortDef.format.video.xFramerate = 15 << 16;
+ m_sOutPortDef.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ m_sOutPortDef.format.video.eCompressionFormat = eCodec;
+
+ // Initialize the video color format for input port
+ OMX_INIT_STRUCT(&m_sInPortFormat, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ m_sInPortFormat.nPortIndex = (OMX_U32) PORT_INDEX_IN;
+ m_sInPortFormat.nIndex = 0;
+ m_sInPortFormat.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ m_sInPortFormat.eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+ // Initialize the compression format for output port
+ OMX_INIT_STRUCT(&m_sOutPortFormat, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ m_sOutPortFormat.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sOutPortFormat.nIndex = 0;
+ m_sOutPortFormat.eColorFormat = OMX_COLOR_FormatUnused;
+ m_sOutPortFormat.eCompressionFormat = eCodec;
+
+ OMX_INIT_STRUCT(&m_sPriorityMgmt, OMX_PRIORITYMGMTTYPE); ///@todo determine if we need this
+
+ OMX_INIT_STRUCT(&m_sInBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE);
+ m_sInBufSupplier.nPortIndex = (OMX_U32) PORT_INDEX_IN;
+
+ OMX_INIT_STRUCT(&m_sOutBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE);
+ m_sOutBufSupplier.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+
+ // Initialize error reslience
+ OMX_INIT_STRUCT(&m_sErrorCorrection, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE);
+ m_sErrorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sErrorCorrection.bEnableHEC = OMX_FALSE;
+ m_sErrorCorrection.bEnableResync = OMX_FALSE;
+ m_sErrorCorrection.nResynchMarkerSpacing = OMX_FALSE;
+ m_sErrorCorrection.bEnableDataPartitioning = OMX_FALSE;
+ m_sErrorCorrection.bEnableRVLC = OMX_FALSE;
+
+ // rotation
+ OMX_INIT_STRUCT(&m_sConfigFrameRotation, OMX_CONFIG_ROTATIONTYPE);
+ m_sConfigFrameRotation.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigFrameRotation.nRotation = 0;
+
+ // mp4 specific init
+ OMX_INIT_STRUCT(&m_sParamMPEG4, OMX_VIDEO_PARAM_MPEG4TYPE);
+ m_sParamMPEG4.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamMPEG4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level0;
+ m_sParamMPEG4.nSliceHeaderSpacing = 0;
+ m_sParamMPEG4.bSVH = OMX_FALSE;
+ m_sParamMPEG4.bGov = OMX_FALSE;
+ m_sParamMPEG4.nPFrames = 29; // 2 second intra period for default 15 fps
+ m_sParamMPEG4.bACPred = OMX_TRUE;
+ m_sParamMPEG4.nTimeIncRes = 30; // delta = 2 @ 15 fps
+ m_sParamMPEG4.nAllowedPictureTypes = 2; // pframe and iframe
+ m_sParamMPEG4.nHeaderExtension = 1; // number of video packet headers per vop
+ m_sParamMPEG4.bReversibleVLC = OMX_FALSE;
+
+ // h264 (avc) specific init
+ OMX_INIT_STRUCT(&m_sParamAVC, OMX_VIDEO_PARAM_AVCTYPE);
+ m_sParamAVC.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamAVC.eProfile = OMX_VIDEO_AVCProfileBaseline;
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel1;
+ m_sParamAVC.nSliceHeaderSpacing = 0;
+ m_sParamAVC.nPFrames = 29;
+ m_sParamAVC.nBFrames = 0;
+ m_sParamAVC.bUseHadamard = OMX_TRUE;
+ m_sParamAVC.nRefFrames = 1;
+ m_sParamAVC.nRefIdx10ActiveMinus1 = 0;
+ m_sParamAVC.nRefIdx11ActiveMinus1 = 0;
+ m_sParamAVC.bEnableUEP = OMX_FALSE;
+ m_sParamAVC.bEnableFMO = OMX_FALSE;
+ m_sParamAVC.bEnableASO = OMX_FALSE;
+ m_sParamAVC.bEnableRS = OMX_FALSE;
+ m_sParamAVC.nAllowedPictureTypes = 2;
+ m_sParamAVC.bFrameMBsOnly = OMX_TRUE;
+ m_sParamAVC.bMBAFF = OMX_FALSE;
+ m_sParamAVC.bEntropyCodingCABAC = OMX_FALSE;
+ m_sParamAVC.bWeightedPPrediction = OMX_FALSE;
+ m_sParamAVC.nWeightedBipredicitonMode = OMX_FALSE;
+ m_sParamAVC.bconstIpred = OMX_FALSE;
+ m_sParamAVC.bDirect8x8Inference = OMX_FALSE;
+ m_sParamAVC.bDirectSpatialTemporal = OMX_FALSE;
+ m_sParamAVC.nCabacInitIdc = 0;
+ m_sParamAVC.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; // enabled by default
+
+ // h263 specific init
+ OMX_INIT_STRUCT(&m_sParamH263, OMX_VIDEO_PARAM_H263TYPE);
+ m_sParamH263.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamH263.nPFrames = 29;
+ m_sParamH263.nBFrames = 0;
+ m_sParamH263.eProfile = OMX_VIDEO_H263ProfileBaseline;
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level10;
+ m_sParamH263.bPLUSPTYPEAllowed = OMX_FALSE;
+ m_sParamH263.nAllowedPictureTypes = 2;
+ m_sParamH263.bForceRoundingTypeToZero = OMX_TRUE; ///@todo determine what this should be
+ m_sParamH263.nPictureHeaderRepetition = 0; ///@todo determine what this should be
+ m_sParamH263.nGOBHeaderInterval = 0; ///@todo determine what this should be
+
+ OMX_INIT_STRUCT(&m_sParamQPs, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
+ m_sParamQPs.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ if (eCodec == OMX_VIDEO_CodingAVC)
+ {
+ m_sParamQPs.nQpI = 30;
+ m_sParamQPs.nQpP = 30;
+ m_sParamQPs.nQpB = 0; // unsupported
+ }
+ else
+ {
+ m_sParamQPs.nQpI = 14;
+ m_sParamQPs.nQpP = 14;
+ m_sParamQPs.nQpB = 0; // unsupported
+ }
+
+ OMX_INIT_STRUCT(&m_sConfigIntraRefreshVOP, OMX_CONFIG_INTRAREFRESHVOPTYPE);
+ m_sConfigIntraRefreshVOP.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigIntraRefreshVOP.IntraRefreshVOP = OMX_FALSE;
+
+#ifdef QCOM_OMX_VENC_EXT
+ OMX_INIT_STRUCT(&m_sConfigQpRange, QOMX_VIDEO_TEMPORALSPATIALTYPE);
+ m_sConfigQpRange.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigQpRange.nTSFactor = 100;
+
+ OMX_INIT_STRUCT(&m_sConfigIntraPeriod, QOMX_VIDEO_INTRAPERIODTYPE);
+ m_sConfigIntraPeriod.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigIntraPeriod.nPFrames = 29;
+#endif
+
+ OMX_INIT_STRUCT(&m_sConfigNAL, OMX_VIDEO_CONFIG_NALSIZE);
+ m_sConfigNAL.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigNAL.nNaluBytes = 0;
+
+ OMX_INIT_STRUCT(&m_sParamIntraRefresh, OMX_VIDEO_PARAM_INTRAREFRESHTYPE);
+ m_sParamIntraRefresh.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamIntraRefresh.eRefreshMode = OMX_VIDEO_IntraRefreshMax;
+ m_sParamIntraRefresh.nAirMBs = 0;
+ m_sParamIntraRefresh.nAirRef = 0;
+ m_sParamIntraRefresh.nCirMBs = 0;
+
+ if (driver_set_default_config() != OMX_ErrorNone)
+ {
+ goto bail;
+ }
+ if (driver_get_buffer_reqs(&m_sInPortDef, PORT_INDEX_IN) != OMX_ErrorNone)
+ {
+ goto bail;
+ }
+ if (driver_get_buffer_reqs(&m_sOutPortDef, PORT_INDEX_OUT) != OMX_ErrorNone)
+ {
+ goto bail;
+ }
+
+ /// used buffer managers
+ QC_OMX_MSG_MEDIUM("creating used input bm");
+ m_pInBufferMgr = new VencBufferManager(&result);
+ if (m_pInBufferMgr == NULL)
+ {
+ QC_OMX_MSG_ERROR("failed to create used input buffer manager");
+ result = OMX_ErrorInsufficientResources;
+ goto bail;
+ }
+ else if (result != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to create used input buffer manager");
+ goto bail;
+ }
+ QC_OMX_MSG_MEDIUM("creating used output Buffer Manager");
+ m_pOutBufferMgr = new VencBufferManager(&result);
+ if (result != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to create used output buffer manager");
+ goto bail;
+ }
+ else if (m_pOutBufferMgr == NULL)
+ {
+ QC_OMX_MSG_ERROR("failed to create used output buffer manager");
+ result = OMX_ErrorInsufficientResources;
+ goto bail;
+ }
+
+ QC_OMX_MSG_MEDIUM("creating component thread");
+ if (pthread_create(&m_ComponentThread,
+ NULL,
+ component_thread,
+ (void *)this) != 0)
+ {
+ QC_OMX_MSG_ERROR("failed to create component thread");
+ result = OMX_ErrorInsufficientResources;
+ goto bail;
+ }
+ else
+ {
+ bCThread = OMX_TRUE;
+ }
+
+ QC_OMX_MSG_MEDIUM("creating reader thread");
+ if (pthread_create(&m_ReaderThread,
+ NULL,
+ reader_thread_entry,
+ (void *)this) != 0)
+ {
+ QC_OMX_MSG_ERROR("failed to create reader thread");
+ result = OMX_ErrorInsufficientResources;
+ goto bail;
+ }
+ else
+ {
+ bRThread = OMX_TRUE;
+ }
+
+ QC_OMX_MSG_MEDIUM("we are now in the OMX_StateLoaded state");
+
+ m_eState = OMX_StateLoaded;
+
+ return result;
+
+bail:
+ if (bCThread)
+ {
+ if (m_pMsgQ->PushMsg(VencMsgQ::MSG_ID_EXIT, NULL) == OMX_ErrorNone)
+ {
+ if (pthread_join(m_ComponentThread, NULL) != 0)
+ {
+ QC_OMX_MSG_ERROR("failed to destroy thread");
+ }
+ }
+ }
+ if (bRThread)
+ {
+ if (DeviceIoControl(m_nFd,
+ VENC_IOCTL_CMD_STOP_READ_MSG) == 0)
+ {
+ if (pthread_join(m_ReaderThread, NULL) != 0)
+ {
+ QC_OMX_MSG_ERROR("failed to destroy thread");
+ }
+ }
+ }
+ if (m_pMsgQ != NULL)
+ {
+ delete m_pMsgQ;
+ }
+ if (m_pInBufferMgr)
+ {
+ delete m_pInBufferMgr;
+ }
+ if (m_pOutBufferMgr)
+ {
+ delete m_pOutBufferMgr;
+ }
+ if (m_pComponentName)
+ {
+ free(m_pComponentName);
+ }
+ return result;
+}
+
+Venc* Venc::get_instance()
+{
+ if (g_pVencInstance)
+ {
+ QC_OMX_MSG_ERROR("Singleton Class can't created more than one instance");
+ return NULL;
+ }
+ g_pVencInstance = new Venc();
+ return g_pVencInstance;
+}
+
+OMX_ERRORTYPE Venc::get_component_version(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_STRING pComponentName,
+ OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
+ OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
+ OMX_OUT OMX_UUIDTYPE* pComponentUUID)
+{
+ if (hComponent == NULL ||
+ pComponentName == NULL ||
+ pComponentVersion == NULL ||
+ pSpecVersion == NULL ||
+ pComponentUUID == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ memcpy(pComponentName, m_pComponentName, OMX_MAX_STRINGNAME_SIZE);
+ pSpecVersion->nVersion = OMX_SPEC_VERSION;
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::send_command(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_COMMANDTYPE Cmd,
+ OMX_IN OMX_U32 nParam1,
+ OMX_IN OMX_PTR pCmdData)
+{
+
+ VencMsgQ::MsgIdType msgId;
+ VencMsgQ::MsgDataType msgData;
+ if(m_eState == OMX_StateInvalid)
+ {
+ return OMX_ErrorInvalidState;
+ }
+
+ switch (Cmd)
+ {
+ case OMX_CommandStateSet:
+ QC_OMX_MSG_MEDIUM("sending command MSG_ID_STATE_CHANGE");
+ msgId = VencMsgQ::MSG_ID_STATE_CHANGE;
+ msgData.eState = (OMX_STATETYPE) nParam1;
+ break;
+
+ case OMX_CommandFlush:
+ QC_OMX_MSG_MEDIUM("sending command MSG_ID_FLUSH");
+ msgId = VencMsgQ::MSG_ID_FLUSH;
+ msgData.nPortIndex = nParam1;
+ break;
+
+ case OMX_CommandPortDisable:
+ if((nParam1 != (OMX_U32)PORT_INDEX_IN) && (nParam1 != (OMX_U32)PORT_INDEX_OUT) &&
+ (nParam1 != (OMX_U32)PORT_INDEX_BOTH))
+ {
+ QC_OMX_MSG_ERROR("bad port index to call OMX_CommandPortDisable");
+ return OMX_ErrorBadPortIndex;
+ }
+ QC_OMX_MSG_MEDIUM("sending command MSG_ID_PORT_DISABLE");
+ msgId = VencMsgQ::MSG_ID_PORT_DISABLE;
+ msgData.nPortIndex = nParam1;
+ break;
+
+ case OMX_CommandPortEnable:
+ if((nParam1 != (OMX_U32)PORT_INDEX_IN) && (nParam1 != (OMX_U32)PORT_INDEX_OUT) &&
+ (nParam1 != (OMX_U32)PORT_INDEX_BOTH))
+ {
+ QC_OMX_MSG_ERROR("bad port index to call OMX_CommandPortEnable");
+ return OMX_ErrorBadPortIndex;
+ }
+ QC_OMX_MSG_MEDIUM("sending command MSG_ID_PORT_ENABLE");
+ msgId = VencMsgQ::MSG_ID_PORT_ENABLE;
+ msgData.nPortIndex = nParam1;
+ break;
+
+ case OMX_CommandMarkBuffer:
+ QC_OMX_MSG_MEDIUM("sending command MSG_ID_MARK_BUFFER");
+ msgId = VencMsgQ::MSG_ID_MARK_BUFFER;
+ msgData.sMarkBuffer.nPortIndex = nParam1;
+ memcpy(&msgData.sMarkBuffer.sMarkData,
+ pCmdData,
+ sizeof(OMX_MARKTYPE));
+ break;
+ default:
+ QC_OMX_MSG_ERROR("invalid command %d", (int) Cmd);
+ return OMX_ErrorBadParameter;
+ }
+
+ m_pMsgQ->PushMsg(msgId, &msgData);
+ sem_wait(&m_cmd_lock);
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::get_parameter(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nParamIndex,
+ OMX_INOUT OMX_PTR pCompParam)
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Supported Param Index Type
+ // ============================================================================
+ // OMX_IndexParamVideoPortFormat OMX_VIDEO_PARAM_PORTFORMATTYPE
+ // OMX_IndexParamPortDefinition OMX_PARAM_PORTDEFINITIONTYPE
+ // OMX_IndexParamVideoInit OMX_PORT_PARAM_TYPE
+ // OMX_IndexParamVideoBitrate OMX_VIDEO_PARAM_BITRATETYPE
+ // OMX_IndexParamVideoMpeg4 OMX_VIDEO_PARAM_MPEG4TYPE
+ // OMX_IndexParamVideoProfileLevelQuerySupported OMX_VIDEO_PARAM_PROFILELEVEL
+ // OMX_IndexParamVideoProfileLevelCurrent OMX_VIDEO_PARAM_PROFILELEVEL
+ //OMX_IndexParamVideoErrorCorrection OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE
+ ///////////////////////////////////////////////////////////////////////////////
+ if (pCompParam == NULL)
+ {
+ QC_OMX_MSG_ERROR("param is null");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_eState != OMX_StateLoaded)
+ {
+ QC_OMX_MSG_ERROR("we must be in the loaded state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ switch (nParamIndex)
+ {
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_PORTFORMATTYPE*>(pCompParam);
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(pParam, &m_sInPortFormat, sizeof(m_sInPortFormat));
+ }
+ else if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(pParam, &m_sOutPortFormat, sizeof(m_sOutPortFormat));
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("GetParameter called on Bad Port Index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ break;
+
+ }
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE* pParam = reinterpret_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pCompParam);
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(pParam, &m_sInPortDef, sizeof(m_sInPortDef));
+ }
+ else if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(pParam, &m_sOutPortDef, sizeof(m_sOutPortDef));
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("GetParameter called on Bad Port Index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexParamVideoInit:
+ {
+ OMX_PORT_PARAM_TYPE* pParam = reinterpret_cast<OMX_PORT_PARAM_TYPE*>(pCompParam);
+ memcpy(pParam, &m_sPortParam, sizeof(m_sPortParam));
+ break;
+ }
+ case OMX_IndexParamVideoBitrate:
+ {
+ OMX_VIDEO_PARAM_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_BITRATETYPE*>(pCompParam);
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate));
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bitrate is an output port param");
+ return OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ OMX_VIDEO_PARAM_MPEG4TYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_MPEG4TYPE*>(pCompParam);
+ memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4));
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelCurrent:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_PROFILELEVELTYPE*>(pCompParam);
+ memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel));
+
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ OMX_VIDEO_PARAM_H263TYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_H263TYPE*>(pCompParam);
+ memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263));
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_VIDEO_PARAM_AVCTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_AVCTYPE*>(pCompParam);
+ memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC));
+ break;
+ }
+#ifdef QCOM_OMX_VENC_EXT
+ case QOMX_IndexParamVideoSyntaxHdr: // QCOM extensions added
+ {
+ QOMX_VIDEO_SYNTAXHDRTYPE * pParam =
+ reinterpret_cast<QOMX_VIDEO_SYNTAXHDRTYPE*>(pCompParam);
+
+ if (pParam != NULL &&
+ pParam->data != NULL &&
+ pParam->nBytes != 0)
+ {
+ int nOutSize;
+ struct ven_seq_header sequence;
+ struct venc_pmem sbuf;
+ sequence.pHdrBuf = (unsigned char*) pParam->data;
+ sequence.nBufSize = (unsigned long) pParam->nBytes;
+ sequence.nHdrLen = 0;
+
+ if (sequence.nBufSize > 0 ) {
+ pmem_alloc(&sbuf, pParam->nBytes, VENC_PMEM_EBI1);
+ if (!ven_get_sequence_hdr(m_pDevice, &sbuf, &nOutSize))
+ {
+ pParam->nBytes = (OMX_U32) sequence.nBufSize;
+ memcpy(pParam->data, sbuf.virt, nOutSize);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to get syntax header");
+ result = translate_driver_error(GetLastError());
+ }
+ pmem_free(&sbuf);
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("Invalid param(s)");
+ result = OMX_ErrorBadParameter;
+ }
+ break;
+ }
+#endif
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_PROFILELEVELTYPE*>(pCompParam);
+
+
+ if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ static const OMX_U32 MPEG4Profile[][2] =
+ { { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level0 },
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level0b },
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level1 },
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level2 },
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level3 }};
+
+ static const OMX_U32 nSupport = sizeof(MPEG4Profile) / (sizeof(OMX_U32) * 2);
+ if (pParam->nProfileIndex < nSupport)
+ {
+ pParam->eProfile = (OMX_VIDEO_MPEG4PROFILETYPE) MPEG4Profile[pParam->nProfileIndex][0];
+ pParam->eLevel = (OMX_VIDEO_MPEG4LEVELTYPE) MPEG4Profile[pParam->nProfileIndex][1];
+ }
+ else
+ {
+ result = OMX_ErrorNoMore;
+ }
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
+ {
+ static const OMX_U32 H264Profile[][2] =
+ { { (OMX_U32) OMX_VIDEO_AVCProfileBaseline, (OMX_U32) OMX_VIDEO_AVCLevel1 },
+ { (OMX_U32) OMX_VIDEO_AVCProfileBaseline, (OMX_U32) OMX_VIDEO_AVCLevel1b },
+ { (OMX_U32) OMX_VIDEO_AVCProfileBaseline, (OMX_U32) OMX_VIDEO_AVCLevel11 },
+ { (OMX_U32) OMX_VIDEO_AVCProfileBaseline, (OMX_U32) OMX_VIDEO_AVCLevel12 },
+ { (OMX_U32) OMX_VIDEO_AVCProfileBaseline, (OMX_U32) OMX_VIDEO_AVCLevel13 }};
+
+ static const OMX_U32 nSupport = sizeof(H264Profile) / (sizeof(OMX_U32) * 2);
+ if (pParam->nProfileIndex < nSupport)
+ {
+ pParam->eProfile = (OMX_VIDEO_AVCPROFILETYPE) H264Profile[pParam->nProfileIndex][0];
+ pParam->eLevel = (OMX_VIDEO_AVCLEVELTYPE) H264Profile[pParam->nProfileIndex][1];
+ QC_OMX_MSG_MEDIUM("get_parameter: h264: level supported(%d) \n", pParam->eLevel);
+ }
+ else
+ {
+ result = OMX_ErrorNoMore;
+ }
+
+ }
+ else
+ {
+ static const OMX_U32 H263Profile[][2] =
+ { { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level10 },
+ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level20 },
+ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level30 },
+ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level45 },
+ { (OMX_U32) OMX_VIDEO_H263ProfileISWV2, (OMX_U32) OMX_VIDEO_H263Level10 },
+ { (OMX_U32) OMX_VIDEO_H263ProfileISWV2, (OMX_U32) OMX_VIDEO_H263Level45 }};
+
+ static const OMX_U32 nSupport = sizeof(H263Profile) / (sizeof(OMX_U32) * 2);
+ if (pParam->nProfileIndex < nSupport)
+ {
+ pParam->eProfile = (OMX_VIDEO_H263PROFILETYPE) H263Profile[pParam->nProfileIndex][0];
+ pParam->eLevel = (OMX_VIDEO_H263LEVELTYPE) H263Profile[pParam->nProfileIndex][1];
+ }
+ else
+ {
+ result = OMX_ErrorNoMore;
+ }
+ }
+ break;
+ }
+ case OMX_IndexParamVideoErrorCorrection:
+ {
+ OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*>(pCompParam);
+ memcpy(pParam, &m_sErrorCorrection, sizeof(m_sErrorCorrection));
+ break;
+ }
+ case OMX_IndexParamVideoQuantization:
+ {
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_QUANTIZATIONTYPE*>(pCompParam);
+ memcpy(pParam, &m_sParamQPs, sizeof(m_sParamQPs));
+ break;
+ }
+ case OMX_IndexParamVideoIntraRefresh:
+ {
+ OMX_VIDEO_PARAM_INTRAREFRESHTYPE* pParam = reinterpret_cast<OMX_VIDEO_PARAM_INTRAREFRESHTYPE*>(pCompParam);
+ memcpy(pParam, &m_sParamIntraRefresh, sizeof(m_sParamIntraRefresh));
+ break;
+ }
+ case OMX_COMPONENT_CAPABILITY_TYPE_INDEX:
+ {
+ OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(pCompParam);
+ pParam->iIsOMXComponentMultiThreaded = OMX_TRUE;
+ pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE;
+ pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
+ pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
+ pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE;
+ pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE;
+ pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE;
+ pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE;
+
+ // m_bIsQcomPvt = OMX_TRUE;
+
+ QC_OMX_MSG_MEDIUM("Supporting capability index in encoder node");
+ break;
+ }
+ default:
+ QC_OMX_MSG_ERROR("unsupported index 0x%x", (int) nParamIndex);
+ result = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::driver_get_buffer_reqs(OMX_PARAM_PORTDEFINITIONTYPE* pPortDef, PortIndexType eIndex)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pPortDef != NULL)
+ {
+ struct ven_allocator_property property;
+ int nOutSize;
+ int rc = 0;
+
+ if (eIndex == PORT_INDEX_IN)
+ {
+ rc = ven_get_input_req(m_pDevice,&property);
+ }
+ else
+ {
+ rc = ven_get_output_req(m_pDevice,&property);
+ }
+
+ if (!rc)
+ {
+ pPortDef->nBufferCountMin = property.min_count;
+ pPortDef->nBufferCountActual = property.actual_count;
+ pPortDef->nBufferSize = property.data_size;
+ pPortDef->nBufferAlignment = property.alignment;
+ pPortDef->bBuffersContiguous = OMX_FALSE;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to get buffer req");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+}
+
+OMX_ERRORTYPE Venc::translate_profile(unsigned int* pDriverProfile,
+ OMX_U32 eProfile,
+ OMX_VIDEO_CODINGTYPE eCodec)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ switch ((OMX_VIDEO_MPEG4PROFILETYPE) eProfile)
+ {
+ case OMX_VIDEO_MPEG4ProfileSimple:
+ *pDriverProfile = VEN_PROFILE_MPEG4_SP;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported profile");
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+ }
+ else if (eCodec == OMX_VIDEO_CodingH263)
+ {
+ switch ((OMX_VIDEO_H263PROFILETYPE) eProfile)
+ {
+ case OMX_VIDEO_H263ProfileBaseline:
+ *pDriverProfile = VEN_PROFILE_H263_BASELINE;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported profile");
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+ }
+ else if (eCodec == OMX_VIDEO_CodingAVC)
+ {
+ switch ((OMX_VIDEO_AVCPROFILETYPE) eProfile)
+ {
+ case OMX_VIDEO_AVCProfileBaseline:
+ *pDriverProfile = VEN_PROFILE_H264_BASELINE;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported profile");
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unsupported codec");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+}
+
+OMX_ERRORTYPE Venc::translate_level(unsigned int* pDriverLevel,
+ OMX_U32 eLevel,
+ OMX_VIDEO_CODINGTYPE eCodec)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+
+ switch ((OMX_VIDEO_MPEG4LEVELTYPE) eLevel)
+ {
+ case OMX_VIDEO_MPEG4Level0:
+ *pDriverLevel = VEN_LEVEL_MPEG4_0;
+ break;
+ case OMX_VIDEO_MPEG4Level0b:
+ *pDriverLevel = VEN_LEVEL_MPEG4_0B;
+ break;
+ case OMX_VIDEO_MPEG4Level1:
+ *pDriverLevel = VEN_LEVEL_MPEG4_1;
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ *pDriverLevel = VEN_LEVEL_MPEG4_2;
+ break;
+ case OMX_VIDEO_MPEG4Level3:
+ *pDriverLevel = VEN_LEVEL_MPEG4_3;
+ break;
+ case OMX_VIDEO_MPEG4Level4:
+ *pDriverLevel = VEN_LEVEL_MPEG4_4;
+ break;
+ case OMX_VIDEO_MPEG4Level4a:
+ *pDriverLevel = VEN_LEVEL_MPEG4_4A;
+ break;
+ case OMX_VIDEO_MPEG4Level5:
+ *pDriverLevel = VEN_LEVEL_MPEG4_6;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported level");
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+ }
+ else if (eCodec == OMX_VIDEO_CodingH263)
+ {
+
+ switch ((OMX_VIDEO_H263LEVELTYPE) eLevel)
+ {
+ case OMX_VIDEO_H263Level10:
+ *pDriverLevel = VEN_LEVEL_H263_10;
+ break;
+ case OMX_VIDEO_H263Level20:
+ *pDriverLevel = VEN_LEVEL_H263_20;
+ break;
+ case OMX_VIDEO_H263Level30:
+ *pDriverLevel = VEN_LEVEL_H263_30;
+ break;
+ case OMX_VIDEO_H263Level40:
+ *pDriverLevel = VEN_LEVEL_H263_40;
+ break;
+ case OMX_VIDEO_H263Level45:
+ *pDriverLevel = VEN_LEVEL_H263_45;
+ break;
+ case OMX_VIDEO_H263Level50:
+ *pDriverLevel = VEN_LEVEL_H263_50;
+ break;
+ case OMX_VIDEO_H263Level60:
+ *pDriverLevel = VEN_LEVEL_H263_60;
+ break;
+ case OMX_VIDEO_H263Level70:
+ *pDriverLevel = VEN_LEVEL_H263_70;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported level");
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+ }
+ else if (eCodec == OMX_VIDEO_CodingAVC)
+ {
+
+ switch ((OMX_VIDEO_AVCLEVELTYPE) eLevel)
+ {
+ case OMX_VIDEO_AVCLevel1:
+ *pDriverLevel = VEN_LEVEL_H264_1;
+ break;
+ case OMX_VIDEO_AVCLevel1b:
+ *pDriverLevel = VEN_LEVEL_H264_1B;
+ break;
+ case OMX_VIDEO_AVCLevel11:
+ *pDriverLevel = VEN_LEVEL_H264_1P1;
+ break;
+ case OMX_VIDEO_AVCLevel12:
+ *pDriverLevel = VEN_LEVEL_H264_1P2;
+ break;
+ case OMX_VIDEO_AVCLevel13:
+ *pDriverLevel = VEN_LEVEL_H264_1P3;
+ break;
+ case OMX_VIDEO_AVCLevel2:
+ *pDriverLevel = VEN_LEVEL_H264_2;
+ break;
+ case OMX_VIDEO_AVCLevel21:
+ *pDriverLevel = VEN_LEVEL_H264_2P1;
+ break;
+ case OMX_VIDEO_AVCLevel22:
+ *pDriverLevel = VEN_LEVEL_H264_2P2;
+ break;
+ case OMX_VIDEO_AVCLevel3:
+ *pDriverLevel = VEN_LEVEL_H264_3;
+ break;
+ case OMX_VIDEO_AVCLevel31:
+ *pDriverLevel = VEN_LEVEL_H264_3P1;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported level");
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unsupported codec");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+}
+
+
+
+OMX_ERRORTYPE Venc::translate_driver_error(int driverResult)
+{
+ static const int nAppErrorCodeBit = 0x20000000;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // see if this is encoder specific error
+ if (driverResult & nAppErrorCodeBit)
+ {
+ switch (driverResult & ~nAppErrorCodeBit)
+ {
+ case VENC_S_SUCCESS:
+ QC_OMX_MSG_ERROR("unexpected success");
+ result = OMX_ErrorNone;
+ break;
+ case VENC_S_EFAIL:
+ result = OMX_ErrorUndefined;
+ break;
+ case VENC_S_EBADPARAM:
+ result = OMX_ErrorBadParameter;
+ break;
+ case VENC_S_EINVALSTATE:
+ result = OMX_ErrorInvalidState;
+ break;
+ case VENC_S_ENOSWRES:
+ result = OMX_ErrorInsufficientResources;
+ break;
+ case VENC_S_ENOHWRES:
+ result = OMX_ErrorInsufficientResources;
+ break;
+ case VENC_S_ETIMEOUT:
+ result = OMX_ErrorTimeout;
+ break;
+ case VENC_S_ENOTSUPP:
+ result = OMX_ErrorUnsupportedSetting;
+ break;
+ case VENC_S_ENOTIMPL:
+ result = OMX_ErrorNotImplemented;
+ break;
+ case VENC_S_EFLUSHED:
+ case VENC_S_EINSUFBUF:
+ case VENC_S_ENOTPMEM:
+ case VENC_S_ENOPREREQ:
+ case VENC_S_ENOREATMPT:
+ case VENC_S_ECMDQFULL:
+ case VENC_S_EINVALCMD:
+ case VENC_S_EBUFFREQ:
+ result = OMX_ErrorUndefined;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unexpected error code");
+ result = OMX_ErrorUndefined;
+ break;
+ }
+ }
+ else if (driverResult == 0)
+ {
+ QC_OMX_MSG_ERROR("not expecting success");
+ result = OMX_ErrorUndefined;
+ }
+ else
+ {
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::is_multi_slice_mode_supported()
+{
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ if(!strncmp(m_pComponentName,"OMX.qcom.video.encoder.avc",strlen("OMX.qcom.video.encoder.avc"))
+ && m_sInPortDef.format.video.nFrameHeight * m_sInPortDef.format.video.nFrameWidth <= (VEN_VGA_DX * VEN_VGA_DY / 2) ) {
+ ret = OMX_ErrorNone;
+ } else {
+ ret = OMX_ErrorUnsupportedSetting;
+ }
+ return ret;
+}
+
+OMX_ERRORTYPE Venc::driver_set_default_config()
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int nOutSize;
+ int rc = 0;
+ struct ven_base_cfg baseCfg;
+ ////////////////////////////////////////
+ // set base config
+ ////////////////////////////////////////
+ QC_OMX_MSG_HIGH("driver_set_default_config: pcofig: %p \n", &(m_pDevice->config.base_config));
+
+
+ baseCfg.input_width = m_sInPortDef.format.video.nFrameWidth;
+ baseCfg.input_height = m_sInPortDef.format.video.nFrameHeight;
+ baseCfg.dvs_width = m_sOutPortDef.format.video.nFrameWidth;
+ baseCfg.dvs_height = m_sOutPortDef.format.video.nFrameHeight;
+ if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ baseCfg.codec_type = VEN_CODEC_MPEG4;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263)
+ {
+ baseCfg.codec_type = VEN_CODEC_H263;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
+ {
+ baseCfg.codec_type = VEN_CODEC_H264;
+ }
+ baseCfg.fps_num = m_sConfigFramerate.xEncodeFramerate >> 16;
+ baseCfg.fps_den = 1; /// @integrate need to figure out how to set this
+ baseCfg.target_bitrate = m_sParamBitrate.nTargetBitrate;
+ baseCfg.input_format= VEN_INPUTFMT_NV21; /// @integrate need to make this configurable
+
+ if (ven_set_base_cfg(m_pDevice, &baseCfg))
+ {
+ QC_OMX_MSG_ERROR("failed to set base config");
+ result = translate_driver_error(GetLastError());
+ }
+
+ ////////////////////////////////////////
+ // set profile
+ ////////////////////////////////////////
+ /* if (result == OMX_ErrorNone)
+ {
+ struct ven_profile profile;
+ translate_profile(&profile.profile,
+ m_sParamProfileLevel.eProfile,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_codec_profile(m_pDevice,&profile);
+ if (rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set profile");
+ result = translate_driver_error(GetLastError());
+ }
+ } */
+
+ ////////////////////////////////////////
+ // set level
+ ////////////////////////////////////////
+ /*
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile_level level;
+ translate_level(&level.level,
+ m_sParamProfileLevel.eLevel,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_profile_level(m_pDevice, &level);
+ if (rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set level");
+ result = translate_driver_error(GetLastError());
+ }
+ } */
+
+ ////////////////////////////////////////
+ // set rate control
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_rate_ctrl_cfg rateControl;
+ if (m_sParamBitrate.eControlRate == OMX_Video_ControlRateDisable)
+ {
+ rateControl.rc_mode = VEN_RC_OFF;
+ }
+ else if (m_sParamBitrate.eControlRate == OMX_Video_ControlRateVariable)
+ {
+ rateControl.rc_mode = VEN_RC_VBR_CFR;
+ }
+ else if (m_sParamBitrate.eControlRate == OMX_Video_ControlRateVariableSkipFrames)
+ {
+ rateControl.rc_mode = VEN_RC_VBR_VFR;
+ }
+ else if (m_sParamBitrate.eControlRate == OMX_Video_ControlRateConstantSkipFrames)
+ {
+ rateControl.rc_mode = VEN_RC_CBR_VFR;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid rc");
+ }
+
+ if (ven_set_rate_control(m_pDevice, &rateControl) != 0 )
+ {
+ QC_OMX_MSG_ERROR("failed to set rate control");
+ }
+ }
+
+ ////////////////////////////////////////
+ // set slice config
+ ////////////////////////////////////////
+
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_multi_slice_cfg slice;
+ slice.mslice_mode = VENC_SLICE_MODE_DEFAULT; // default to no slicing
+ slice.mslice_size = 0;
+ rc = ven_set_multislice_cfg(m_pDevice, &slice);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set slice config");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set rotation
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_rotation rotation;
+ rotation.rotation = m_sConfigFrameRotation.nRotation;
+
+ rc = ven_set_rotation(m_pDevice, &rotation);
+ if (rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set rotation");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set vop time increment
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_vop_timing_cfg timeInc;
+ timeInc.vop_time_resolution = m_sParamMPEG4.nTimeIncRes;
+
+ rc = ven_set_vop_timing(m_pDevice, &timeInc);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set time resolution");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set intra period
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_intra_period intraPeriod;
+
+#if 0
+ if (m_sParamMPEG4.bGov)
+ {
+#endif
+ intraPeriod.num_pframes = m_sParamMPEG4.nPFrames;
+#if 0
+ }
+ else
+ {
+ intraPeriod.num_pframes = 0;
+ }
+#endif
+
+ if (ven_set_intra_period(m_pDevice,&intraPeriod) !=0)
+ {
+ QC_OMX_MSG_ERROR("failed to set intra period");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set session qp's
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ if (m_sParamBitrate.eControlRate == OMX_Video_ControlRateDisable)
+ {
+ struct ven_session_qp sessionQP;
+ sessionQP.iframe_qp = m_sParamQPs.nQpI;
+ sessionQP.pframe_qp = m_sParamQPs.nQpP;
+
+ rc = ven_set_session_qp(m_pDevice, &sessionQP);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set session QPs");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ }
+
+#ifdef QCOM_OMX_VENC_EXT
+ ////////////////////////////////////////
+ // set min/max qp's
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_qp_range qpRange;
+ qpRange.min_qp = 2;
+ if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4 ||
+ m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) {
+ qpRange.max_qp = 8 + (int) roundingup(m_sConfigQpRange.nTSFactor * 0.23);
+ }else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC){
+ qpRange.max_qp = 33 + roundingup(m_sConfigQpRange.nTSFactor * 0.18);
+ }
+
+ rc = ven_set_qp_range(m_pDevice, &qpRange);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set qp range");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+#endif
+
+ ////////////////////////////////////////
+ // set ac prediction
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_switch acPred;
+
+ if (m_sParamMPEG4.bACPred == OMX_TRUE &&
+ m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ acPred.status = 1;
+ }
+ else
+ {
+ acPred.status = 0;
+ }
+ rc = ven_set_ac_prediction(m_pDevice, &acPred);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set ac prediction");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set short header
+ ////////////////////////////////////////
+
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_switch shortHeader;
+ shortHeader.status = m_sParamMPEG4.bSVH == OMX_TRUE ? 1 : 0;
+ rc = ven_set_short_hdr(m_pDevice, &shortHeader);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set short header");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set header extension coding
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_switch hec; // for default config
+ hec.status = (unsigned char) m_sErrorCorrection.bEnableHEC;//@integrate this is a hack // == OMX_TRUE ? 1 : 0;
+
+ rc = ven_set_hec(m_pDevice, &hec);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set hec");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set intra refresh
+ ////////////////////////////////////////
+#if 0
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_intra_refresh ir;
+ if (m_sParamIntraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic)
+ {
+ ir.ir_mode = VEN_IR_RANDOM;
+ ir.mb_count = 0;
+ }
+ else
+ {
+ ir.ir_mode = VEN_IR_OFF;
+ ir.mb_count = 0;
+ }
+
+ rc = ven_set_intra_refresh_rate(m_pDevice, &ir);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set intra refresh");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+#endif
+
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_port_fmt(OMX_IN OMX_VIDEO_PARAM_PORTFORMATTYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if (pParam->xFramerate != 0)
+ {
+ QC_OMX_MSG_ERROR("Frame rate is for input port (refer to OMX IL spec)");
+ // result = OMX_ErrorUnsupportedSetting;
+ }
+ }
+
+ int nOutSize;
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_base_cfg baseCfg;
+ baseCfg.input_width = m_sInPortDef.format.video.nFrameWidth;
+ baseCfg.input_height = m_sInPortDef.format.video.nFrameHeight;
+ baseCfg.dvs_width = m_sOutPortDef.format.video.nFrameWidth;
+ baseCfg.dvs_height = m_sOutPortDef.format.video.nFrameHeight;
+ if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ baseCfg.codec_type = VEN_CODEC_MPEG4;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263)
+ {
+ baseCfg.codec_type = VEN_CODEC_H263;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
+ {
+ baseCfg.codec_type = VEN_CODEC_H264;
+ }
+ baseCfg.fps_num = m_sConfigFramerate.xEncodeFramerate >> 16;
+ baseCfg.fps_den = 1; /// @integrate need to figure out how to set this
+ baseCfg.target_bitrate = m_sParamBitrate.nTargetBitrate;
+ baseCfg.input_format= VEN_INPUTFMT_NV21; /// @integrate need to make this configurable
+
+ rc = ven_set_base_cfg(m_pDevice, &baseCfg);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set base config");
+ result = OMX_ErrorUndefined;
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(&m_sInPortFormat, pParam, sizeof(m_sInPortFormat));
+ m_sConfigFramerate.xEncodeFramerate = pParam->xFramerate;
+ m_sInPortDef.format.video.xFramerate = pParam->xFramerate;
+ }
+ else
+ {
+ memcpy(&m_sOutPortFormat, pParam, sizeof(m_sOutPortFormat));
+ }
+
+ }
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_port_def(OMX_IN OMX_PARAM_PORTDEFINITIONTYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ int code;
+ struct ven_allocator_property property;
+ int rc = 0;
+ OMX_PARAM_PORTDEFINITIONTYPE* pLocalDef;
+
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ pLocalDef = &m_sOutPortDef;
+ if (pParam->format.video.xFramerate != 0)
+ {
+ QC_OMX_MSG_ERROR("Frame rate is for input port (refer to OMX IL spec)");
+ // result = OMX_ErrorUnsupportedSetting;
+
+ }
+ }
+ else
+ {
+ pLocalDef = &m_sInPortDef;
+ if (pParam->format.video.nBitrate != 0)
+ {
+ QC_OMX_MSG_ERROR("Bitrate rate is for output port");
+ result = OMX_ErrorUnsupportedSetting;
+ }
+ }
+
+ ////////////////////////////////////////
+ // set base config
+ ////////////////////////////////////////
+ int nOutSize;
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_base_cfg baseCfg;
+ OMX_PARAM_PORTDEFINITIONTYPE* pInDef;
+ OMX_PARAM_PORTDEFINITIONTYPE* pOutDef;
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ pInDef = pParam;
+ pOutDef = &m_sOutPortDef;
+ }
+ else
+ {
+ pInDef = &m_sInPortDef;
+ pOutDef = pParam;
+ }
+ baseCfg.input_width = pInDef->format.video.nFrameWidth;
+ baseCfg.input_height = pInDef->format.video.nFrameHeight;
+ baseCfg.dvs_width = pOutDef->format.video.nFrameWidth;
+ baseCfg.dvs_height = pOutDef->format.video.nFrameHeight;
+ if (pOutDef->format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ baseCfg.codec_type = VEN_CODEC_MPEG4;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263)
+ {
+ baseCfg.codec_type = VEN_CODEC_H263;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
+ {
+ baseCfg.codec_type = VEN_CODEC_H264;
+ }
+
+ baseCfg.fps_num = pInDef->format.video.xFramerate >> 16;
+ baseCfg.fps_den = 1; /// @integrate need to figure out how to set this
+ baseCfg.target_bitrate = pOutDef->format.video.nBitrate;
+ baseCfg.input_format= VEN_INPUTFMT_NV21; /// @integrate need to make this configurable
+
+ rc = ven_set_base_cfg(m_pDevice, &baseCfg);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set base config");
+ result = translate_driver_error(GetLastError());
+ }
+
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE tmpReq;
+
+ // copy our local definition into temp copy
+ memcpy(&tmpReq, pLocalDef, sizeof(tmpReq));
+
+ // get the driver buffer requirements since may have changed when base config has changed
+ result = driver_get_buffer_reqs(&tmpReq, (PortIndexType) pParam->nPortIndex);
+
+ if (result == OMX_ErrorNone)
+ {
+ // update local copy of buffer requirements with driver requirements
+ pLocalDef->nBufferCountMin = tmpReq.nBufferCountMin;
+ pLocalDef->nBufferCountActual = tmpReq.nBufferCountActual;
+ pLocalDef->nBufferSize = tmpReq.nBufferSize;
+ pLocalDef->nBufferAlignment = tmpReq.nBufferAlignment;
+ pLocalDef->bBuffersContiguous = OMX_FALSE;
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ pLocalDef = &m_sInPortDef;
+ }
+ else
+ {
+ pLocalDef = &m_sOutPortDef;
+ }
+
+ /// @integrate this is a hack. how to handle buff req change due to frame size change
+ pParam->nBufferSize = pLocalDef->nBufferSize;
+
+ QC_OMX_MSG_LOW("Before update buffer: actual: %d, min: %d\n",
+ pLocalDef->nBufferCountActual, pLocalDef->nBufferCountMin);
+ QC_OMX_MSG_LOW("After update buffer: actual:%d, min: %d \n",
+ pParam->nBufferCountActual, pParam->nBufferCountMin);
+
+ QC_OMX_MSG_LOW("Before update buffer: size: %d, alignment: %d\n",
+ pLocalDef->nBufferSize, pLocalDef->nBufferAlignment);
+ QC_OMX_MSG_LOW("After update buffer: size:%d, alignment: %d \n",
+ pParam->nBufferSize, pParam->nBufferAlignment);
+ if (pParam->nBufferCountActual >= pLocalDef->nBufferCountMin && // must be greater or equal to min requirement
+ pParam->nBufferCountMin == pLocalDef->nBufferCountMin && // min count is read only!
+ pParam->nBufferSize >= pLocalDef->nBufferSize && // must be greater or equal to min buffer size
+ pParam->nBufferAlignment == pLocalDef->nBufferAlignment) // alignment is read only!
+ {
+
+ QC_OMX_MSG_LOW("Before update buffer: min: %d, actual: %d\n",
+ pLocalDef->nBufferCountMin, pLocalDef->nBufferCountMin);
+ QC_OMX_MSG_LOW("After update buffer: actual:%d, min: %d \n",
+ pParam->nBufferCountActual, pParam->nBufferCountMin);
+
+ property.min_count = pParam->nBufferCountMin;
+ property.actual_count = pParam->nBufferCountActual;
+ property.data_size = pParam->nBufferSize;
+ property.alignment = pParam->nBufferAlignment;
+ property.suffix_size = 0;
+
+ ////////////////////////////////////////
+ // set buffer requirements
+ ////////////////////////////////////////
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ rc = ven_set_input_req(m_pDevice, &property);
+ }
+ else
+ {
+ rc = ven_set_output_req(m_pDevice, &property);
+ }
+ if(!rc)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(&m_sInPortDef, pParam, sizeof(m_sInPortDef));
+ m_sInPortFormat.xFramerate = pParam->format.video.xFramerate;
+ }
+ else
+ {
+ memcpy(&m_sOutPortDef, pParam, sizeof(m_sOutPortDef));
+ m_sConfigBitrate.nEncodeBitrate = pParam->format.video.nBitrate;
+ m_sParamBitrate.nTargetBitrate = pParam->format.video.nBitrate;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to set buffer req");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("violation of buffer requirements");
+ }
+ }
+
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::adjust_profile_level( )
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_U32 nFrameHeight = m_sInPortDef.format.video.nFrameHeight;
+ OMX_U32 nFrameWidth = m_sInPortDef.format.video.nFrameWidth;
+
+ if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_QCIF_DX, VEN_QCIF_DY))
+ {
+ m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level0;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_CIF_DX, VEN_CIF_DY))
+ {
+ m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level2;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_VGA_DX, VEN_VGA_DY))
+ {
+ m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level4a;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_HD720P_DX, VEN_HD720P_DY))
+ {
+ m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level5;
+ }
+ m_sParamProfileLevel.eLevel = (OMX_U32)m_sParamMPEG4.eLevel;
+ }
+ else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)
+ {
+ if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_QCIF_DX, VEN_QCIF_DY))
+ {
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel1;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_CIF_DX, VEN_CIF_DY))
+ {
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel12;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_VGA_DX, VEN_VGA_DY))
+ {
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel22;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_D1_DX, VEN_D1_DY))
+ {
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel3;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_HD720P_DX, VEN_HD720P_DY))
+ {
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel31;
+ }
+ m_sParamProfileLevel.eLevel = (OMX_U32)m_sParamAVC.eLevel;
+ }
+ else {
+ if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_QCIF_DX, VEN_QCIF_DY))
+ {
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level10;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_CIF_DX, VEN_CIF_DY))
+ {
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level20;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_VGA_DX, VEN_VGA_DY))
+ {
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level30;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_D1_DX, VEN_D1_DY))
+ {
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level60;
+ }
+ else if (VEN_FRAME_SIZE_IN_RANGE(nFrameWidth, nFrameHeight, VEN_HD720P_DX, VEN_HD720P_DY))
+ {
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level70;
+ }
+ m_sParamProfileLevel.eLevel = (OMX_U32)m_sParamH263.eLevel;
+ }
+ QC_OMX_MSG_MEDIUM("adjust_profile_level: level: %d \n", m_sParamProfileLevel.eLevel);
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_video_init(OMX_IN OMX_PORT_PARAM_TYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pParam != NULL)
+ {
+ memcpy(&m_sPortParam, pParam, sizeof(m_sPortParam));
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_bitrate(OMX_IN OMX_VIDEO_PARAM_BITRATETYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // set bitrate
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_target_bitrate bitrate;
+ bitrate.target_bitrate = pParam->nTargetBitrate;
+
+ if (ven_set_target_bitrate(m_pDevice,&bitrate) != 0)
+ {
+ QC_OMX_MSG_ERROR("error setting bitrate");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set rate control
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_rate_ctrl_cfg rateControl;
+
+ if (pParam->eControlRate == OMX_Video_ControlRateDisable)
+ {
+ rateControl.rc_mode = VEN_RC_OFF;
+ }
+ else if (pParam->eControlRate == OMX_Video_ControlRateVariable)
+ {
+ rateControl.rc_mode = VEN_RC_VBR_CFR;
+ }
+ else if (pParam->eControlRate == OMX_Video_ControlRateVariableSkipFrames)
+ {
+ rateControl.rc_mode = VEN_RC_VBR_VFR;
+ }
+ else if (pParam->eControlRate == OMX_Video_ControlRateConstantSkipFrames)
+ {
+ rateControl.rc_mode = VEN_RC_CBR_VFR;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid rc selection");
+ result = OMX_ErrorUnsupportedSetting;
+ }
+
+ rc = ven_set_rate_control(m_pDevice, &rateControl);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("error setting rate control");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamBitrate, pParam, sizeof(m_sParamBitrate));
+
+ // also need to set configuration bitrate
+ m_sConfigBitrate.nEncodeBitrate = pParam->nTargetBitrate;
+ m_sParamBitrate.nTargetBitrate = pParam->nTargetBitrate;
+ m_sOutPortDef.format.video.nBitrate = pParam->nTargetBitrate;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_mpeg4(OMX_IN OMX_VIDEO_PARAM_MPEG4TYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+
+ ////////////////////////////////////////
+ // set short header
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_switch shortHeader;
+ shortHeader.status = pParam->bSVH == OMX_TRUE ? 1 : 0;
+ rc = ven_set_short_hdr(m_pDevice, &shortHeader);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set short header");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+#ifdef QCOM_OMX_VENC_EXT
+ ////////////////////////////////////////
+ // set intra period
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_intra_period intraPeriod;
+
+#if 0
+ if (pParam->bGov)
+ {
+#endif
+ intraPeriod.num_pframes = pParam->nPFrames;
+#if 0
+ }
+ else
+ {
+ intraPeriod.num_pframes = 0;
+ }
+#endif
+
+ if (ven_set_intra_period(m_pDevice,&intraPeriod) != 0 )
+ {
+ QC_OMX_MSG_ERROR("failed to set intra period");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+#endif
+
+ ////////////////////////////////////////
+ // set ac prediction
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_switch acPred;
+ acPred.status = pParam->bACPred == OMX_TRUE ? 1 : 0;
+
+ rc = ven_set_ac_prediction(m_pDevice, &acPred);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set ac prediction");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+
+ ////////////////////////////////////////
+ // set vop time increment
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_vop_timing_cfg timeInc;
+ timeInc.vop_time_resolution = pParam->nTimeIncRes;
+
+ rc = ven_set_vop_timing(m_pDevice, &timeInc);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set time resolution");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set profile
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile profile;
+ translate_profile(&profile.profile,
+ pParam->eProfile,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_codec_profile(m_pDevice, &profile);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set profile");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set level
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile_level level;
+ translate_level(&level.level,
+ pParam->eLevel,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_profile_level(m_pDevice, &level);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set level");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set header extension coding
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_switch hec; // for mp4 update
+ hec.status = (unsigned char) pParam->nHeaderExtension; /// @integrate do we need to add a param to HEC
+
+ rc = ven_set_hec(m_pDevice, &hec);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set hec");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamMPEG4, pParam, sizeof(m_sParamMPEG4));
+ m_sParamProfileLevel.eLevel = (OMX_U32) pParam->eLevel;
+ m_sParamProfileLevel.eProfile = (OMX_U32) pParam->eProfile;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_profile_level(OMX_IN OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+
+ ////////////////////////////////////////
+ // set profile
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_profile profile;
+ translate_profile(&profile.profile,
+ m_sParamProfileLevel.eProfile,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_codec_profile(m_pDevice, &profile);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set profile");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set level
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile_level level;
+ translate_level(&level.level,
+ m_sParamProfileLevel.eLevel,
+ m_sOutPortDef.format.video.eCompressionFormat);
+
+ rc = ven_set_profile_level(m_pDevice, &level);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set level");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamProfileLevel, pParam, sizeof(m_sParamProfileLevel));
+ m_sParamH263.eProfile = (OMX_VIDEO_H263PROFILETYPE) pParam->eProfile;
+ m_sParamAVC.eProfile = (OMX_VIDEO_AVCPROFILETYPE) pParam->eProfile;
+ m_sParamMPEG4.eProfile = (OMX_VIDEO_MPEG4PROFILETYPE) pParam->eProfile;
+ m_sParamH263.eLevel = (OMX_VIDEO_H263LEVELTYPE) pParam->eLevel;
+ m_sParamAVC.eLevel = (OMX_VIDEO_AVCLEVELTYPE) pParam->eLevel;
+ m_sParamMPEG4.eLevel = (OMX_VIDEO_MPEG4LEVELTYPE) pParam->eLevel;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_err_correct(OMX_IN OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+
+ ////////////////////////////////////////
+ // set slice config
+ ////////////////////////////////////////
+ int nOutSize;
+ if(pParam->bEnableResync) {
+ result = is_multi_slice_mode_supported();
+ if(OMX_ErrorNone == result) {
+ struct ven_multi_slice_cfg slice;
+ slice.mslice_mode = pParam->bEnableResync == OMX_TRUE ? VENC_SLICE_MODE_BIT : VENC_SLICE_MODE_DEFAULT;
+ slice.mslice_size = pParam->nResynchMarkerSpacing;
+ rc = ven_set_multislice_cfg(m_pDevice, &slice);
+ if(rc) {
+ QC_OMX_MSG_ERROR("failed to set slice config");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ }
+
+ ////////////////////////////////////////
+ // set header extension coding
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ // make sure we don't overwrite HEC interval with a boolean value
+ if (m_sParamMPEG4.nHeaderExtension == 0)
+ {
+ struct ven_switch hec; // for ER config
+ hec.status = (unsigned char) pParam->bEnableHEC;///@integrate this is a hack // == OMX_TRUE ? 1 : 0;
+
+ rc = ven_set_hec(m_pDevice, &hec);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set hec");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sErrorCorrection, pParam, sizeof(m_sErrorCorrection));
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_h263(OMX_IN OMX_VIDEO_PARAM_H263TYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // set intra period
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_intra_period intraPeriod;
+ intraPeriod.num_pframes = pParam->nPFrames;
+ if (ven_set_intra_period(m_pDevice,&intraPeriod) != 0 )
+
+ {
+ QC_OMX_MSG_ERROR("failed to set intra period");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set profile
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile profile;
+ translate_profile(&profile.profile,
+ m_sParamProfileLevel.eProfile,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_codec_profile(m_pDevice, &profile);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set profile");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set level
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile_level level;
+ translate_level(&level.level,
+ m_sParamProfileLevel.eLevel,
+ m_sOutPortDef.format.video.eCompressionFormat);
+
+ rc = ven_set_profile_level(m_pDevice, &level);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set level");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set slice
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone && pParam->nGOBHeaderInterval)
+ {
+ result = is_multi_slice_mode_supported();
+ if(OMX_ErrorNone == result) {
+ struct ven_multi_slice_cfg slice;
+ slice.mslice_mode = pParam->nGOBHeaderInterval == 0 ? VENC_SLICE_MODE_DEFAULT : VENC_SLICE_MODE_GOB;
+ slice.mslice_size = pParam->nGOBHeaderInterval;
+ rc = ven_set_multislice_cfg(m_pDevice, &slice);
+ if(rc) {
+ QC_OMX_MSG_ERROR("failed to set slice config");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamH263, pParam, sizeof(m_sParamH263));
+ m_sParamProfileLevel.eProfile = pParam->eProfile;
+ m_sParamProfileLevel.eLevel = pParam->eLevel;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_avc(OMX_IN OMX_VIDEO_PARAM_AVCTYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // set intra period
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_intra_period intraPeriod;
+ intraPeriod.num_pframes = pParam->nPFrames;
+ if (ven_set_intra_period(m_pDevice,&intraPeriod) != 0 )
+ {
+ QC_OMX_MSG_ERROR("failed to set intra period");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set profile
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile profile;
+ translate_profile(&profile.profile,
+ pParam->eProfile,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_codec_profile(m_pDevice, &profile);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set profile");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set level
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ struct ven_profile_level level;
+ translate_level(&level.level,
+ pParam->eLevel,
+ m_sOutPortDef.format.video.eCompressionFormat);
+ rc = ven_set_profile_level(m_pDevice, &level);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set level");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ ////////////////////////////////////////
+ // set slice
+ ////////////////////////////////////////
+ if (result == OMX_ErrorNone && pParam->nSliceHeaderSpacing)
+ {
+ result = is_multi_slice_mode_supported();
+ if(OMX_ErrorNone == result) {
+ struct ven_multi_slice_cfg slice;
+ slice.mslice_mode = pParam->nSliceHeaderSpacing == 0 ? VENC_SLICE_MODE_DEFAULT : VENC_SLICE_MODE_MB;
+ slice.mslice_size = pParam->nSliceHeaderSpacing;
+ rc = ven_set_multislice_cfg(m_pDevice, &slice);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set slice config");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamAVC, pParam, sizeof(m_sParamAVC));
+ m_sParamProfileLevel.eProfile = pParam->eProfile;
+ m_sParamProfileLevel.eLevel = pParam->eLevel;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_quantization(OMX_IN OMX_VIDEO_PARAM_QUANTIZATIONTYPE* pParam)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // set intra period
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_session_qp sessionQP;
+ sessionQP.iframe_qp = pParam->nQpI;
+ sessionQP.pframe_qp = pParam->nQpP;
+
+ rc = ven_set_session_qp(m_pDevice, &sessionQP);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set session QPs");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamQPs, pParam, sizeof(m_sParamQPs));
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_param_intra_refresh(OMX_IN OMX_VIDEO_PARAM_INTRAREFRESHTYPE* pParam)
+{
+ int rc = 0;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pParam != NULL)
+ {
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // set intra refresh
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_intra_refresh ir;
+ if (pParam->eRefreshMode == OMX_VIDEO_IntraRefreshCyclic)
+ {
+ ir.ir_mode = VEN_IR_RANDOM;
+ ir.mb_count = 5;
+ }
+ else
+ {
+ ir.ir_mode = VEN_IR_OFF;
+ ir.mb_count = 0;
+ }
+
+ rc = ven_set_intra_refresh_rate(m_pDevice, &ir);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set intra refresh");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sParamIntraRefresh, pParam, sizeof(m_sParamIntraRefresh));
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::set_parameter(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_IN OMX_PTR pCompParam)
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Supported Param Index Type
+ // ============================================================================
+ // OMX_IndexParamVideoPortFormat OMX_VIDEO_PARAM_PORTFORMATTYPE
+ // OMX_IndexParamPortDefinition OMX_PARAM_PORTDEFINITIONTYPE
+ // OMX_IndexParamVideoInit OMX_PORT_PARAM_TYPE
+ // OMX_IndexParamVideoBitrate OMX_VIDEO_PARAM_BITRATETYPE
+ // OMX_IndexParamVideoMpeg4 OMX_VIDEO_PARAM_MPEG4TYPE
+ // OMX_IndexParamVideoProfileLevelCurrent OMX_VIDEO_PARAM_PROFILELEVEL
+ ///////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pCompParam == NULL)
+ {
+ QC_OMX_MSG_ERROR("param is null");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_eState != OMX_StateLoaded)
+ {
+ QC_OMX_MSG_ERROR("set_parameter must be in the loaded state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ switch (nIndex)
+ {
+ case OMX_IndexParamVideoPortFormat:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoPortFormat");
+ result = update_param_port_fmt(reinterpret_cast<OMX_VIDEO_PARAM_PORTFORMATTYPE*>(pCompParam));
+ result = adjust_profile_level();
+ break;
+ }
+ case OMX_IndexParamPortDefinition:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamPortDefinition");
+ result = update_param_port_def(reinterpret_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pCompParam));
+ result = adjust_profile_level();
+ break;
+ }
+ case OMX_IndexParamVideoInit:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoInit");
+ result = update_param_video_init(reinterpret_cast<OMX_PORT_PARAM_TYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoBitrate:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoBitrate");
+ result = update_param_bitrate(reinterpret_cast<OMX_VIDEO_PARAM_BITRATETYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoMpeg4");
+ result = update_param_mpeg4(reinterpret_cast<OMX_VIDEO_PARAM_MPEG4TYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelCurrent:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoProfileLevelCurrent");
+ result = update_param_profile_level(reinterpret_cast<OMX_VIDEO_PARAM_PROFILELEVELTYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoErrorCorrection:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoErrorCorrection");
+ result = update_param_err_correct(reinterpret_cast<OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoH263");
+ result = update_param_h263(reinterpret_cast<OMX_VIDEO_PARAM_H263TYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoAvc");
+ result = update_param_avc(reinterpret_cast<OMX_VIDEO_PARAM_AVCTYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoQuantization:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoQuantization");
+ result = update_param_quantization(reinterpret_cast<OMX_VIDEO_PARAM_QUANTIZATIONTYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamVideoIntraRefresh:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexParamVideoIntraRefresh");
+ result = update_param_intra_refresh(reinterpret_cast<OMX_VIDEO_PARAM_INTRAREFRESHTYPE*>(pCompParam));
+ break;
+ }
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) pCompParam;
+ QC_OMX_MSG_LOW("OMX_IndexParamStandardComponentRole");
+ if(!strncmp(m_pComponentName,"OMX.qcom.video.encoder.mpeg4",strlen("OMX.qcom.video.encoder.mpeg4")))
+ {
+ if(!strcmp((const char*)comp_role->cRole, pRoleMPEG4))
+ {
+ memcpy(comp_role->cRole, m_cRole, strlen((char*) m_cRole) + 1);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unknown Index");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp(m_pComponentName,"OMX.qcom.video.encoder.h263",strlen("OMX.qcom.video.encoder.h263")))
+ {
+ if(!strcmp((const char*)comp_role->cRole, pRoleH263))
+ {
+ memcpy(comp_role->cRole, m_cRole, strlen((char*) m_cRole) + 1);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unknown Index");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp(m_pComponentName,"OMX.qcom.video.encoder.avc",strlen("OMX.qcom.video.encoder.avc")))
+ {
+ if(!strcmp((const char*)comp_role->cRole, pRoleAVC))
+ {
+ memcpy(comp_role->cRole, m_cRole, strlen((char*) m_cRole) + 1);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unknown Index");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unknown param");
+ return OMX_ErrorInvalidComponentName;
+ }
+ break;
+ }
+
+ case OMX_QcomIndexPlatformPvt:
+ result = OMX_ErrorNone;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("unsupported index 0x%x", (int) nIndex);
+ result = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ return result;
+}
+
+
+OMX_ERRORTYPE Venc::get_config(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_INOUT OMX_PTR pCompConfig)
+{
+ ////////////////////////////////////////////////////////////////
+ // Supported Config Index Type
+ // =============================================================
+ // OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE
+ // OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE
+ // OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE
+ ////////////////////////////////////////////////////////////////
+
+ if (pCompConfig == NULL)
+ {
+ QC_OMX_MSG_ERROR("param is null");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_eState == OMX_StateInvalid)
+ {
+ QC_OMX_MSG_ERROR("can't be in invalid state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ //@todo need to validate params
+ switch (nIndex)
+ {
+ case OMX_IndexConfigVideoBitrate:
+ {
+ OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(pCompConfig);
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate));
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bitrate is for output port");
+ return OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexConfigVideoFramerate:
+ {
+ OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(pCompConfig);
+ if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate));
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("framerate is for input port (refer to OMX IL spec)");
+ return OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexConfigCommonRotate:
+ {
+ OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(pCompConfig);
+ if(m_eState != OMX_StateLoaded)
+ {
+ // we only allow this at init time!
+ QC_OMX_MSG_ERROR("rotation can only be configured in loaded state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation));
+ break;
+ }
+ case OMX_IndexConfigVideoIntraVOPRefresh:
+ {
+ OMX_CONFIG_INTRAREFRESHVOPTYPE* pParam = reinterpret_cast<OMX_CONFIG_INTRAREFRESHVOPTYPE*>(pCompConfig);
+ memcpy(pParam, &m_sConfigIntraRefreshVOP, sizeof(m_sConfigIntraRefreshVOP));
+ break;
+ }
+#ifdef QCOM_OMX_VENC_EXT
+ case QOMX_IndexConfigVideoTemporalSpatialTradeOff:
+ {
+ QOMX_VIDEO_TEMPORALSPATIALTYPE* pParam = reinterpret_cast<QOMX_VIDEO_TEMPORALSPATIALTYPE*>(pCompConfig);
+ memcpy(pParam, &m_sConfigQpRange, sizeof(m_sConfigQpRange));
+ break;
+ }
+ case QOMX_IndexConfigVideoIntraperiod:
+ {
+ QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(pCompConfig);
+ memcpy(pParam, &m_sConfigIntraPeriod, sizeof(m_sConfigIntraPeriod));
+ break;
+ }
+#endif
+ case OMX_IndexConfigVideoNalSize:
+ {
+ OMX_VIDEO_CONFIG_NALSIZE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_NALSIZE*>(pCompConfig);
+ memcpy(pParam, &m_sConfigNAL, sizeof(m_sConfigNAL));
+ break;
+ }
+ default:
+ QC_OMX_MSG_ERROR("unsupported index %d", (int) nIndex);
+ return OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::update_config_bitrate(OMX_IN OMX_VIDEO_CONFIG_BITRATETYPE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+
+ ////////////////////////////////////////
+ // set bitrate
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_target_bitrate bitrate;
+ bitrate.target_bitrate = pConfig->nEncodeBitrate;
+
+ if (ven_set_target_bitrate(m_pDevice,&bitrate ) != 0)
+ {
+ QC_OMX_MSG_ERROR("error setting bitrate");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sConfigBitrate, pConfig, sizeof(m_sConfigBitrate));
+ // also need to set other params + config
+ m_sConfigBitrate.nEncodeBitrate = pConfig->nEncodeBitrate;
+ m_sParamBitrate.nTargetBitrate = pConfig->nEncodeBitrate;
+ m_sOutPortDef.format.video.nBitrate = pConfig->nEncodeBitrate;
+ }
+
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_config_frame_rate(OMX_IN OMX_CONFIG_FRAMERATETYPE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ ////////////////////////////////////////
+ // set bitrate
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_frame_rate frameRate;
+ frameRate.fps_numerator = pConfig->xEncodeFramerate >> 16; /// @integrate how to get the denominator from this
+ frameRate.fps_denominator = 1;
+
+ rc = ven_set_frame_rate(m_pDevice, &frameRate);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("error setting frame rate");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sConfigFramerate, pConfig, sizeof(m_sConfigFramerate));
+ m_sConfigFramerate.xEncodeFramerate = pConfig->xEncodeFramerate;
+ m_sInPortDef.format.video.xFramerate = pConfig->xEncodeFramerate;
+ m_sInPortFormat.xFramerate = pConfig->xEncodeFramerate;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index. frame rate is for input port (refer to OMX IL spec)");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_config_rotate(OMX_IN OMX_CONFIG_ROTATIONTYPE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(m_eState == OMX_StateLoaded)
+ {
+
+ ////////////////////////////////////////
+ // set rotation
+ ////////////////////////////////////////
+ int nOutSize;
+ {
+ struct ven_rotation rotation;
+
+ switch (pConfig->nRotation)
+ {
+ case 0:
+ rotation.rotation = VEN_ROTATION_0;
+ break;
+ case 90:
+ rotation.rotation = VEN_ROTATION_90;
+ break;
+ case 180:
+ rotation.rotation = VEN_ROTATION_180;
+ break;
+ case 270:
+ rotation.rotation = VEN_ROTATION_270;
+ break;
+ default:
+ QC_OMX_MSG_ERROR("invalid rotation %d", (int) pConfig->nRotation);
+ result = OMX_ErrorBadParameter;
+ break;
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ rc = ven_set_rotation(m_pDevice, &rotation);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set rotation");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(&m_sConfigFrameRotation, pConfig, sizeof(m_sConfigFrameRotation));
+ }
+ }
+ else
+ {
+ // we only allow this at init time!
+ QC_OMX_MSG_ERROR("frame rate can only be configured in loaded state");
+ result = OMX_ErrorIncorrectStateOperation;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::update_config_intra_vop_refresh(OMX_IN OMX_CONFIG_INTRAREFRESHVOPTYPE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // request iframe
+ ////////////////////////////////////////
+ int nOutSize;
+ if (pConfig->IntraRefreshVOP == OMX_TRUE)
+ {
+ QC_OMX_MSG_HIGH("requesting iframe...");
+ rc = ven_request_iframe(m_pDevice);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to request iframe");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("why indicate you dont want an intra frame?");
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+#ifdef QCOM_OMX_VENC_EXT
+OMX_ERRORTYPE Venc::update_config_qp_range(OMX_IN QOMX_VIDEO_TEMPORALSPATIALTYPE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if (pConfig->nTSFactor > 0 && pConfig->nTSFactor <= 100) {
+ int nOutSize;
+ struct ven_qp_range qp;
+ qp.min_qp = 2;
+ if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4 ||
+ m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) {
+ qp.max_qp = 8 + (int) roundingup(pConfig->nTSFactor * 0.23);
+ } else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) {
+ qp.max_qp = 33 + roundingup(pConfig->nTSFactor * 0.18);
+ }
+ QC_OMX_MSG_HIGH("setting qp range");
+ if (ven_set_qp_range(m_pDevice, &qp) != 0)
+ {
+ QC_OMX_MSG_ERROR("failed to set qp range");
+ result = translate_driver_error(GetLastError());
+ }
+ else
+ {
+ memcpy(&m_sConfigQpRange, pConfig, sizeof(m_sConfigQpRange));
+ }
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+#endif
+
+OMX_ERRORTYPE Venc::update_config_nal_size(OMX_IN OMX_VIDEO_CONFIG_NALSIZE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int rc = 0;
+
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ result = is_multi_slice_mode_supported();
+ if(OMX_ErrorNone == result) {
+ int nOutSize;
+ struct ven_multi_slice_cfg slice;
+ slice.mslice_mode = VENC_SLICE_MODE_BIT;
+ slice.mslice_size = (unsigned long) pConfig->nNaluBytes * 8;
+ rc = ven_set_multislice_cfg(m_pDevice, &slice);
+ if(rc)
+ {
+ QC_OMX_MSG_ERROR("failed to set slice config");
+ result = translate_driver_error(GetLastError());
+ }
+ else
+ {
+ memcpy(&m_sConfigNAL, pConfig, sizeof(m_sConfigNAL));
+ }
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+
+#ifdef QCOM_OMX_VENC_EXT
+OMX_ERRORTYPE Venc::update_config_intra_period(OMX_IN QOMX_VIDEO_INTRAPERIODTYPE* pConfig)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pConfig != NULL)
+ {
+ if (pConfig->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ ////////////////////////////////////////
+ // request iframe
+ ////////////////////////////////////////
+ int nOutSize;
+ struct ven_intra_period intra;
+ intra.num_pframes = (unsigned long) pConfig->nPFrames;
+ QC_OMX_MSG_HIGH("setting intra period");
+ if (ven_set_intra_period(m_pDevice, &intra) != 0 )
+ {
+ QC_OMX_MSG_ERROR("failed to set intra period");
+ result = translate_driver_error(GetLastError());
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("bad port index");
+ result = OMX_ErrorBadPortIndex;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+}
+#endif
+
+OMX_ERRORTYPE Venc::set_config(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_IN OMX_PTR pCompConfig)
+{
+
+ ////////////////////////////////////////////////////////////////
+ // Supported Config Index Type
+ // =============================================================
+ // OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE
+ // OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE
+ // OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE
+ ////////////////////////////////////////////////////////////////
+
+ if (pCompConfig == NULL)
+ {
+ QC_OMX_MSG_ERROR("param is null");
+ return OMX_ErrorBadParameter;
+ }
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ switch (nIndex)
+ {
+ case OMX_IndexConfigVideoBitrate:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexConfigVideoBitrate");
+ result = update_config_bitrate(reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(pCompConfig));
+ break;
+ }
+ case OMX_IndexConfigVideoFramerate:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexConfigVideoFramerate");
+ result = update_config_frame_rate(reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(pCompConfig));
+ break;
+ }
+ case OMX_IndexConfigCommonRotate:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexConfigCommonRotate");
+ result = update_config_rotate(reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(pCompConfig));
+ break;
+ }
+ case OMX_IndexConfigVideoIntraVOPRefresh:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexConfigVideoIntraVOPRefresh");
+ result = update_config_intra_vop_refresh(reinterpret_cast<OMX_CONFIG_INTRAREFRESHVOPTYPE*>(pCompConfig));
+ break;
+ }
+#ifdef QCOM_OMX_VENC_EXT
+ case QOMX_IndexConfigVideoTemporalSpatialTradeOff:
+ {
+ QC_OMX_MSG_MEDIUM("QOMX_IndexConfigVideoTemporalSpatialTradeOff");
+ result = update_config_qp_range(reinterpret_cast<QOMX_VIDEO_TEMPORALSPATIALTYPE*>(pCompConfig));
+ break;
+ }
+ case QOMX_IndexConfigVideoIntraperiod:
+ {
+ QC_OMX_MSG_MEDIUM("QOMX_IndexConfigVideoIntraperiod");
+ result = update_config_intra_period(reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(pCompConfig));
+ break;
+ }
+#endif
+ case OMX_IndexConfigVideoNalSize:
+ {
+ QC_OMX_MSG_MEDIUM("OMX_IndexConfigVideoNalSize");
+ result = update_config_nal_size(reinterpret_cast<OMX_VIDEO_CONFIG_NALSIZE*>(pCompConfig));
+ break;
+ }
+ default:
+ QC_OMX_MSG_ERROR("unsupported index %d", (int) nIndex);
+ result = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ return result;
+}
+
+
+OMX_ERRORTYPE Venc::get_extension_index(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_STRING cParameterName,
+ OMX_OUT OMX_INDEXTYPE* pIndexType)
+{
+ return OMX_ErrorNotImplemented;
+}
+
+
+OMX_ERRORTYPE Venc::get_state(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_STATETYPE* pState)
+{
+ (void) hComponent;
+ if (pState == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ *pState = m_eState;
+ return OMX_ErrorNone;
+}
+
+
+OMX_ERRORTYPE Venc::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 nPort,
+ OMX_IN OMX_HANDLETYPE hTunneledComp,
+ OMX_IN OMX_U32 nTunneledPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup)
+{
+ (void) hComp;
+ (void) nPort;
+ (void) hTunneledComp;
+ (void) nTunneledPort;
+ (void) pTunnelSetup;
+ return OMX_ErrorTunnelingUnsupported;
+}
+
+OMX_ERRORTYPE Venc::use_buffer(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN OMX_U32 nSizeBytes,
+ OMX_IN OMX_U8* pBuffer)
+{
+
+ if (ppBufferHdr == NULL || nSizeBytes == 0 || pBuffer == NULL)
+ {
+ QC_OMX_MSG_ERROR("bad param %p %lu %p",ppBufferHdr, nSizeBytes, pBuffer);
+ return OMX_ErrorBadParameter;
+ }
+
+ if(m_eState == OMX_StateInvalid)
+ {
+ QC_OMX_MSG_ERROR("UseBuffer - called in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+ if (nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ QC_OMX_MSG_MEDIUM("client allocated input buffer %p for component", pBuffer);
+ if (nSizeBytes != m_sInPortDef.nBufferSize)
+ {
+ QC_OMX_MSG_ERROR("buffer size(%lu) does not match our requirements(%lu)",
+ nSizeBytes,m_sInPortDef.nBufferSize);
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_nInBuffAllocated == 0)
+ {
+ m_pPrivateInPortData = new PrivatePortData[m_sInPortDef.nBufferCountActual];
+ m_pInBuffHeaders = new OMX_BUFFERHEADERTYPE[m_sInPortDef.nBufferCountActual];
+ memset(m_pPrivateInPortData, 0, sizeof(PrivatePortData) * m_sInPortDef.nBufferCountActual);
+ memset(m_pInBuffHeaders, 0, sizeof(OMX_BUFFERHEADERTYPE) * m_sInPortDef.nBufferCountActual);
+ }
+
+#if 0
+ int bFail;
+ int nOutSize;
+
+ QC_OMX_MSG_LOW("Input buffer: fd %d, offset: %d \n", ((struct venc_pmem *)pAppPrivate)->fd,
+ ((struct venc_pmem *)pAppPrivate)->offset);
+
+ bFail = DeviceIoControl(m_nFd,
+ VENC_IOCTL_SET_INPUT_BUFFER,
+ pAppPrivate);
+ if (bFail)
+ {
+ QC_OMX_MSG_ERROR("failed to set buffer");
+ return OMX_ErrorUndefined;
+ }
+#endif
+
+ OMX_U32 i;
+ for (i = 0; i < m_sInPortDef.nBufferCountActual; i++)
+ {
+ if (m_pInBuffHeaders[i].nAllocLen == 0)
+ {
+ OMX_INIT_STRUCT(&m_pInBuffHeaders[i], OMX_BUFFERHEADERTYPE);
+ m_pInBuffHeaders[i].pBuffer = pBuffer;
+ m_pInBuffHeaders[i].nAllocLen = nSizeBytes;
+ m_pInBuffHeaders[i].pAppPrivate = pAppPrivate;
+ m_pInBuffHeaders[i].nInputPortIndex = (OMX_U32) PORT_INDEX_IN;
+ m_pInBuffHeaders[i].nOutputPortIndex = (OMX_U32) PORT_INDEX_NONE;
+ m_pInBuffHeaders[i].pInputPortPrivate = &m_pPrivateInPortData[i];
+ m_pPrivateInPortData[i].bComponentAllocated = OMX_FALSE;
+
+ *ppBufferHdr = &m_pInBuffHeaders[i];
+
+ ++m_nInBuffAllocated;
+ break;
+ }
+ }
+ if (m_nInBuffAllocated == m_sInPortDef.nBufferCountActual)
+ {
+ QC_OMX_MSG_LOW("I/P port populated");
+ m_sInPortDef.bPopulated = OMX_TRUE;
+ }
+ if (i == m_sInPortDef.nBufferCountActual)
+ {
+ QC_OMX_MSG_ERROR("could not find free buffer");
+ return OMX_ErrorUndefined;
+ }
+ }
+ else if (nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ QC_OMX_MSG_MEDIUM("client allocated output buffer 0x%x for component",(int) pBuffer);
+ if (nSizeBytes != m_sOutPortDef.nBufferSize)
+ {
+ QC_OMX_MSG_ERROR("buffer size does not match our requirements");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_nOutBuffAllocated == 0)
+ {
+ m_pPrivateOutPortData = new PrivatePortData[m_sOutPortDef.nBufferCountActual];
+ m_pOutBuffHeaders = new OMX_BUFFERHEADERTYPE[m_sOutPortDef.nBufferCountActual];
+ memset(m_pPrivateOutPortData, 0, sizeof(PrivatePortData) * m_sOutPortDef.nBufferCountActual);
+ memset(m_pOutBuffHeaders, 0, sizeof(OMX_BUFFERHEADERTYPE) * m_sOutPortDef.nBufferCountActual);
+ }
+
+#if 0
+ int bFail;
+ int nOutSize;
+
+ bFail = DeviceIoControl(m_nFd,
+ VENC_IOCTL_SET_OUTPUT_BUFFER,
+ pAppPrivate);
+ if (bFail)
+ {
+ QC_OMX_MSG_ERROR("failed to set buffer");
+ return OMX_ErrorUndefined;
+ }
+#endif
+ OMX_U32 i;
+ for (i = 0; i < m_sOutPortDef.nBufferCountActual; i++)
+ {
+ if (m_pOutBuffHeaders[i].nAllocLen == 0)
+ {
+ OMX_INIT_STRUCT(&m_pOutBuffHeaders[i], OMX_BUFFERHEADERTYPE);
+ m_pOutBuffHeaders[i].pBuffer = pBuffer;
+ m_pOutBuffHeaders[i].nAllocLen = nSizeBytes;
+ m_pOutBuffHeaders[i].pAppPrivate = pAppPrivate;
+ m_pOutBuffHeaders[i].nInputPortIndex = (OMX_U32) PORT_INDEX_NONE;
+ m_pOutBuffHeaders[i].nOutputPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_pOutBuffHeaders[i].pOutputPortPrivate = &m_pPrivateOutPortData[i];
+ m_pPrivateOutPortData[i].bComponentAllocated = OMX_FALSE;
+
+ *ppBufferHdr = &m_pOutBuffHeaders[i];
+
+ ++m_nOutBuffAllocated;
+ break;
+ }
+ }
+ if (m_nOutBuffAllocated == m_sOutPortDef.nBufferCountActual)
+ {
+ QC_OMX_MSG_LOW("I/P port populated");
+ m_sOutPortDef.bPopulated = OMX_TRUE;
+ }
+
+ if (i == m_sOutPortDef.nBufferCountActual)
+ {
+ QC_OMX_MSG_ERROR("could not find free buffer");
+ return OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid port index");
+ return OMX_ErrorBadPortIndex;
+ }
+ if (BITMASK_PRESENT(m_nFlags, OMX_COMPONENT_IDLE_PENDING) &&
+ m_sInPortDef.bPopulated && m_sOutPortDef.bPopulated)
+ {
+ QC_OMX_MSG_PROFILE("Ports populated, go to idle state \n");
+ m_eState = OMX_StateIdle;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle, NULL);
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::allocate_buffer(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN OMX_U32 nSizeBytes)
+{
+ QC_OMX_MSG_MEDIUM("Attempt to allocate buffer of %d bytes", (int) nSizeBytes);
+ int cnt, i, bFail;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBufferHdr = NULL;
+ PrivatePortData* pPrivateData;
+
+ if (ppBuffer == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ if(m_eState == OMX_StateInvalid)
+ {
+ QC_OMX_MSG_ERROR("AllocateBuffer - called in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if (nSizeBytes == m_sOutPortDef.nBufferSize)
+ {
+ cnt = (int) m_sOutPortDef.nBufferCountActual;
+
+ if (m_nOutBuffAllocated == 0)
+ {
+ m_pPrivateOutPortData = new PrivatePortData[m_sOutPortDef.nBufferCountActual];
+ m_pOutBuffHeaders = new OMX_BUFFERHEADERTYPE[m_sOutPortDef.nBufferCountActual];
+ memset(m_pPrivateOutPortData, 0, sizeof(PrivatePortData) * m_sOutPortDef.nBufferCountActual);
+ memset(m_pOutBuffHeaders, 0, sizeof(OMX_BUFFERHEADERTYPE) * m_sOutPortDef.nBufferCountActual);
+ }
+
+ for (i = 0; i < cnt; i++)
+ {
+ if (m_pOutBuffHeaders[i].pBuffer == NULL)
+ {
+ OMX_INIT_STRUCT(&m_pOutBuffHeaders[i], OMX_BUFFERHEADERTYPE);
+ pBufferHdr = &m_pOutBuffHeaders[i];
+ pPrivateData = &m_pPrivateOutPortData[i];
+ break;
+ }
+ }
+
+ if (pBufferHdr != NULL)
+ {
+
+ result = pmem_alloc(&pPrivateData->sPmemInfo,
+ m_sOutPortDef.nBufferSize, VENC_PMEM_SMI);
+ if (result != OMX_ErrorNone) {
+ QC_OMX_MSG_ERROR("Failed to allocate pmem buffer");
+ }
+
+ bFail = DeviceIoControl(m_nFd,
+ VENC_IOCTL_SET_OUTPUT_BUFFER,
+ &(pPrivateData->sPmemInfo));
+
+ if (!bFail)
+ {
+ pBufferHdr->pBuffer =(OMX_U8 *)(pPrivateData->sPmemInfo).virt;
+ pBufferHdr->nAllocLen = m_sOutPortDef.nBufferSize;
+ pBufferHdr->nAllocLen = nSizeBytes;
+ //pBufferHdr->pAppPrivate = pAppPrivate;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* private_info =
+ (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* )malloc(
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO));
+ private_info->pmem_fd = pPrivateData->sPmemInfo.fd;
+ private_info->offset = pPrivateData->sPmemInfo.offset;
+ pBufferHdr->pPlatformPrivate = (OMX_PTR)private_info;
+ pBufferHdr->nInputPortIndex = (OMX_U32) PORT_INDEX_NONE;
+ pBufferHdr->nOutputPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ pBufferHdr->pOutputPortPrivate = pPrivateData;
+ pPrivateData->bComponentAllocated = OMX_TRUE;
+ *ppBuffer = pBufferHdr;
+ ++m_nOutBuffAllocated;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unable to set output buffer");
+ result = OMX_ErrorUndefined;
+ }
+ } // pBufferHdr
+ if (m_nOutBuffAllocated == m_sOutPortDef.nBufferCountActual)
+ {
+ m_sOutPortDef.bPopulated = OMX_TRUE;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("buffer size does not match our requirements %lu %lu",
+ nSizeBytes, m_sOutPortDef.nBufferSize);
+ result = OMX_ErrorBadParameter;
+ }
+ }
+
+ if (nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ if (nSizeBytes == m_sInPortDef.nBufferSize)
+ {
+ cnt = (int) m_sInPortDef.nBufferCountActual;
+
+ if (m_nInBuffAllocated == 0)
+ {
+ m_pPrivateInPortData = new PrivatePortData[m_sInPortDef.nBufferCountActual];
+ m_pInBuffHeaders = new OMX_BUFFERHEADERTYPE[m_sInPortDef.nBufferCountActual];
+ memset(m_pPrivateInPortData, 0, sizeof(PrivatePortData) * m_sInPortDef.nBufferCountActual);
+ memset(m_pInBuffHeaders, 0, sizeof(OMX_BUFFERHEADERTYPE) * m_sInPortDef.nBufferCountActual);
+ }
+
+ for (i = 0; i < cnt; i++)
+ {
+ if (m_pInBuffHeaders[i].pBuffer == NULL)
+ {
+ OMX_INIT_STRUCT(&m_pInBuffHeaders[i], OMX_BUFFERHEADERTYPE);
+ pBufferHdr = &m_pInBuffHeaders[i];
+ pPrivateData = &m_pPrivateInPortData[i];
+ break;
+ }
+ }
+
+ if (pBufferHdr != NULL)
+ {
+
+ result = pmem_alloc(&pPrivateData->sPmemInfo,
+ m_sInPortDef.nBufferSize, VENC_PMEM_SMI);
+ if (result != OMX_ErrorNone) {
+ QC_OMX_MSG_ERROR("Failed to allocate pmem buffer");
+ }
+ bFail = DeviceIoControl(m_nFd,
+ VENC_IOCTL_SET_INPUT_BUFFER,
+ &(pPrivateData->sPmemInfo));
+
+ if (!bFail)
+ {
+ pBufferHdr->pBuffer = (OMX_U8 *)(pPrivateData->sPmemInfo).virt;
+ pBufferHdr->nAllocLen = m_sInPortDef.nBufferSize;
+ //pBufferHdr->pAppPrivate = pAppPrivate;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* private_info =
+ (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* )malloc(
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO));
+ private_info->pmem_fd = pPrivateData->sPmemInfo.fd;
+ private_info->offset = pPrivateData->sPmemInfo.offset;
+ pBufferHdr->pPlatformPrivate = (OMX_PTR)private_info;
+ pBufferHdr->nInputPortIndex = (OMX_U32) PORT_INDEX_IN;
+ pBufferHdr->nOutputPortIndex = (OMX_U32) PORT_INDEX_NONE;
+ pBufferHdr->pInputPortPrivate = pPrivateData;
+ pPrivateData->bComponentAllocated = OMX_TRUE;
+ *ppBuffer = pBufferHdr;
+ ++m_nInBuffAllocated;
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("unable to set input buffer");
+ result = OMX_ErrorUndefined;
+ }
+ } // pBufferHdr
+
+ if (m_nInBuffAllocated == m_sInPortDef.nBufferCountActual)
+ {
+ m_sInPortDef.bPopulated = OMX_TRUE;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("buffer size does not match our requirements %lu %lu",
+ nSizeBytes, m_sInPortDef.nBufferSize);
+ result = OMX_ErrorBadParameter;
+ }
+ }
+
+ if (BITMASK_PRESENT(m_nFlags, OMX_COMPONENT_IDLE_PENDING) &&
+ m_sInPortDef.bPopulated && m_sOutPortDef.bPopulated)
+ {
+ QC_OMX_MSG_PROFILE("Ports populated, go to idle state \n");
+ m_eState = OMX_StateIdle;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle, NULL);
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::free_buffer(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (! pBufferHdr || !(pBufferHdr->pBuffer))
+ {
+ QC_OMX_MSG_ERROR("null param");
+ return OMX_ErrorBadParameter;
+ }
+
+ QC_OMX_MSG_MEDIUM("freeing 0x%x", pBufferHdr->pBuffer);
+ if (nPortIndex == PORT_INDEX_OUT)
+ {
+ PrivatePortData* pPortData =
+ ((PrivatePortData*) pBufferHdr->pOutputPortPrivate);
+
+ if (pPortData->bComponentAllocated) {
+ result = pmem_free(&pPortData->sPmemInfo);
+ if (result != OMX_ErrorNone) {
+ QC_OMX_MSG_ERROR("failed to free buffer");
+ }
+ free(pBufferHdr->pPlatformPrivate);
+ pBufferHdr->pPlatformPrivate = NULL;
+ }
+ else {
+ QC_OMX_MSG_HIGH("No need to free output buffer allocated by clients");
+ }
+
+ // indicate buffer is available for alloc again
+ pBufferHdr->pBuffer = NULL;
+ pBufferHdr->nAllocLen = 0;
+ m_sOutPortDef.bPopulated = OMX_FALSE;
+ --m_nOutBuffAllocated;
+
+ if (m_nOutBuffAllocated == 0)
+ {
+ delete [] m_pPrivateOutPortData;
+ delete [] m_pOutBuffHeaders;
+ }
+ QC_OMX_MSG_HIGH("Done with free_buffer, output \n");
+ }
+ else if (nPortIndex == PORT_INDEX_IN)
+ {
+ PrivatePortData* pPortData =
+ ((PrivatePortData*) pBufferHdr->pInputPortPrivate);
+
+ if (pPortData->bComponentAllocated) {
+ result = pmem_free(&pPortData->sPmemInfo);
+ if (result != OMX_ErrorNone) {
+ QC_OMX_MSG_ERROR("failed to free buffer");
+ }
+ free(pBufferHdr->pPlatformPrivate);
+ pBufferHdr->pPlatformPrivate = NULL;
+ }
+ else {
+ QC_OMX_MSG_HIGH("No need to free input buffer allocated by clients");
+ }
+
+ // indicate buffer is available for alloc again
+ pBufferHdr->pBuffer = NULL;
+ pBufferHdr->nAllocLen = 0;
+ m_sInPortDef.bPopulated = OMX_FALSE;
+ --m_nInBuffAllocated;
+
+ if (m_nInBuffAllocated == 0)
+ {
+ delete [] m_pPrivateInPortData;
+ delete [] m_pInBuffHeaders;
+ }
+ QC_OMX_MSG_HIGH("Done with free_buffer, input \n");
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid port");
+ result = OMX_ErrorBadParameter;
+ }
+ if (BITMASK_PRESENT((m_nFlags), OMX_COMPONENT_LOADING_PENDING) &&
+ (m_nInBuffAllocated == 0) && (m_nOutBuffAllocated == 0))
+ {
+ QC_OMX_MSG_PROFILE("free buffer done, switch to loaded state");
+ m_eState = OMX_StateLoaded;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ m_eState,
+ NULL);
+ }
+ return result;
+}
+
+OMX_ERRORTYPE Venc::allocate_q6_buffers(struct venc_buffers *pbufs)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int i, size, nReconSize, nWbSize, nCmdSize, nVlcSize;
+ int width, height;
+
+ QC_OMX_MSG_MEDIUM("Attempt to allocate q6 buffers ");
+
+ width = m_sOutPortDef.format.video.nFrameWidth;
+ height = m_sOutPortDef.format.video.nFrameHeight;
+ if(OMX_ErrorNone != is_multi_slice_mode_supported()) {
+ nCmdSize = width * height * 3 / 2;
+ } else {
+ nCmdSize = width * height * 4;
+ }
+ nVlcSize = 3072 * width / 16;
+ nReconSize = nWbSize = (((width + 31) >> 5) << 5) * height * 3 / 2;
+ // allocate recon buffers
+ for (i = 0; i < VENC_MAX_RECON_BUFFERS && result == OMX_ErrorNone; i++)
+ {
+ result = pmem_alloc(&(pbufs->recon_buf[i]), nReconSize, VENC_PMEM_SMI);
+ if (result == OMX_ErrorNone)
+ {
+ QC_OMX_MSG_HIGH("allocated recon buffer: pVirt=0x%x, nPhy=0x%x, \n",
+ pbufs->recon_buf[i].virt,
+ pbufs->recon_buf[i].phys);
+ QC_OMX_MSG_HIGH("allocated recon buffer: fd=%d, offset=%d src=%d\n",
+ pbufs->recon_buf[i].fd,
+ pbufs->recon_buf[i].offset,
+ pbufs->recon_buf[i].src);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to allocate recon buffer");
+ }
+ }
+
+ // allocate wb buffer
+ if (result == OMX_ErrorNone)
+ {
+ result = pmem_alloc(&(pbufs->wb_buf), nWbSize, VENC_PMEM_SMI);
+ if (result == OMX_ErrorNone)
+ {
+ QC_OMX_MSG_HIGH("allocated wb buffer: pVirt=0x%x, nPhy=0x%x,\n",
+ pbufs->wb_buf.virt,
+ pbufs->wb_buf.phys);
+ QC_OMX_MSG_HIGH("allocated wb buffer: fd=%d, offset=%d src=%d\n",
+ pbufs->wb_buf.fd,
+ pbufs->wb_buf.offset,
+ pbufs->wb_buf.src);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to allocate wb buffer");
+ goto err_wb_buf_allocation;
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ result = pmem_alloc(&(pbufs->cmd_buf), nCmdSize, VENC_PMEM_SMI);
+ if (result == OMX_ErrorNone)
+ {
+ QC_OMX_MSG_HIGH("allocated cmd buffer: pVirt=0x%x, nPhy=0x%x,\n",
+ pbufs->cmd_buf.virt,
+ pbufs->cmd_buf.phys);
+ QC_OMX_MSG_HIGH("allocated cmd buffer: fd=%d, offset=%d src=%d\n",
+ pbufs->cmd_buf.fd,
+ pbufs->cmd_buf.offset,
+ pbufs->cmd_buf.src);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to allocate cmd buffer");
+ goto err_cmd_buf_allocation;
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ result = pmem_alloc(&(pbufs->vlc_buf), nCmdSize, VENC_PMEM_EBI1);
+ if (result == OMX_ErrorNone)
+ {
+ QC_OMX_MSG_HIGH("allocated vlc buffer: pVirt=0x%x, nPhy=0x%x,\n",
+ pbufs->vlc_buf.virt,
+ pbufs->vlc_buf.phys);
+ QC_OMX_MSG_HIGH("allocated vlc buffer: fd=%d, offset=%d src=%d\n",
+ pbufs->vlc_buf.fd,
+ pbufs->vlc_buf.offset,
+ pbufs->vlc_buf.src);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to allocate vlc buffer");
+ goto err_vlc_buf_allocation;
+ }
+ }
+ return result;
+
+err_vlc_buf_allocation:
+ (void)pmem_free(&(pbufs->cmd_buf));
+err_cmd_buf_allocation:
+ (void)pmem_free(&(pbufs->wb_buf));
+err_wb_buf_allocation:
+ for (i = 0; i < VENC_MAX_RECON_BUFFERS; i++)
+ {
+ if (pbufs->recon_buf[i].virt != NULL)
+ {
+ (void) pmem_free(&(pbufs->recon_buf[i]));
+ }
+ }
+ return result;
+}
+
+
+OMX_ERRORTYPE Venc::free_q6_buffers(struct venc_buffers *pbufs)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int i;
+
+ for (i = 0; i < VENC_MAX_RECON_BUFFERS; i++)
+ {
+ result = pmem_free(&(pbufs->recon_buf[i]));
+
+ if (result != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to free recon buf");
+ }
+ }
+
+ result = pmem_free(&(pbufs->wb_buf));
+ if (result != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to free wb buf");
+ }
+
+ result = pmem_free(&(pbufs->cmd_buf));
+ if (result != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to free command buf");
+ }
+
+ result = pmem_free(&(pbufs->vlc_buf));
+ if (result != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to free VLC buf");
+ }
+ return result;
+}
+
+
+OMX_ERRORTYPE Venc::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pInBuffer)
+{
+ (void) hComponent;
+
+ QC_OMX_MSG_LOW("emptying buffer...");
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pInBuffer != NULL)
+ {
+ VencMsgQ::MsgDataType msgData;
+ msgData.pBuffer = pInBuffer;
+ result = m_pMsgQ->PushMsg(VencMsgQ::MSG_ID_EMPTY_BUFFER, &msgData);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("buffer header is null");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+}
+
+OMX_ERRORTYPE Venc::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ (void) hComponent;
+
+ QC_OMX_MSG_LOW("Fill buffer with hdr:0x%x \n",pBuffer);
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pBuffer != NULL)
+ {
+ VencMsgQ::MsgDataType msgData;
+ msgData.pBuffer = pBuffer;
+ result = m_pMsgQ->PushMsg(VencMsgQ::MSG_ID_FILL_BUFFER, &msgData);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("buffer header is null");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+}
+
+OMX_ERRORTYPE Venc::set_callbacks(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_CALLBACKTYPE* pCallbacks,
+ OMX_IN OMX_PTR pAppData)
+{
+ if (pCallbacks == NULL ||
+ hComponent == NULL ||
+ pCallbacks->EmptyBufferDone == NULL ||
+ pCallbacks->FillBufferDone == NULL ||
+ pCallbacks->EventHandler == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ m_sCallbacks.EventHandler = pCallbacks->EventHandler;
+ m_sCallbacks.EmptyBufferDone = pCallbacks->EmptyBufferDone;
+ m_sCallbacks.FillBufferDone = pCallbacks->FillBufferDone;
+ m_pAppData = pAppData;
+ m_hSelf = hComponent;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::component_deinit(OMX_IN OMX_HANDLETYPE hComponent)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ QC_OMX_MSG_MEDIUM("deinitializing component...");
+
+ if (m_pMsgQ->PushMsg(VencMsgQ::MSG_ID_EXIT,
+ NULL) == OMX_ErrorNone)
+ {
+ pthread_join(m_ComponentThread, NULL);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to send thread exit msg");
+ return OMX_ErrorUndefined;
+ }
+
+ if (DeviceIoControl(m_nFd,
+ VENC_IOCTL_CMD_STOP_READ_MSG,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ NULL) == 0)
+ {
+ (void) pthread_join(m_ReaderThread, NULL);
+ QC_OMX_MSG_MEDIUM("Reader thread joined");
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("error killing reader thread");
+ }
+
+ if (m_pMsgQ)
+ delete m_pMsgQ;
+ if (m_pOutBufferMgr)
+ delete m_pOutBufferMgr;
+ if (m_pInBufferMgr)
+ delete m_pInBufferMgr;
+ if (m_pComponentName)
+ free(m_pComponentName);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::use_EGL_image(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN void* eglImage)
+{
+ return OMX_ErrorNotImplemented;
+}
+
+OMX_ERRORTYPE Venc::component_role_enum(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_U8 *cRole,
+ OMX_IN OMX_U32 nIndex)
+{
+
+ static const char* roles[] = {"*",
+ "video_encoder",
+ "video_encoder.mpeg4",
+ "video_encoder.avc",
+ "video_encoder.h263"};
+ static const OMX_U32 nRoles = sizeof(roles) / sizeof(char*);
+
+ if (cRole == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ if (nIndex < nRoles)
+ {
+ memcpy((char*) cRole, roles[nIndex], strlen(roles[nIndex]) + 1);
+ return OMX_ErrorNone;
+ }
+ else
+ {
+ return OMX_ErrorNoMore;
+ }
+}
+
+void *Venc::component_thread(void *pClassObj)
+{
+ OMX_BOOL bRunning = OMX_TRUE;
+ Venc* pVenc = reinterpret_cast<Venc*>(pClassObj);
+
+ QC_OMX_MSG_MEDIUM("component thread has started");
+
+ if (pVenc == NULL)
+ {
+ QC_OMX_MSG_ERROR("thread param is null. exiting.");
+ return 0;
+ }
+
+ while (bRunning)
+ {
+ VencMsgQ::MsgType msg;
+ QC_OMX_MSG_LOW("component thread is checking msg q...");
+ if (pVenc->m_pMsgQ->PopMsg(&msg) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to pop msg");
+ }
+
+ QC_OMX_MSG_LOW("Component thread got msg");
+
+ switch (msg.id)
+ {
+ case VencMsgQ::MSG_ID_EXIT:
+ QC_OMX_MSG_LOW("got MSG_ID_EXIT");
+
+ bRunning = OMX_FALSE;
+ break;
+ case VencMsgQ::MSG_ID_MARK_BUFFER:
+ QC_OMX_MSG_LOW("got MSG_ID_MARK_BUFFER for port %d", (int) msg.data.sMarkBuffer.nPortIndex);
+ pVenc->process_mark_buffer(msg.data.sMarkBuffer.nPortIndex,
+ &msg.data.sMarkBuffer.sMarkData);
+ break;
+ case VencMsgQ::MSG_ID_PORT_ENABLE:
+ QC_OMX_MSG_LOW("got MSG_ID_PORT_ENABLE for port %d", (int) msg.data.nPortIndex);
+ pVenc->process_port_enable(msg.data.nPortIndex);
+ break;
+ case VencMsgQ::MSG_ID_PORT_DISABLE:
+ QC_OMX_MSG_LOW("got MSG_ID_PORT_DISABLE for port %d", (int) msg.data.nPortIndex);
+ pVenc->process_port_disable(msg.data.nPortIndex);
+ break;
+ case VencMsgQ::MSG_ID_FLUSH:
+ QC_OMX_MSG_LOW("got MSG_ID_FLUSH for port %d", (int) msg.data.nPortIndex);
+ pVenc->process_flush(msg.data.nPortIndex);
+ break;
+ case VencMsgQ::MSG_ID_STATE_CHANGE:
+ QC_OMX_MSG_LOW("got MSG_ID_STATE_CHANGE");
+ pVenc->process_state_change(msg.data.eState);
+ break;
+ case VencMsgQ::MSG_ID_EMPTY_BUFFER:
+ QC_OMX_MSG_LOW("got MSG_ID_EMPTY_BUFFER");
+ pVenc->process_empty_buffer(msg.data.pBuffer);
+ break;
+ case VencMsgQ::MSG_ID_FILL_BUFFER:
+ QC_OMX_MSG_LOW("got MSG_ID_FILL_BUFFER");
+ pVenc->process_fill_buffer(msg.data.pBuffer);
+ break;
+ case VencMsgQ::MSG_ID_DRIVER_MSG:
+ QC_OMX_MSG_LOW("got MSG_ID_DRIVER_MSG");
+ pVenc->process_driver_msg(&msg.data.sDriverMsg);
+ break;
+ default:
+ QC_OMX_MSG_ERROR("invalid msg id %d", msg.id);
+ break;
+ }
+ }
+ QC_OMX_MSG_MEDIUM("component thread is exiting");
+ return 0;
+}
+
+void *Venc::reader_thread_entry(void *pClassObj)
+{
+ if (pClassObj)
+ {
+ QC_OMX_MSG_MEDIUM("reader thread entry \n");
+ (reinterpret_cast<Venc*>(pClassObj))->reader_thread();
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null thread data");
+ }
+
+ return NULL;
+}
+
+void Venc::reader_thread()
+{
+ int bExecute = OMX_TRUE;
+
+ while (bExecute == OMX_TRUE)
+ {
+ int driverRet;
+ struct ven_timeout timeout;
+ struct venc_msg msg;
+ VencMsgQ::MsgDataType data;
+ timeout.millisec = VEN_TIMEOUT_INFINITE;
+
+ QC_OMX_MSG_LOW("reader thread for next message");
+ /* driverRet = DeviceIoControl(m_pDevice,
+ VENC_IOCTL_CMD_READ_NEXT_MSG,
+ &timeout,
+ sizeof(timeout),
+ &msg,
+ sizeof(msg),
+ NULL,
+ NULL); */
+ driverRet = DeviceIoControl(m_nFd,
+ VENC_IOCTL_CMD_READ_NEXT_MSG,
+ &msg);
+
+ if (!driverRet)
+ {
+ if (msg.msg_code == VENC_MSG_STOP_READING_MSG)
+ {
+ QC_OMX_MSG_LOW("reader thread exiting");
+ bExecute = OMX_FALSE;
+ }
+ else
+ {
+ QC_OMX_MSG_LOW("Receive msg");
+ data.sDriverMsg = msg;
+ m_pMsgQ->PushMsg(VencMsgQ::MSG_ID_DRIVER_MSG, &data);
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("reader thread error");
+ bExecute = OMX_FALSE;
+ }
+ }
+}
+
+void Venc::process_state_change(OMX_STATETYPE eState)
+{
+ int rc = 0;
+#define GOTO_STATE(eState) \
+ { \
+ m_eState = eState; \
+ m_sCallbacks.EventHandler(m_hSelf, \
+ m_pAppData, \
+ OMX_EventCmdComplete, \
+ OMX_CommandStateSet, \
+ eState, \
+ NULL); \
+ }
+
+ // -susan: comment out for now
+ /* if (eState == m_eState)
+ {
+ QC_OMX_MSG_ERROR("attempted to change to the same state");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorSameState,
+ 0 , NULL);
+ return;
+ } */
+
+
+ // We will issue OMX_EventCmdComplete when we get device layer
+ // status callback for the corresponding state.
+
+ switch (eState)
+ {
+ case OMX_StateInvalid:
+ {
+ QC_OMX_MSG_MEDIUM("Attempt to go to OMX_StateInvalid");
+ m_eState = eState;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorInvalidState,
+ 0 , NULL);
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ m_eState, NULL);
+ break;
+ }
+ case OMX_StateLoaded:
+ {
+ QC_OMX_MSG_MEDIUM("Attempt to go to OMX_StateLoaded");
+ if (m_eState == OMX_StateIdle)
+ {
+ if ((m_nInBuffAllocated == 0) && (m_nOutBuffAllocated == 0))
+ {
+ GOTO_STATE(OMX_StateLoaded);
+ }
+ else {
+ BITMASK_SET(m_nFlags, OMX_COMPONENT_LOADING_PENDING);
+ }
+ }
+ else
+ {
+ if (m_eState != OMX_StateLoaded) {
+ QC_OMX_MSG_ERROR("invalid state transition to OMX_StateLoaded");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+ }
+ }
+ break;
+ }
+ case OMX_StateIdle:
+ {
+ QC_OMX_MSG_MEDIUM("Attempt to go to OMX_StateIdle");
+ if (m_eState == OMX_StateLoaded)
+ {
+ if (m_sInPortDef.bPopulated && m_sOutPortDef.bPopulated)
+ {
+ GOTO_STATE(OMX_StateIdle);
+ }
+ else {
+ BITMASK_SET(m_nFlags, OMX_COMPONENT_IDLE_PENDING);
+ }
+ }
+ else if (m_eState == OMX_StateExecuting || m_eState == OMX_StatePause)
+ {
+ int driverRet;
+ driverRet = ioctl(m_nFd, VENC_IOCTL_CMD_STOP);
+ if (driverRet)
+ {
+ QC_OMX_MSG_ERROR("Error sending stop command to driver");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+ }
+ }
+ else
+ {
+#if 0
+ // susan: temp fix
+ QC_OMX_MSG_ERROR("invalid state transition to OMX_StateIdle");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+#endif
+ }
+ break;
+ }
+ case OMX_StateExecuting:
+ {
+ QC_OMX_MSG_MEDIUM("Attempt to go to OMX_StateExecuting");
+ if (m_eState == OMX_StateIdle)
+ {
+ int driverRet;
+ allocate_q6_buffers(&m_sQ6Buffers);
+
+ driverRet = ven_start(m_pDevice, &m_sQ6Buffers);
+ if (driverRet)
+ {
+ QC_OMX_MSG_ERROR("Error sending start command to driver");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ (OMX_U32) OMX_ErrorUndefined,
+ (OMX_U32) 0 , NULL);
+ }
+ }
+ else if (m_eState == OMX_StatePause)
+ {
+ int driverRet;
+ driverRet = ioctl(m_nFd, VENC_IOCTL_CMD_RESUME);
+ if (driverRet)
+ {
+ QC_OMX_MSG_ERROR("Error sending resume command to driver");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ (OMX_U32) OMX_ErrorUndefined,
+ (OMX_U32) 0 , NULL);
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid state transition to OMX_StateExecuting");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+ }
+ break;
+ }
+ case OMX_StatePause:
+ {
+ QC_OMX_MSG_MEDIUM("Attempt to go to OMX_StatePause");
+ if (m_eState == OMX_StateExecuting)
+ {
+ int driverRet;
+ driverRet = ioctl(m_nFd, VENC_IOCTL_CMD_PAUSE);
+ if (driverRet)
+ {
+ QC_OMX_MSG_ERROR("Error sending start command to driver");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ (OMX_U32) OMX_ErrorUndefined,
+ (OMX_U32) 0 , NULL);
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("invalid state transition to OMX_StatePause");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+ }
+ break;
+ }
+ case OMX_StateWaitForResources:
+ {
+ QC_OMX_MSG_MEDIUM("Attempt to go to OMX_StateWaitForResources");
+ /// @todo determine what to do with this transition, for now return an error
+ QC_OMX_MSG_ERROR("Transitioning to OMX_StateWaitForResources");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+
+ break;
+ }
+ default:
+ {
+ QC_OMX_MSG_ERROR("invalid state %d", (int) eState);
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorIncorrectStateTransition,
+ 0 , NULL);
+ break;
+ }
+ }
+ sem_post(&m_cmd_lock);
+#undef GOTO_STATE
+}
+
+void Venc::process_flush(OMX_U32 nPortIndex)
+{
+ QC_OMX_MSG_HIGH("flushing...");
+
+
+ if (nPortIndex == (OMX_U32) OMX_ALL)
+ {
+ int driverRet;
+ struct venc_buffer_flush flush;
+ flush.flush_mode = VENC_FLUSH_ALL;
+ driverRet = ioctl(m_nFd, VENC_IOCTL_CMD_FLUSH, &flush);
+ if (driverRet)
+ {
+ QC_OMX_MSG_ERROR("failed to issue flush");
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_HIGH("we only support flushing all ports");
+ }
+
+}
+
+void Venc::process_port_enable(OMX_U32 nPortIndex)
+{
+ /// @todo implement
+}
+
+void Venc::process_port_disable(OMX_U32 nPortIndex)
+{
+ /// @todo implement
+}
+
+void Venc::process_mark_buffer(OMX_U32 nPortIndex,
+ const OMX_MARKTYPE* pMarkData)
+{
+ /// @todo implement
+}
+void Venc::process_empty_buffer(OMX_BUFFERHEADERTYPE* pBufferHdr)
+{
+ int result = VENC_S_SUCCESS;
+ struct venc_buffer input;
+ struct venc_pmem pmem_input;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pParam1;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pParam2;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam;
+
+ if (pBufferHdr == NULL) {
+ QC_OMX_MSG_ERROR("Empty input buffer");
+ }
+
+ // if (m_bIsQcomPvt) {
+ // pParam1 = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_LIST *>(pBufferHdr->pPlatformPrivate);
+ // pParam2 = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_ENTRY *>(pParam1->entryList);
+ // pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>(pParam2->entry);
+
+ //input.ptr_buffer = (unsigned char *)pBufferHdr->pAppPrivate;
+
+
+ pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>(pBufferHdr->pPlatformPrivate);
+ pmem_input.fd = pParam->pmem_fd;
+ pmem_input.offset = pParam->offset;
+ pmem_input.src = VENC_PMEM_SMI;
+ pmem_input.size = m_sInPortDef.nBufferSize;
+ input.ptr_buffer = (unsigned char *)&pmem_input;
+
+ input.len = pBufferHdr->nFilledLen;
+ input.size = pBufferHdr->nAllocLen;
+ input.time_stamp = pBufferHdr->nTimeStamp;
+ if (pBufferHdr->nFlags & OMX_BUFFERFLAG_EOS)
+ {
+ input.flags = VENC_FLAG_EOS;
+ }
+ else
+ {
+ input.flags = 0;
+ }
+ input.client_data = (unsigned long) pBufferHdr;
+ result = DeviceIoControl(m_nFd,
+ VENC_IOCTL_CMD_ENCODE_FRAME,
+ &input);
+ if (result)
+ {
+ QC_OMX_MSG_ERROR("failed to encode frame");
+ if (m_sCallbacks.EmptyBufferDone(m_hSelf,
+ m_pAppData,
+ pBufferHdr) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("EBD failed");
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_LOW("Push buffer %p \n", pBufferHdr);
+ // this should not happen but print an error just in case
+ if (m_pInBufferMgr->PushBuffer(pBufferHdr) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to push input buffer");
+ }
+ }
+}
+
+void Venc::process_fill_buffer(OMX_BUFFERHEADERTYPE* pBufferHdr)
+{
+ int driverRet;
+ struct venc_buffer output;
+ struct venc_pmem pmem_output;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pParam1;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pParam2;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam;
+
+ if (pBufferHdr == NULL) {
+ QC_OMX_MSG_ERROR("Empty input buffer");
+ }
+
+ // if (m_bIsQcomPvt) {
+ //pParam1 = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_LIST *>(pBufferHdr->pPlatformPrivate);
+ //pParam2 = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_ENTRY *>(pParam1->entryList);
+ //pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>(pParam2->entry);
+
+ /* pOutput = &((struct venc_pmem *)output.ptr_buffer);
+ pOutput->fd = pParam->pmem_fd;
+ pOutput->offset = pParam->offset; */
+
+ QC_OMX_MSG_LOW("Fill_output: client_data:0x%x \n", pBufferHdr);
+ // output.ptr_buffer = (unsigned char *)pBufferHdr->pAppPrivate;
+
+ pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>(pBufferHdr->pPlatformPrivate);
+ pmem_output.fd = pParam->pmem_fd;
+ pmem_output.offset = pParam->offset;
+ /*We should enhance OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO to store
+ * pmem source info. Hardcoding for now.*/
+ pmem_output.src = VENC_PMEM_SMI;
+ pmem_output.size = m_sOutPortDef.nBufferSize;
+ output.ptr_buffer = (unsigned char *)&pmem_output;
+
+ output.client_data = (unsigned long) pBufferHdr;
+ driverRet = DeviceIoControl(m_nFd,
+ VENC_IOCTL_CMD_FILL_OUTPUT_BUFFER,
+ &output);
+ if (driverRet)
+ {
+ QC_OMX_MSG_ERROR("failed to encode frame");
+ if (m_sCallbacks.FillBufferDone(m_hSelf,
+ m_pAppData,
+ pBufferHdr) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("FBD failed");
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_LOW("Push output buffer %p \n", pBufferHdr);
+ // this should not happen but print an error just in case
+ if (m_pOutBufferMgr->PushBuffer(pBufferHdr) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("failed to push output buffer");
+ }
+ }
+
+}
+
+void Venc::process_driver_msg(struct venc_msg* pMsg)
+{
+ /// @todo implement
+ if (pMsg != NULL)
+ {
+ switch (pMsg->msg_code)
+ {
+ case VENC_MSG_INPUT_BUFFER_DONE:
+ QC_OMX_MSG_LOW("received VENC_MSG_INPUT_BUFFER_DONE from driver");
+ process_status_input_buffer_done(&pMsg->msg_data.buf, pMsg->status_code);
+ break;
+ case VENC_MSG_OUTPUT_BUFFER_DONE:
+ QC_OMX_MSG_LOW("received VENC_MSG_OUTPUT_BUFFER_DONE from driver");
+ process_status_output_buffer_done(&pMsg->msg_data.buf, pMsg->status_code);
+ break;
+ case VENC_MSG_FLUSH:
+ QC_OMX_MSG_LOW("received VENC_MSG_FLUSH from driver");
+ process_status_flush_done(&pMsg->msg_data.flush_ret, pMsg->status_code);
+ break;
+ case VENC_MSG_START:
+ QC_OMX_MSG_LOW("received VENC_MSG_START from driver");
+ process_status_start_done(pMsg->status_code);
+ break;
+ case VENC_MSG_STOP:
+ QC_OMX_MSG_MEDIUM("received VENC_MSG_STOP from driver");
+ process_status_stop_done(pMsg->status_code);
+ break;
+ case VENC_MSG_PAUSE:
+ QC_OMX_MSG_MEDIUM("received VENC_MSG_PAUSE from driver");
+ process_status_pause_done(pMsg->status_code);
+ break;
+ case VENC_MSG_RESUME:
+ QC_OMX_MSG_MEDIUM("received VENC_MSG_RESUME from driver");
+ process_status_resume_done(pMsg->status_code);
+ break;
+ case VENC_MSG_STOP_READING_MSG: // fallthrough
+ case VENC_MSG_NEED_OUTPUT_BUFFER: // fallthrough
+ QC_OMX_MSG_ERROR("unsupported msg %d", pMsg->msg_code);
+ break;
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null msg");
+ }
+}
+
+void Venc::process_status_input_buffer_done(void* pArg, unsigned long nStatus)
+{
+ struct venc_buffer *pData = (struct venc_buffer *)pArg;
+ OMX_BUFFERHEADERTYPE* pBufferHdr;
+
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("Fill output buffer failed (%lu) \n", nStatus);
+ }
+ if (pArg == NULL)
+ {
+ QC_OMX_MSG_ERROR("Empty args from output buffer done \n");
+ }
+
+ pBufferHdr = (OMX_BUFFERHEADERTYPE*)(pData->client_data);
+
+ QC_OMX_MSG_LOW("Pop buffer %p \n", pBufferHdr);
+ if (m_pInBufferMgr->PopBuffer(pBufferHdr) == OMX_ErrorNone)
+ {
+ if (m_sCallbacks.EmptyBufferDone(m_hSelf,
+ m_pAppData,
+ pBufferHdr) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("EBD failed");
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to pop buffer");
+ }
+
+}
+void Venc::process_status_output_buffer_done(void* pArg, unsigned long nStatus)
+{
+ struct venc_buffer *pData = (struct venc_buffer *)pArg;
+ OMX_BUFFERHEADERTYPE* pBufferHdr;
+
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("Fill output buffer failed (%lu) \n", nStatus);
+ }
+
+ if (pArg == NULL)
+ {
+ QC_OMX_MSG_ERROR("Empty args from output buffer done \n");
+ }
+
+ pBufferHdr = (OMX_BUFFERHEADERTYPE*)(pData->client_data);
+ QC_OMX_MSG_LOW("Pop buffer %p \n", pBufferHdr);
+ if (m_pOutBufferMgr->PopBuffer(pBufferHdr) == OMX_ErrorNone)
+ {
+ pBufferHdr->nFilledLen = pData->len;
+ pBufferHdr->nTimeStamp = pData->time_stamp;
+ pBufferHdr->nFlags = 0;
+ if (pData->flags & VENC_FLAG_SYNC_FRAME)
+ {
+ QC_OMX_MSG_LOW("got iframe");
+ pBufferHdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+ }
+ if (pData->flags & VENC_FLAG_EOS)
+ {
+ QC_OMX_MSG_MEDIUM("got eos");
+ pBufferHdr->nFlags |= OMX_BUFFERFLAG_EOS;
+ }
+ if (pData->flags & VENC_FLAG_END_OF_FRAME)
+ {
+ pBufferHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+ }
+ if (pData->flags & VENC_FLAG_CODEC_CONFIG)
+ {
+ QC_OMX_MSG_LOW("got syntax syntax header");
+ pBufferHdr->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
+ }
+
+ QC_OMX_MSG_LOW("Before calling FillBufferDone callback \n");
+ if (m_sCallbacks.FillBufferDone(m_hSelf,
+ m_pAppData,
+ pBufferHdr) != OMX_ErrorNone)
+ {
+ QC_OMX_MSG_ERROR("FBD failed");
+ }
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("failed to pop buffer");
+ }
+}
+
+void Venc::process_status_flush_done(struct venc_buffer_flush* pData, unsigned long nStatus)
+{
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("async flush failed");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorUndefined,
+ 0,
+ NULL);
+ }
+ else
+ {
+
+ if (pData != NULL)
+ {
+ OMX_U32 portIndex = pData->flush_mode == VENC_FLUSH_INPUT ?
+ PORT_INDEX_IN : PORT_INDEX_OUT;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandFlush,
+ portIndex,
+ NULL);
+ }
+ else
+ {
+ QC_OMX_MSG_ERROR("null data");
+ }
+ }
+}
+
+void Venc::process_status_start_done(unsigned long nStatus)
+{
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("async start failed %lu", nStatus);
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorUndefined,
+ 0,
+ NULL);
+ }
+ else
+ {
+ m_eState = OMX_StateExecuting;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ NULL);
+ }
+}
+
+void Venc::process_status_stop_done(unsigned long nStatus)
+{
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("async stop failed");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorUndefined,
+ 0,
+ NULL);
+ }
+ else
+ {
+ free_q6_buffers(&m_sQ6Buffers);
+ m_eState = OMX_StateIdle;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+ }
+}
+
+void Venc::process_status_pause_done(unsigned long nStatus)
+{
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("async pause failed");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorUndefined,
+ 0,
+ NULL);
+ }
+ else
+ {
+ m_eState = OMX_StatePause;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StatePause,
+ NULL);
+ }
+}
+
+void Venc::process_status_resume_done(unsigned long nStatus)
+{
+ if (nStatus != VENC_S_SUCCESS)
+ {
+ QC_OMX_MSG_ERROR("async resume failed");
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventError,
+ OMX_ErrorUndefined,
+ 0,
+ NULL);
+ }
+ else
+ {
+ m_eState = OMX_StateExecuting;
+ m_sCallbacks.EventHandler(m_hSelf,
+ m_pAppData,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ NULL);
+ }
+}
+
+OMX_ERRORTYPE Venc::pmem_alloc(struct venc_pmem *pBuf, int size, int pmem_region_id)
+{
+ struct pmem_region region;
+
+ QC_OMX_MSG_HIGH("Opening pmem files with size 0x%x...",size);
+ if (pmem_region_id == VENC_PMEM_EBI1)
+ pBuf->fd = open("/dev/pmem_adsp", O_RDWR);
+ else if (pmem_region_id == VENC_PMEM_SMI)
+ pBuf->fd = open("/dev/pmem_smipool", O_RDWR);
+ else {
+ QC_OMX_MSG_ERROR("Pmem region id not supported \n", pmem_region_id);
+ return OMX_ErrorBadParameter;
+ }
+
+ if (pBuf->fd < 0) {
+ QC_OMX_MSG_ERROR("error could not open pmem device %d\n", pmem_region_id);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ pBuf->src = pmem_region_id;
+ pBuf->offset = 0;
+ pBuf->size = (size + 4095) & (~4095);
+
+ QC_OMX_MSG_HIGH("Allocate pmem of size:0x%x, fd:%d \n", size, pBuf->fd);
+ pBuf->virt = mmap(NULL, pBuf->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, pBuf->fd, 0);
+
+ if (pBuf->virt == MAP_FAILED) {
+ QC_OMX_MSG_ERROR("error mmap failed with size:%d \n",size);
+ close(pBuf->fd);
+ pBuf->fd = -1;
+ return OMX_ErrorInsufficientResources;
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE Venc::pmem_free(struct venc_pmem* pBuf)
+{
+ QC_OMX_MSG_HIGH("Free pmem of fd: %d, size:%d \n", pBuf->fd, pBuf->size);
+ close(pBuf->fd);
+ pBuf->fd = -1;
+ munmap(pBuf->virt, pBuf->size);
+ pBuf->offset = 0;
+ pBuf->phys = pBuf->virt = NULL;
+ return OMX_ErrorNone;
+}
diff --git a/omx/mm-video/qdsp6/venc/omx/src/OMX_Venc.def b/omx/mm-video/qdsp6/venc/omx/src/OMX_Venc.def
new file mode 100644
index 0000000..6b0d6b5
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/omx/src/OMX_Venc.def
@@ -0,0 +1,31 @@
+;--------------------------------------------------------------------------
+;Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+; the names of its contributors may be used to endorse or promote
+; products derived from this software without specific prior written
+; permission.
+
+;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+;CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+;EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+;PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+;OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+;OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+;ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;--------------------------------------------------------------------------
+
+LIBRARY QC_OMXVidEnc
+
+EXPORTS get_omx_component_factory_fn
diff --git a/omx/mm-video/qdsp6/venc/omx/src/OMX_VencBufferManager.cpp b/omx/mm-video/qdsp6/venc/omx/src/OMX_VencBufferManager.cpp
new file mode 100644
index 0000000..f889401
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/omx/src/OMX_VencBufferManager.cpp
@@ -0,0 +1,236 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Include Files
+ * -------------------------------------------------------------------------*/
+#include "OMX_VencBufferManager.h"
+#include "venc_debug.h"
+#include <stdio.h>
+#include <string.h>
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Global Data Definitions
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Static Variable Definitions
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Static Function Declarations and Definitions
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Externalized Function Definitions
+ * -------------------------------------------------------------------------*/
+
+VencBufferManager::VencBufferManager(OMX_ERRORTYPE* pResult)
+ : m_pHead(NULL),
+ m_nBuffers(0)
+{
+
+
+ if (pResult == NULL)
+ {
+ QC_OMX_MSG_ERROR("result is null");
+ return;
+ }
+ *pResult = OMX_ErrorNone;
+ (void) pthread_mutex_init(&m_mutex, NULL);
+ memset(&m_sFreeNodePool, 0, sizeof(m_sFreeNodePool));
+}
+
+VencBufferManager::~VencBufferManager()
+{
+ (void) pthread_mutex_destroy(&m_mutex);
+}
+
+OMX_ERRORTYPE
+VencBufferManager::PopBuffer(OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ Node *pSave = NULL;
+ Node *pCurr;
+ pCurr = m_pHead;
+
+ if (!pBuffer)
+ {
+ QC_OMX_MSG_ERROR("null buffer");
+ return OMX_ErrorBadParameter;
+ }
+ else if (m_pHead == NULL)
+ {
+ QC_OMX_MSG_ERROR("list is empty");
+ return OMX_ErrorUndefined;
+ }
+ else
+ {
+ pthread_mutex_lock(&m_mutex);
+ while (pCurr != NULL &&
+ pCurr->pBuffer != pBuffer)
+ {
+ pSave = pCurr;
+ pCurr = pCurr->pNext;
+ }
+
+ if (pCurr && pCurr->pBuffer == pBuffer)
+ {
+ if (pCurr == m_pHead)
+ {
+ pCurr = pCurr->pNext;
+ FreeNode(m_pHead);
+ m_pHead = pCurr;
+ }
+ else
+ {
+ pSave->pNext = pCurr->pNext;
+ FreeNode(pCurr);
+ }
+ --m_nBuffers;
+ pthread_mutex_unlock(&m_mutex);
+
+ return OMX_ErrorNone;
+ }
+ else
+ {
+ pthread_mutex_unlock(&m_mutex);
+ QC_OMX_MSG_ERROR("error here");
+ return OMX_ErrorUndefined;
+ }
+ }
+}
+
+OMX_ERRORTYPE
+VencBufferManager::PopFirstBuffer(OMX_BUFFERHEADERTYPE** ppBuffer)
+{
+ if (!ppBuffer)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ else
+ {
+ pthread_mutex_lock(&m_mutex);
+ if (m_pHead)
+ {
+ OMX_ERRORTYPE result;
+ result = PopBuffer(m_pHead->pBuffer);
+ *ppBuffer = m_pHead->pBuffer;
+ pthread_mutex_unlock(&m_mutex);
+ return result;
+ }
+ pthread_mutex_unlock(&m_mutex);
+ QC_OMX_MSG_ERROR("list is empty");
+ return OMX_ErrorUndefined;
+ }
+}
+
+OMX_ERRORTYPE
+VencBufferManager::PushBuffer(OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ Node *pSave;
+ Node *pCurr;
+ Node *pTemp;
+
+ pthread_mutex_lock(&m_mutex);
+ pTemp = AllocNode();
+ if (!pTemp)
+ {
+ pthread_mutex_unlock(&m_mutex);
+ QC_OMX_MSG_ERROR("no more buffers to allocate");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ pTemp->pBuffer = pBuffer;
+ pTemp->pNext = NULL;
+
+ if (m_pHead == NULL)
+ {
+ m_pHead = pTemp;
+ }
+ else
+ {
+ pCurr = m_pHead;
+ while (pCurr != NULL)
+ {
+ pSave = pCurr;
+ pCurr = pCurr->pNext;
+ }
+ pSave->pNext = pTemp;
+ }
+ m_nBuffers++;
+
+ pthread_mutex_unlock(&m_mutex);
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE
+VencBufferManager::GetNumBuffers(OMX_U32* pnBuffers)
+{
+ if (!pnBuffers)
+ return OMX_ErrorBadParameter;
+
+ *pnBuffers = m_nBuffers;
+ return OMX_ErrorNone;
+}
+
+VencBufferManager::Node*
+VencBufferManager::AllocNode()
+{
+ for (int i = 0; i < MAX_FREE_BUFFERS; i++)
+ {
+ if (m_sFreeNodePool[i].pBuffer == NULL)
+ {
+ return &m_sFreeNodePool[i];
+ }
+ }
+ return NULL;
+}
+
+void
+VencBufferManager:: FreeNode(Node* pNode)
+{
+ for (int i = 0; i < MAX_FREE_BUFFERS; i++)
+ {
+ if (pNode == &m_sFreeNodePool[i])
+ {
+ pNode->pBuffer = NULL;
+ pNode->pNext = NULL;
+ return;
+ }
+ }
+
+ QC_OMX_MSG_ERROR("invalid buffer"); // will never happen by nature of calling function
+}
diff --git a/omx/mm-video/qdsp6/venc/omx/src/OMX_VencBufferManager.h b/omx/mm-video/qdsp6/venc/omx/src/OMX_VencBufferManager.h
new file mode 100644
index 0000000..90477ba
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/omx/src/OMX_VencBufferManager.h
@@ -0,0 +1,103 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef OMX_VENC_BUFFER_MANAGER_H
+#define OMX_VENC_BUFFER_MANAGER_H
+
+/*----------------------------------------------------------------------------
+ * Include Files
+ * -------------------------------------------------------------------------*/
+#include <pthread.h>
+#include "OMX_Core.h"
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ * Class Definitions
+ ---------------------------------------------------------------------------*/
+
+/// Buffer manager class
+class VencBufferManager
+{
+ public:
+ /// Constructor
+ VencBufferManager(OMX_ERRORTYPE* pResult);
+ /// Destructor
+ ~VencBufferManager();
+ /// Pops the specified buffer
+ OMX_ERRORTYPE PopBuffer(OMX_BUFFERHEADERTYPE* pBuffer);
+ /// Pops the first buffer in the list
+ OMX_ERRORTYPE PopFirstBuffer(OMX_BUFFERHEADERTYPE** ppBuffer);
+ /// Pushes a buffer in the list
+ OMX_ERRORTYPE PushBuffer(OMX_BUFFERHEADERTYPE* pBuffer);
+ /// Get the number of buffers in the list
+ OMX_ERRORTYPE GetNumBuffers(OMX_U32* pnBuffers);
+
+ private:
+ /// List node
+ struct Node
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ Node* pNext;
+ };
+
+ private:
+ /// Default constructor unallowed
+ VencBufferManager() {}
+
+ /// Allocate node from free node pool
+ Node* AllocNode();
+
+ /// Put node back in the free node pool
+ void FreeNode(Node* pNode);
+
+ private:
+
+ /// head of list
+ Node * m_pHead;
+
+ /// number of buffers in list
+ int m_nBuffers;
+
+ // max buffer number assumption
+ static const int MAX_FREE_BUFFERS = 50;
+
+ /// free node pool
+ Node m_sFreeNodePool[MAX_FREE_BUFFERS];
+
+ /// mutex for the list
+ pthread_mutex_t m_mutex;
+};
+
+#endif // #ifndef OMX_VENC_DEVICE_CALLBACK_H
diff --git a/omx/mm-video/qdsp6/venc/omx/src/OMX_VencMsgQ.h b/omx/mm-video/qdsp6/venc/omx/src/OMX_VencMsgQ.h
new file mode 100644
index 0000000..0b18d54
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/omx/src/OMX_VencMsgQ.h
@@ -0,0 +1,190 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef OMX_VENC_MSG_Q_H
+#define OMX_VENC_MSG_Q_H
+
+/*----------------------------------------------------------------------------
+ * Include Files
+ * -------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "OMX_Core.h"
+#include "venc_debug.h"
+#include <linux/msm_q6venc.h>
+
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ * Class Definitions
+ ---------------------------------------------------------------------------*/
+
+///@todo document
+class VencMsgQ
+{
+ public:
+ /// max size for component thread message queue
+ static const int MAX_MSG_QUEUE_SIZE = 50;
+
+ /// Ids for thread messages
+ enum MsgIdType
+ {
+ MSG_ID_EXIT, ///< Thread exit command
+ MSG_ID_STATE_CHANGE, ///< State change command
+ MSG_ID_FLUSH, ///< Flush command
+ MSG_ID_PORT_DISABLE, ///< Port disable command
+ MSG_ID_PORT_ENABLE, ///< Port enable command
+ MSG_ID_MARK_BUFFER, ///< Mark buffer command
+ MSG_ID_EMPTY_BUFFER, ///< Empty buffer
+ MSG_ID_FILL_BUFFER, ///< Fill buffer
+ MSG_ID_DRIVER_MSG ///< Async driver status msg
+ };
+
+ /// Data for thread messages
+ union MsgDataType
+ {
+ OMX_STATETYPE eState; ///< State associated with MSG_ID_STATE_CHANGE
+ OMX_U32 nPortIndex; ///< Port index for MSG_ID_FLUSH,
+ ///< MSG_ID_PORT_ENABLE
+ ///< MSG_ID_PORT_DISABLE
+
+ /// anonymous structure for MSG_ID_MARK_BUFFER
+ struct
+ {
+ OMX_U32 nPortIndex; ///< Corresponding port for command
+ OMX_MARKTYPE sMarkData; ///< Mark data structure
+ } sMarkBuffer;
+
+ OMX_BUFFERHEADERTYPE* pBuffer; ///< For MSG_ID_EMPTY_BUFFER and MSG_ID_FILL_BUFFER
+
+ ///
+ struct venc_msg sDriverMsg;
+ };
+
+ /// Msgs for component thread
+ struct MsgType
+ {
+ MsgIdType id; ///< message id
+ MsgDataType data; ///< message data
+ };
+
+ public:
+
+ VencMsgQ() :
+ m_nHead(0),
+ m_nSize(0)
+ {
+ memset(m_aMsgQ, 0, sizeof(MsgType) * MAX_MSG_QUEUE_SIZE);
+ (void) pthread_mutex_init(&m_mutex, NULL);
+ (void) pthread_cond_init(&m_signal, NULL);
+ }
+
+ ~VencMsgQ()
+ {
+ (void) pthread_mutex_destroy(&m_mutex);
+ (void) pthread_cond_destroy(&m_signal);
+ }
+
+ OMX_ERRORTYPE PushMsg(MsgIdType eMsgId,
+ const MsgDataType* pMsgData)
+ {
+ QC_OMX_MSG_LOW("pushing msg...", 0, 0, 0);
+ pthread_mutex_lock(&m_mutex);
+ // find the tail of the queue
+ int idx = (m_nHead + m_nSize) % MAX_MSG_QUEUE_SIZE;
+
+ if (m_nSize >= MAX_MSG_QUEUE_SIZE)
+ {
+ QC_OMX_MSG_ERROR("msg q is full...");
+ pthread_mutex_unlock(&m_mutex);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ // put data at tail of queue
+ if (pMsgData != NULL)
+ {
+ memcpy(&m_aMsgQ[idx].data, pMsgData, sizeof(MsgDataType));
+ }
+ m_aMsgQ[idx].id = eMsgId;
+
+ // update queue size
+ m_nSize++;
+
+ QC_OMX_MSG_LOW("push msg after size: %d", m_nSize, 0, 0);
+ // unlock queue
+ pthread_cond_signal(&m_signal);
+ pthread_mutex_unlock(&m_mutex);
+ // signal the component thread
+ // pthread_cond_signal(&m_signal);
+ QC_OMX_MSG_LOW("push msg done", 0, 0, 0);
+ return OMX_ErrorNone;
+ }
+
+ OMX_ERRORTYPE PopMsg(MsgType* pMsg)
+ {
+ // listen for a message...
+ QC_OMX_MSG_LOW("waiting for msg", 0, 0, 0);
+ pthread_mutex_lock(&m_mutex);
+
+ while (m_nSize == 0)
+ {
+ pthread_cond_wait(&m_signal, &m_mutex);
+ }
+ QC_OMX_MSG_LOW("got & copy msg", 0, 0, 0);
+
+ // get msg at head of queue
+ memcpy(pMsg, &m_aMsgQ[m_nHead], sizeof(MsgType));
+
+ // pop message off the queue
+ m_nHead = (m_nHead + 1) % MAX_MSG_QUEUE_SIZE;
+ m_nSize--;
+ QC_OMX_MSG_LOW("pop msg after size: %d", m_nSize, 0, 0);
+ pthread_mutex_unlock(&m_mutex);
+ QC_OMX_MSG_LOW("PopMsg done", 0, 0, 0);
+ return OMX_ErrorNone;
+ }
+
+ private:
+
+ MsgType m_aMsgQ[MAX_MSG_QUEUE_SIZE]; ///< queue data
+ int m_nHead; ///< head of the queue
+ int m_nSize; ///< size of the queue
+
+ pthread_mutex_t m_mutex; ///< message q lock
+ pthread_cond_t m_signal; ///< message q data available signal
+};
+#endif // #ifndef OMX_VENC_MSG_Q_H
diff --git a/omx/mm-video/qdsp6/venc/test/app/src/venctest_App.cpp b/omx/mm-video/qdsp6/venc/test/app/src/venctest_App.cpp
new file mode 100644
index 0000000..f844515
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/app/src/venctest_App.cpp
@@ -0,0 +1,193 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "venctest_Script.h"
+#include "venctest_Debug.h"
+#include "venctest_ComDef.h"
+#include "venctest_ITestCase.h"
+#include "venctest_TestCaseFactory.h"
+
+void RunScript(OMX_STRING pScriptFile)
+{
+ OMX_S32 nPass = 0;
+ OMX_S32 nFail = 0;
+ OMX_S32 nTestCase = 0;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+
+ printf("Start in RunScript \n");
+
+ venctest::Script script;
+ script.Configure(pScriptFile);
+
+ printf("Done config script file \n");
+
+ if (result == OMX_ErrorNone)
+ {
+ venctest::TestDescriptionType testDescription;
+ do
+ {
+ result = script.NextTest(&testDescription);
+
+ printf("Finish NextTest with name %s\n", testDescription.cTestName);
+ if (result == OMX_ErrorNone)
+ {
+ for (OMX_S32 i = 0; i < testDescription.nSession; i++)
+ {
+ venctest::ITestCase* pTest =
+ venctest::TestCaseFactory::AllocTest((OMX_STRING) testDescription.cTestName);
+
+ printf("Before Running test \n");
+ if (pTest != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Running test %ld", nPass + nFail);
+ result = pTest->Start(testDescription.cConfigFile, i);
+
+ printf("After running test \n");
+ if (result == OMX_ErrorNone)
+ {
+ result = pTest->Finish();
+ if (result == OMX_ErrorNone)
+ {
+ ++nPass;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("test %ld failed", nPass + nFail);
+ ++nFail;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("error starting test");
+ ++nFail;
+ }
+
+ (void) venctest::TestCaseFactory::DestroyTest(pTest);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("unable to alloc test");
+ }
+
+ }
+ }
+ else if (result != OMX_ErrorNoMore)
+ {
+ VENC_TEST_MSG_ERROR("error parsing script");
+ }
+
+ } while (result != OMX_ErrorNoMore);
+ }
+
+ VENC_TEST_MSG_HIGH("passed %ld out of %ld tests", nPass, nPass + nFail);
+
+}
+
+void RunTest(OMX_STRING pTestName,
+ OMX_STRING pConfigFile,
+ OMX_S32 nSession)
+{
+ OMX_S32 nPass = 0;
+ OMX_S32 nFail = 0;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ for (OMX_S32 i = 0; i < nSession; i++)
+ {
+ venctest::ITestCase* pTest =
+ venctest::TestCaseFactory::AllocTest((OMX_STRING) pTestName);
+
+ if (pTest != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Running test %ld", nPass + nFail);
+ result = pTest->Start(pConfigFile, i);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = pTest->Finish();
+ if (result == OMX_ErrorNone)
+ {
+ ++nPass;
+ }
+ else
+ {
+ ++nFail;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("error starting test");
+ }
+
+ (void) venctest::TestCaseFactory::DestroyTest(pTest);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("unable to alloc test");
+ }
+ }
+
+ VENC_TEST_MSG_HIGH("passed %ld out of %ld tests", nPass, nPass + nFail);
+}
+
+int main(int argc, char* argv[])
+{
+ OMX_Init();
+
+ if (argc == 2)
+ {
+ OMX_STRING pScriptFile = (OMX_STRING) argv[1];
+
+ RunScript(pScriptFile);
+ }
+ else if (argc == 4)
+ {
+ OMX_STRING pTestName = (OMX_STRING) argv[1];
+ OMX_STRING pConfigFile = (OMX_STRING) argv[2];
+ OMX_STRING pNumSession = (OMX_STRING) argv[3];
+ OMX_S32 nSession;
+
+ nSession = atoi((char*) pNumSession);
+
+ RunTest(pTestName, pConfigFile, nSession);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("invalid number of command args %d", argc);
+ VENC_TEST_MSG_ERROR("./mm-venc-omx-test ENCODE Config.cfg 1");
+ }
+
+ OMX_Deinit();
+}
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_ComDef.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_ComDef.h
new file mode 100644
index 0000000..d5cce04
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_ComDef.h
@@ -0,0 +1,128 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_COMDEF_H
+#define _VENC_TEST_COMDEF_H
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "OMX_Video.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Maximum length for a file name
+ */
+ static const OMX_S32 VENC_TEST_MAX_STRING = 128;
+
+ /**
+ * @brief Resync marker types
+ */
+ enum ResyncMarkerType
+ {
+ RESYNC_MARKER_NONE, ///< No resync marker
+ RESYNC_MARKER_BITS, ///< Resync marker for MPEG4, H.264, and H.263 annex K
+ RESYNC_MARKER_MB, ///< MB resync marker for MPEG4, H.264, and H.263 annex K
+ RESYNC_MARKER_GOB ///< GOB resync marker for H.263
+ };
+
+ /**
+ * @brief Encoder configuration
+ */
+ struct EncoderConfigType
+ {
+ ////////////////////////////////////////
+ //======== Common static config
+ OMX_VIDEO_CODINGTYPE eCodec; ///< Config File Key: Codec
+ OMX_VIDEO_CONTROLRATETYPE eControlRate; ///< Config File Key: RC
+ OMX_S32 nResyncMarkerSpacing; ///< Config File Key: ResyncMarkerSpacing
+ ResyncMarkerType eResyncMarkerType; ///< Config File Key: ResyncMarkerType
+ OMX_BOOL bEnableIntraRefresh; ///< Config File Key: EnableIntraRefresh
+ OMX_S32 nFrameWidth; ///< Config File Key: FrameWidth
+ OMX_S32 nFrameHeight; ///< Config File Key: FrameHeight
+ OMX_S32 nOutputFrameWidth; ///< Config File Key: OutputFrameWidth
+ OMX_S32 nOutputFrameHeight; ///< Config File Key: OutputFrameHeight
+ OMX_S32 nDVSXOffset; ///< Config File Key: DVSXOffset
+ OMX_S32 nDVSYOffset; ///< Config File Key: DVSYOffset
+ OMX_S32 nBitrate; ///< Config File Key: Bitrate
+ OMX_S32 nFramerate; ///< Config File Key: FPS
+ OMX_S32 nRotation; ///< Config File Key: Rotation
+ OMX_S32 nInBufferCount; ///< Config File Key: InBufferCount
+ OMX_S32 nOutBufferCount; ///< Config File Key: OutBufferCount
+ char cInFileName[VENC_TEST_MAX_STRING]; ///< Config File Key: InFile
+ char cOutFileName[VENC_TEST_MAX_STRING]; ///< Config File Key: OutFile
+ OMX_S32 nFrames; ///< Config File Key: NumFrames
+ OMX_S32 nIntraPeriod; ///< Config File Key: IntraPeriod
+ OMX_S32 nMinQp; ///< Config File Key: MinQp
+ OMX_S32 nMaxQp; ///< Config File Key: MaxQp
+ OMX_BOOL bProfileMode; ///< Config File Key: ProfileMode
+
+ ////////////////////////////////////////
+ //======== Mpeg4 static config
+ OMX_S32 nHECInterval; ///< Config File Key: HECInterval
+ OMX_S32 nTimeIncRes; ///< Config File Key: TimeIncRes
+ OMX_BOOL bEnableShortHeader; ///< Config File Key: EnableShortHeader
+
+ ////////////////////////////////////////
+ //======== H.263 static config
+
+ OMX_BOOL bInUseBuffer;
+ OMX_BOOL bOutUseBuffer;
+
+ };
+
+ /**
+ * @brief Dynamic configuration
+ */
+ struct DynamicConfigType
+ {
+ OMX_S32 nIFrameRequestPeriod; ///< Config File Key: IFrameRequestPeriod
+ OMX_S32 nUpdatedFramerate; ///< Config File Key: UpdatedFPS
+ OMX_S32 nUpdatedBitrate; ///< Config File Key: UpdatedBitrate
+ OMX_S32 nUpdatedMinQp; ///< Config File Key: MinQp
+ OMX_S32 nUpdatedMaxQp; ///< Config File Key: MaxQp
+ OMX_S32 nUpdatedFrames; ///< Config File Key: UpdatedNumFrames
+ OMX_S32 nUpdatedIntraPeriod; ///< Config File Key: UpdatedIntraPeriod
+ };
+
+ /**
+ * @brief Test description structure
+ */
+ struct TestDescriptionType
+ {
+ char cTestName[VENC_TEST_MAX_STRING]; ///< The name of the test
+ char cConfigFile[VENC_TEST_MAX_STRING]; ///< Encoder config file name
+ OMX_S32 nSession; ///< Number of sessions to run
+ };
+}
+
+#endif // #ifndef _VENC_TEST_COMDEF_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Config.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Config.h
new file mode 100644
index 0000000..e8f3a3e
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Config.h
@@ -0,0 +1,93 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_CONFIG_H
+#define _VENC_TEST_CONFIG_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ComDef.h"
+
+
+namespace venctest
+{
+ class File; // forward declaration
+
+ /**
+ * @brief Class for configuring video encoder and video encoder test cases
+ */
+ class Config
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ Config();
+
+ /**
+ * @brief Destructor
+ */
+ ~Config();
+
+ /**
+ * @brief Parses the config file obtaining the configuration
+ *
+ * @param pFileName The name of the config file
+ * @param pEncoderConfig The encoder config.
+ * @param pDynamicConfig The dynamic encoder config. Optional (NULL is valid).
+ */
+ OMX_ERRORTYPE Parse(OMX_STRING pFileName,
+ EncoderConfigType* pEncoderConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ /**
+ * @brief Gets the current or default encoder configuration.
+ *
+ * @param pEncoderConfig The configuration
+ */
+ OMX_ERRORTYPE GetEncoderConfig(EncoderConfigType* pEncoderConfig);
+
+ /**
+ * @brief Gets the current or default dynamic encoder configuration.
+ *
+ * @param pDynamicConfig The configuration
+ */
+ OMX_ERRORTYPE GetDynamicConfig(DynamicConfigType* pDynamicConfig);
+
+ private:
+ EncoderConfigType m_sEncoderConfig;
+ DynamicConfigType m_sDynamicConfig;
+ };
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_CONFIG_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Debug.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Debug.h
new file mode 100644
index 0000000..735b0c9
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Debug.h
@@ -0,0 +1,81 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_DEBUG_H
+#define _VENC_TEST_DEBUG_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include <stdio.h>
+#include <string.h>
+
+#define LOG_NDEBUG 0
+
+#ifdef _ANDROID_LOG_
+#ifndef LOG_TAG
+#define LOG_TAG "VENC_TEST"
+#include <utils/Log.h>
+#endif
+
+#define VENC_TEST_MSG_HIGH(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_PROFILE(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_ERROR(fmt, ...) LOGE("VENC_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__, ## __VA_ARGS__)
+#define VENC_TEST_MSG_FATAL(fmt, ...) LOGE("VENC_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+
+// #ifdef _ANDROID_LOG_DEBUG
+#if 1
+#define VENC_TEST_MSG_LOW(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_MEDIUM(fmt, ...) LOGE("%s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#else
+#define VENC_TEST_MSG_LOW(fmt, ...)
+#define VENC_TEST_MSG_MEDIUM(fmt, ...)
+#endif
+
+#else
+
+#define VENC_TEST_REMOVE_SLASH(x) strrchr(x, '/') != NULL ? strrchr(x, '/') + 1 : x
+
+#define VENC_TEST_MSG_HIGH(fmt, ...) fprintf(stderr, "VENC_TEST_HIGH %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_PROFILE(fmt, ...) fprintf(stderr, "VENC_TEST_PROFILE %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_ERROR(fmt, ...) fprintf(stderr, "VENC_TEST_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_FATAL(fmt, ...) fprintf(stderr, "VENC_TEST_ERROR %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+
+#ifdef VENC_MSG_LOG_DEBUG
+#define VENC_TEST_MSG_LOW(fmt, ...) fprintf(stderr, "VENC_TEST_LOW %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#define VENC_TEST_MSG_MEDIUM(fmt, ...) fprintf(stderr, "VENC_TEST_MEDIUM %s::%d "fmt"\n",__FUNCTION__, __LINE__,## __VA_ARGS__)
+#else
+#define VENC_TEST_MSG_LOW(fmt, ...)
+#define VENC_TEST_MSG_MEDIUM(fmt, ...)
+#endif
+
+#endif //#ifdef _ANDROID_LOG_
+
+#endif // #ifndef _VENC_TEST_DEBUG_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Encoder.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Encoder.h
new file mode 100644
index 0000000..bac0d47
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Encoder.h
@@ -0,0 +1,296 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_ENCODER_H
+#define _VENC_TEST_ENCODER_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ComDef.h"
+#include "qc_omx_common.h"
+
+namespace venctest
+{
+
+ class Signal; // forward declaration
+ class Pmem; // forward declaration
+ class SignalQueue; // forward declaration
+ class StatsThread; // forward declaration
+
+ class Encoder
+ {
+ public:
+
+ /**
+ * @brief Event cb type. Refer to OMX IL spec for param details.
+ */
+ typedef OMX_ERRORTYPE (*EventCallbackType)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+ /**
+ * @brief Empty buffer done cb type. Refer to OMX IL spec for param details.
+ */
+ typedef OMX_ERRORTYPE (*EmptyDoneCallbackType)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**
+ * @brief Fill buffer done cb type. Refer to OMX IL spec for param details.
+ */
+ typedef OMX_ERRORTYPE (*FillDoneCallbackType)(
+ OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+ public:
+
+ /**
+ * @brief Constructor
+ *
+ * @param pEmptyDoneFn Empty buffer done callback. Refer to OMX IL spec
+ * @param pFillDoneFn Fill buffer done callback. Refer to OMX IL spec
+ * @param pAppData Client data passed to buffer and event callbacks
+ * @param eCodec The codec
+ */
+ Encoder(EmptyDoneCallbackType pEmptyDoneFn,
+ FillDoneCallbackType pFillDoneFn,
+ OMX_PTR pAppData,
+ OMX_VIDEO_CODINGTYPE eCodec);
+
+ /**
+ * @brief Destructor
+ */
+ ~Encoder();
+
+ private:
+
+ /**
+ * @brief Private default constructor. Use public constructor.
+ */
+ Encoder();
+
+
+ public:
+
+ ///////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////
+ // Init time methods
+ ///////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////
+
+ /**
+ * @brief Configure the encoder
+ *
+ * @param pConfig The encoder configuration
+ */
+ OMX_ERRORTYPE Configure(EncoderConfigType* pConfig);
+
+ /**
+ * @brief Enables OMX_UseBuffer allocation scheme. Default is OMX_AllocateBuffer.
+ *
+ * @param bUseBuffer Set to OMX_TRUE for OMX_UseBuffer model
+ */
+ OMX_ERRORTYPE EnableUseBufferModel(OMX_BOOL bInUseBuffer, OMX_BOOL bOutUseBuffer);
+
+ /**
+ * @brief Synchronously transitions the encoder to OMX_StateExecuting.
+ *
+ * Only valid in OMX_StateLoaded;
+ */
+ OMX_ERRORTYPE GoToExecutingState();
+
+ /**
+ * @brief Get the out of band syntax header
+ *
+ * Only valid in OMX_StateLoaded;
+ */
+ OMX_ERRORTYPE GetOutOfBandSyntaxHeader(OMX_U8* pSyntaxHdr,
+ OMX_S32 nSyntaxHdrLen,
+ OMX_S32* pSyntaxHdrFilledLen);
+
+ ///////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////
+ // Run time methods
+ ///////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////
+
+ /**
+ * @brief Synchronously transitions the encoder to OMX_StateLoaded.
+ *
+ * Only valid in OMX_StateExecuting;
+ */
+ OMX_ERRORTYPE GoToLoadedState();
+
+ /**
+ * @brief Deliver an input (yuv) buffer to the encoder.
+ *
+ * @param pBuffer The populated input buffer.
+ */
+ OMX_ERRORTYPE DeliverInput(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**
+ * @brief Deliver an output (bitstream) buffer to the encoder.
+ *
+ * @param pBuffer The un-populated output buffer.
+ */
+ OMX_ERRORTYPE DeliverOutput(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**
+ * @brief Get array of input or output buffer pointers header.
+ *
+ * Only valid in the executing state after all buffers have been allocated.
+ *
+ * @param bIsInput Set to OMX_TRUE for input OMX_FALSE for output.
+ * @return NULL upon failure, array of buffer header pointers otherwise.
+ */
+ OMX_BUFFERHEADERTYPE** GetBuffers(OMX_BOOL bIsInput);
+
+ /**
+ * @brief Request for an iframe to be generated.
+ */
+ OMX_ERRORTYPE RequestIntraVOP();
+
+ /**
+ * @brief Set the intra period. It is valid to change this configuration at run-time
+ *
+ * @param nIntraPeriod The iframe interval in units of frames
+ */
+ OMX_ERRORTYPE SetIntraPeriod(OMX_S32 nIntraPeriod);
+
+ /**
+ * @brief Change the encoding quality
+ *
+ * @param nFramerate The updated frame rate
+ * @param nBitrate The updated bitrate
+ * @param nMinQp The updated min qp
+ * @param nMaxQp The updated max qp
+ */
+ OMX_ERRORTYPE ChangeQuality(OMX_S32 nFramerate,
+ OMX_S32 nBitrate,
+ OMX_S32 nMinQp,
+ OMX_S32 nMaxQp);
+
+ /**
+ * @brief Set the encoder state
+ *
+ * This method can be asynchronous or synchronous. If asynchonous,
+ * WaitState can be called to wait for the corresponding state
+ * transition to complete.
+ *
+ * @param eState The state to enter
+ * @param bSynchronous If OMX_TRUE, synchronously wait for the state transition to complete
+ */
+ OMX_ERRORTYPE SetState(OMX_STATETYPE eState,
+ OMX_BOOL bSynchronous);
+
+ /**
+ * @brief Wait for the corresponding state transition to complete
+ *
+ * @param eState The state to wait for
+ */
+ OMX_ERRORTYPE WaitState(OMX_STATETYPE eState);
+
+ /**
+ * @brief Allocate all input and output buffers
+ */
+ OMX_ERRORTYPE AllocateBuffers();
+
+ /**
+ * @brief Free all input and output buffers
+ */
+ OMX_ERRORTYPE FreeBuffers();
+
+ /**
+ * @brief Flush the encoder
+ */
+ OMX_ERRORTYPE Flush();
+
+ private:
+
+ static OMX_ERRORTYPE EventCallback(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+ static OMX_ERRORTYPE EmptyDoneCallback(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FillDoneCallback(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ SignalQueue* m_pSignalQueue;
+ Pmem* m_pInMem;
+ Pmem* m_pOutMem;
+ StatsThread* m_pStats;
+ EncoderConfigType m_sConfig;
+ EventCallbackType m_pEventFn;
+ EmptyDoneCallbackType m_pEmptyDoneFn;
+ FillDoneCallbackType m_pFillDoneFn;
+ OMX_PTR m_pAppData;
+ OMX_BOOL m_bInUseBuffer;
+ OMX_BOOL m_bOutUseBuffer;
+ OMX_BUFFERHEADERTYPE** m_pInputBuffers;
+ OMX_BUFFERHEADERTYPE** m_pOutputBuffers;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *m_pInBufPvtList;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *m_pInBufPmemInfo;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *m_pInBufPvtEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *m_pOutBufPvtList;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *m_pOutBufPmemInfo;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *m_pOutBufPvtEntry;
+ OMX_HANDLETYPE m_hEncoder;
+ OMX_STATETYPE m_eState;
+ OMX_S32 m_nInputBuffers;
+ OMX_S32 m_nOutputBuffers;
+ OMX_S32 m_nInputBufferSize;
+ OMX_S32 m_nOutputBufferSize;
+ OMX_VIDEO_CODINGTYPE m_eCodec;
+ OMX_S32 m_nInFrameIn;
+ OMX_S32 m_nOutFrameIn;
+ OMX_S32 m_nInFrameOut;
+ OMX_S32 m_nOutFrameOut;
+
+
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_ENCODER_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_File.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_File.h
new file mode 100644
index 0000000..09b294e
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_File.h
@@ -0,0 +1,107 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_FILE_H
+#define _VENC_TEST_FILE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Class for reading from and writing to files
+ */
+ class File
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ File();
+
+ /**
+ * @brief Destructor
+ */
+ ~File();
+
+ /**
+ * @brief Opens the file in read or write mode
+ *
+ * @param pFileName The name of the file
+ * @param bReadOnly Set to OMX_TRUE for read access, OMX_FALSE for write access.
+ */
+ OMX_ERRORTYPE Open(OMX_STRING pFileName,
+ OMX_BOOL bReadOnly);
+
+ /**
+ * @brief Reads the file. Only valid in read mode.
+ *
+ * @param pBuffer The buffer to read into
+ * @param nBytes The number of bytes to read
+ * @param pBytesRead The number of bytes actually read (output)
+ */
+ OMX_ERRORTYPE Read(OMX_U8* pBuffer,
+ OMX_S32 nBytes,
+ OMX_S32* pBytesRead);
+
+ /**
+ * @brief Writes to the file. Only valid in write mode.
+ *
+ * @param pBuffer The buffer to write from
+ * @param nBytes The number of bytes to write
+ * @param pBytesWritten The number of bytes actually written (output)
+ */
+ OMX_ERRORTYPE Write(OMX_U8* pBuffer,
+ OMX_U32 nBytes,
+ OMX_U32* pBytesWritten);
+
+ /**
+ * @brief Reposition the file pointer.
+ *
+ * @param nBytes The number of bytes from the start of file
+ */
+ OMX_ERRORTYPE SeekStart(OMX_S32 nBytes);
+
+ /**
+ * @brief Closes the file
+ */
+ OMX_ERRORTYPE Close();
+ private:
+ void* m_pFile;
+ OMX_BOOL m_bReadOnly;
+ };
+}
+
+#endif // #ifndef _VENC_TEST_FILE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_FileSink.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_FileSink.h
new file mode 100644
index 0000000..b7924bd
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_FileSink.h
@@ -0,0 +1,120 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_FILE_SINK_H
+#define _VENC_TEST_FILE_SINK_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ class SignalQueue; // forward declaration
+
+ /**
+ * @brief Writes encoded bitstream to file.
+ *
+ * Frames are written to file asynchronously as they are delivered.
+ */
+ class FileSink
+ {
+ public:
+
+ /**
+ * @brief Frame callback for bitstream buffer release
+ */
+ typedef void (*FrameReleaseFnType) (OMX_BUFFERHEADERTYPE* pBuffer);
+
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ FileSink();
+
+ /**
+ * @brief Destructor
+ */
+ ~FileSink();
+
+ public:
+
+ /**
+ * @brief Configure the file writer
+ *
+ * @param nFrames The number of frames to write. Thread exits when nFrames are written.
+ * @param pFileName The name of the output file. Specify NULL for no file I/O.
+ * @param nTestNum The test number
+ * @param pFrameReleaseFn The callback to invoke when after frames are written
+ */
+ OMX_ERRORTYPE Configure(OMX_S32 nFrames,
+ OMX_STRING pFileName,
+ OMX_S32 nTestNum,
+ FrameReleaseFnType pFrameReleaseFn);
+
+ /**
+ * @brief Asynchronously write an encoded frame to file.
+ *
+ * @param pBuffer The frame to write.
+ */
+ OMX_ERRORTYPE Write(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**
+ * @brief Starts the writer thread.
+ *
+ */
+ OMX_ERRORTYPE Start();
+
+ /**
+ * @brief Wait for writer thread to finish.
+ *
+ * Function will block until the Sink has received and written all frames.
+ */
+ OMX_ERRORTYPE Finish();
+
+ private:
+ static OMX_ERRORTYPE SinkThreadEntry(OMX_PTR pThreadData);
+ OMX_ERRORTYPE SinkThread();
+
+ private:
+ OMX_S32 m_nFrames;
+ File* m_pFile;
+ SignalQueue* m_pBufferQueue;
+ Thread* m_pThread;
+ OMX_BOOL m_bStarted;
+ FrameReleaseFnType m_pFrameReleaseFn;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_FILE_SINK_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_FileSource.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_FileSource.h
new file mode 100644
index 0000000..9bc0ce2
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_FileSource.h
@@ -0,0 +1,177 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_FILE_SOURCE_H
+#define _VENC_TEST_FILE_SOURCE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+ class File; // forward declaration
+ class SignalQueue; // forward declaration
+ class Thread; // forward declaration
+
+ /**
+ * @brief Delivers YUV data in two different modes.
+ *
+ * In live mode, buffers are pre-populated with YUV data at the time
+ * of configuration. The source will loop through and deliver the
+ * pre-populated buffers throughout the life of the session. Frames will be
+ * delivered at the configured frame rate. This mode is useful for gathering
+ * performance statistics as no file reads are performed at run-time.
+ *
+ * In non-live mode, buffers are populated with YUV data at run time.
+ * Buffers are delivered downstream as they become available. Timestamps
+ * are based on the configured frame rate, not on the system clock.
+ *
+ */
+ class FileSource
+ {
+ public:
+
+ /**
+ * @brief Frame callback for YUV buffer deliver
+ */
+ typedef void (*FrameDeliveryFnType) (OMX_BUFFERHEADERTYPE* pBuffer);
+
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ FileSource();
+
+ /**
+ * @brief Destructor
+ */
+ ~FileSource();
+
+ public:
+
+ /**
+ * @brief Configures the source
+ *
+ * @param nFrames The number of frames to to play.
+ * @param nFramerate The frame rate to emulate.
+ * @param nFrameWidth The frame width.
+ * @param nFrameHeight The frame height.
+ * @param nBuffers The number of buffers allocated for the session.
+ * @param pFrameDeliverFn Frame delivery callback.
+ * @param pFileName Name of the file to read from
+ * @param nDVSXOffset Smaller frame pixel offset in the x direction
+ * @param nDVSYOffset Smaller frame pixel offset in the y direction
+ * @param bEnableLiveMode If true will encode in real time.
+ */
+ OMX_ERRORTYPE Configure(OMX_S32 nFrames,
+ OMX_S32 nFramerate,
+ OMX_S32 nFrameWidth,
+ OMX_S32 nFrameHeight,
+ OMX_S32 nBuffers,
+ FrameDeliveryFnType pFrameDeliverFn,
+ OMX_STRING pFileName,
+ OMX_S32 nDVSXOffset,
+ OMX_S32 nDVSYOffset,
+ OMX_BOOL bLiveMode);
+
+ /**
+ * @brief Changes the frame rate
+ *
+ * The frame rate will take effect immediately.
+ *
+ * @param nFramerate The new frame rate.
+ */
+ OMX_ERRORTYPE ChangeFrameRate(OMX_S32 nFramerate);
+
+ /**
+ * @brief Starts the delivery of buffers.
+ *
+ * All buffers should be registered through the SetFreeBuffer function
+ * prior to calling this function.
+ *
+ * Source will continue to deliver buffers at the specified
+ * rate until the specified number of frames have been delivered.
+ *
+ * Note that Source will not deliver buffers unless it has ownership
+ * of atleast 1 buffer. If Source does not have ownership of buffer when
+ * timer expires, it will block until a buffer is given to the component.
+ * Free buffers should be given to the Source through SetFreeBuffer
+ * function.
+ */
+ OMX_ERRORTYPE Start();
+
+ /**
+ * @brief Wait for the thread to finish.
+ *
+ * Function will block until the Source has delivered all frames.
+ */
+ OMX_ERRORTYPE Finish();
+
+ /**
+ * @brief Gives ownership of the buffer to the source.
+ *
+ * All bufffers must be registered with the Source prior
+ * to invoking Start. This will give initial ownership to
+ * the source.
+ *
+ * After Start is called, buffers must be given ownership
+ * when yuv buffers are free.
+ *
+ * @param pBuffer Pointer to the buffer
+ */
+ OMX_ERRORTYPE SetFreeBuffer(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ static OMX_ERRORTYPE SourceThreadEntry(OMX_PTR pThreadData);
+ OMX_ERRORTYPE SourceThread();
+
+ private:
+ OMX_S32 m_nFrames;
+ OMX_S32 m_nFramesRegistered;
+ OMX_S32 m_nFramerate;
+ OMX_S32 m_nFrameWidth;
+ OMX_S32 m_nFrameHeight;
+ OMX_S32 m_nBuffers;
+ OMX_S32 m_nDVSXOffset;
+ OMX_S32 m_nDVSYOffset;
+ File* m_pFile;
+ SignalQueue* m_pBufferQueue;
+ Thread* m_pThread;
+ OMX_BOOL m_bStarted;
+ FrameDeliveryFnType m_pFrameDeliverFn;
+ OMX_BOOL m_bLiveMode;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_FILE_SOURCE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_ITestCase.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_ITestCase.h
new file mode 100644
index 0000000..a686ef6
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_ITestCase.h
@@ -0,0 +1,127 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_ITEST_CASE_H
+#define _VENC_TEST_ITEST_CASE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+
+ class Thread; // forward declaration
+
+ /**
+ * @brief A test case interface
+ */
+ class ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ *
+ * Must explicitly be called by all derived classes
+ */
+ ITestCase();
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~ITestCase();
+
+ public:
+
+ /**
+ * @brief Start the test asynchronously
+ */
+ OMX_ERRORTYPE Start(OMX_STRING pConfigFileName,
+ OMX_S32 nTestNum);
+
+ /**
+ * @brief Block until the test case is finished
+ *
+ * @return The final test result
+ */
+ OMX_ERRORTYPE Finish();
+
+ protected:
+
+ /**
+ * @brief Checks for an error and sets the final test result.
+ *
+ * When the test case exection is complete, the first error encountered
+ * will be returned.
+ *
+ * @returns eTestResult
+ */
+ OMX_ERRORTYPE CheckError(OMX_ERRORTYPE eTestResult);
+
+ private:
+
+ /**
+ * @brief The execution function for the test case
+ *
+ */
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum) = 0;
+
+ /**
+ * @brief Validates test case specific configuration assumptions.
+ *
+ * Required to be implemented by each test case. If no assumptions are
+ * made, simply return OMX_ErrorNone.
+ */
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig) = 0;
+
+ /**
+ * @brief Thread entry
+ *
+ * Invokes the child class's Execute method
+ */
+ static OMX_ERRORTYPE ThreadEntry(OMX_PTR pThreadData);
+
+ private:
+ Thread* m_pThread;
+ EncoderConfigType m_sConfig;
+ DynamicConfigType m_sDynamicConfig;
+ OMX_ERRORTYPE m_eTestResult;
+ OMX_S32 m_nTestNum;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_ITEST_CASE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Mutex.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Mutex.h
new file mode 100644
index 0000000..272004a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Mutex.h
@@ -0,0 +1,73 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_MUTEX_H
+#define _VENC_TEST_MUTEX_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+ /**
+ * @brief Mutex class
+ */
+ class Mutex
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ Mutex();
+
+ /**
+ * @brief Destructor
+ */
+ ~Mutex();
+
+ /**
+ * @brief Locks the mutex
+ */
+ OMX_ERRORTYPE Lock();
+
+ /**
+ * @brief Unlocks the mutex
+ */
+ OMX_ERRORTYPE UnLock();
+ private:
+
+ void* m_pMutex;
+ };
+}
+
+#endif // #ifndef _VENC_TEST_MUTEX_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Parser.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Parser.h
new file mode 100644
index 0000000..52e6617
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Parser.h
@@ -0,0 +1,171 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_PARSER_H
+#define _VENC_TEST_PARSER_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+ class ParserStrVector
+ {
+ public:
+ ParserStrVector();
+
+ ~ParserStrVector();
+
+ OMX_S32 size();
+
+ void clear();
+
+ OMX_STRING operator[] (OMX_S32 i);
+
+ void push_back(OMX_STRING s);
+
+ private:
+ static const int ParserMaxStrings = 256;
+ OMX_STRING pStr[ParserMaxStrings];
+ OMX_S32 count;
+ };
+
+ class File; // forward declaration
+
+ /**
+ * @brief String and file parser utility class
+ */
+ class Parser
+ {
+ public:
+
+ /**
+ * @brief Reads a line from the specified file
+ *
+ * @param pFile The file to read from. The file must be opened in read mode.
+ * @param nMaxRead Maximium number of bytes to read (size of buffer).
+ * @param pBuffer The buffer to read into
+ *
+ * @return Number of chars in the line
+ */
+ static OMX_S32 ReadLine(File* pFile,
+ OMX_S32 nMaxRead,
+ OMX_STRING pBuf);
+
+ /**
+ * @brief Converts a string to lowercase
+ *
+ * @param pStr The buffer containing input text
+ * @param pLowerStr The pre-allocated buffer to store lowercase text into
+ */
+ static OMX_ERRORTYPE StringToLower(OMX_STRING pStr,
+ OMX_STRING pLowerStr);
+
+ /**
+ * @brief Compares to strings case insensitive
+ *
+ * @param pStr1 The first string to compare
+ * @param pStr2 The second string to compare
+ *
+ * @return 0 if equal
+ */
+ static OMX_S32 StringICompare(OMX_STRING pStr1,
+ OMX_STRING pStr2);
+
+ /**
+ * @brief Removes '#' style comments from the specified string thru null termination
+ *
+ * NOTE: Modifies the specified string.
+ *
+ * @param pStr The string to remove comments from
+ */
+ static OMX_ERRORTYPE RemoveComments(OMX_STRING pStr);
+
+ /**
+ * @brief Tokenizes the string according to the specified delimiters
+ *
+ * NOTE: Modifies the specified string.
+ *
+ * @param pTokens
+ * @param pStr
+ * @param pDelims
+ */
+ static OMX_S32 TokenizeString(ParserStrVector* pTokens,
+ OMX_STRING pStr,
+ OMX_STRING pDelims);
+
+ /**
+ * @brief Removes all leading and trailing whitespace from the string
+ *
+ * NOTE: Modifies the specified string.
+ *
+ * @param pStr The string to trim
+ *
+ * @return Repositioned pointer of the the specified string
+ */
+ static OMX_STRING Trim(OMX_STRING pStr);
+
+ /**
+ * @brief Returns a pointer to the first instance of the specified delimiters
+ *
+ * @param pStr The string to search
+ * @param pDelims The string of delimiters to search for
+ *
+ * @return Repositioned pointer of the the specified string
+ */
+ static OMX_STRING StrChrs(OMX_STRING pStr,
+ OMX_STRING pDelims);
+
+ /**
+ * @brief Appends test number to a file name. Useful for bitexactness.
+ *
+ * This method will modify the contents of pFileName.
+ *
+ * Example 1: If pFileName = "test.m4v" and nTestNum is 2, then the
+ * result would be test_00002.m4v.
+ *
+ * Example 2: If pFileName = "test" and nTestNum is 2, then the
+ * result would be test_00002.
+ *
+ * @param pFileName The original name of the file.
+ * @param nTestNum The test number
+ *
+ */
+ static OMX_ERRORTYPE AppendTestNum(OMX_STRING pFileName,
+ OMX_S32 nTestNum);
+ private:
+ Parser() {}
+ ~Parser() {}
+ };
+}
+
+#endif // #ifndef _VENC_TEST_PARSER_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Pmem.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Pmem.h
new file mode 100644
index 0000000..5ce517e
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Pmem.h
@@ -0,0 +1,95 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_PMEM_H
+#define _VENC_TEST_PMEM_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <linux/msm_q6venc.h>
+#include <linux/android_pmem.h>
+#include "venc_debug.h"
+
+#include <sys/mman.h>
+
+
+namespace venctest
+{
+
+ /**
+ * @brief Class for allocating / deallocating pmem buffers.
+ *
+ * Underlying implementation is hidden. Optionally allocate a single pool of
+ * memory and slice into multiple buffers.
+ */
+ class Pmem
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ Pmem(OMX_S32 nBuffers);
+
+ /**
+ * @brief Destructor
+ */
+ ~Pmem();
+
+ public:
+
+ OMX_ERRORTYPE Allocate(OMX_U8** ppBuffer,
+ OMX_S32 nBytes, int pmem_region_id);
+
+ OMX_ERRORTYPE Free(OMX_U8* pBuffer);
+
+ private:
+
+ Pmem() {} // don't allow default constructor
+ OMX_ERRORTYPE pmem_alloc(struct venc_pmem *pBuf, int size, int pmem_region_id);
+ OMX_ERRORTYPE pmem_free(struct venc_pmem *pBuf);
+
+ private:
+
+ OMX_S32 m_nBuffers;
+ OMX_S32 m_nBuffersAlloc;
+ struct venc_pmem* m_pBufferInfo;
+
+ };
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_PMEM_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Queue.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Queue.h
new file mode 100644
index 0000000..cf23dd3
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Queue.h
@@ -0,0 +1,107 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_QUEUE_H
+#define _VENC_TEST_QUEUE_H
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Queue class.
+ */
+ class Queue
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ *
+ * @param nMaxQueueSize Max number of items in queue (size)
+ * @param nMaxDataSize Max data size
+ */
+ Queue(OMX_S32 nMaxQueueSize,
+ OMX_S32 nMaxDataSize);
+
+ /**
+ * @brief Destructor
+ */
+ ~Queue();
+
+ private:
+ Queue(); // private default constructor
+ public:
+
+ /**
+ * @brief Pushes an item onto the queue.
+ *
+ * @param pData Pointer to the data
+ * @param nDataSize Size of the data in bytes
+ */
+ OMX_ERRORTYPE Push(OMX_PTR pData,
+ OMX_S32 nDataSize);
+
+ /**
+ * @brief Pops an item from the queue.
+ *
+ * @param pData Pointer to the data
+ * @param nDataSize Size of the data buffer in bytes
+ */
+ OMX_ERRORTYPE Pop(OMX_PTR pData,
+ OMX_S32 nDataSize);
+
+ /**
+ * @brief Peeks at the item at the head of the queue
+ *
+ * Nothing will be removed from the queue
+ *
+ * @param pData Pointer to the data
+ * @param nDataSize Size of the data in bytes
+ *
+ * @return OMX_ErrorNotReady if there is no data
+ */
+ OMX_ERRORTYPE Peek(OMX_PTR pData,
+ OMX_S32 nDataSize);
+
+ /**
+ * @brief Get the size of the queue.
+ */
+ OMX_S32 GetSize();
+
+ private:
+ OMX_PTR m_pHandle;
+ };
+}
+
+#endif // #ifndef _VENC_TEST_QUEUE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Script.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Script.h
new file mode 100644
index 0000000..c888c84
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Script.h
@@ -0,0 +1,85 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_SCRIPT_H
+#define _VENC_TEST_SCRIPT_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class File; // forward declaration
+
+ /**
+ * @brief Class for parsing test case script file
+ */
+ class Script
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ Script();
+
+ /**
+ * @brief Destructor
+ */
+ ~Script();
+
+ public:
+
+ /**
+ * @brief Parses the script file
+ *
+ * This method can only be called one time per instantiation of this class
+ *
+ * @param pFileName The name of the script file
+ */
+ OMX_ERRORTYPE Configure(OMX_STRING pFileName);
+
+ /**
+ * @brief Parses the next test from the test script
+ *
+ * @return OMX_ErrorNoMore if there are no more tests to run
+ */
+ OMX_ERRORTYPE NextTest(TestDescriptionType* pTestDescription);
+
+ private:
+ File* m_pFile;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_SCRIPT_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Signal.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Signal.h
new file mode 100644
index 0000000..1571f02
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Signal.h
@@ -0,0 +1,81 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_SIGNAL_H
+#define _VENC_TEST_SIGNAL_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Class for sending signals to threads
+ *
+ * Signals behave similarly to binary (not counting) semaphores.
+ */
+ class Signal
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ Signal();
+
+ /**
+ * @brief Destructor
+ */
+ ~Signal();
+
+ public:
+
+ /**
+ * @brief Set a signal
+ */
+ OMX_ERRORTYPE Set();
+
+ /**
+ * @brief Wait for signal to be set
+ *
+ * @param nTimeoutMillis Milliseconds before timeout. Specify 0 for infinite.
+ */
+ OMX_ERRORTYPE Wait(OMX_S32 nTimeoutMillis);
+
+ private:
+
+ void* m_pSignal;
+ };
+}
+
+#endif // #ifndef _VENC_TEST_SIGNAL_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_SignalQueue.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_SignalQueue.h
new file mode 100644
index 0000000..a7460c0
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_SignalQueue.h
@@ -0,0 +1,119 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_SIGNAL_QUEUE_H
+#define _VENC_TEST_SIGNAL_QUEUE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+ class Signal; // forward declaration
+ class Mutex; // forward declaration
+ class Queue; // forward declaration
+
+ /**
+ * @brief Signal queue class.
+ *
+ * Reader will block on Pop until the writer adds an item
+ * to the queue via the Push method.
+ */
+ class SignalQueue
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ *
+ * @param nMaxQueueSize Max number of items in queue (size)
+ * @param nMaxDataSize Max data size
+ */
+ SignalQueue(OMX_S32 nMaxQueueSize,
+ OMX_S32 nMaxDataSize);
+
+ /**
+ * @brief Destructor
+ */
+ ~SignalQueue();
+
+ private:
+ SignalQueue(); // private default constructor
+
+ public:
+
+ /**
+ * @brief Pushes an item onto the queue.
+ *
+ * @param pData Pointer to the data
+ * @param nDataSize Size of the data in bytes
+ */
+ OMX_ERRORTYPE Push(OMX_PTR pData,
+ OMX_S32 nDataSize);
+
+ /**
+ * @brief Pops an item from the queue.
+ *
+ * @param pData Pointer to the data
+ * @param nDataSize Size of the data buffer in bytes
+ * @param nTimeoutMillis Milliseconds before timeout. Specify 0 for infinite.
+ */
+ OMX_ERRORTYPE Pop(OMX_PTR pData,
+ OMX_S32 nDataSize,
+ OMX_S32 nTimeoutMillis);
+
+ /**
+ * @brief Peeks at the item at the head of the queue
+ *
+ * Method will not block and nothing will be removed from the queue
+ *
+ * @param pData Pointer to the data
+ * @param nDataSize Size of the data in bytes
+ *
+ * @return OMX_ErrorNotReady if there is no data
+ */
+ OMX_ERRORTYPE Peek(OMX_PTR pData,
+ OMX_S32 nDataSize);
+
+ /**
+ * @brief Get the size of the queue.
+ */
+ OMX_S32 GetSize();
+
+ private:
+ Signal* m_pSignal;
+ Mutex* m_pMutex;
+ Queue* m_pQueue;
+ };
+}
+
+#endif // #ifndef _VENC_TEST_SIGNAL_QUEUE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Sleeper.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Sleeper.h
new file mode 100644
index 0000000..fce938e
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Sleeper.h
@@ -0,0 +1,62 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_SLEEPER_H
+#define _VENC_TEST_SLEEPER_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Utility class for sleeping
+ */
+ class Sleeper
+ {
+ public:
+
+ /**
+ * @brief Sleep for the specified time
+ *
+ * @param nTimeMillis The time to sleep in milliseconds
+ */
+ static OMX_ERRORTYPE Sleep(OMX_S32 nTimeMillis);
+
+ private:
+ Sleeper() {}
+ ~Sleeper() {}
+ };
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_SLEEPER_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_StatsThread.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_StatsThread.h
new file mode 100644
index 0000000..41e3fa8
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_StatsThread.h
@@ -0,0 +1,105 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_STATS_THREAD_H
+#define _VENC_TEST_STATS_THREAD_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ class Thread; // forward declaration
+ class Signal; // forward declaration
+ class Mutex; // forward declaration
+
+ /**
+ * @brief Collects frame statistics and periodically displays the information
+ *
+ */
+ class StatsThread
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ StatsThread(OMX_S32 nSamplePeriodMillis);
+
+ /**
+ * @brief Destructor
+ */
+ ~StatsThread();
+
+ public:
+
+ /**
+ * @brief Starts the stats thread
+ *
+ */
+ OMX_ERRORTYPE Start();
+
+ /**
+ * @brief Tell stats thread to finish
+ *
+ * Function will block until the stats thread has exited
+ */
+ OMX_ERRORTYPE Finish();
+
+ /**
+ * @brief Set input frame statistics info
+ */
+ OMX_ERRORTYPE SetInputStats(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /**
+ * @brief Set output frame statistics info
+ */
+ OMX_ERRORTYPE SetOutputStats(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ static int StatsThreadEntry(OMX_PTR pThreadData);
+ OMX_ERRORTYPE StatsThreadFn();
+
+ private:
+ void *m_pThread;
+ void *m_pSignal;
+ void *m_pMutex;
+ OMX_S32 m_nSamplePeriodMillis;
+ OMX_S32 m_nInputFrames;
+ OMX_S32 m_nOutputFrames;
+ OMX_S64 m_nBits;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_STATS_THREAD_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestCaseFactory.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestCaseFactory.h
new file mode 100644
index 0000000..8e236ab
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestCaseFactory.h
@@ -0,0 +1,69 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_CASE_FACTORY_H
+#define _VENC_TEST_CASE_FACTORY_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+
+ class ITestCase; // forward declaration
+
+ /**
+ * @brief A test case class factory. All test cases created/destroyed through this class.
+ */
+ class TestCaseFactory
+ {
+ public:
+
+ /**
+ * @brief Allocates a test case object
+ */
+ static ITestCase* AllocTest(OMX_STRING pTestName);
+
+ /**
+ * @brief Destroys a test case object
+ */
+ static OMX_ERRORTYPE DestroyTest(ITestCase* pTest);
+
+ private:
+ TestCaseFactory(){}
+ ~TestCaseFactory(){}
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_CASE_FACTORY_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestChangeIntraPeriod.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestChangeIntraPeriod.h
new file mode 100644
index 0000000..8dd0102
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestChangeIntraPeriod.h
@@ -0,0 +1,100 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_CHANGE_INTRA_PERIOD_H
+#define _VENC_TEST_CHANGE_INTRA_PERIOD_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+ class SignalQueue; // forward declaration
+ class File; // forward declaration
+
+ /**
+ * @brief Test case for dynamic intra period configuration
+ */
+ class TestChangeIntraPeriod : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestChangeIntraPeriod() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestChangeIntraPeriod();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ OMX_ERRORTYPE ProcessSyntaxHeader();
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ OMX_ERRORTYPE EncodeFrames(EncoderConfigType* pEncoderConfig,
+ OMX_S32 nFrames,
+ OMX_S32 nIntraPeriod);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ SignalQueue* m_pSignalQueue;
+ File* m_pSource;
+ File* m_pSink;
+ OMX_TICKS m_nTimeStamp;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_CHANGE_INTRA_PERIOD_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestChangeQuality.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestChangeQuality.h
new file mode 100644
index 0000000..317c089
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestChangeQuality.h
@@ -0,0 +1,97 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_CHANGE_QUALITY_H
+#define _VENC_TEST_CHANGE_QUALITY_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+
+namespace venctest
+{
+ class FileSource; // forward declaration
+ class FileSink; // forward declaration
+ class Encoder; // forward declaration
+ class Mutex; // forward declaration
+
+ /**
+ * @brief Test case for dynamic quality configuration
+ */
+ class TestChangeQuality : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestChangeQuality() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestChangeQuality();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ static void SourceDeliveryFn(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static void SinkReleaseFn(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ FileSource* m_pSource;
+ FileSink* m_pSink;
+ Encoder* m_pEncoder;
+ Mutex* m_pMutex;
+ OMX_S32 m_nFramesCoded;
+ OMX_S32 m_nFramesDelivered;
+ OMX_S64 m_nBits;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_CHANGE_QUALITY_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestEOS.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestEOS.h
new file mode 100644
index 0000000..c2a8ff3
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestEOS.h
@@ -0,0 +1,126 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_EOS_H
+#define _VENC_TEST_EOS_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+ class SignalQueue; // forward declaration
+ class File; // forward declaration
+
+ /**
+ * @brief Test case that encodes 1 frame at a time (serially).
+ */
+ class TestEOS : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestEOS() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestEOS();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ /**
+ * @brief Delivers an output buffer and waits for the syntax header
+ */
+ OMX_ERRORTYPE ProcessSyntaxHeader();
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ /**
+ * @brief Expects eos complete at start of session before yuv delivery
+ *
+ * @param bEmptyEOSBuffer If true, eos will be attached to an empty input buffer
+ */
+ OMX_ERRORTYPE EOSTestSessionStart(OMX_BOOL bEmptyEOSBuffer);
+
+ /**
+ * @brief Rapidly sends multiple frames to encoder with last frame indicating eos
+ *
+ * @param bEmptyEOSBuffer If true, eos will be attached to an empty input buffer
+ */
+ OMX_ERRORTYPE EOSTestRapidFire(OMX_BOOL bEmptyEOSBuffer);
+
+ /**
+ * @brief Ensures that encoder will not deliver eos when it doesn't have any output buffers
+ *
+ * @param bEmptyEOSBuffer If true, eos will be attached to an empty input buffer
+ */
+ OMX_ERRORTYPE EOSTestDelayOutput(OMX_BOOL bEmptyEOSBuffer);
+
+ /**
+ * @brief Returns the next timestamp.
+ *
+ * This must be called for every frame that is delivered to the encoder!
+ */
+ OMX_TICKS NextTimeStamp(OMX_S32 nFramerate);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ SignalQueue* m_pSignalQueue;
+ File* m_pSource;
+ EncoderConfigType* m_pConfig;
+ OMX_TICKS m_nTimeStamp;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_FILE_ENCODER_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestEncode.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestEncode.h
new file mode 100644
index 0000000..0364ba2
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestEncode.h
@@ -0,0 +1,95 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_PROFILE_ENCODE_H
+#define _VENC_TEST_PROFILE_ENCODE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+
+namespace venctest
+{
+ class FileSource; // forward declaration
+ class FileSink; // forward declaration
+ class Encoder; // forward declaration
+
+ /**
+ * @brief Test case for bitrate and frame rate analysis
+ */
+ class TestEncode : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestEncode() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestEncode();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+
+ static void SourceDeliveryFn(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static void SinkReleaseFn(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ FileSource* m_pSource;
+ FileSink* m_pSink;
+ Encoder* m_pEncoder;
+ OMX_S32 m_nFramesCoded;
+ OMX_S64 m_nBits;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_PROFILE_ENCODE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestFlush.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestFlush.h
new file mode 100644
index 0000000..649ed52
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestFlush.h
@@ -0,0 +1,99 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_FLUSH_H
+#define _VENC_TEST_FLUSH_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+ class File; // forward declaration
+
+ /**
+ * @brief Test case that for flushing. A stress test.
+ */
+ class TestFlush : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestFlush() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestFlush();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ OMX_ERRORTYPE DeliverBuffers(OMX_BOOL bDeliverInput,
+ OMX_BOOL bDeliverOutput,
+ EncoderConfigType* pConfig);
+
+ OMX_ERRORTYPE CheckBufferQueues(OMX_S32 nInputBuffers,
+ OMX_S32 nOutputBuffers);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ File* m_pSource;
+ File* m_pSink;
+ OMX_TICKS m_nTimeStamp;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_FLUSH_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestGetSyntaxHdr.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestGetSyntaxHdr.h
new file mode 100644
index 0000000..903ae7f
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestGetSyntaxHdr.h
@@ -0,0 +1,88 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_GET_SYNTAX_HDR
+#define _VENC_TEST_GET_SYNTAX_HDR
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class SignalQueue; // forward declaration
+
+ /**
+ * @brief Test case for in-band and out-of-band syntax header.
+ */
+ class TestGetSyntaxHdr : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestGetSyntaxHdr() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestGetSyntaxHdr();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ OMX_ERRORTYPE GetInBandSyntaxHeader(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ SignalQueue* m_pSignalQueue;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_GET_SYNTAX_HDR
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestIFrameRequest.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestIFrameRequest.h
new file mode 100644
index 0000000..cb25f7a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestIFrameRequest.h
@@ -0,0 +1,99 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_IFRAME_REQUEST_H
+#define _VENC_TEST_IFRAME_REQUEST_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+ class SignalQueue; // forward declaration
+ class File; // forward declaration
+
+ /**
+ * @brief Test case for iframe request verification
+ */
+ class TestIFrameRequest : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestIFrameRequest() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestIFrameRequest();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ OMX_ERRORTYPE ProcessSyntaxHeader();
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+
+ OMX_ERRORTYPE EncodeFrames(EncoderConfigType* pEncoderConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ SignalQueue* m_pSignalQueue;
+ File* m_pSource;
+ File* m_pSink;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_IFRAME_REQUEST_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestPmem.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestPmem.h
new file mode 100644
index 0000000..2151ed7
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestPmem.h
@@ -0,0 +1,84 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_PMEM_H
+#define _VENC_TEST_PMEM_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+
+ /**
+ * @brief Test case for both alloc and use buffer models of pmem allocation
+ */
+ class TestPmem : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestPmem() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestPmem();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_PMEM_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestProfileEncode.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestProfileEncode.h
new file mode 100644
index 0000000..1f28e4a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestProfileEncode.h
@@ -0,0 +1,94 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_PROFILE_ENCODE_H
+#define _VENC_TEST_PROFILE_ENCODE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+
+namespace venctest
+{
+ class FileSource; // forward declaration
+ class FileSink; // forward declaration
+ class Encoder; // forward declaration
+
+ /**
+ * @brief Test case for bitrate and frame rate analysis
+ */
+ class TestProfileEncode : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestProfileEncode() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestProfileEncode();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+
+ static void SourceDeliveryFn(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static void SinkReleaseFn(OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ FileSource* m_pSource;
+ FileSink* m_pSink;
+ Encoder* m_pEncoder;
+ OMX_S32 m_nFramesCoded;
+ OMX_S64 m_nBits;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_PROFILE_ENCODE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestSerialEncode.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestSerialEncode.h
new file mode 100644
index 0000000..4eaa9b3
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestSerialEncode.h
@@ -0,0 +1,96 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_SERIAL_ENCODE_H
+#define _VENC_TEST_SERIAL_ENCODE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+ class SignalQueue; // forward declaration
+ class File; // forward declaration
+
+ /**
+ * @brief Test case that encodes 1 frame at a time (serially).
+ */
+ class TestSerialEncode : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestSerialEncode() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestSerialEncode();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ OMX_ERRORTYPE ProcessSyntaxHeader();
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ OMX_ERRORTYPE EncodeFrames(EncoderConfigType* pEncoderConfig);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ SignalQueue* m_pSignalQueue;
+ File* m_pSource;
+ File* m_pSink;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_FILE_ENCODER_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestStateExecutingToIdle.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestStateExecutingToIdle.h
new file mode 100644
index 0000000..21ba58c
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestStateExecutingToIdle.h
@@ -0,0 +1,97 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_STATE_EXECUTING_TO_IDLE_H
+#define _VENC_TEST_STATE_EXECUTING_TO_IDLE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+
+ /**
+ * @brief Test case for executing to idle. A stress test.
+ */
+ class TestStateExecutingToIdle : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestStateExecutingToIdle() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestStateExecutingToIdle();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+
+ OMX_ERRORTYPE DeliverBuffers(OMX_BOOL bDeliverInput,
+ OMX_BOOL bDeliverOutput,
+ EncoderConfigType* pConfig);
+
+ OMX_ERRORTYPE CheckBufferQueues(OMX_S32 nInputBuffers,
+ OMX_S32 nOutputBuffers);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ OMX_TICKS m_nTimeStamp;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_STATE_EXECUTING_TO_IDLE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestStatePause.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestStatePause.h
new file mode 100644
index 0000000..1205090
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_TestStatePause.h
@@ -0,0 +1,95 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_STATE_EXECUTING_TO_PAUSE_H
+#define _VENC_TEST_STATE_EXECUTING_TO_PAUSE_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venctest_ITestCase.h"
+#include "venctest_ComDef.h"
+
+namespace venctest
+{
+ class Encoder; // forward declaration
+ class Queue; // forward declaration
+ class Mutex; // forward declaration
+
+ /**
+ * @brief Test case for the pause state. A stress test.
+ */
+ class TestStatePause : public ITestCase
+ {
+ public:
+
+ /**
+ * @brief Constructor
+ */
+ TestStatePause() ;
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~TestStatePause();
+
+ private:
+
+ virtual OMX_ERRORTYPE Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum);
+
+ virtual OMX_ERRORTYPE ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig);
+
+ OMX_ERRORTYPE DeliverBuffers(OMX_BOOL bDeliverInput,
+ OMX_BOOL bDeliverOutput,
+ EncoderConfigType* pConfig);
+
+ static OMX_ERRORTYPE EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ static OMX_ERRORTYPE FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ private:
+ Encoder* m_pEncoder;
+ Mutex* m_pMutex;
+ Queue* m_pInputQueue;
+ Queue* m_pOutputQueue;
+ OMX_TICKS m_nTimeStamp;
+ };
+
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_STATE_EXECUTING_TO_PAUSE_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Thread.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Thread.h
new file mode 100644
index 0000000..edf2993
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Thread.h
@@ -0,0 +1,98 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_THREAD_H
+#define _VENC_TEST_THREAD_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+#include "venc_thread.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Thread class
+ */
+ class Thread
+ {
+ public:
+
+ /**
+ * @brief Thread start function pointer
+ */
+ typedef OMX_ERRORTYPE (*StartFnType) (OMX_PTR pThreadData);
+
+ public:
+
+ /**
+ * @brief Constructor (NOTE: does not create the thread!)
+ */
+ Thread();
+
+ /**
+ * @brief Destructor (NOTE: does not destroty the thread!)
+ */
+ ~Thread();
+
+ /**
+ * @brief Starts the thread at the specified function
+ *
+ * @param pFn Pointer to the thread start function
+ * @param pThreadArgs Arguments passed in to the thread (null is valid)
+ * @param nPriority Priority of the thread, unique to each platform.
+ */
+ OMX_ERRORTYPE Start(StartFnType pFn,
+ OMX_PTR pThreadArgs,
+ OMX_S32 nPriority);
+
+ /**
+ * @brief Joins the thread
+ *
+ * Function will block until the thread exits.
+ *
+ * @param pThreadResult If not NULL the threads status will be store here
+ */
+ OMX_ERRORTYPE Join(OMX_ERRORTYPE* pThreadResult);
+
+ private:
+ static int ThreadEntry(void* pThreadData);
+
+ private:
+ StartFnType m_pFn;
+ OMX_S32 m_nPriority;
+ void* m_pThread;
+ OMX_PTR m_pThreadArgs;
+ };
+}
+
+#endif // #ifndef _VENC_TEST_THREAD_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Time.h b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Time.h
new file mode 100644
index 0000000..8155c37
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/inc/venctest_Time.h
@@ -0,0 +1,60 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VENC_TEST_TIME_H
+#define _VENC_TEST_TIME_H
+
+/*========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+==========================================================================*/
+#include "OMX_Core.h"
+
+namespace venctest
+{
+
+ /**
+ * @brief Utility class for sleeping
+ */
+ class Time
+ {
+ public:
+
+ /**
+ * @brief Get the timestamp in microseconds
+ */
+ static OMX_TICKS GetTimeMicrosec();
+
+ private:
+ Time() {}
+ ~Time() {}
+ };
+} // namespace venctest
+
+#endif // #ifndef _VENC_TEST_TIME_H
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Config.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Config.cpp
new file mode 100644
index 0000000..b4a9974
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Config.cpp
@@ -0,0 +1,434 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_Config.h"
+#include "venctest_Parser.h"
+#include "venctest_File.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace venctest
+{
+ struct ConfigEnum
+ {
+ const OMX_STRING pEnumName;
+ OMX_S32 eEnumVal;
+ };
+
+ // Codecs
+ static ConfigEnum g_pCodecEnums[] =
+ {
+ {(OMX_STRING)"MP4", (int) OMX_VIDEO_CodingMPEG4},
+ {(OMX_STRING)"H263", (int) OMX_VIDEO_CodingH263},
+ {(OMX_STRING)"H264", (int) OMX_VIDEO_CodingAVC},
+ {(OMX_STRING)0, 0}
+ };
+
+ // Rate control flavors
+ static ConfigEnum g_pVencRCEnums[] =
+ {
+ {(OMX_STRING)"RC_OFF", (int) OMX_Video_ControlRateDisable},
+ {(OMX_STRING)"RC_VBR_VFR", (int) OMX_Video_ControlRateVariableSkipFrames}, // Camcorder
+ {(OMX_STRING)"RC_VBR_CFR", (int) OMX_Video_ControlRateVariable}, // Camcorder
+ {(OMX_STRING)"RC_CBR_VFR", (int) OMX_Video_ControlRateConstantSkipFrames}, // QVP
+ {(OMX_STRING)0, 0}
+ };
+
+ // Resync marker types
+ static ConfigEnum m_pResyncMarkerType[] =
+ {
+ {(OMX_STRING)"NONE", (int) RESYNC_MARKER_NONE},
+ {(OMX_STRING)"BITS", (int) RESYNC_MARKER_BITS},
+ {(OMX_STRING)"MB", (int) RESYNC_MARKER_MB},
+ {(OMX_STRING)"GOB", (int) RESYNC_MARKER_GOB},
+ {(OMX_STRING)0, 0}
+ };
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_S32 ParseEnum(ConfigEnum* pConfigEnum,
+ OMX_STRING pEnumName)
+ {
+ OMX_S32 idx = 0;
+ while (pConfigEnum[idx].pEnumName)
+ {
+ if (Parser::StringICompare(pEnumName,
+ pConfigEnum[idx].pEnumName) == 0)
+ {
+ return pConfigEnum[idx].eEnumVal;
+ }
+ idx++;
+ }
+ VENC_TEST_MSG_ERROR("error could not find enum");
+ return -1;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Config::Config()
+ {
+ static const OMX_STRING pInFileName = (OMX_STRING)"";
+
+ // set some default values
+ memset(&m_sEncoderConfig, 0, sizeof(m_sEncoderConfig));
+ m_sEncoderConfig.eCodec = OMX_VIDEO_CodingMPEG4;
+ m_sEncoderConfig.eControlRate = OMX_Video_ControlRateDisable;
+ m_sEncoderConfig.nFrameWidth = 640;
+ m_sEncoderConfig.nFrameHeight = 480;
+ m_sEncoderConfig.nOutputFrameWidth = m_sEncoderConfig.nFrameWidth;
+ m_sEncoderConfig.nOutputFrameHeight = m_sEncoderConfig.nFrameHeight;
+ m_sEncoderConfig.nDVSXOffset = 0;
+ m_sEncoderConfig.nDVSYOffset = 0;
+ m_sEncoderConfig.nBitrate = 768000;
+ m_sEncoderConfig.nFramerate = 30;
+ m_sEncoderConfig.nTimeIncRes = 30;
+ m_sEncoderConfig.nRotation = 0;
+ m_sEncoderConfig.nInBufferCount = 3;
+ m_sEncoderConfig.nOutBufferCount = 3;
+ m_sEncoderConfig.nHECInterval = 0;
+ m_sEncoderConfig.nResyncMarkerSpacing = 0;
+ m_sEncoderConfig.eResyncMarkerType = RESYNC_MARKER_NONE;
+ m_sEncoderConfig.bEnableIntraRefresh = OMX_FALSE;
+ m_sEncoderConfig.nFrames = 30;
+ m_sEncoderConfig.bEnableShortHeader = OMX_FALSE;
+ m_sEncoderConfig.nIntraPeriod = m_sEncoderConfig.nFramerate * 2;
+ m_sEncoderConfig.nMinQp = 2;
+ m_sEncoderConfig.nMaxQp = 31;
+ m_sEncoderConfig.bProfileMode = OMX_FALSE;
+ m_sEncoderConfig.bInUseBuffer= OMX_FALSE;
+ m_sEncoderConfig.bOutUseBuffer= OMX_FALSE;
+
+ // default dynamic config
+ m_sDynamicConfig.nIFrameRequestPeriod = 0;
+ m_sDynamicConfig.nUpdatedBitrate = m_sEncoderConfig.nBitrate;
+ m_sDynamicConfig.nUpdatedFramerate = m_sEncoderConfig.nFramerate;
+ m_sDynamicConfig.nUpdatedMinQp = m_sEncoderConfig.nMinQp;
+ m_sDynamicConfig.nUpdatedMaxQp = m_sEncoderConfig.nMaxQp;
+ m_sDynamicConfig.nUpdatedFrames = m_sEncoderConfig.nFrames;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Config::~Config()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Config::Parse(OMX_STRING pFileName,
+ EncoderConfigType* pEncoderConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ static const OMX_S32 maxLineLen = 256;
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+
+ OMX_S32 nLine = 0;
+
+ ParserStrVector v;
+ char pBuf[maxLineLen];
+ char* pTrimmed;
+
+ File f;
+ result = f.Open(pFileName,
+ OMX_TRUE);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error opening file");
+ return OMX_ErrorBadParameter;
+ }
+
+ while (Parser::ReadLine(&f, maxLineLen, pBuf) != -1)
+ {
+ OMX_S32 nTok = 0;
+ (void) Parser::RemoveComments(pBuf);
+ pTrimmed = Parser::Trim(pBuf);
+ if (strlen(pTrimmed) != 0)
+ nTok = Parser::TokenizeString(&v, pTrimmed, (OMX_STRING)"\t =");
+
+ VENC_TEST_MSG_LOW("ntok = %ld", nTok);
+ switch (v.size())
+ {
+ case 0: // blank line
+ break;
+ case 1: // use default value
+ break;
+ case 2: // user has a preferred config
+
+ ///////////////////////////////////////////
+ ///////////////////////////////////////////
+ // Encoder config
+ ///////////////////////////////////////////
+ ///////////////////////////////////////////
+ if (Parser::StringICompare((OMX_STRING)"FrameWidth", v[0]) == 0)
+ {
+ m_sEncoderConfig.nFrameWidth = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("FrameWidth = %ld", m_sEncoderConfig.nFrameWidth);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"FrameHeight", v[0]) == 0)
+ {
+ m_sEncoderConfig.nFrameHeight = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("FrameHeight = %ld", m_sEncoderConfig.nFrameHeight);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"OutputFrameWidth", v[0]) == 0)
+ {
+ m_sEncoderConfig.nOutputFrameWidth = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("OutputFrameWidth = %ld", m_sEncoderConfig.nOutputFrameWidth);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"OutputFrameHeight", v[0]) == 0)
+ {
+ m_sEncoderConfig.nOutputFrameHeight = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("OutputFrameHeight = %ld", m_sEncoderConfig.nOutputFrameHeight);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"DVSXOffset", v[0]) == 0)
+ {
+ m_sEncoderConfig.nDVSXOffset = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("DVSXOffset = %ld", m_sEncoderConfig.nDVSXOffset);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"DVSYOffset", v[0]) == 0)
+ {
+ m_sEncoderConfig.nDVSYOffset = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("DVSYOffset = %ld", m_sEncoderConfig.nDVSYOffset);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"Rotation", v[0]) == 0)
+ {
+ m_sEncoderConfig.nRotation = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("Rotation = %ld", m_sEncoderConfig.nRotation);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"FPS", v[0]) == 0)
+ {
+ m_sEncoderConfig.nFramerate = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("FPS = %ld", m_sEncoderConfig.nFramerate);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"Bitrate", v[0]) == 0)
+ {
+ m_sEncoderConfig.nBitrate = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("Bitrate = %ld", m_sEncoderConfig.nBitrate);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"RC", v[0]) == 0)
+ {
+ m_sEncoderConfig.eControlRate =
+ (OMX_VIDEO_CONTROLRATETYPE) ParseEnum(g_pVencRCEnums, v[1]);
+ VENC_TEST_MSG_LOW("RC = %d", m_sEncoderConfig.eControlRate);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"Codec", v[0]) == 0)
+ {
+ m_sEncoderConfig.eCodec = (OMX_VIDEO_CODINGTYPE) ParseEnum(g_pCodecEnums, v[1]);
+ VENC_TEST_MSG_LOW("Codec = %d", m_sEncoderConfig.eCodec);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"InBufferCount", v[0]) == 0)
+ {
+ m_sEncoderConfig.nInBufferCount = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("InBufferCount = %ld", m_sEncoderConfig.nInBufferCount);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"OutBufferCount", v[0]) == 0)
+ {
+ m_sEncoderConfig.nOutBufferCount = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("OutBufferCount = %ld", m_sEncoderConfig.nOutBufferCount);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"HECInterval", v[0]) == 0)
+ {
+ m_sEncoderConfig.nHECInterval = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("HECInterval = %d\n", (int) m_sEncoderConfig.nHECInterval);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"ResyncMarkerSpacing", v[0]) == 0)
+ {
+ m_sEncoderConfig.nResyncMarkerSpacing = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("ResyncMarkerSpacing = %d\n", (int) m_sEncoderConfig.nResyncMarkerSpacing);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"ResyncMarkerType", v[0]) == 0)
+ {
+ m_sEncoderConfig.eResyncMarkerType = (ResyncMarkerType) ParseEnum(m_pResyncMarkerType, v[1]);
+ VENC_TEST_MSG_LOW("ResyncMarkerType = %d\n", (int) m_sEncoderConfig.eResyncMarkerType);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"EnableIntraRefresh", v[0]) == 0)
+ {
+ m_sEncoderConfig.bEnableIntraRefresh = (OMX_BOOL) atoi(v[1]) == 1 ? OMX_TRUE : OMX_FALSE;
+ VENC_TEST_MSG_LOW("EnableIntraRefresh = %d\n", (int) m_sEncoderConfig.bEnableIntraRefresh);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"TimeIncRes", v[0]) == 0)
+ {
+ m_sEncoderConfig.nTimeIncRes = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("TimeIncRes = %d\n", (int) m_sEncoderConfig.nTimeIncRes);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"EnableShortHeader", v[0]) == 0)
+ {
+ m_sEncoderConfig.bEnableShortHeader = (OMX_BOOL) atoi(v[1]);
+ VENC_TEST_MSG_LOW("EnableShortHeader = %d\n", (int) m_sEncoderConfig.bEnableShortHeader);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"IntraPeriod", v[0]) == 0)
+ {
+ m_sEncoderConfig.nIntraPeriod = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("IntraPeriod = %d\n", (int) m_sEncoderConfig.nIntraPeriod);
+ }
+
+ else if (Parser::StringICompare((OMX_STRING)"InFile", v[0]) == 0)
+ {
+ memcpy(m_sEncoderConfig.cInFileName, v[1], (strlen(v[1])+1));
+ VENC_TEST_MSG_LOW("InFile");
+ }
+ else if (Parser::StringICompare((OMX_STRING)"OutFile", v[0]) == 0)
+ {
+ memcpy(m_sEncoderConfig.cOutFileName, v[1], (strlen(v[1])+1));
+ VENC_TEST_MSG_LOW("OutFile");
+ }
+ else if (Parser::StringICompare((OMX_STRING)"NumFrames", v[0]) == 0)
+ {
+ m_sEncoderConfig.nFrames = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("NumFrames = %ld", m_sEncoderConfig.nFrames);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"MinQp", v[0]) == 0)
+ {
+ m_sEncoderConfig.nMinQp = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("MinQp = %ld", m_sEncoderConfig.nMinQp);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"MaxQp", v[0]) == 0)
+ {
+ m_sEncoderConfig.nMaxQp = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("MaxQp = %ld", m_sEncoderConfig.nMaxQp);
+ }
+
+ ///////////////////////////////////////////
+ ///////////////////////////////////////////
+ // Dynamic config
+ ///////////////////////////////////////////
+ ///////////////////////////////////////////
+ else if (Parser::StringICompare((OMX_STRING)"IFrameRequestPeriod", v[0]) == 0)
+ {
+ m_sDynamicConfig.nIFrameRequestPeriod = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("IFrameRequestPeriod = %d\n", (int) m_sDynamicConfig.nIFrameRequestPeriod);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"UpdatedBitrate", v[0]) == 0)
+ {
+ m_sDynamicConfig.nUpdatedBitrate = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("UpdatedBitrate = %d\n", (int) m_sDynamicConfig.nUpdatedBitrate);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"UpdatedFPS", v[0]) == 0)
+ {
+ m_sDynamicConfig.nUpdatedFramerate = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("UpdatedFPS = %d\n", (int) m_sDynamicConfig.nUpdatedFramerate);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"UpdatedMinQp", v[0]) == 0)
+ {
+ m_sDynamicConfig.nUpdatedMinQp = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("UpdatedMinQp = %d\n", (int) m_sDynamicConfig.nUpdatedMinQp);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"UpdatedMaxQp", v[0]) == 0)
+ {
+ m_sDynamicConfig.nUpdatedMaxQp = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("UpdatedMaxQp = %d\n", (int) m_sDynamicConfig.nUpdatedMaxQp);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"UpdatedNumFrames", v[0]) == 0)
+ {
+ m_sDynamicConfig.nUpdatedFrames = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("UpdatedNumFrames = %d\n", (int) m_sDynamicConfig.nUpdatedFrames);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"UpdatedIntraPeriod", v[0]) == 0)
+ {
+ m_sDynamicConfig.nUpdatedIntraPeriod = (OMX_S32) atoi(v[1]);
+ VENC_TEST_MSG_LOW("UpdatedIntraPeriod = %d\n", (int) m_sDynamicConfig.nUpdatedIntraPeriod);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"ProfileMode", v[0]) == 0)
+ {
+ m_sEncoderConfig.bProfileMode = (OMX_BOOL) atoi(v[1]);
+ VENC_TEST_MSG_LOW("ProfileMode = %d\n", (int) m_sEncoderConfig.bProfileMode);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"InUseBuffer", v[0]) == 0)
+ {
+ m_sEncoderConfig.bInUseBuffer = (OMX_BOOL)atoi(v[1]);
+ }
+ else if (Parser::StringICompare((OMX_STRING)"OutUseBuffer", v[0]) == 0)
+ {
+ m_sEncoderConfig.bOutUseBuffer = (OMX_BOOL)atoi(v[1]);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("invalid config file key line %ld", nLine);
+ }
+ break;
+ default:
+ VENC_TEST_MSG_ERROR("error with config parsing line %ld", nLine);
+ break;
+ }
+ v.clear();
+
+ ++nLine;
+ }
+
+ (void) f.Close();
+
+ memcpy(pEncoderConfig, &m_sEncoderConfig, sizeof(m_sEncoderConfig));
+
+ if (pDynamicConfig != NULL) // optional param
+ {
+ memcpy(pDynamicConfig, &m_sDynamicConfig, sizeof(m_sDynamicConfig));
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Config::GetEncoderConfig(EncoderConfigType* pEncoderConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pEncoderConfig != NULL)
+ {
+ memcpy(pEncoderConfig, &m_sEncoderConfig, sizeof(m_sEncoderConfig));
+ }
+ else
+ {
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Config::GetDynamicConfig(DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pDynamicConfig != NULL)
+ {
+ memcpy(pDynamicConfig, &m_sDynamicConfig, sizeof(m_sDynamicConfig));
+ }
+ else
+ {
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Encoder.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Encoder.cpp
new file mode 100644
index 0000000..607e18d
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Encoder.cpp
@@ -0,0 +1,1432 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Encoder.h"
+#include "venctest_Debug.h"
+#include "venctest_Signal.h"
+#include "venctest_Pmem.h"
+#include "venctest_SignalQueue.h"
+#include "venctest_StatsThread.h"
+#include "OMX_Component.h"
+#include "OMX_QCOMExtns.h"
+
+#define OMX_SPEC_VERSION 0x00000101
+#define OMX_INIT_STRUCT(_s_, _name_) \
+ memset((_s_), 0x0, sizeof(_name_)); \
+ (_s_)->nSize = sizeof(_name_); \
+ (_s_)->nVersion.nVersion = OMX_SPEC_VERSION
+
+namespace venctest
+{
+
+ static const OMX_U32 PORT_INDEX_IN = 0;
+ static const OMX_U32 PORT_INDEX_OUT = 1;
+
+
+ struct CmdType
+ {
+ OMX_EVENTTYPE eEvent;
+ OMX_COMMANDTYPE eCmd;
+ OMX_U32 sCmdData;
+ OMX_ERRORTYPE eResult;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Encoder::Encoder()
+ {
+ VENC_TEST_MSG_ERROR("Should not be here this is a private constructor");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Encoder::Encoder(EmptyDoneCallbackType pEmptyDoneFn,
+ FillDoneCallbackType pFillDoneFn,
+ OMX_PTR pAppData,
+ OMX_VIDEO_CODINGTYPE eCodec)
+ : m_pSignalQueue(new SignalQueue(32, sizeof(CmdType))),
+ m_pInMem(0),
+ m_pOutMem(0),
+ m_pStats(new StatsThread(2000)), // 2 second statistics intervals
+ m_pEventFn(NULL),
+ m_pEmptyDoneFn(pEmptyDoneFn),
+ m_pFillDoneFn(pFillDoneFn),
+ m_pAppData(pAppData),
+ m_bInUseBuffer(OMX_FALSE),
+ m_bOutUseBuffer(OMX_FALSE),
+ m_pInputBuffers(NULL),
+ m_pOutputBuffers(NULL),
+ m_hEncoder(NULL),
+ m_eState(OMX_StateLoaded),
+ m_nInputBuffers(0),
+ m_nOutputBuffers(0),
+ m_nInputBufferSize(0),
+ m_nOutputBufferSize(0),
+ m_eCodec(eCodec),
+ m_nInFrameIn(0),
+ m_nOutFrameIn(0),
+ m_nInFrameOut(0),
+ m_nOutFrameOut(0)
+ {
+ static OMX_CALLBACKTYPE callbacks = {EventCallback,
+ EmptyDoneCallback,
+ FillDoneCallback};
+
+ if (m_pEmptyDoneFn == NULL)
+ {
+ VENC_TEST_MSG_ERROR("Empty buffer fn is NULL");
+ }
+ if (m_pFillDoneFn == NULL)
+ {
+ VENC_TEST_MSG_ERROR("Fill buffer fn is NULL");
+ }
+
+ // MPEG4
+ if (eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ VENC_TEST_MSG_MEDIUM("Getting handle for mpeg4");
+ if (OMX_GetHandle(&m_hEncoder,
+ (OMX_STRING)"OMX.qcom.video.encoder.mpeg4",
+ this,
+ &callbacks) != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("Error getting component handle");
+ }
+ }
+ // H263
+ else if (eCodec == OMX_VIDEO_CodingH263)
+ {
+ VENC_TEST_MSG_MEDIUM("Getting handle for h263");
+ if (OMX_GetHandle(&m_hEncoder,
+ (OMX_STRING)"OMX.qcom.video.encoder.h263",
+ this,
+ &callbacks) != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("Error getting component handle");
+ }
+ }
+ // H264
+ else if (eCodec == OMX_VIDEO_CodingAVC)
+ {
+ VENC_TEST_MSG_MEDIUM("Getting handle for avc");
+ if (OMX_GetHandle(&m_hEncoder,
+ (OMX_STRING)"OMX.qcom.video.encoder.avc",
+ this,
+ &callbacks) != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("Error getting component handle");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Invalid codec selection");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Encoder::~Encoder()
+ {
+ OMX_FreeHandle(m_hEncoder);
+ if (m_pSignalQueue)
+ {
+ delete m_pSignalQueue;
+ }
+ if (m_pStats)
+ {
+ delete m_pStats;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::Configure(EncoderConfigType* pConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pConfig == NULL)
+ {
+ result = OMX_ErrorBadParameter;
+ }
+ else
+ {
+ m_nInputBuffers = pConfig->nInBufferCount;
+ m_nOutputBuffers = pConfig->nOutBufferCount;
+ }
+
+ //////////////////////////////////////////
+ // port format (set the codec)
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE fmt;
+ OMX_INIT_STRUCT(&fmt, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ fmt.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoPortFormat,
+ (OMX_PTR) &fmt);
+ if (result == OMX_ErrorNone)
+ {
+ fmt.eCompressionFormat = m_eCodec;
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoPortFormat,
+ (OMX_PTR) &fmt);
+ }
+ }
+
+ //////////////////////////////////////////
+ // codec specific config
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ if (m_eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ OMX_VIDEO_PARAM_MPEG4TYPE mp4;
+ OMX_INIT_STRUCT(&mp4, OMX_VIDEO_PARAM_MPEG4TYPE);
+ mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoMpeg4,
+ (OMX_PTR) &mp4);
+
+ if (result == OMX_ErrorNone)
+ {
+ mp4.nTimeIncRes = pConfig->nTimeIncRes;
+ mp4.nPFrames = pConfig->nIntraPeriod - 1;
+
+ mp4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ mp4.eLevel = OMX_VIDEO_MPEG4Level5;
+
+ if (pConfig->nOutputFrameWidth > 176 &&
+ pConfig->nOutputFrameHeight > 144)
+ {
+ mp4.eLevel = OMX_VIDEO_MPEG4Level2;
+ }
+ else
+ {
+ mp4.eLevel = OMX_VIDEO_MPEG4Level0;
+ }
+ mp4.bACPred = OMX_TRUE;
+ mp4.bSVH = pConfig->bEnableShortHeader;
+ mp4.nHeaderExtension = pConfig->nHECInterval;
+
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoMpeg4,
+ (OMX_PTR) &mp4);
+ }
+ }
+ else if (m_eCodec == OMX_VIDEO_CodingH263)
+ {
+ OMX_VIDEO_PARAM_H263TYPE h263;
+ OMX_INIT_STRUCT(&h263, OMX_VIDEO_PARAM_H263TYPE);
+ h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoH263,
+ (OMX_PTR) &h263);
+
+ if (result == OMX_ErrorNone)
+ {
+ h263.nPFrames = pConfig->nIntraPeriod - 1;
+ h263.nBFrames = 0;
+
+ h263.eProfile = OMX_VIDEO_H263ProfileBaseline;
+
+ h263.eLevel = OMX_VIDEO_H263Level10;
+ h263.bPLUSPTYPEAllowed = OMX_FALSE;
+ h263.nAllowedPictureTypes = 2;
+ h263.bForceRoundingTypeToZero = OMX_TRUE;
+ h263.nPictureHeaderRepetition = 0;
+
+
+ if (pConfig->eResyncMarkerType == RESYNC_MARKER_GOB)
+ {
+ h263.nGOBHeaderInterval = pConfig->nResyncMarkerSpacing;
+ }
+ else if (pConfig->eResyncMarkerType == RESYNC_MARKER_MB)
+ {
+ OMX_VIDEO_PARAM_MPEG4TYPE mp4;
+ OMX_INIT_STRUCT(&mp4, OMX_VIDEO_PARAM_MPEG4TYPE);
+ mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoMpeg4,
+ (OMX_PTR) &mp4);
+
+ if (result == OMX_ErrorNone)
+ {
+ // annex k
+ mp4.nSliceHeaderSpacing = pConfig->nResyncMarkerSpacing;
+
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoMpeg4,
+ (OMX_PTR) &mp4);
+ }
+
+ h263.nGOBHeaderInterval = 0;
+ }
+ else
+ {
+ h263.nGOBHeaderInterval = 0;
+ }
+
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoH263,
+ (OMX_PTR) &h263);
+ }
+ }
+ else if (m_eCodec == OMX_VIDEO_CodingAVC)
+ {
+ OMX_VIDEO_PARAM_AVCTYPE avc;
+ OMX_INIT_STRUCT(&avc, OMX_VIDEO_PARAM_AVCTYPE);
+ avc.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoAvc,
+ (OMX_PTR) &avc);
+
+ if (result == OMX_ErrorNone)
+ {
+ avc.nPFrames = pConfig->nIntraPeriod - 1;
+ avc.nBFrames = 0;
+ avc.eProfile = OMX_VIDEO_AVCProfileBaseline;
+ avc.eLevel = OMX_VIDEO_AVCLevel1;
+ if (pConfig->nOutputFrameWidth * pConfig->nOutputFrameHeight / 256 < 792)
+ {
+ avc.eLevel = OMX_VIDEO_AVCLevel21;
+ }
+ else if (pConfig->nOutputFrameWidth * pConfig->nOutputFrameHeight / 256 < 1620)
+ {
+ avc.eLevel = OMX_VIDEO_AVCLevel22;
+ }
+
+ if (pConfig->eResyncMarkerType == RESYNC_MARKER_MB)
+ {
+ avc.nSliceHeaderSpacing = pConfig->nResyncMarkerSpacing;
+ }
+ else
+ {
+ avc.nSliceHeaderSpacing = 0;
+ }
+
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoAvc,
+ (OMX_PTR) &avc);
+ }
+ }
+
+ }
+
+ //////////////////////////////////////////
+ // error resilience
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ // see if we already configured error resilience (which is the case for h263)
+ if (m_eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrection; //OMX_IndexParamVideoErrorCorrection
+ OMX_INIT_STRUCT(&errorCorrection, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE);
+ errorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoErrorCorrection,
+ (OMX_PTR) &errorCorrection);
+
+ if (result == OMX_ErrorNone)
+ {
+ if (m_eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ errorCorrection.bEnableHEC = pConfig->nHECInterval == 0 ? OMX_FALSE : OMX_TRUE;
+ }
+ else
+ {
+ errorCorrection.bEnableHEC = OMX_FALSE;
+ }
+
+ if (pConfig->eResyncMarkerType == RESYNC_MARKER_BITS)
+ {
+ errorCorrection.bEnableResync = OMX_TRUE;
+ errorCorrection.nResynchMarkerSpacing = pConfig->nResyncMarkerSpacing;
+ }
+ else
+ {
+ errorCorrection.bEnableResync = OMX_FALSE;
+ errorCorrection.nResynchMarkerSpacing = 0;
+ }
+
+ errorCorrection.bEnableDataPartitioning = OMX_FALSE; // MP4 Resync
+
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoErrorCorrection,
+ (OMX_PTR) &errorCorrection);
+ }
+ }
+ }
+#ifdef QCOM_OMX_EXT
+ //////////////////////////////////////////
+ // qp
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_QCOM_VIDEO_CONFIG_QPRANGE qp; // OMX_QcomIndexConfigVideoQPRange
+ qp.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ result = OMX_GetConfig(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
+ (OMX_PTR) &qp);
+ if (result == OMX_ErrorNone)
+ {
+ qp.nMinQP = (OMX_U32) pConfig->nMinQp;
+ qp.nMaxQP = (OMX_U32) pConfig->nMaxQp;
+ result = OMX_SetConfig(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
+ (OMX_PTR) &qp);
+ }
+ }
+#endif
+ //////////////////////////////////////////
+ // bitrate
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate
+ OMX_INIT_STRUCT(&bitrate, OMX_VIDEO_PARAM_BITRATETYPE);
+ bitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoBitrate,
+ (OMX_PTR) &bitrate);
+ if (result == OMX_ErrorNone)
+ {
+ bitrate.eControlRate = pConfig->eControlRate;
+ bitrate.nTargetBitrate = pConfig->nBitrate;
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoBitrate,
+ (OMX_PTR) &bitrate);
+ }
+ }
+
+ //////////////////////////////////////////
+ // quantization
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->eControlRate == OMX_Video_ControlRateDisable)
+ {
+ ///////////////////////////////////////////////////////////
+ // QP Config
+ ///////////////////////////////////////////////////////////
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE qp; // OMX_IndexParamVideoQuantization
+ OMX_INIT_STRUCT(&qp, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
+ qp.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoQuantization,
+ (OMX_PTR) &qp);
+ if (result == OMX_ErrorNone)
+ {
+ if (m_eCodec == OMX_VIDEO_CodingAVC)
+ {
+ qp.nQpI = 30;
+ qp.nQpP = 30;
+ }
+ else
+ {
+ qp.nQpI = 14;
+ qp.nQpP = 14;
+ }
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoQuantization,
+ (OMX_PTR) &qp);
+ }
+ }
+ }
+
+ //////////////////////////////////////////
+ // frame rate
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_CONFIG_FRAMERATETYPE framerate; // OMX_IndexConfigVideoFramerate
+ framerate.nPortIndex = (OMX_U32) PORT_INDEX_IN; // input
+ result = OMX_GetConfig(m_hEncoder,
+ OMX_IndexConfigVideoFramerate,
+ (OMX_PTR) &framerate);
+ if (result == OMX_ErrorNone)
+ {
+ framerate.xEncodeFramerate = pConfig->nFramerate << 16;
+ result = OMX_SetConfig(m_hEncoder,
+ OMX_IndexConfigVideoFramerate,
+ (OMX_PTR) &framerate);
+ }
+ }
+
+ //////////////////////////////////////////
+ // rotation
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_CONFIG_ROTATIONTYPE framerotate; // OMX_IndexConfigCommonRotate
+ framerotate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetConfig(m_hEncoder,
+ OMX_IndexConfigCommonRotate,
+ (OMX_PTR) &framerotate);
+ if (result == OMX_ErrorNone)
+ {
+
+ framerotate.nRotation = pConfig->nRotation;
+
+ result = OMX_SetConfig(m_hEncoder,
+ OMX_IndexConfigCommonRotate,
+ (OMX_PTR) &framerotate);
+ }
+ }
+
+ //////////////////////////////////////////
+ // intra refresh
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_VIDEO_PARAM_INTRAREFRESHTYPE ir; // OMX_IndexParamVideoIntraRefresh
+ OMX_INIT_STRUCT(&ir, OMX_VIDEO_PARAM_INTRAREFRESHTYPE);
+ ir.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamVideoIntraRefresh,
+ (OMX_PTR) &ir);
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->bEnableIntraRefresh == OMX_TRUE)
+ {
+ /// @todo need an extension dynamic for intra refresh configuration
+ ir.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
+ ir.nCirMBs = 5;
+
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamVideoIntraRefresh,
+ (OMX_PTR) &ir);
+ }
+ }
+ }
+
+ //////////////////////////////////////////
+ // input buffer requirements
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE inPortDef; // OMX_IndexParamPortDefinition
+ OMX_INIT_STRUCT(&inPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
+ inPortDef.nPortIndex = (OMX_U32) PORT_INDEX_IN; // input
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamPortDefinition,
+ (OMX_PTR) &inPortDef);
+ if (result == OMX_ErrorNone)
+ {
+ inPortDef.nBufferCountActual = m_nInputBuffers;
+ inPortDef.format.video.nFrameWidth = pConfig->nFrameWidth;
+ inPortDef.format.video.nFrameHeight = pConfig->nFrameHeight;
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamPortDefinition,
+ (OMX_PTR) &inPortDef);
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamPortDefinition,
+ (OMX_PTR) &inPortDef);
+
+ if (m_nInputBuffers != (OMX_S32) inPortDef.nBufferCountActual)
+ {
+ VENC_TEST_MSG_ERROR("Buffer reqs dont match...");
+ }
+ }
+
+ m_nInputBufferSize = (OMX_S32) inPortDef.nBufferSize;
+ }
+
+ //////////////////////////////////////////
+ // output buffer requirements
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE outPortDef; // OMX_IndexParamPortDefinition
+ OMX_INIT_STRUCT(&outPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
+ outPortDef.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamPortDefinition,
+ (OMX_PTR) &outPortDef);
+ if (result == OMX_ErrorNone)
+ {
+ outPortDef.nBufferCountActual = m_nOutputBuffers;
+ outPortDef.format.video.nFrameWidth = pConfig->nOutputFrameWidth;
+ outPortDef.format.video.nFrameHeight = pConfig->nOutputFrameHeight;
+ result = OMX_SetParameter(m_hEncoder,
+ OMX_IndexParamPortDefinition,
+ (OMX_PTR) &outPortDef);
+ result = OMX_GetParameter(m_hEncoder,
+ OMX_IndexParamPortDefinition,
+ (OMX_PTR) &outPortDef);
+
+ if (m_nOutputBuffers != (OMX_S32) outPortDef.nBufferCountActual)
+ {
+ VENC_TEST_MSG_ERROR("Buffer reqs dont match...");
+ }
+ }
+
+ m_nOutputBufferSize = (OMX_S32) outPortDef.nBufferSize;
+ }
+
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::EnableUseBufferModel(OMX_BOOL bInUseBuffer, OMX_BOOL bOutUseBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ m_bInUseBuffer = bInUseBuffer;
+ m_bOutUseBuffer = bOutUseBuffer;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::GoToExecutingState()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (m_eState == OMX_StateLoaded)
+ {
+ ///////////////////////////////////////
+ // 1. send idle state command
+ // 2. allocate input buffers
+ // 3. allocate output buffers
+ // 4. wait for idle state complete
+ // 5. send executing state command and wait for complete
+ ///////////////////////////////////////
+
+ m_nInFrameIn = 0;
+ m_nOutFrameIn = 0;
+ m_nInFrameOut = 0;
+ m_nOutFrameOut = 0;
+
+ // send idle state comand
+ VENC_TEST_MSG_MEDIUM("going to state OMX_StateIdle...");
+ result = SetState(OMX_StateIdle, OMX_FALSE);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = AllocateBuffers();
+ }
+
+ // wait for idle state complete
+ if (result == OMX_ErrorNone)
+ {
+ result = WaitState(OMX_StateIdle);
+ }
+
+ // send executing state command and wait for complete
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_MEDIUM("going to state OMX_StateExecuting...");
+ result = SetState(OMX_StateExecuting, OMX_TRUE);
+ }
+
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("invalid state");
+ result = OMX_ErrorIncorrectStateTransition;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::GetOutOfBandSyntaxHeader(OMX_U8* pSyntaxHdr,
+ OMX_S32 nSyntaxHdrLen,
+ OMX_S32* pSyntaxHdrFilledLen)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+#ifdef QCOM_OMX_EXT
+ if (pSyntaxHdr != NULL &&
+ nSyntaxHdrLen > 0 &&
+ pSyntaxHdrFilledLen != NULL)
+ {
+ OMX_QCOM_VIDEO_PARAM_SYNTAXHDRTYPE syntax;
+ OMX_INIT_STRUCT(&syntax, OMX_QCOM_VIDEO_PARAM_SYNTAXHDRTYPE);
+ syntax.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ syntax.pBuff = pSyntaxHdr;
+ syntax.nBuffLen = (OMX_U32) nSyntaxHdrLen;
+ result = OMX_GetParameter(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyntaxHdr,
+ (OMX_PTR) &syntax);
+ if (result == OMX_ErrorNone)
+ {
+ *pSyntaxHdrFilledLen = (OMX_S32) syntax.nFilledLen;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to get syntax header");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad param(s)");
+ result = OMX_ErrorBadParameter;
+ }
+#endif
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::GoToLoadedState()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ ///////////////////////////////////////
+ // 1. send idle state command and wait for complete
+ // 2. send loaded state command
+ // 3. free input buffers
+ // 4. free output buffers
+ // 5. wait for loaded state complete
+ ///////////////////////////////////////
+
+ // send idle state comand and wait for complete
+ if (m_eState == OMX_StateExecuting ||
+ m_eState == OMX_StatePause)
+ {
+ VENC_TEST_MSG_MEDIUM("going to state OMX_StateIdle...");
+ result = SetState(OMX_StateIdle, OMX_TRUE);
+ }
+
+
+ // send loaded state command
+ VENC_TEST_MSG_MEDIUM("going to state OMX_StateLoaded...");
+ result = SetState(OMX_StateLoaded, OMX_FALSE);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = FreeBuffers();
+
+ // wait for loaded state complete
+ result = WaitState(OMX_StateLoaded);
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::DeliverInput(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_MEDIUM("deliver input frame %ld", m_nInFrameIn);
+ ++m_nInFrameIn;
+
+ if (m_pStats != NULL)
+ {
+ (void) m_pStats->SetInputStats(pBuffer);
+ }
+
+ return OMX_EmptyThisBuffer(m_hEncoder, pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::DeliverOutput(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_MEDIUM("deliver output frame %ld", m_nOutFrameIn);
+ ++m_nOutFrameIn;
+ pBuffer->nFlags = 0;
+ return OMX_FillThisBuffer(m_hEncoder, pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_BUFFERHEADERTYPE** Encoder::GetBuffers(OMX_BOOL bIsInput)
+ {
+ OMX_BUFFERHEADERTYPE** ppBuffers;
+ if (m_eState == OMX_StateExecuting)
+ {
+ ppBuffers = (bIsInput == OMX_TRUE) ? m_pInputBuffers : m_pOutputBuffers;
+ }
+ else
+ {
+ ppBuffers = NULL;
+ }
+ return ppBuffers;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::RequestIntraVOP()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_CONFIG_INTRAREFRESHVOPTYPE vop;
+
+ vop.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetConfig(m_hEncoder,
+ OMX_IndexConfigVideoIntraVOPRefresh,
+ (OMX_PTR) &vop);
+
+ if (result == OMX_ErrorNone)
+ {
+ vop.IntraRefreshVOP = OMX_TRUE;
+ result = OMX_SetConfig(m_hEncoder,
+ OMX_IndexConfigVideoIntraVOPRefresh,
+ (OMX_PTR) &vop);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to get state");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::SetIntraPeriod(OMX_S32 nIntraPeriod)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+#ifdef QCOM_OMX_EXT
+ OMX_QCOM_VIDEO_CONFIG_INTRAPERIODTYPE intra;
+
+ intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
+ result = OMX_GetConfig(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexConfigVideoIntraperiod,
+ (OMX_PTR) &intra);
+
+ if (result == OMX_ErrorNone)
+ {
+ intra.nPFrames = (OMX_U32) nIntraPeriod - 1;
+ result = OMX_SetConfig(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexConfigVideoIntraperiod,
+ (OMX_PTR) &intra);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to get state");
+ }
+#endif
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::ChangeQuality(OMX_S32 nFramerate,
+ OMX_S32 nBitrate,
+ OMX_S32 nMinQp,
+ OMX_S32 nMaxQp)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ (void) nMinQp;
+ (void) nMaxQp;
+
+ //////////////////////////////////////////
+ // frame rate
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_CONFIG_FRAMERATETYPE framerate; // OMX_IndexConfigVideoFramerate
+ framerate.nPortIndex = (OMX_U32) PORT_INDEX_IN; // input
+ result = OMX_GetConfig(m_hEncoder,
+ OMX_IndexConfigVideoFramerate,
+ (OMX_PTR) &framerate);
+ if (result == OMX_ErrorNone)
+ {
+ framerate.xEncodeFramerate = ((OMX_U32) nFramerate) << 16;
+ result = OMX_SetConfig(m_hEncoder,
+ OMX_IndexConfigVideoFramerate,
+ (OMX_PTR) &framerate);
+ }
+ }
+
+ //////////////////////////////////////////
+ // bitrate
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_VIDEO_CONFIG_BITRATETYPE bitrate; // OMX_IndexConfigVideoFramerate
+ bitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ result = OMX_GetConfig(m_hEncoder,
+ OMX_IndexConfigVideoBitrate,
+ (OMX_PTR) &bitrate);
+ if (result == OMX_ErrorNone)
+ {
+ bitrate.nEncodeBitrate = (OMX_U32) nBitrate;
+ result = OMX_SetConfig(m_hEncoder,
+ OMX_IndexConfigVideoBitrate,
+ (OMX_PTR) &bitrate);
+ }
+ }
+#ifdef QCOM_OMX_EXT
+ //////////////////////////////////////////
+ // qp
+ //////////////////////////////////////////
+ if (result == OMX_ErrorNone)
+ {
+ OMX_QCOM_VIDEO_CONFIG_QPRANGE qp; // OMX_QcomIndexConfigVideoQPRange
+ qp.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ result = OMX_GetConfig(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
+ (OMX_PTR) &qp);
+ if (result == OMX_ErrorNone)
+ {
+ qp.nMinQP = (OMX_U32) nMinQp;
+ qp.nMaxQP = (OMX_U32) nMaxQp;
+ result = OMX_SetConfig(m_hEncoder,
+ (OMX_INDEXTYPE) OMX_QcomIndexConfigVideoQPRange,
+ (OMX_PTR) &qp);
+ }
+ }
+#endif
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error changing quality");
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::AllocateBuffers()
+ {
+ int i;
+ OMX_U8 *pBuffer;
+ struct venc_pmem *pMem;
+ void *pVirt;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ m_pInputBuffers = new OMX_BUFFERHEADERTYPE*[m_nInputBuffers];
+ m_pInBufPvtList = new OMX_QCOM_PLATFORM_PRIVATE_LIST[m_nInputBuffers];
+ m_pInBufPmemInfo = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO[m_nInputBuffers];
+ m_pInBufPvtEntry = new OMX_QCOM_PLATFORM_PRIVATE_ENTRY[m_nInputBuffers];
+
+ m_pOutputBuffers = new OMX_BUFFERHEADERTYPE*[m_nOutputBuffers];
+ m_pOutBufPvtList = new OMX_QCOM_PLATFORM_PRIVATE_LIST[m_nOutputBuffers];
+ m_pOutBufPmemInfo = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO[m_nOutputBuffers];
+ m_pOutBufPvtEntry = new OMX_QCOM_PLATFORM_PRIVATE_ENTRY[m_nOutputBuffers];
+ //////////////////////////////////////////
+ // USE BUFFER MODEL
+ //////////////////////////////////////////
+
+ if (m_bInUseBuffer == OMX_TRUE)
+ {
+ VENC_TEST_MSG_MEDIUM("USE BUFFER INPUT: allocating input buffer");
+ // allocate input buffers
+ m_pInMem = new Pmem(m_nInputBuffers);
+ for (i = 0; i < m_nInputBuffers; i++)
+ {
+
+ result = m_pInMem->Allocate(&pBuffer, m_nInputBufferSize, VENC_PMEM_SMI);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error allocating input buffer");
+ break;
+ }
+
+ pMem = (venc_pmem*)pBuffer;
+ pVirt = pMem->virt;
+ /* VENC_TEST_MSG_MEDIUM("allocating input buffer fd:%d, offset:%d ", pBuffer->fd, pBuffer->offset); */
+ result = OMX_UseBuffer(m_hEncoder,
+ &m_pInputBuffers[i],
+ PORT_INDEX_IN, // port index
+ (OMX_PTR)pBuffer, // pAppPrivate
+ m_nInputBufferSize,
+ (OMX_U8 *)pVirt);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error using input buffer");
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Register pmem buffer: hdr=%p, fd%d, offset0x%x",
+ &m_pInputBuffers[i], pMem->fd, pMem->offset);
+ // Set the PMEM Info structure
+ m_pInBufPmemInfo[i].pmem_fd = pMem->fd;
+ m_pInBufPmemInfo[i].offset = pMem->offset;
+
+ //Link the entry structure pmem Info
+ m_pInBufPvtEntry[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ m_pInBufPvtEntry[i].entry = &m_pInBufPmemInfo[i];
+
+ // Initialize the List structure to have one entry
+ m_pInBufPvtList[i].nEntries = 1;
+ m_pInBufPvtList[i].entryList = &m_pInBufPvtEntry[i];
+
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* private_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* )malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO));
+ private_info->pmem_fd = pMem->fd;
+ private_info->offset = pMem->offset;
+ m_pInputBuffers[i]->pPlatformPrivate = (OMX_PTR)private_info;
+
+ VENC_TEST_MSG_HIGH("Test App: entry = %p\n",m_pInBufPvtEntry[i].entry);
+
+ }
+ } else {
+ VENC_TEST_MSG_MEDIUM("ALLOCATE BUFFER INPUT: allocating input buffer");
+ for (i = 0; i < m_nInputBuffers; i++)
+ {
+ result = OMX_AllocateBuffer(m_hEncoder,
+ &m_pInputBuffers[i],
+ PORT_INDEX_IN, // port index
+ this, // pAppPrivate
+ m_nInputBufferSize);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error allocating input buffer");
+ break;
+ }
+ }
+ }
+
+ if (m_bOutUseBuffer == OMX_TRUE) {
+ VENC_TEST_MSG_MEDIUM("USE BUFFER OUTPUT: allocating output");
+ // allocate output buffers
+ m_pOutMem = new Pmem(m_nOutputBuffers);
+ for (i = 0; i < m_nOutputBuffers; i++)
+ {
+ result = m_pOutMem->Allocate(&pBuffer, m_nOutputBufferSize, VENC_PMEM_SMI);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error allocating output buffer");
+ break;
+ }
+
+ pMem = (venc_pmem*)pBuffer;
+ pVirt = pMem->virt;
+ result = OMX_UseBuffer(m_hEncoder,
+ &m_pOutputBuffers[i],
+ PORT_INDEX_OUT, // port index
+ (OMX_PTR)pBuffer, // pAppPrivate
+ m_nOutputBufferSize,
+ (OMX_U8 *)pVirt);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error using output buffer");
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Register pmem buffer: hdr=%p, fd%d, offset0x%x",
+ &m_pOutputBuffers[i], pMem->fd, pMem->offset);
+ // Set the PMEM Info structure
+ m_pOutBufPmemInfo[i].pmem_fd = pMem->fd;
+ m_pOutBufPmemInfo[i].offset = pMem->offset;
+
+ //Link the entry structure pmem Info
+ m_pOutBufPvtEntry[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ m_pOutBufPvtEntry[i].entry = &m_pOutBufPmemInfo[i];
+
+ // Initialize the List structure to have one entry
+ m_pOutBufPvtList[i].nEntries = 1;
+ m_pOutBufPvtList[i].entryList = &m_pOutBufPvtEntry[i];
+
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* private_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* )malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO));
+ private_info->pmem_fd = pMem->fd;
+ private_info->offset = pMem->offset;
+ m_pOutputBuffers[i]->pPlatformPrivate = (OMX_PTR)private_info;
+ }
+ } else {
+ VENC_TEST_MSG_MEDIUM("ALLOCATE BUFFER OUTPUT: allocating output");
+ // allocate output buffers
+ for (i = 0; i < m_nOutputBuffers; i++)
+ {
+ result = OMX_AllocateBuffer(m_hEncoder,
+ &m_pOutputBuffers[i],
+ PORT_INDEX_OUT, // port index
+ this, // pAppPrivate
+ m_nOutputBufferSize);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error allocating output buffer");
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::FreeBuffers()
+ {
+ int i;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (m_pInputBuffers)
+ {
+ for (i = 0; i < m_nInputBuffers; i++)
+ {
+ VENC_TEST_MSG_MEDIUM("freeing input buffer %d", i);
+
+ result = OMX_FreeBuffer(m_hEncoder,
+ PORT_INDEX_IN, // port index
+ m_pInputBuffers[i]);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error freeing input buffer");
+ }
+ if (m_bInUseBuffer == OMX_TRUE)
+ {
+ result = m_pInMem->Free((OMX_U8 *)m_pInputBuffers[i]->pAppPrivate);
+ }
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error freeing input pmem");
+ }
+ }
+
+ delete [] m_pInputBuffers;
+ delete [] m_pInBufPvtList;
+ delete [] m_pInBufPmemInfo;
+ delete [] m_pInBufPvtEntry;
+
+ m_pInputBuffers = NULL;
+ m_pInBufPvtList = NULL;
+ m_pInBufPmemInfo = NULL;
+ m_pInBufPvtEntry = NULL;
+ }
+
+ // free output buffers
+ if (m_pOutputBuffers)
+ {
+ for (i = 0; i < m_nOutputBuffers; i++)
+ {
+ VENC_TEST_MSG_MEDIUM("freeing output buffer %d", i);
+ result = OMX_FreeBuffer(m_hEncoder,
+ PORT_INDEX_OUT, // port index
+ m_pOutputBuffers[i]);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error freeing output buffer");
+ }
+
+ if (m_bOutUseBuffer == OMX_TRUE)
+ {
+ result = m_pOutMem->Free((OMX_U8*)m_pOutputBuffers[i]->pAppPrivate);
+ }
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error freeing output pmem");
+ }
+ }
+ delete [] m_pOutputBuffers;
+ m_pOutputBuffers = NULL;
+ delete [] m_pOutBufPvtList;
+ m_pOutBufPvtList = NULL;
+ delete [] m_pOutBufPmemInfo;
+ m_pOutBufPmemInfo = NULL;
+ delete [] m_pOutBufPvtEntry;
+ m_pOutBufPvtEntry = NULL;
+ }
+
+ if (m_pInMem)
+ delete m_pInMem;
+ m_pInMem = NULL;
+
+ if (m_pOutMem)
+ delete m_pOutMem;
+ m_pOutMem = NULL;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::SetState(OMX_STATETYPE eState,
+ OMX_BOOL bSynchronous)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ result = OMX_SendCommand(m_hEncoder,
+ OMX_CommandStateSet,
+ (OMX_U32) eState,
+ NULL);
+
+ if (result == OMX_ErrorNone)
+ {
+ if (result == OMX_ErrorNone)
+ {
+ if (bSynchronous == OMX_TRUE)
+ {
+ result = WaitState(eState);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to wait state");
+ }
+ }
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to set state");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::WaitState(OMX_STATETYPE eState)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ CmdType cmd;
+
+ (void) m_pSignalQueue->Pop(&cmd, sizeof(cmd), 0); // infinite wait
+ result = cmd.eResult;
+
+ if (cmd.eEvent == OMX_EventCmdComplete)
+ {
+ if (cmd.eCmd == OMX_CommandStateSet)
+ {
+ if ((OMX_STATETYPE) cmd.sCmdData == eState)
+ {
+ m_eState = (OMX_STATETYPE) cmd.sCmdData;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("wrong state (%d)", (int) cmd.sCmdData);
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("expecting state change");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("expecting cmd complete");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::Flush()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ result = OMX_SendCommand(m_hEncoder,
+ OMX_CommandFlush,
+ OMX_ALL,
+ NULL);
+ if (result == OMX_ErrorNone)
+ {
+ CmdType cmd;
+ if (m_pSignalQueue->Pop(&cmd, sizeof(cmd), 0) != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error popping signal");
+ }
+ result = cmd.eResult;
+ if (cmd.eEvent != OMX_EventCmdComplete || cmd.eCmd != OMX_CommandFlush)
+ {
+ VENC_TEST_MSG_ERROR("expecting flush");
+ result = OMX_ErrorUndefined;
+ }
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to wait for flush");
+ result = OMX_ErrorUndefined;
+ }
+ else
+ {
+ if (m_pSignalQueue->Pop(&cmd, sizeof(cmd), 0) != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error popping signal");
+ }
+ else
+ {
+ result = cmd.eResult;
+ if (cmd.eEvent != OMX_EventCmdComplete || cmd.eCmd != OMX_CommandFlush)
+ {
+ VENC_TEST_MSG_ERROR("expecting flush");
+ result = OMX_ErrorUndefined;
+ }
+ }
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to wait for flush");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to set state");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::EventCallback(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (eEvent == OMX_EventCmdComplete)
+ {
+ if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet)
+ {
+ VENC_TEST_MSG_MEDIUM("Event callback with state change");
+
+ switch ((OMX_STATETYPE) nData2)
+ {
+ case OMX_StateLoaded:
+ VENC_TEST_MSG_HIGH("state status OMX_StateLoaded");
+ break;
+ case OMX_StateIdle:
+ VENC_TEST_MSG_HIGH("state status OMX_StateIdle");
+ break;
+ case OMX_StateExecuting:
+ VENC_TEST_MSG_HIGH("state status OMX_StateExecuting");
+ break;
+ case OMX_StatePause:
+ VENC_TEST_MSG_HIGH("state status OMX_StatePause");
+ break;
+ case OMX_StateInvalid:
+ VENC_TEST_MSG_HIGH("state status OMX_StateInvalid");
+ break;
+ case OMX_StateWaitForResources:
+ VENC_TEST_MSG_HIGH("state status OMX_StateWaitForResources");
+ break;
+ default:
+ VENC_TEST_MSG_HIGH("state status Invalid");
+ break;
+ }
+
+ CmdType cmd;
+ cmd.eEvent = OMX_EventCmdComplete;
+ cmd.eCmd = OMX_CommandStateSet;
+ cmd.sCmdData = nData2;
+ cmd.eResult = result;
+
+ if (((Encoder*) pAppData)->m_eState != OMX_StateExecuting &&
+ (OMX_STATETYPE) nData2 == OMX_StateExecuting)
+ {
+ // we are entering the execute state
+ ((Encoder*) pAppData)->m_pStats->Start();
+ }
+ else if (((Encoder*) pAppData)->m_eState == OMX_StateExecuting &&
+ (OMX_STATETYPE) nData2 != OMX_StateExecuting)
+ {
+ // we are leaving the execute state
+ ((Encoder*) pAppData)->m_pStats->Finish();
+ }
+
+ result = ((Encoder*) pAppData)->m_pSignalQueue->Push(&cmd, sizeof(cmd));
+ }
+ else if ((OMX_COMMANDTYPE) nData1 == OMX_CommandFlush)
+ {
+ VENC_TEST_MSG_MEDIUM("Event callback with flush status");
+ VENC_TEST_MSG_HIGH("flush status");
+
+ CmdType cmd;
+ cmd.eEvent = OMX_EventCmdComplete;
+ cmd.eCmd = OMX_CommandFlush;
+ cmd.sCmdData = 0;
+ cmd.eResult = result;
+ result = ((Encoder*) pAppData)->m_pSignalQueue->Push(&cmd, sizeof(cmd));
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("error status");
+ VENC_TEST_MSG_ERROR("Unimplemented command");
+ }
+ }
+ else if (eEvent == OMX_EventError)
+ {
+ VENC_TEST_MSG_ERROR("async error");
+ CmdType cmd;
+ cmd.eEvent = OMX_EventError;
+ cmd.eCmd = OMX_CommandMax;
+ cmd.sCmdData = 0;
+ cmd.eResult = (OMX_ERRORTYPE) nData1;
+ result = ((Encoder*) pAppData)->m_pSignalQueue->Push(&cmd, sizeof(cmd));
+ }
+ else if (eEvent == OMX_EventBufferFlag)
+ {
+ VENC_TEST_MSG_MEDIUM("got buffer flag event");
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Unimplemented event");
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::EmptyDoneCallback(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ VENC_TEST_MSG_MEDIUM("releasing input frame %ld", ((Encoder*) pAppData)->m_nInFrameOut);
+ if (((Encoder*) pAppData)->m_pEmptyDoneFn)
+ {
+ ((Encoder*) pAppData)->m_pEmptyDoneFn(hComponent,
+ ((Encoder*) pAppData)->m_pAppData, // forward the client from constructor
+ pBuffer);
+ }
+ ++((Encoder*) pAppData)->m_nInFrameOut;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Encoder::FillDoneCallback(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ VENC_TEST_MSG_MEDIUM("releasing output frame %ld", ((Encoder*) pAppData)->m_nOutFrameOut);
+
+ if (((Encoder*) pAppData)->m_pStats != NULL)
+ {
+ (void) ((Encoder*) pAppData)->m_pStats->SetOutputStats(pBuffer);
+ }
+
+ if (((Encoder*) pAppData)->m_pFillDoneFn)
+ {
+ ((Encoder*) pAppData)->m_pFillDoneFn(hComponent,
+ ((Encoder*) pAppData)->m_pAppData, // forward the client from constructor
+ pBuffer);
+ }
+ ++((Encoder*) pAppData)->m_nOutFrameOut;
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_File.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_File.cpp
new file mode 100644
index 0000000..3a2cdcf
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_File.cpp
@@ -0,0 +1,215 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_File.h"
+#include "venc_file.h"
+
+namespace venctest
+{
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ File::File()
+ : m_pFile(NULL),
+ m_bReadOnly(OMX_TRUE)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ File::~File()
+ {
+ if (m_pFile)
+ venc_file_close(m_pFile);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE File::Open(OMX_STRING pFileName,
+ OMX_BOOL bReadOnly)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pFileName != NULL)
+ {
+ if (m_pFile == NULL)
+ {
+ int ret;
+ m_bReadOnly = bReadOnly;
+ if (bReadOnly == OMX_TRUE)
+ {
+ ret = venc_file_open(&m_pFile, (char*) pFileName, 1);
+ }
+ else
+ {
+ ret = venc_file_open(&m_pFile, (char*) pFileName, 0);
+ }
+
+ if (ret != 0)
+ {
+ VENC_TEST_MSG_ERROR("Unable to open file");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("File is already open");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE File::Read(OMX_U8* pBuffer,
+ OMX_S32 nBytes,
+ OMX_S32* pBytesRead)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (m_bReadOnly == OMX_TRUE)
+ {
+ if (pBuffer != NULL)
+ {
+ if (nBytes > 0)
+ {
+ if (pBytesRead != NULL)
+ {
+ *pBytesRead = (OMX_S32) venc_file_read(m_pFile, (void*) pBuffer, (int) nBytes);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Null param");
+ result = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Bytes must be > 0");
+ result = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Null param");
+ result = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("File is open for writing");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE File::Write(OMX_U8* pBuffer,
+ OMX_U32 nBytes,
+ OMX_U32* pBytesWritten)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (m_bReadOnly == OMX_FALSE)
+ {
+ if (pBuffer != NULL)
+ {
+ if (nBytes > 0)
+ {
+ if (pBytesWritten != NULL)
+ {
+ *pBytesWritten = venc_file_write(m_pFile, (void*) pBuffer, (int) nBytes);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Null param");
+ result = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Bytes must be > 0");
+ result = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Null param");
+ result = OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("File is open for reading");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE File::SeekStart(OMX_S32 nBytes)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (nBytes >= 0)
+ {
+ if (venc_file_seek_start(m_pFile, (int) nBytes) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to seek");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE File::Close()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (m_pFile != NULL)
+ {
+ venc_file_close(m_pFile);
+ m_pFile = NULL;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("File was already closed");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_FileSink.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_FileSink.cpp
new file mode 100644
index 0000000..d2bbac3
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_FileSink.cpp
@@ -0,0 +1,315 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_Thread.h"
+#include "venctest_SignalQueue.h"
+#include "venctest_File.h"
+#include "venctest_Time.h"
+#include "venctest_FileSink.h"
+#include "venctest_Parser.h"
+
+namespace venctest
+{
+ static const OMX_S32 MAX_BUFFER_ASSUME = 16;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ FileSink::FileSink()
+ : m_nFrames(0),
+ m_pFile(),
+ m_pBufferQueue(new SignalQueue(MAX_BUFFER_ASSUME, sizeof(OMX_BUFFERHEADERTYPE*))),
+ m_pThread(new Thread()),
+ m_bStarted(OMX_FALSE),
+ m_pFrameReleaseFn(NULL)
+ {
+ VENC_TEST_MSG_LOW("created sink");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ FileSink::~FileSink()
+ {
+ if (m_pFile != NULL)
+ {
+ (void) m_pFile->Close();
+ delete m_pFile;
+ }
+ if (m_pBufferQueue != NULL)
+ {
+ delete m_pBufferQueue;
+ }
+ if (m_pThread != NULL)
+ {
+ delete m_pThread;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSink::Configure(OMX_S32 nFrames,
+ OMX_STRING pFileName,
+ OMX_S32 nTestNum,
+ FrameReleaseFnType pFrameReleaseFn)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (nFrames >= 0 &&
+ pFrameReleaseFn != NULL)
+ {
+ m_nFrames = nFrames;
+ m_pFrameReleaseFn = pFrameReleaseFn;
+
+ if (pFileName != NULL &&
+ Parser::StringICompare((OMX_STRING)"", pFileName) != 0)
+ {
+ (void) Parser::AppendTestNum(pFileName, nTestNum);
+
+ m_pFile = new File();
+ if (m_pFile != NULL)
+ {
+ VENC_TEST_MSG_MEDIUM("Opening output file...");
+ result = m_pFile->Open(pFileName, OMX_FALSE);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("Failed to open file");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Failed to allocate file");
+ result = OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_MEDIUM("No output file");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Bad param(s)");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSink::Write(OMX_BUFFERHEADERTYPE* pBufferHdr)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pBufferHdr != NULL && pBufferHdr->pBuffer != NULL)
+ {
+ result = m_pBufferQueue->Push(&pBufferHdr,
+ sizeof(OMX_BUFFERHEADERTYPE**));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to push buffer");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad params");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSink::Start()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // make sure we've been configured
+ if (m_nFrames >= 0)
+ {
+ VENC_TEST_MSG_MEDIUM("starting thread...");
+ result = m_pThread->Start(SinkThreadEntry, // thread fn
+ this, // thread data
+ 0); // thread priority
+ if (result == OMX_ErrorNone)
+ {
+ m_bStarted = OMX_TRUE;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to start thread");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("source has not been configured");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSink::Finish()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (m_bStarted == OMX_TRUE)
+ {
+ if (m_pThread != NULL)
+ {
+ OMX_ERRORTYPE threadResult;
+
+ VENC_TEST_MSG_MEDIUM("waiting for thread to finish...");
+
+ // wait for thread to exit
+ result = m_pThread->Join(&threadResult);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = threadResult;
+ }
+
+ if (threadResult != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("sink thread execution error");
+ }
+ }
+
+ m_bStarted = OMX_FALSE;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("already stopped");
+ result = OMX_ErrorIncorrectStateTransition;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSink::SinkThreadEntry(OMX_PTR pThreadData)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorBadParameter;
+ if (pThreadData)
+ {
+ result = ((FileSink*) pThreadData)->SinkThread();
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSink::SinkThread()
+ {
+ OMX_BOOL bKeepGoing = OMX_TRUE;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ VENC_TEST_MSG_MEDIUM("thread has started");
+
+ for (OMX_S32 i = 0; i < m_nFrames && bKeepGoing == OMX_TRUE; i++)
+ {
+
+ OMX_BUFFERHEADERTYPE* pBufferHdr = NULL;
+
+ result = m_pBufferQueue->Pop(&pBufferHdr,
+ sizeof(pBufferHdr),
+ 0); // wait forever
+
+ if (result == OMX_ErrorNone)
+ {
+ if (pBufferHdr != NULL)
+ {
+ OMX_U32 nBytes;
+
+ if (m_pFile != NULL)
+ {
+ if (pBufferHdr->nFilledLen > 0)
+ {
+ VENC_TEST_MSG_MEDIUM("writing frame %ld with %lu bytes...", i, pBufferHdr->nFilledLen);
+ result = m_pFile->Write((OMX_U8 *)pBufferHdr->pBuffer,
+ pBufferHdr->nFilledLen,
+ &nBytes);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error writing to file...");
+ }
+ else if (nBytes != pBufferHdr->nFilledLen)
+ {
+ VENC_TEST_MSG_ERROR("mismatched number of bytes in file write");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("skipping frame %ld...",i);
+ }
+
+ }
+ else
+ {
+ VENC_TEST_MSG_MEDIUM("received frame %ld...",i);
+ }
+
+ if (pBufferHdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
+ {
+ // this is just the syntax header, not a frame so increase loop count
+ VENC_TEST_MSG_HIGH("got codecconfig");
+ ++m_nFrames;
+ }
+
+ if (pBufferHdr->nFlags & OMX_BUFFERFLAG_EOS)
+ {
+ // this is the last frame. note that we may get fewer frames
+ // than expected if RC is enabled with frame skips
+ VENC_TEST_MSG_HIGH("got eos");
+ bKeepGoing = OMX_FALSE;
+ }
+
+ m_pFrameReleaseFn(pBufferHdr);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Buffer is null");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Error getting buffer");
+ bKeepGoing = OMX_FALSE;
+ }
+ }
+ VENC_TEST_MSG_HIGH("Sink thread is exiting...");
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_FileSource.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_FileSource.cpp
new file mode 100644
index 0000000..ee50c5d
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_FileSource.cpp
@@ -0,0 +1,416 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_Thread.h"
+#include "venctest_SignalQueue.h"
+#include "venctest_Sleeper.h"
+#include "venctest_File.h"
+#include "venctest_Time.h"
+#include "venctest_FileSource.h"
+
+namespace venctest
+{
+ static const OMX_S32 MAX_BUFFER_ASSUME = 16;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ FileSource::FileSource()
+ : m_nFrames(0),
+ m_nFramesRegistered(0),
+ m_nFramerate(0),
+ m_nFrameWidth(0),
+ m_nFrameHeight(0),
+ m_nBuffers(0),
+ m_nDVSXOffset(0),
+ m_nDVSYOffset(0),
+ m_pFile(NULL),
+ m_pBufferQueue(new SignalQueue(MAX_BUFFER_ASSUME, sizeof(OMX_BUFFERHEADERTYPE*))),
+ m_pThread(new Thread()),
+ m_bStarted(OMX_FALSE),
+ m_pFrameDeliverFn(NULL)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ FileSource::~FileSource()
+ {
+ if (m_pFile != NULL)
+ {
+ (void) m_pFile->Close();
+ delete m_pFile;
+ }
+ if (m_pBufferQueue != NULL)
+ {
+ delete m_pBufferQueue;
+ }
+ if (m_pThread != NULL)
+ {
+ delete m_pThread;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::Configure(OMX_S32 nFrames,
+ OMX_S32 nFramerate,
+ OMX_S32 nFrameWidth,
+ OMX_S32 nFrameHeight,
+ OMX_S32 nBuffers,
+ FrameDeliveryFnType pFrameDeliverFn,
+ OMX_STRING pFileName,
+ OMX_S32 nDVSXOffset,
+ OMX_S32 nDVSYOffset,
+ OMX_BOOL bLiveMode)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (nFrames >= 0 &&
+ nFramerate > 0 &&
+ nFrameWidth > 0 &&
+ nFrameHeight > 0 &&
+ nDVSXOffset >= 0 &&
+ nDVSYOffset >= 0 &&
+ nBuffers > 0 &&
+ nBuffers <= MAX_BUFFER_ASSUME &&
+ pFrameDeliverFn != NULL)
+ {
+ m_nFrames = nFrames;
+ m_nFramerate = nFramerate;
+ m_nFrameWidth = nFrameWidth;
+ m_nFrameHeight = nFrameHeight;
+ m_nBuffers = nBuffers;
+ m_nDVSXOffset = nDVSXOffset;
+ m_nDVSYOffset = nDVSYOffset;
+ m_pFrameDeliverFn = pFrameDeliverFn;
+ m_bLiveMode = bLiveMode;
+
+ if (pFileName != NULL)
+ {
+ m_pFile = new File();
+ if (m_pFile != NULL)
+ {
+ result = m_pFile->Open(pFileName, OMX_TRUE);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("Failed to open file");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Failed to allocate file");
+ result = OMX_ErrorInsufficientResources;
+ }
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad params");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::ChangeFrameRate(OMX_S32 nFramerate)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (nFramerate > 0)
+ {
+ m_nFramerate = nFramerate;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad frame rate");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::Start()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // make sure we've been configured
+ if (m_nFrames >= 0 &&
+ m_nFramerate >= 0 &&
+ m_nBuffers > 0)
+ {
+ if (m_nFramesRegistered == m_nBuffers)
+ {
+
+ VENC_TEST_MSG_MEDIUM("starting thread...");
+
+ result = m_pThread->Start(SourceThreadEntry, // thread fn
+ this, // thread data
+ 0); // thread priority
+
+ if (result == OMX_ErrorNone)
+ {
+ m_bStarted = OMX_TRUE;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to start thread");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("need to register all buffers with the source");
+ result = OMX_ErrorUndefined;
+ }
+
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("source has not been configured");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::Finish()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (m_bStarted == OMX_TRUE)
+ {
+ if (m_pThread != NULL)
+ {
+ OMX_ERRORTYPE threadResult;
+
+ VENC_TEST_MSG_MEDIUM("waiting for thread to finish...");
+
+ // wait for thread to exit
+ result = m_pThread->Join(&threadResult);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = threadResult;
+ }
+
+ if (threadResult != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("source thread execution error");
+ }
+ }
+
+ m_bStarted = OMX_FALSE;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("already stopped");
+ result = OMX_ErrorIncorrectStateTransition;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::SetFreeBuffer(OMX_BUFFERHEADERTYPE* pBufferHdr)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pBufferHdr != NULL && pBufferHdr->pBuffer != NULL)
+ {
+ // if we have not started then the client is registering buffers
+ if (m_bStarted == OMX_FALSE)
+ {
+ // need to fill the buffer with YUV data upon registration
+ if (m_nFramesRegistered < m_nBuffers &&
+ m_bLiveMode == OMX_TRUE)
+ {
+
+ VENC_TEST_MSG_MEDIUM("register buffer");
+
+ if (m_pFile)
+ {
+ OMX_S32 nFrameBytes = m_nFrameWidth * m_nFrameHeight * 3 / 2;
+ OMX_S32 nBytesRead;
+ result = m_pFile->Read((OMX_U8*)pBufferHdr->pBuffer,
+ nFrameBytes,
+ &nBytesRead);
+ if (result != OMX_ErrorNone ||
+ nBytesRead != nFrameBytes)
+ {
+ VENC_TEST_MSG_HIGH("yuv file is too small"
+ "result(%d) nFrameBytes(%ld) nBytesRead(%ld)",
+ result, nFrameBytes, nBytesRead);
+ result = m_pFile->SeekStart(0);
+ result = m_pFile->Read((OMX_U8 *)pBufferHdr->pBuffer,
+ nFrameBytes,
+ &nBytesRead);
+ }
+ }
+ }
+
+ ++m_nFramesRegistered;
+ }
+ result = m_pBufferQueue->Push(&pBufferHdr,
+ sizeof(OMX_BUFFERHEADERTYPE**));
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad params");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::SourceThreadEntry(OMX_PTR pThreadData)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorBadParameter;
+ if (pThreadData)
+ {
+ result = ((FileSource*) pThreadData)->SourceThread();
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE FileSource::SourceThread()
+ {
+ OMX_BOOL bKeepGoing = OMX_TRUE;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_TICKS nTimeStamp = 0;
+
+ VENC_TEST_MSG_MEDIUM("thread has started");
+
+ for (OMX_S32 i = 0; i < m_nFrames && bKeepGoing == OMX_TRUE; i++)
+ {
+
+ OMX_BUFFERHEADERTYPE* pBufferHdr = NULL;
+ const OMX_S32 nFrameBytes = m_nFrameWidth * m_nFrameHeight * 3 / 2;
+
+ // Since frame rate can change at any time, let's make sure that we use
+ // the same frame rate for the duration of this loop iteration
+ OMX_S32 nFramerate = m_nFramerate;
+
+ // If in live mode we deliver frames in a real-time fashion
+ if (m_bLiveMode == OMX_TRUE)
+ {
+ Sleeper::Sleep(1000 / nFramerate);
+
+ if (m_pBufferQueue->GetSize() <= 0)
+ {
+ VENC_TEST_MSG_MEDIUM("No buffers. Block until buffer available...");
+ }
+
+ VENC_TEST_MSG_MEDIUM("Wait for free buffer...");
+
+ result = m_pBufferQueue->Pop(&pBufferHdr,
+ sizeof(pBufferHdr),
+ 0); // wait forever
+ }
+
+ // if not in live mode, we deliver frames as they become available
+ else
+ {
+ result = m_pBufferQueue->Pop(&pBufferHdr,
+ sizeof(pBufferHdr),
+ 0); // wait forever
+ if (m_pFile != NULL)
+ {
+ OMX_S32 nBytesRead;
+ result = m_pFile->Read((OMX_U8 *)pBufferHdr->pBuffer,
+ nFrameBytes,
+ &nBytesRead);
+ if (result != OMX_ErrorNone ||
+ nBytesRead != nFrameBytes)
+ {
+ VENC_TEST_MSG_HIGH("yuv file is too small"
+ "result:%d,nFrameBytse(%ld),nBytesRead(%ld)",
+ result, nFrameBytes, nBytesRead);
+
+ VENC_TEST_MSG_HIGH("buffer virt %p \n", pBufferHdr->pBuffer);
+ result = m_pFile->SeekStart(0);
+ result = m_pFile->Read((OMX_U8 *)pBufferHdr->pBuffer,
+ nFrameBytes,
+ &nBytesRead);
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ if (pBufferHdr != NULL)
+ {
+ VENC_TEST_MSG_MEDIUM("delivering frame %ld...",i);
+
+ if (m_bLiveMode == OMX_TRUE)
+ {
+ nTimeStamp = (OMX_TICKS) Time::GetTimeMicrosec();
+ }
+ else
+ {
+ nTimeStamp = nTimeStamp + (OMX_TICKS) (1000000 / nFramerate);
+ }
+
+ pBufferHdr->nFilledLen = nFrameBytes;
+ pBufferHdr->nTimeStamp = nTimeStamp;
+
+ // set the EOS flag if this is the last frame
+ pBufferHdr->nFlags = 0;
+ if (i == m_nFrames - 1)
+ {
+ pBufferHdr->nFlags = OMX_BUFFERFLAG_EOS;
+ }
+
+ pBufferHdr->nOffset = ((m_nFrameWidth * m_nDVSYOffset) + m_nDVSXOffset) * 3 / 2;
+ m_pFrameDeliverFn(pBufferHdr);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Buffer is null");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Error getting buffer");
+ bKeepGoing = OMX_FALSE;
+ }
+ }
+ VENC_TEST_MSG_HIGH("Source thread is exiting...");
+ return result;
+ }
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_ITestCase.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_ITestCase.cpp
new file mode 100644
index 0000000..edc15f2
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_ITestCase.cpp
@@ -0,0 +1,185 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ITestCase.h"
+#include "venctest_Thread.h"
+#include "venctest_Debug.h"
+#include "venctest_Parser.h"
+
+// test case object headers
+#include "venctest_TestChangeIntraPeriod.h"
+#include "venctest_TestChangeQuality.h"
+#include "venctest_TestEOS.h"
+#include "venctest_TestGetSyntaxHdr.h"
+#include "venctest_TestIFrameRequest.h"
+#include "venctest_TestPmem.h"
+#include "venctest_TestProfileEncode.h"
+#include "venctest_TestSerialEncode.h"
+#include "venctest_TestStateExecutingToIdle.h"
+#include "venctest_Config.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ ITestCase::ITestCase()
+ : m_pThread(new Thread()),
+ m_eTestResult(OMX_ErrorNone),
+ m_nTestNum(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ ITestCase::~ITestCase()
+ {
+ if (m_pThread)
+ {
+ delete m_pThread;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE ITestCase::Start(OMX_STRING pConfigFileName,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ Config config;
+ config.GetEncoderConfig(&m_sConfig);
+ config.GetDynamicConfig(&m_sDynamicConfig);
+
+ m_nTestNum = nTestNum;
+
+ result = config.Parse(pConfigFileName, &m_sConfig, &m_sDynamicConfig);
+ if (result == OMX_ErrorNone)
+ {
+ result = ValidateAssumptions(&m_sConfig, &m_sDynamicConfig);
+
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_MEDIUM("Starting test thread...");
+ if (m_pThread)
+ {
+ result = m_pThread->Start(ThreadEntry, // thread entry
+ this, // thread args
+ 0); // priority
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Start test thread failed...");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Invalid config. Assumptions not validated");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Error parsing config file");
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE ITestCase::Finish()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorUndefined;
+
+ if (m_pThread)
+ {
+ OMX_ERRORTYPE threadResult;
+
+ VENC_TEST_MSG_MEDIUM("waiting for thread to finish...");
+
+ // wait for thread to exit
+ result = m_pThread->Join(&threadResult);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = threadResult;
+ }
+
+ if (threadResult != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("test case thread execution error");
+ }
+ }
+
+ // let's not over-ride the original error with a different result
+ if (m_eTestResult == OMX_ErrorNone)
+ {
+ m_eTestResult = result;
+ }
+
+ return m_eTestResult;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE ITestCase::CheckError(OMX_ERRORTYPE eTestResult)
+ {
+ // The first error we encounter (if one actually occurs) is the final test result.
+ // Do not over-ride the original error!
+ if (m_eTestResult == OMX_ErrorNone)
+ {
+ m_eTestResult = eTestResult;
+ }
+
+ // Simply return the result that was passed in
+ return eTestResult;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE ITestCase::ThreadEntry(OMX_PTR pThreadData)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ ITestCase* pTest = (ITestCase*) pThreadData;
+ result = pTest->Execute(&pTest->m_sConfig, &pTest->m_sDynamicConfig,
+ pTest->m_nTestNum);
+
+ if (pTest->m_eTestResult == OMX_ErrorNone)
+ {
+ result = pTest->m_eTestResult;
+ }
+
+ return pTest->m_eTestResult;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Mutex.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Mutex.cpp
new file mode 100644
index 0000000..4e758d9
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Mutex.cpp
@@ -0,0 +1,86 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Mutex.h"
+#include "venctest_Debug.h"
+#include "venc_mutex.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Mutex::Mutex() :
+ m_pMutex(NULL)
+ {
+ if (venc_mutex_create(&m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to init mutex");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Mutex::~Mutex()
+ {
+ if (venc_mutex_destroy(m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to destroy mutex");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Mutex::Lock()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (venc_mutex_lock(m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to lock mutex");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Mutex::UnLock()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (venc_mutex_unlock(m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to unlock mutex");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+}
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Parser.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Parser.cpp
new file mode 100644
index 0000000..11a8c36
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Parser.cpp
@@ -0,0 +1,401 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Parser.h"
+#include "venctest_File.h"
+#include "venctest_Debug.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <cctype>
+#include <string.h>
+
+namespace venctest
+{
+
+ ParserStrVector::ParserStrVector()
+ : count(0)
+ {
+ clear();
+ }
+
+ ParserStrVector::~ParserStrVector()
+ {
+ clear();
+ }
+
+ OMX_S32 ParserStrVector::size() { return count; }
+
+ void ParserStrVector::clear()
+ {
+ count = 0;
+ }
+
+ OMX_STRING ParserStrVector::operator[] (OMX_S32 i)
+ {
+ if (i < count)
+ {
+ return pStr[i];
+ }
+ else
+ {
+ return (OMX_STRING) NULL;
+ }
+ }
+
+ void ParserStrVector::push_back(OMX_STRING s)
+ {
+ if (count < ParserMaxStrings)
+ {
+ pStr[count++] = s;
+ }
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_S32 Parser::ReadLine(File* pFile,
+ OMX_S32 nMaxRead,
+ OMX_STRING pBuf)
+ {
+ OMX_S32 nTotal = 0; // total number of chars read
+ OMX_S32 nRead = 0; // fread return value
+ OMX_S32 numChars = 0; // number of chars read excluding \r\n
+ OMX_S32 keepGoing = 1;
+
+ pFile->Read((OMX_U8*) &pBuf[nTotal], 1, &nRead);
+ while (keepGoing &&
+ nTotal < nMaxRead &&
+ nRead > 0)
+ {
+ switch (pBuf[nTotal])
+ {
+ case '\n':
+ keepGoing = 0;
+ case '\r':
+ pBuf[nTotal] = (char) 0;
+ break;
+ default:
+ numChars++;
+ }
+
+ nTotal++;
+ if (keepGoing)
+ {
+ pFile->Read((OMX_U8*) &pBuf[nTotal], 1, &nRead);
+ }
+ }
+
+ // terminate string
+ pBuf[numChars] = 0;
+
+ // we have reached the end of the file
+ // and nothing was read
+ if (nRead <= 0 && nTotal == 0)
+ {
+ return -1;
+ }
+
+ // several cases:
+ // 1. end of line with chars read (return n)
+ // 2. end of line with no chars read (return 0)
+ // 3. end of file with chars read (return n)
+ // next time function is called -1 will be returned
+ return numChars;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Parser::StringToLower(OMX_STRING pStr,
+ OMX_STRING pLowerStr)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_S32 i, l;
+ if (!pStr)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ l = (OMX_S32) strlen(pStr);
+
+ for (i = 0; i < l; i++)
+ {
+ pLowerStr[i] = (char) tolower(pStr[i]);
+ }
+ pLowerStr[i] = (char) 0;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_S32 Parser::StringICompare(OMX_STRING pStr1,
+ OMX_STRING pStr2)
+ {
+ OMX_S32 result = 0;
+ OMX_S32 strl1,strl2;
+
+ strl1 = (OMX_S32) strlen(pStr1);
+ strl2 = (OMX_S32) strlen(pStr2);
+
+ if (strl1 != strl2)
+ {
+ result = 1; // not equal if lenghts are different
+ }
+ else if (strl1 == 0 && strl2 == 0)
+ {
+ result = 0; // equal if empty string
+ }
+ else
+ {
+
+ OMX_STRING pLower1 = (OMX_STRING) malloc(strl1+1);
+ OMX_STRING pLower2 = (OMX_STRING) malloc(strl2+1);
+
+ memcpy(pLower1, pStr1, strl1+1);
+ memcpy(pLower2, pStr2, strl2+1);
+
+ StringToLower(pStr1, pLower1);
+ StringToLower(pStr2, pLower2);
+
+ result = (OMX_S32) strcmp(pLower1, pLower2);
+
+ free(pLower1);
+ free(pLower2);
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Parser::RemoveComments(OMX_STRING pStr)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_STRING p;
+ if (!pStr)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ if ((p = StrChrs(pStr, (OMX_STRING)"#")) != NULL)
+ {
+ *p = 0;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_S32 Parser::TokenizeString(ParserStrVector* pTokens,
+ OMX_STRING pStr,
+ OMX_STRING pDelims)
+ {
+ char* pOut;
+ char* pIn = pStr;
+
+ if (!pTokens || !(pIn = Trim(pIn)) || !pDelims)
+ {
+ return 0;
+ }
+
+ if (*pIn)
+ {
+ pTokens->push_back(pIn);
+ while (*pIn && (pOut = StrChrs(pIn, pDelims)))
+ {
+ if (*pIn == '"' ||
+ *pIn == '\'')
+ {
+ // ignore delimeters in quotes
+ char* pQuote = pIn;
+ int len = (int) strlen(pIn);
+ for (int i = 0; i < len; i++)
+ {
+ ++pIn;
+ if (*pQuote == *pIn)
+ {
+ *pIn = (char) 0;
+ ++pIn;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // advance past the last delimeter
+ for (int i = 0; i < (int) strlen(pDelims); i++)
+ {
+ if (*pOut && *pOut == pDelims[i])
+ {
+ *pOut = 0;
+ pOut++;
+ i = -1;
+ }
+ }
+
+ if (strlen(pOut))
+ {
+ if (*pOut == '\'' || *pOut == '"')
+ {
+ // remove the quotation mark
+ pTokens->push_back(pOut+1);
+ }
+ else
+ {
+ pTokens->push_back(pOut);
+ }
+ }
+ pIn = pOut;
+ }
+ }
+
+ return (OMX_S32) pTokens->size();
+ }
+ return 0;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_STRING Parser::Trim(OMX_STRING pStr)
+ {
+ OMX_STRING pEnd;
+ OMX_STRING pStart;
+ OMX_STRING p;
+
+ if (!pStr)
+ {
+ return 0;
+ }
+
+ pStart = pStr;
+ pEnd = pStr + strlen(pStr) - 1;
+
+ // remove leading whitespace
+ while (*pStart && (*pStart == ' ' || *pStart == '\t'))
+ {
+ pStart++;
+ }
+
+ // remove trailing whitespace
+ p = pEnd;
+ while ((*p) && (*p == ' ' || *p == '\t'))
+ {
+ if (p == pStart)
+ {
+ break;
+ }
+ *p = 0;
+ p--;
+ }
+
+ return pStart;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ OMX_STRING Parser::StrChrs(OMX_STRING pStr,
+ OMX_STRING pDelims)
+ {
+ OMX_S32 nDelim = (OMX_S32) strlen(pDelims);
+ OMX_S32 len = (OMX_S32) strlen(pStr);
+ OMX_STRING ret = 0;
+ OMX_S32 i = 0, j = 0;
+
+ if (len == 0 || nDelim == 0)
+ return ret;
+
+ for (i = 0; i < len; i++)
+ {
+ for (j = 0; j < nDelim; j++)
+ {
+ if (pDelims[j] == pStr[i])
+ {
+ ret = &pStr[i];
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ OMX_ERRORTYPE Parser::AppendTestNum(OMX_STRING pFileName,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+
+ if (pFileName != NULL)
+ {
+ static const OMX_S32 nMaxExtnLen = 64;
+
+ OMX_S32 nMaxFileNameLen = VENC_TEST_MAX_STRING;
+ OMX_STRING pInsert = StrChrs(pFileName, (OMX_STRING) ".");
+
+ // ensure the extension is less than 64 chars
+ if (pInsert != NULL && strlen(pInsert) >= nMaxExtnLen - 1)
+ {
+ // if the file extension is too big then just ignore it
+ // and advance to the end of the string
+ pInsert = NULL;
+ }
+
+ if (pInsert != NULL)
+ {
+ char pExtnCopy[nMaxExtnLen];
+
+ // make a copy of the file extension
+ memcpy(pExtnCopy, (char*) pInsert, strlen((char*) pInsert) + 1);
+
+ nMaxFileNameLen -= ((OMX_S32) pInsert) - ((OMX_S32) pFileName);
+
+ // append the number and the file extension
+ sprintf((char* ) pInsert, "_%05d%s",
+ (int) nTestNum, (char*) pExtnCopy);
+ }
+ else
+ {
+ // we have no file extension so just append the number
+ pInsert = pFileName + strlen((char*) pFileName);
+
+ nMaxFileNameLen -= ((OMX_S32) pInsert) - ((OMX_S32) pFileName);
+
+ sprintf((char* ) pInsert, "_%05d", (int) nTestNum);
+ }
+ }
+ else
+ {
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+ }
+
+} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Pmem.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Pmem.cpp
new file mode 100644
index 0000000..fc0c231
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Pmem.cpp
@@ -0,0 +1,235 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Pmem.h"
+#include "venctest_Debug.h"
+
+#include <string.h>
+
+// pmem include files
+/*
+extern "C"
+{
+ #include "pmem.h"
+}
+*/
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Pmem::Pmem(OMX_S32 nBuffers)
+ : m_nBuffers(nBuffers),
+ m_nBuffersAlloc(0),
+ m_pBufferInfo(new venc_pmem[nBuffers])
+ {
+ if (m_pBufferInfo != NULL)
+ {
+ memset(m_pBufferInfo, 0, sizeof(struct venc_pmem) * nBuffers);
+ }
+ // do nothing
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Pmem::~Pmem()
+ {
+ if (m_pBufferInfo != NULL)
+ {
+ delete [] m_pBufferInfo;
+ }
+ }
+
+ OMX_ERRORTYPE Pmem::pmem_alloc(struct venc_pmem *pBuf, int size, int pmem_region_id)
+ {
+ struct pmem_region region;
+
+ QC_OMX_MSG_HIGH("Opening pmem files with size 0x%x...",size,0,0);
+
+ if (pmem_region_id == VENC_PMEM_EBI1)
+ pBuf->fd = open("/dev/pmem_adsp", O_RDWR);
+ else if (pmem_region_id == VENC_PMEM_SMI)
+ pBuf->fd = open("/dev/pmem_smipool", O_RDWR);
+ else {
+ QC_OMX_MSG_ERROR("Pmem region id not supported \n", pmem_region_id);
+ return OMX_ErrorBadParameter;
+ }
+
+ if (pBuf->fd < 0) {
+ QC_OMX_MSG_ERROR("error could not open pmem device");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ pBuf->offset = 0;
+ pBuf->size = (size + 4095) & (~4095);
+
+ /* QC_OMX_MSG_HIGH("Allocate pmem of size:0x%x, fd:%d \n", pBuf->size, pBuf->fd, 0); */
+ pBuf->virt = mmap(NULL, pBuf->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, pBuf->fd, 0);
+
+ QC_OMX_MSG_HIGH("Allocate pmem of size:0x%x, fd:%d virt:%p\n", pBuf->size, pBuf->fd, pBuf->virt);
+ if (pBuf->virt == MAP_FAILED) {
+ QC_OMX_MSG_ERROR("error mmap failed with size:%d",size);
+ close(pBuf->fd);
+ pBuf->fd = -1;
+ return OMX_ErrorInsufficientResources;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ OMX_ERRORTYPE Pmem::pmem_free(struct venc_pmem* pBuf)
+ {
+ QC_OMX_MSG_HIGH("Free pmem of size:0x%x, fd:%d \n",pBuf->size, pBuf->fd, 0);
+ close(pBuf->fd);
+ pBuf->fd = -1;
+ munmap(pBuf->virt, pBuf->size);
+ pBuf->offset = 0;
+ pBuf->phys = pBuf->virt = NULL;
+ return OMX_ErrorNone;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Pmem::Allocate(OMX_U8 ** ppBuffer,
+ OMX_S32 nBytes, int pmem_region_id)
+ {
+ void *pVirt;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ static const OMX_S32 PMEM_ALIGN = 4096;
+ static const OMX_U32 PMEM_ALIGN_MASK = 0xFFFFF000;
+ OMX_S32 nBytesAlign;
+
+ if (ppBuffer != NULL && nBytes > 0)
+ {
+ if (m_nBuffersAlloc < m_nBuffers)
+ {
+ OMX_S32 i = 0;
+ struct venc_pmem* pBuffer = NULL;
+
+ // look for a free info structure
+ while (pBuffer == NULL)
+ {
+ if (m_pBufferInfo[i].virt == NULL)
+ {
+ pBuffer = &m_pBufferInfo[i];
+ }
+ ++i;
+ }
+
+ if (pBuffer != NULL)
+ {
+ nBytesAlign = (nBytes + 4095) & (~4095);
+ pmem_alloc(pBuffer, nBytesAlign, pmem_region_id);
+
+ pVirt = pBuffer->virt;
+ if (pVirt != NULL)
+ {
+ /* pInfo->pVirt = (OMX_U8*) (((OMX_U32) (pVirt + PMEM_ALIGN)) & PMEM_ALIGN_MASK);
+ pInfo->pVirtBase = pBuf->virt;
+ pInfo->nBytes = nBytes;
+ pInfo->nBytesAlign = nBytesAlign; */
+
+ VENC_TEST_MSG_HIGH("Allocate buffer: fd:%d, offset:%d, pVirt=%p \n", pBuffer->fd,
+ pBuffer->offset, pBuffer->virt);
+ // --susan
+ *ppBuffer = (OMX_U8 *)pBuffer;
+ /* *ppBuffer = (OMX_U8 *)pInfo->virt; */
+ ++m_nBuffersAlloc;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("pmem alloc failed");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("error finding buffer");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("ran out of buffers");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad params");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Pmem::Free(OMX_U8* pBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pBuffer != NULL)
+ {
+ OMX_S32 i = 0;
+ struct venc_pmem* pInfo = NULL;
+
+ // look for a free info structure
+ while (i < m_nBuffers )
+ {
+ if (&m_pBufferInfo[i] == (struct venc_pmem *)pBuffer)
+ {
+ pInfo = &m_pBufferInfo[i];
+ break;
+ }
+ ++i;
+ }
+
+ if (pInfo != NULL)
+ {
+ pmem_free(pInfo);
+ --m_nBuffersAlloc;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("error finding buffer");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("bad params");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Queue.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Queue.cpp
new file mode 100644
index 0000000..2dd8d61
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Queue.cpp
@@ -0,0 +1,131 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Debug.h"
+#include "venctest_Queue.h"
+#include "venc_queue.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Queue::Queue()
+ {
+ VENC_TEST_MSG_ERROR("default constructor should not be here (private)");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Queue::Queue(OMX_S32 nMaxQueueSize,
+ OMX_S32 nMaxDataSize)
+ : m_pHandle(NULL)
+ {
+ VENC_TEST_MSG_LOW("constructor %ld %ld", nMaxQueueSize, nMaxDataSize);
+ if (venc_queue_create((void**) &m_pHandle, (int) nMaxQueueSize, (int) nMaxDataSize) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to create queue");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Queue::~Queue()
+ {
+ VENC_TEST_MSG_LOW("destructor");
+ if (venc_queue_destroy((void*) m_pHandle) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to create queue");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Queue::Pop(OMX_PTR pData,
+ OMX_S32 nDataSize)
+ {
+ VENC_TEST_MSG_LOW("Pop");
+
+ OMX_ERRORTYPE result = Peek(pData, nDataSize);
+
+ if (result == OMX_ErrorNone)
+ {
+ if (venc_queue_pop((void*) m_pHandle, pData, (int) nDataSize) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop queue");
+ result = OMX_ErrorUndefined;
+ }
+ }
+
+ return result;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Queue::Push(OMX_PTR pData,
+ OMX_S32 nDataSize)
+ {
+ VENC_TEST_MSG_LOW("Push");
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (venc_queue_push((void*) m_pHandle, (void*) pData, (int) nDataSize) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to push onto queue");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ OMX_ERRORTYPE Queue::Peek(OMX_PTR pData,
+ OMX_S32 nDataSize)
+ {
+ VENC_TEST_MSG_LOW("Pop");
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (venc_queue_peek((void*) m_pHandle, (void*) pData, (int) nDataSize) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to peek into queue");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_S32 Queue::GetSize()
+ {
+ return (OMX_S32) venc_queue_size((void*) m_pHandle);
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Script.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Script.cpp
new file mode 100644
index 0000000..c9776dd
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Script.cpp
@@ -0,0 +1,146 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Debug.h"
+#include "venctest_Script.h"
+#include "venctest_File.h"
+#include "venctest_Parser.h"
+#include "venctest_ComDef.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Script::Script()
+ : m_pFile(new File)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Script::~Script()
+ {
+ if (m_pFile)
+ {
+ delete m_pFile;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Script::Configure(OMX_STRING pFileName)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (pFileName != NULL)
+ {
+ if (m_pFile)
+ {
+ result = m_pFile->Open(pFileName, OMX_TRUE);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to open file");
+ }
+ }
+ else
+ {
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("null param");
+ result = OMX_ErrorBadParameter;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Script::NextTest(TestDescriptionType* pTestDescription)
+ {
+ static const OMX_S32 maxFieldName = 64;
+ static const OMX_S32 maxLineLen = maxFieldName * 2;
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ ParserStrVector v;
+ OMX_S32 nLine = 0;
+
+ while (result != OMX_ErrorNoMore)
+ {
+ char pBuf[maxLineLen];
+ char* pTrimmed;
+ OMX_S32 nChars = Parser::ReadLine(m_pFile, maxLineLen, pBuf);
+ v.clear();
+ if (nChars > 0)
+ {
+ (void) Parser::RemoveComments(pBuf);
+ pTrimmed = Parser::Trim(pBuf);
+
+ // No empty lines
+ if (strlen(pTrimmed) != 0)
+ {
+ (void) Parser::TokenizeString(&v, pTrimmed, (OMX_STRING)"\t ");
+ if (v.size() == 3)
+ {
+ break;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("badly formatted script file. %ld tokens on line %ld", v.size(), nLine);
+ result = OMX_ErrorUndefined;
+ }
+ }
+ }
+ else if (nChars < 0)
+ {
+ result = OMX_ErrorNoMore;
+ }
+ ++nLine;
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ memcpy(pTestDescription->cTestName, v[0], strlen(v[0])+1);
+
+ memcpy(pTestDescription->cConfigFile, v[1], strlen(v[1])+1);
+
+ pTestDescription->nSession = (OMX_S32) atoi(v[2]);
+ }
+
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Signal.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Signal.cpp
new file mode 100644
index 0000000..c9f996d
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Signal.cpp
@@ -0,0 +1,94 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Signal.h"
+#include "venctest_Debug.h"
+#include "venc_signal.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Signal::Signal()
+ : m_pSignal(NULL)
+ {
+ if (venc_signal_create(&m_pSignal) != 0)
+ {
+ VENC_TEST_MSG_ERROR("error creating signal");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Signal::~Signal()
+ {
+ if (venc_signal_destroy(m_pSignal) != 0)
+ {
+ VENC_TEST_MSG_ERROR("error destroying signal");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Signal::Set()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (venc_signal_set(m_pSignal) != 0)
+ {
+ VENC_TEST_MSG_ERROR("error setting signal");
+ result = OMX_ErrorUndefined;
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Signal::Wait(OMX_S32 nTimeoutMillis)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ int ret = venc_signal_wait(m_pSignal, (int) nTimeoutMillis);
+
+ if (ret == 2)
+ {
+ result = OMX_ErrorTimeout;
+ }
+ else if (ret != 0)
+ {
+ VENC_TEST_MSG_ERROR("error waiting for signal");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_SignalQueue.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_SignalQueue.cpp
new file mode 100644
index 0000000..a749509
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_SignalQueue.cpp
@@ -0,0 +1,156 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Debug.h"
+#include "venctest_Mutex.h"
+#include "venctest_Queue.h"
+#include "venctest_Signal.h"
+#include "venctest_SignalQueue.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ SignalQueue::SignalQueue()
+ {
+ VENC_TEST_MSG_ERROR("default constructor should not be here (private)");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ SignalQueue::SignalQueue(OMX_S32 nMaxQueueSize,
+ OMX_S32 nMaxDataSize)
+ : m_pSignal(new Signal()),
+ m_pMutex(new Mutex()),
+ m_pQueue(new Queue(nMaxQueueSize, nMaxDataSize))
+ {
+ VENC_TEST_MSG_LOW("constructor %ld %ld", nMaxQueueSize, nMaxDataSize);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ SignalQueue::~SignalQueue()
+ {
+ VENC_TEST_MSG_LOW("destructor");
+ if (m_pMutex != NULL)
+ delete m_pMutex;
+ if (m_pSignal != NULL)
+ delete m_pSignal;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE SignalQueue::Pop(OMX_PTR pData,
+ OMX_S32 nDataSize,
+ OMX_S32 nTimeoutMillis)
+ {
+ VENC_TEST_MSG_LOW("Pop");
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // wait for signal or for data to come into queue
+ while (GetSize() == 0 && result == OMX_ErrorNone)
+ {
+ result = m_pSignal->Wait(nTimeoutMillis);
+ }
+
+ // did we timeout?
+ if (result == OMX_ErrorNone)
+ {
+ // lock mutex
+ m_pMutex->Lock();
+
+ result = m_pQueue->Pop(pData, nDataSize);
+
+ // unlock mutex
+ m_pMutex->UnLock();
+ }
+ else if (result != OMX_ErrorTimeout)
+ {
+ VENC_TEST_MSG_ERROR("Error waiting for signal");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE SignalQueue::Push(OMX_PTR pData,
+ OMX_S32 nDataSize)
+ {
+ VENC_TEST_MSG_LOW("Push");
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // lock mutex
+ m_pMutex->Lock();
+
+ result = m_pQueue->Push(pData, nDataSize);
+
+ // unlock mutex
+ m_pMutex->UnLock();
+
+
+ if (result == OMX_ErrorNone)
+ {
+ m_pSignal->Set();
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE SignalQueue::Peek(OMX_PTR pData,
+ OMX_S32 nDataSize)
+ {
+ VENC_TEST_MSG_LOW("Peek");
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // lock mutex
+ m_pMutex->Lock();
+
+ result = m_pQueue->Peek(pData, nDataSize);
+
+ // unlock mutex
+ m_pMutex->UnLock();
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_S32 SignalQueue::GetSize()
+ {
+ return m_pQueue->GetSize();
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Sleeper.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Sleeper.cpp
new file mode 100644
index 0000000..2bfd43a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Sleeper.cpp
@@ -0,0 +1,52 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Sleeper.h"
+#include "venctest_Debug.h"
+#include "venc_sleep.h"
+
+namespace venctest
+{
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Sleeper::Sleep(OMX_S32 nTimeMillis)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (venc_sleep((int) nTimeMillis) != 0)
+ {
+ VENC_TEST_MSG_ERROR("error sleeping");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_StatsThread.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_StatsThread.cpp
new file mode 100644
index 0000000..be2bff3
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_StatsThread.cpp
@@ -0,0 +1,259 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_Thread.h"
+#include "venctest_Signal.h"
+#include "venctest_Mutex.h"
+#include "venctest_Time.h"
+#include "venc_mutex.h"
+#include "venc_signal.h"
+#include "venc_thread.h"
+#include "venctest_StatsThread.h"
+
+namespace venctest
+{
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ StatsThread::StatsThread(OMX_S32 nSamplePeriodMillis)
+ : m_pThread(NULL),
+ m_pSignal(NULL),
+ m_pMutex(NULL),
+ m_nSamplePeriodMillis(nSamplePeriodMillis),
+ m_nInputFrames(0),
+ m_nOutputFrames(0),
+ m_nBits(0)
+ {
+ if (venc_mutex_create(&m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to create mutex");
+ }
+
+ if (venc_signal_create(&m_pSignal) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to create signal");
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ StatsThread::~StatsThread()
+ {
+ venc_signal_destroy(m_pSignal);
+ venc_mutex_destroy(m_pMutex);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE StatsThread::Start()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ m_nInputFrames = 0;
+ m_nOutputFrames = 0;
+ m_nBits = 0;
+
+ VENC_TEST_MSG_MEDIUM("starting stats thread...");
+ if (venc_thread_create(&m_pThread,
+ StatsThreadEntry, // thread fn
+ this, 0) != 0) // arg
+
+ {
+ VENC_TEST_MSG_ERROR("failed to start stats thread");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE StatsThread::Finish()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (m_pThread != NULL)
+ {
+
+ VENC_TEST_MSG_MEDIUM("waiting for stats thread to finish...");
+
+ venc_thread_destroy(m_pThread, (int *)&result);
+
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE StatsThread::SetInputStats(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (venc_mutex_lock(m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("mutex lock failure");
+ }
+
+ if (pBuffer != NULL)
+ {
+ if (pBuffer->nFilledLen > 0)
+ {
+ ++m_nInputFrames;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("null buffer");
+ result = OMX_ErrorBadParameter;
+ }
+
+ if (venc_mutex_unlock(m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("mutex unlock failure");
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE StatsThread::SetOutputStats(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ if (venc_mutex_lock(m_pMutex) != 0 )
+ {
+ VENC_TEST_MSG_ERROR("mutex lock failure");
+ }
+
+ if (pBuffer != NULL)
+ {
+ m_nBits = m_nBits + pBuffer->nFilledLen * 8;
+
+ if ((pBuffer->nFilledLen > 0) &&
+ ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0) &&
+ ((pBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) != 0))
+ {
+ ++m_nOutputFrames;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("null buffer");
+ result = OMX_ErrorBadParameter;
+ }
+
+ if (venc_mutex_unlock(m_pMutex)!= 0)
+ {
+ VENC_TEST_MSG_ERROR("mutex unlock failure");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ int StatsThread::StatsThreadEntry(void * pThreadData)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorBadParameter;
+ if (pThreadData)
+ {
+ result = ((StatsThread*) pThreadData)->StatsThreadFn();
+ }
+ return 0;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE StatsThread::StatsThreadFn()
+ {
+ OMX_BOOL bKeepGoing = OMX_TRUE;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ VENC_TEST_MSG_MEDIUM("Stats thread has started");
+#if 0
+ while (bKeepGoing == OMX_TRUE)
+ {
+ struct timespec time;
+ int result = 0;
+
+ clock_gettime(CLOCK_REALTIME, &time);
+ time.tv_sec += STATS_WAIT_TIME_SEC;
+ result = pthread_cond_timedwait(m_pSignal, m_pMutex, &time);
+ if (result == ETIMEDOUT)
+ {
+ OMX_S32 nBitrate;
+ OMX_S32 nInputFPS;
+ OMX_S32 nOutputFPS;
+
+ if (venc_mutex_lock(m_pMutex) != 0 )
+ {
+ VENC_TEST_MSG_ERROR("mutex lock failure");
+ }
+
+ if (nWaitTime > 0 && (nWaitTime / 1000 > 0))
+ {
+ nBitrate = (OMX_S32) (m_nBits / (nWaitTime / 1000));
+ nInputFPS = (OMX_S32) (m_nInputFrames / (nWaitTime / 1000));
+ nOutputFPS = (OMX_S32) (m_nOutputFrames / (nWaitTime / 1000));
+ }
+ else
+ {
+ nBitrate = 0;
+ nInputFPS = 0;
+ nOutputFPS = 0;
+ }
+
+ m_nInputFrames = 0;
+ m_nOutputFrames = 0;
+ m_nBits = 0;
+
+ if (venc_mutex_unlock(m_pMutex) != 0)
+ {
+ VENC_TEST_MSG_ERROR("mutex unlock failure");
+ }
+
+ VENC_TEST_MSG_PROFILE("Time=%d millis, Input FPS=%d",
+ (int) nWaitTime, (int) nInputFPS);
+ VENC_TEST_MSG_PROFILE("Output FPS=%d, Bitrate=%d",
+ (int) nOutputFPS, (int) nBitrate);
+ }
+ else
+ {
+ bKeepGoing = OMX_FALSE;
+ }
+ }
+#endif
+ VENC_TEST_MSG_HIGH("Stats thread is exiting...");
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestCaseFactory.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestCaseFactory.cpp
new file mode 100644
index 0000000..8f96e4d
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestCaseFactory.cpp
@@ -0,0 +1,131 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_TestCaseFactory.h"
+#include "venctest_ITestCase.h"
+#include "venctest_Thread.h"
+#include "venctest_Debug.h"
+#include "venctest_Parser.h"
+
+// test case object headers
+#include "venctest_TestChangeIntraPeriod.h"
+#include "venctest_TestChangeQuality.h"
+// #include "venctest_TestEOS.h"
+#include "venctest_TestGetSyntaxHdr.h"
+#include "venctest_TestIFrameRequest.h"
+// #include "venctest_TestPmem.h"
+// #include "venctest_TestProfileEncode.h"
+#include "venctest_TestEncode.h"
+#include "venctest_TestStateExecutingToIdle.h"
+#include "venctest_TestStatePause.h"
+#include "venctest_TestFlush.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ ITestCase* TestCaseFactory::AllocTest(OMX_STRING pTestName)
+ {
+ ITestCase* pTest = NULL;
+
+ if (Parser::StringICompare(pTestName, (OMX_STRING)"CHANGE_INTRA_PERIOD") == 0)
+ {
+ pTest = new TestChangeIntraPeriod;
+ }
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"CHANGE_QUALITY") == 0)
+ {
+ pTest = new TestChangeQuality;
+ }
+ /* else if (Parser::StringICompare(pTestName, (OMX_STRING)"EOS") == 0)
+ {
+ pTest = new TestEOS;
+ } */
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"GET_SYNTAX_HDR") == 0)
+ {
+ pTest = new TestGetSyntaxHdr;
+ }
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"IFRAME_REQUEST") == 0)
+ {
+ pTest = new TestIFrameRequest;
+ }
+ /* else if (Parser::StringICompare(pTestName, (OMX_STRING)"PMEM") == 0)
+ {
+ pTest = new TestPmem;
+ }
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"PROFILE_ENCODE") == 0)
+ {
+ pTest = new TestProfileEncode;
+ } */
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"ENCODE") == 0)
+ {
+ pTest = new TestEncode;
+ }
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"STATE_EXECUTING_TO_IDLE") == 0)
+ {
+ pTest = new TestStateExecutingToIdle;
+ }
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"FLUSH") == 0)
+ {
+ pTest = new TestFlush;
+ }
+ else if (Parser::StringICompare(pTestName, (OMX_STRING)"STATE_PAUSE") == 0)
+ {
+ pTest = new TestStatePause;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("invalid test name");
+ }
+
+ return pTest;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestCaseFactory::DestroyTest(ITestCase* pTest)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pTest)
+ {
+ delete pTest;
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("NULL param");
+ result = OMX_ErrorBadParameter;
+ }
+
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestChangeIntraPeriod.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestChangeIntraPeriod.cpp
new file mode 100644
index 0000000..4f1f235
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestChangeIntraPeriod.cpp
@@ -0,0 +1,567 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestChangeIntraPeriod.h"
+#include "venctest_Time.h"
+#include "venctest_Encoder.h"
+#include "venctest_Queue.h"
+#include "venctest_SignalQueue.h"
+#include "venctest_File.h"
+
+namespace venctest
+{
+ static const OMX_U32 PORT_INDEX_IN = 0;
+ static const OMX_U32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestChangeIntraPeriod::TestChangeIntraPeriod()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL),
+ m_pInputQueue(NULL),
+ m_pOutputQueue(NULL),
+ m_pSignalQueue(NULL),
+ m_pSource(NULL),
+ m_pSink(NULL),
+ m_nTimeStamp(0)
+
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestChangeIntraPeriod::~TestChangeIntraPeriod()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeIntraPeriod::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pConfig->eControlRate == OMX_Video_ControlRateVariableSkipFrames ||
+ pConfig->eControlRate == OMX_Video_ControlRateConstantSkipFrames)
+ {
+ VENC_TEST_MSG_ERROR("Frame skip must be disabled for this to work");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nUpdatedIntraPeriod <= 0)
+ {
+ VENC_TEST_MSG_ERROR("Frame skip must be disabled for this to work");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nUpdatedFrames <= 0)
+ {
+ VENC_TEST_MSG_ERROR("Need the updated frame count");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ OMX_S32 stolenFrames = pConfig->nIntraPeriod;
+ if (pConfig->nIntraPeriod > pConfig->nFrames + stolenFrames ||
+ pDynamicConfig->nUpdatedIntraPeriod > pDynamicConfig->nUpdatedFrames - stolenFrames)
+ {
+ VENC_TEST_MSG_ERROR("Intra period should be greater than number of frames");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeIntraPeriod::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create signal queue
+ VENC_TEST_MSG_HIGH("Creating signal queue...");
+ m_pSignalQueue = new SignalQueue(32, sizeof(OMX_BUFFERHEADERTYPE*)); // max 32 messages
+
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pInputQueue = new Queue(pConfig->nInBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+
+ //==========================================
+ // Create output buffer queue
+ VENC_TEST_MSG_HIGH("Creating output buffer queue...");
+ m_pOutputQueue = new Queue(pConfig->nOutBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+ }
+
+ //==========================================
+ // Create and open yuv file
+ if (pConfig->cInFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file source...");
+ m_pSource = new File();
+ result = m_pSource->Open(pConfig->cInFileName, OMX_TRUE);
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not reading from input file");
+ }
+
+ //==========================================
+ // Create and open m4v file
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->cOutFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file sink...");
+ m_pSink = new File();
+ result = m_pSink->Open(pConfig->cOutFileName, OMX_FALSE);
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not writing to output file");
+ }
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pEncoder->EnableUseBufferModel(pConfig->bInUseBuffer,pConfig->bOutUseBuffer);
+ }
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pInputQueue->Push(&ppInputBuffers[i], sizeof(ppInputBuffers[i])); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pOutputQueue->Push(&ppOutputBuffers[i], sizeof(ppOutputBuffers[i])); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get syntax header
+ if (result == OMX_ErrorNone)
+ {
+
+ VENC_TEST_MSG_HIGH("testing change intra period from %ld to %ld",
+ pConfig->nIntraPeriod, pDynamicConfig->nUpdatedIntraPeriod);
+
+ if (pConfig->nFrames > 0 &&
+ pConfig->eCodec != OMX_VIDEO_CodingH263)
+ {
+ result = CheckError(ProcessSyntaxHeader());
+ }
+ }
+
+ //==========================================
+ // Encode first set of frames
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(EncodeFrames(pConfig, pConfig->nFrames, pConfig->nIntraPeriod));
+ }
+
+
+ //==========================================
+ // Change intra period
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("changing intra period from %ld to %ld",
+ pConfig->nIntraPeriod, pDynamicConfig->nUpdatedIntraPeriod);
+
+ result = CheckError(m_pEncoder->SetIntraPeriod(pDynamicConfig->nUpdatedIntraPeriod));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error changing intra period");
+ }
+ }
+
+ OMX_S32 stolenFrames = pConfig->nIntraPeriod;
+
+ //==========================================
+ // Encode frames stolen from second set frames
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(EncodeFrames(pConfig, stolenFrames, pConfig->nIntraPeriod));
+ }
+
+
+ //==========================================
+ // Encode second set of frames
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(EncodeFrames(pConfig, pDynamicConfig->nUpdatedFrames - stolenFrames,
+ pDynamicConfig->nUpdatedIntraPeriod));
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pInputQueue)
+ delete m_pInputQueue;
+ if (m_pOutputQueue)
+ delete m_pOutputQueue;
+ if (m_pSignalQueue)
+ delete m_pSignalQueue;
+ if (m_pSource)
+ delete m_pSource;
+ if (m_pSink)
+ delete m_pSink;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeIntraPeriod::ProcessSyntaxHeader()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ VENC_TEST_MSG_HIGH("waiting for syntax header...");
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 1000)); // wait for 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0)
+ {
+ OMX_U32 nBytesWritten;
+ result = m_pSink->Write(pBuffer->pBuffer,
+ pBuffer->nFilledLen,
+ &nBytesWritten);
+ (void) m_pOutputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error writing to file");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("expecting codeconfig flag");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed popping");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeIntraPeriod::EncodeFrames(EncoderConfigType* pEncoderConfig,
+ OMX_S32 nFrames,
+ OMX_S32 nIntraPeriod)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BOOL bKeepRunning = OMX_TRUE;
+ OMX_S32 nInputDone = 0;
+ OMX_S32 nOutputDone = 0;
+
+ while (bKeepRunning == OMX_TRUE && result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ //==========================================
+ // see if we are finished
+ if (nInputDone == nFrames &&
+ nOutputDone == nFrames)
+ {
+ VENC_TEST_MSG_HIGH("Finished encoding %ld frames", nFrames);
+ bKeepRunning = OMX_FALSE;
+ }
+
+ //==========================================
+ // See if both the input buffer and output buffer have been released.
+ // This will serialize the encoding.
+ else if (nInputDone == nOutputDone)
+ {
+
+ result = m_pInputQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ // shouldn't happen
+ VENC_TEST_MSG_ERROR("failed to pop input");
+ break;
+ }
+
+ OMX_S32 nBytesIn = pEncoderConfig->nFrameWidth * pEncoderConfig->nFrameHeight * 3 / 2;
+ if (m_pSource != NULL)
+ {
+ //==========================================
+ // read some yuv data
+ OMX_S32 nBytesOut = 0;
+ result = m_pSource->Read(pBuffer->pBuffer,
+ nBytesIn,
+ &nBytesOut);
+
+ if (nBytesIn != nBytesOut || result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("yuv file is too small. seeking to start.");
+ result = m_pSource->SeekStart(0);
+ if (result != OMX_ErrorNone)
+ {
+ // shouldn't happen
+ VENC_TEST_MSG_ERROR("failed to seek");
+ break;
+ }
+
+ result = m_pSource->Read(pBuffer->pBuffer,
+ nBytesIn,
+ &nBytesOut);
+ if (result != OMX_ErrorNone)
+ {
+ // shouldn't happen
+ VENC_TEST_MSG_ERROR("failed to read");
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // deliver input
+ VENC_TEST_MSG_HIGH("Delivering input frame=%ld %p", nInputDone, pBuffer->pBuffer);
+ pBuffer->nTimeStamp = m_nTimeStamp;
+ pBuffer->nFilledLen = (OMX_U32) nBytesIn;
+ m_nTimeStamp = m_nTimeStamp + (1000000 / pEncoderConfig->nFramerate);
+ result = CheckError(m_pEncoder->DeliverInput(pBuffer));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ break;
+ }
+
+ //==========================================
+ // deliver output
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Delivering output frame=%ld %p", nOutputDone, pBuffer->pBuffer);
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ break;
+ }
+ }
+
+ if (bKeepRunning == OMX_TRUE)
+ {
+
+ //==========================================
+ // wait for a signal
+ result = CheckError(m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 0)); // wait infinitely
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed popping");
+ break;
+ }
+
+ if (pBuffer->nInputPortIndex == PORT_INDEX_IN)
+ {
+ //==========================================
+ // push the buffer on the back of the buffer queue
+ VENC_TEST_MSG_HIGH("Received input frame=%ld", nInputDone);
+ result = m_pInputQueue->Push(&pBuffer, sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed pushing");
+ break;
+ }
+ ++nInputDone;
+ }
+ else
+ {
+ // we are expecting an iframe
+ if (nOutputDone % nIntraPeriod == 0) // intra period expired
+ {
+ // is this an iframe?
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) == 0)
+ {
+ VENC_TEST_MSG_ERROR("was expecting an iframe");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+ }
+ else if ((pBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) != 0)
+ {
+ // we got an iframe but were not expecting one
+ VENC_TEST_MSG_ERROR("got iframe but not expecting one");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+
+ //==========================================
+ // push the buffer on the back of the buffer queue
+ VENC_TEST_MSG_HIGH("Received output frame=%ld", nOutputDone);
+ result = m_pOutputQueue->Push(&pBuffer, sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed pushing");
+ break;
+ }
+ ++nOutputDone;
+
+ //==========================================
+ // write to file
+ if (m_pSink != NULL)
+ {
+ OMX_U32 nBytesWritten;
+ result = m_pSink->Write(pBuffer->pBuffer,
+ pBuffer->nFilledLen,
+ &nBytesWritten);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error writing to file");
+ }
+ else if (nBytesWritten != pBuffer->nFilledLen)
+ {
+ VENC_TEST_MSG_ERROR("mismatched number of bytes in file write");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeIntraPeriod::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestChangeIntraPeriod*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeIntraPeriod::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestChangeIntraPeriod*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestChangeQuality.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestChangeQuality.cpp
new file mode 100644
index 0000000..97d3423
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestChangeQuality.cpp
@@ -0,0 +1,434 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestChangeQuality.h"
+#include "venctest_Time.h"
+#include "venctest_FileSource.h"
+#include "venctest_FileSink.h"
+#include "venctest_Encoder.h"
+#include "venctest_Sleeper.h"
+#include "venctest_Mutex.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestChangeQuality::TestChangeQuality()
+ : ITestCase(), // invoke the base class constructor
+ m_pSource(NULL),
+ m_pSink(NULL),
+ m_pEncoder(NULL),
+ m_pMutex(NULL),
+ m_nFramesCoded(0),
+ m_nFramesDelivered(0),
+ m_nBits(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestChangeQuality::~TestChangeQuality()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeQuality::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pConfig->eControlRate == OMX_Video_ControlRateDisable)
+ {
+ VENC_TEST_MSG_ERROR("need to enable rate control");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nUpdatedFrames == 0)
+ {
+ VENC_TEST_MSG_ERROR("need to indicate number of frames to encode after quality change");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nUpdatedFramerate == 0)
+ {
+ VENC_TEST_MSG_ERROR("need to configure the second frame rate");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nUpdatedBitrate == 0)
+ {
+ VENC_TEST_MSG_ERROR("need to configure the second bitrate");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeQuality::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ OMX_TICKS nStartTime = 0;
+ OMX_TICKS nEndTime;
+ OMX_TICKS nRunTimeSec;
+ OMX_TICKS nRunTimeMillis;
+ OMX_S32 nFramesCoded;
+ OMX_S32 nFramesDelivered;
+ OMX_S64 nBits;
+
+ //==========================================
+ // Create mutex
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating mutex...");
+ m_pMutex = new Mutex();
+ }
+
+ //==========================================
+ // Create and configure the file source (yuv reader)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating source...");
+ m_pSource = new FileSource();
+ result = CheckError(m_pSource->Configure(
+ pConfig->nFrames + pDynamicConfig->nUpdatedFrames, // deliver only the initial set of frames
+ pConfig->nFramerate, pConfig->nFrameWidth, pConfig->nFrameHeight,
+ pConfig->nInBufferCount, SourceDeliveryFn, pConfig->cInFileName,
+ pConfig->nDVSXOffset, pConfig->nDVSYOffset, OMX_TRUE)); // live mode
+ }
+
+ //==========================================
+ // Create and configure the file sink (m4v writer)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating sink...");
+ m_pSink = new FileSink();
+ result = CheckError(m_pSink->Configure(
+ pConfig->nFrames + pDynamicConfig->nUpdatedFrames, // process the initial frames
+ pConfig->cOutFileName, // and updated quality frames
+ nTestNum,
+ SinkReleaseFn));
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pSource->SetFreeBuffer(
+ ppInputBuffers[i])); // give ownership to source
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pEncoder->DeliverOutput(
+ ppOutputBuffers[i])); // give ownership to encoder
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the sink ready to write m4v output
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("starting the sink thread...");
+ nStartTime = Time::GetTimeMicrosec();
+ result = CheckError(m_pSink->Start());
+ }
+
+ //==========================================
+ // Start reading and delivering frames
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("starting the source thread...");
+ result = CheckError(m_pSource->Start());
+ }
+
+ (void) Sleeper::Sleep(1000 * pConfig->nFrames / pConfig->nFramerate);
+
+ if (result == OMX_ErrorNone)
+ {
+ m_pMutex->Lock();
+
+ //==========================================
+ // Compute stats
+ nEndTime = Time::GetTimeMicrosec();
+ nRunTimeMillis = (nEndTime - nStartTime) / 1000; // convert to millis
+ nRunTimeSec = nRunTimeMillis / 1000; // convert to seconds
+
+ nFramesCoded = m_nFramesCoded;
+ nFramesDelivered = m_nFramesDelivered;
+ nBits = m_nBits;
+ nStartTime = nEndTime;
+
+ // reset statistics
+ m_nFramesCoded = 0;
+ m_nFramesDelivered = 0;
+ m_nBits = 0;
+
+ m_pMutex->UnLock();
+
+ VENC_TEST_MSG_PROFILE("Time = %d millis, Encoded = %d, Dropped = %d",
+ (int) nRunTimeMillis,
+ (int) nFramesCoded,
+ (int) (nFramesDelivered - nFramesCoded));
+
+ if (nRunTimeSec > 0) // ensure no divide by zero
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d",
+ (int) (nBits / nRunTimeSec),
+ (int) (nFramesDelivered / nRunTimeSec),
+ (int) (nFramesCoded / nRunTimeSec));
+ }
+ else
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d", 0, 0, 0);
+ }
+
+ VENC_TEST_MSG_PROFILE("Avg encode time = %d millis per frame",
+ (int) (nRunTimeMillis / nFramesCoded));
+
+ }
+
+ //==========================================
+ // Change the delivery frame rate
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pSource->ChangeFrameRate(
+ pDynamicConfig->nUpdatedFramerate));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to change frame rate");
+ }
+ }
+
+ //==========================================
+ // Change the encoder quality
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pEncoder->ChangeQuality(
+ pDynamicConfig->nUpdatedFramerate, pDynamicConfig->nUpdatedBitrate,
+ pDynamicConfig->nUpdatedMinQp,pDynamicConfig->nUpdatedMaxQp));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to change encoder quality");
+ }
+ }
+
+ //==========================================
+ // Wait for the source to finish delivering all frames
+ if (m_pSource != NULL)
+ {
+ VENC_TEST_MSG_HIGH("waiting for source to finish...");
+ result = CheckError(m_pSource->Finish());
+ VENC_TEST_MSG_HIGH("source is finished");
+ }
+
+ //==========================================
+ // Wait for the sink to finish writing all frames
+ if (m_pSink != NULL)
+ {
+ VENC_TEST_MSG_HIGH("waiting for sink to finish...");
+ result = CheckError(m_pSink->Finish());
+ VENC_TEST_MSG_HIGH("sink is finished");
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ m_pMutex->Lock();
+
+ //==========================================
+ // Compute stats
+ nEndTime = Time::GetTimeMicrosec();
+ nRunTimeMillis = (nEndTime - nStartTime) / 1000; // convert to millis
+ nRunTimeSec = nRunTimeMillis / 1000; // convert to seconds
+
+ nFramesCoded = m_nFramesCoded;
+ nFramesDelivered = m_nFramesDelivered;
+ nBits = m_nBits;
+
+ m_pMutex->UnLock();
+
+ VENC_TEST_MSG_PROFILE("Time = %d millis, Encoded = %d, Dropped = %d",
+ (int) nRunTimeMillis,
+ (int) nFramesCoded,
+ (int) (nFramesDelivered - nFramesCoded));
+
+ if (nRunTimeSec > 0) // ensure no divide by zero
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d",
+ (int) (nBits / nRunTimeSec),
+ (int) (nFramesDelivered / nRunTimeSec),
+ (int) (nFramesCoded / nRunTimeSec));
+ }
+ else
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d", 0, 0, 0);
+ }
+
+ VENC_TEST_MSG_PROFILE("Avg encode time = %d millis per frame",
+ (int) (nRunTimeMillis / nFramesCoded));
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pMutex)
+ delete m_pMutex;
+ if (m_pSource)
+ delete m_pSource;
+ if (m_pSink)
+ delete m_pSink;
+ if (m_pEncoder)
+ delete m_pEncoder;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ void TestChangeQuality::SourceDeliveryFn(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ // Deliver YUV data from source to encoder
+ ((Encoder*) pBuffer->pAppPrivate)->DeliverInput(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ void TestChangeQuality::SinkReleaseFn(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ // Deliver bitstream buffer from sink to encoder
+ ((Encoder*) pBuffer->pAppPrivate)->DeliverOutput(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeQuality::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ TestChangeQuality* pTester = (TestChangeQuality*) pAppData;
+
+ (void) pTester->m_pMutex->Lock();
+ ++pTester->m_nFramesDelivered;
+ (void) pTester->m_pMutex->UnLock();
+
+ // Deliver free yuv buffer to source
+ return pTester->m_pSource->SetFreeBuffer(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestChangeQuality::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+
+ TestChangeQuality* pTester = (TestChangeQuality*) pAppData;
+
+ (void) pTester->m_pMutex->Lock();
+
+ // get performance data
+ if (pBuffer->nFilledLen != 0)
+ {
+ // if it's only the syntax header don't count it as a frame
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)
+ {
+ ++pTester->m_nFramesCoded;
+ }
+
+ // always count the bits regarding whether or not its only syntax header
+ pTester->m_nBits = pTester->m_nBits + (OMX_S32) (pBuffer->nFilledLen * 8);
+ }
+
+ (void) pTester->m_pMutex->UnLock();
+
+ // Deliver encoded m4v output to sink for file write
+ return pTester->m_pSink->Write(pBuffer);
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestEOS.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestEOS.cpp
new file mode 100644
index 0000000..43ef53f
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestEOS.cpp
@@ -0,0 +1,786 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestEOS.h"
+#include "venctest_Time.h"
+#include "venctest_Encoder.h"
+#include "venctest_Queue.h"
+#include "venctest_SignalQueue.h"
+#include "venctest_File.h"
+#include "venctest_Sleeper.h"
+
+namespace venctest
+{
+ static const OMX_U32 PORT_INDEX_IN = 0;
+ static const OMX_U32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestEOS::TestEOS()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL),
+ m_pInputQueue(NULL),
+ m_pOutputQueue(NULL),
+ m_pSignalQueue(NULL),
+ m_pSource(NULL),
+ m_nTimeStamp(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestEOS::~TestEOS()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::ValidateAssumptions(EncoderConfigType* m_pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (m_pConfig->eControlRate == OMX_Video_ControlRateVariableSkipFrames ||
+ m_pConfig->eControlRate == OMX_Video_ControlRateConstantSkipFrames)
+ {
+ VENC_TEST_MSG_ERROR("Frame skip must be disabled for this to work");
+ result = OMX_ErrorUndefined;
+ }
+
+ if (m_pConfig->nInBufferCount != m_pConfig->nOutBufferCount)
+ {
+ VENC_TEST_MSG_ERROR("Need matching number of input and output buffers");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ m_pConfig = pConfig;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create signal queue
+ VENC_TEST_MSG_HIGH("Creating signal queue...");
+ m_pSignalQueue = new SignalQueue(32, sizeof(OMX_BUFFERHEADERTYPE*)); // max 32 messages
+
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pInputQueue = new Queue(m_pConfig->nInBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+
+ //==========================================
+ // Create output buffer queue
+ VENC_TEST_MSG_HIGH("Creating output buffer queue...");
+ m_pOutputQueue = new Queue(m_pConfig->nOutBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+ }
+
+ //==========================================
+ // Create and open yuv file
+ if (m_pConfig->cInFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file source...");
+ m_pSource = new File();
+ result = m_pSource->Open(m_pConfig->cInFileName, OMX_TRUE);
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not reading from input file");
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ m_pConfig->eCodec);
+ result = m_pEncoder->Configure(m_pConfig);
+
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pEncoder->EnableUseBufferModel(m_pConfig->bInUseBuffer, m_pConfig->bOutUseBuffer);
+ }
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = m_pEncoder->GoToExecutingState();
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < m_pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pInputQueue->Push(&ppInputBuffers[i], sizeof(ppInputBuffers[i])); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < m_pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pOutputQueue->Push(&ppOutputBuffers[i], sizeof(ppOutputBuffers[i])); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the syntax header
+ if (result == OMX_ErrorNone)
+ {
+ // let's get the syntax header
+ result = ProcessSyntaxHeader();
+ }
+
+ //==========================================
+ // run eos test, send no input buffers
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Running EOSTestSessionStart with eos attached to valid input...");
+ result = EOSTestSessionStart(OMX_FALSE);
+ }
+
+ //==========================================
+ // run eos test, send no input buffers
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Running EOSTestSessionStart with eos not attached to valid input...");
+ result = EOSTestSessionStart(OMX_TRUE);
+ }
+
+ //==========================================
+ // run eos test, make encoder wait until it gets an output buffer (last frame length!=0)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Running EOSTestDelayOutput with eos attached to valid input...");
+ result = EOSTestDelayOutput(OMX_FALSE);
+ }
+
+ //==========================================
+ // run eos test, make encoder wait until it gets an output buffer (last frame length=0)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Running EOSTestDelayOutput with eos not attached to valid input...");
+ result = EOSTestDelayOutput(OMX_TRUE);
+ }
+
+ //==========================================
+ // run eos test, send multiple frames with last frame length!=0
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Running EOSTestRapidFire with eos attached to valid input...");
+ result = EOSTestRapidFire(OMX_FALSE);
+ }
+
+ //==========================================
+ // run eos test, send multiple frames with last frame length=0
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Running EOSTestRapidFire with eos not attached to valid input...");
+ result = EOSTestRapidFire(OMX_TRUE);
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = m_pEncoder->GoToLoadedState();
+ }
+
+ //==========================================
+ // Close the yuv file
+ if (m_pSource != NULL)
+ {
+ result = m_pSource->Close();
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pInputQueue)
+ delete m_pInputQueue;
+ if (m_pOutputQueue)
+ delete m_pOutputQueue;
+ if (m_pSignalQueue)
+ delete m_pSignalQueue;
+ if (m_pSource)
+ delete m_pSource;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::ProcessSyntaxHeader()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ VENC_TEST_MSG_HIGH("waiting for syntax header...");
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ if (result == OMX_ErrorNone)
+ {
+ pBuffer->nFilledLen = 0;
+ pBuffer->nFlags = 0;
+ result = m_pEncoder->DeliverOutput(pBuffer);
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 1000); // wait for 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)
+ {
+ VENC_TEST_MSG_ERROR("expecting codeconfig flag");
+ result = OMX_ErrorUndefined;
+ }
+ (void) m_pOutputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed popping");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::EOSTestSessionStart(OMX_BOOL bEmptyEOSBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ result = m_pInputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ // deliver input
+ if (bEmptyEOSBuffer == OMX_TRUE)
+ {
+ pBuffer->nFilledLen = 0;
+ }
+ else
+ {
+ pBuffer->nFilledLen = m_pConfig->nFrameWidth *
+ m_pConfig->nFrameHeight * 3 / 2;
+ }
+ pBuffer->nFlags = OMX_BUFFERFLAG_EOS;
+ VENC_TEST_MSG_HIGH("delivering input with eos");
+ pBuffer->nTimeStamp = NextTimeStamp(m_pConfig->nFramerate);
+ result = m_pEncoder->DeliverInput(pBuffer);
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ // deliver output
+ pBuffer->nFlags = 0;
+ pBuffer->nFilledLen = 0;
+ VENC_TEST_MSG_HIGH("delivering output");
+
+ result = m_pEncoder->DeliverOutput(pBuffer);
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ // wait for input and output buffer
+ for (int i = 0; i < 2; i++)
+ {
+ VENC_TEST_MSG_HIGH("waiting for buffer");
+ result = m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 1000); // wait 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if (pBuffer->nInputPortIndex == PORT_INDEX_IN)
+ {
+ VENC_TEST_MSG_HIGH("got input");
+
+ // put it back on the queue
+ (void) m_pInputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("got output");
+
+ // put it back on the queue
+ (void) m_pOutputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ // make sure we get EOS with len == 0
+ if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS)
+ {
+ if (bEmptyEOSBuffer == OMX_TRUE &&
+ pBuffer->nFilledLen != 0)
+ {
+ VENC_TEST_MSG_ERROR("expected a length of 0 but got %d",
+ (int) pBuffer->nFilledLen);
+ result = OMX_ErrorUndefined;
+ }
+ else if (bEmptyEOSBuffer == OMX_FALSE &&
+ pBuffer->nFilledLen == 0)
+ {
+ VENC_TEST_MSG_ERROR("expected a non zero length");
+ result = OMX_ErrorUndefined;
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("eos test passed");
+ }
+
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to get eos");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop msg");
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::EOSTestRapidFire(OMX_BOOL bEmptyEOSBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ OMX_S32 nInputToDeliver = m_pInputQueue->GetSize();
+ OMX_S32 nOutputToDeliver = m_pOutputQueue->GetSize();
+
+ // empty all output buffers
+ if (result == OMX_ErrorNone)
+ {
+ for (OMX_S32 i = 0; i < nOutputToDeliver; i++)
+ {
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ pBuffer->nFilledLen = 0;
+ pBuffer->nFlags = 0;
+ result = m_pEncoder->DeliverOutput(pBuffer);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop buffer");
+ }
+
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ // empty all input buffers
+ if (result == OMX_ErrorNone)
+ {
+ for (OMX_S32 i = 0; i < nInputToDeliver; i++)
+ {
+ result = m_pInputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ if (bEmptyEOSBuffer == OMX_TRUE &&
+ i == nInputToDeliver - 1)
+ {
+ // this is the last frame, and empty eos buffer
+ pBuffer->nFlags = OMX_BUFFERFLAG_EOS;
+ pBuffer->nFilledLen = 0;
+ }
+ else if (bEmptyEOSBuffer == OMX_FALSE &&
+ i == nInputToDeliver - 1)
+ {
+ // this is the last frame, and non-empty eos buffer
+ pBuffer->nFlags = OMX_BUFFERFLAG_EOS;
+ pBuffer->nFilledLen = m_pConfig->nFrameWidth *
+ m_pConfig->nFrameHeight * 3 / 2;
+ }
+ else
+ {
+ // this is not the last frame
+ pBuffer->nFlags = 0;
+ pBuffer->nFilledLen = m_pConfig->nFrameWidth *
+ m_pConfig->nFrameHeight * 3 / 2;
+ }
+
+ // deliver input
+ pBuffer->nTimeStamp = NextTimeStamp(m_pConfig->nFramerate);
+ result = m_pEncoder->DeliverInput(pBuffer);
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop buffer");
+ }
+
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ // lets wait for all buffers to be released from encoder
+ OMX_S32 nLastFlags = 0;
+ OMX_S32 nLastFilledLen = 0;
+ if (result == OMX_ErrorNone)
+ {
+ OMX_S32 nLooop = nInputToDeliver + nOutputToDeliver;
+ OMX_S32 nOutputRemaining = nOutputToDeliver;
+
+ for (OMX_S32 i = 0; i < nLooop; i++)
+ {
+ result = m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 1000); // wait 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if (pBuffer->nInputPortIndex == PORT_INDEX_IN)
+ {
+ m_pInputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ }
+ else
+ {
+ nLastFlags = (OMX_S32) pBuffer->nFlags;
+ nLastFilledLen = (OMX_S32) pBuffer->nFilledLen;
+ m_pOutputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ --nOutputRemaining;
+ if (nOutputRemaining != 0)
+ {
+ // length should not be zero
+ if (nLastFilledLen == 0)
+ {
+ VENC_TEST_MSG_ERROR("unexpected len = 0");
+ result = OMX_ErrorUndefined;
+ break;
+ }
+
+ // we should not have eos
+ if (nLastFlags & OMX_BUFFERFLAG_EOS)
+ {
+ VENC_TEST_MSG_ERROR("unexpected eos");
+ result = OMX_ErrorUndefined;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop buffer %d", (int) result);
+ break;
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ // we are expecting eos flag on last buffer
+ if (nLastFlags & OMX_BUFFERFLAG_EOS)
+ {
+ // see if we get the correct length
+ if (bEmptyEOSBuffer == OMX_TRUE && nLastFilledLen != 0)
+ {
+ VENC_TEST_MSG_ERROR("was expecting any data, length=%d",
+ (int) nLastFilledLen);
+ result = OMX_ErrorUndefined;
+ }
+ else if (bEmptyEOSBuffer == OMX_FALSE && nLastFilledLen == 0)
+ {
+ VENC_TEST_MSG_ERROR("was expecting length=0");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("did not get eos");
+ result = OMX_ErrorUndefined;
+ }
+ }
+
+
+ if (result == OMX_ErrorNone)
+ {
+ if (nInputToDeliver != m_pInputQueue->GetSize())
+ {
+ VENC_TEST_MSG_ERROR("we dont have all our input buffers");
+ result = OMX_ErrorUndefined;
+ }
+ if (nOutputToDeliver != m_pOutputQueue->GetSize())
+ {
+ VENC_TEST_MSG_ERROR("we dont have all our output buffers");
+ result = OMX_ErrorUndefined;
+ }
+ }
+
+ // verify that both queues are now full
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::EOSTestDelayOutput(OMX_BOOL bEmptyEOSBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ result = m_pInputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ // deliver input
+ if (bEmptyEOSBuffer == OMX_TRUE)
+ {
+ pBuffer->nFilledLen = 0;
+ }
+ else
+ {
+ pBuffer->nFilledLen = m_pConfig->nFrameWidth *
+ m_pConfig->nFrameHeight * 3 / 2;
+ }
+ pBuffer->nFlags = OMX_BUFFERFLAG_EOS;
+ VENC_TEST_MSG_HIGH("delivering input with eos");
+ pBuffer->nTimeStamp = NextTimeStamp(m_pConfig->nFramerate);
+ result = m_pEncoder->DeliverInput(pBuffer);
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ (void) Sleeper::Sleep(2000); // sleep for 2 seconds
+
+ if (m_pSignalQueue->GetSize() > 1)
+ {
+ VENC_TEST_MSG_ERROR("we should only have one buffer queued");
+ result = OMX_ErrorUndefined;
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ if (m_pSignalQueue->GetSize() == 1)
+ {
+ VENC_TEST_MSG_HIGH("peeking at buffer to make sure it is input");
+
+ // if we have an input buffer let's make sure it
+ // is not an output buffer since we have not delivered
+ // an output buffer
+ result = m_pSignalQueue->Peek((OMX_PTR) &pBuffer,
+ sizeof(pBuffer));
+
+ if (result == OMX_ErrorNone)
+ {
+ if (pBuffer->nInputPortIndex != PORT_INDEX_IN)
+ {
+ VENC_TEST_MSG_ERROR("this should be an input buffer");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to peek at buffer");
+ }
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ // deliver output
+ pBuffer->nFilledLen = 0;
+ pBuffer->nFlags = 0;
+ VENC_TEST_MSG_HIGH("delivering output");
+
+ result = m_pEncoder->DeliverOutput(pBuffer);
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ // wait for input and output buffer
+ for (int i = 0; i < 2; i++)
+ {
+ VENC_TEST_MSG_HIGH("waiting for buffer");
+ result = m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 1000); // wait 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if (pBuffer->nInputPortIndex == PORT_INDEX_IN)
+ {
+ VENC_TEST_MSG_HIGH("got input");
+
+ // put it back on the queue
+ (void) m_pInputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("got output");
+
+ // put it back on the queue
+ (void) m_pOutputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ // make sure we get EOS with len == 0
+ if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS)
+ {
+ if (bEmptyEOSBuffer == OMX_TRUE &&
+ pBuffer->nFilledLen != 0)
+ {
+ VENC_TEST_MSG_ERROR("expected a length of 0 but got %d",
+ (int) pBuffer->nFilledLen);
+ result = OMX_ErrorUndefined;
+ }
+ else if (bEmptyEOSBuffer == OMX_FALSE &&
+ pBuffer->nFilledLen == 0)
+ {
+ VENC_TEST_MSG_ERROR("expected a non zero length");
+ result = OMX_ErrorUndefined;
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("eos test passed");
+ }
+
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to get eos");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop msg %d", (int) result);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ OMX_TICKS TestEOS::NextTimeStamp(OMX_S32 nFramerate)
+ {
+ OMX_TICKS nTimeStamp = m_nTimeStamp;
+ // increment by the corresponding number of microseconds
+ m_nTimeStamp = m_nTimeStamp + (1000000 / nFramerate);
+ return nTimeStamp;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestEOS*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEOS::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestEOS*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestEncode.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestEncode.cpp
new file mode 100644
index 0000000..373b31a
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestEncode.cpp
@@ -0,0 +1,345 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestEncode.h"
+#include "venctest_Time.h"
+#include "venctest_FileSource.h"
+#include "venctest_FileSink.h"
+#include "venctest_Encoder.h"
+
+namespace venctest
+{
+
+ Encoder* encoder_handle;
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestEncode::TestEncode()
+ : ITestCase(), // invoke the base class constructor
+ m_pSource(NULL),
+ m_pSink(NULL),
+ m_pEncoder(NULL),
+ m_nFramesCoded(0),
+ m_nBits(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestEncode::~TestEncode()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEncode::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEncode::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ OMX_TICKS nStartTime = 0;
+ OMX_TICKS nEndTime;
+ OMX_TICKS nRunTimeSec;
+ OMX_TICKS nRunTimeMillis;
+
+ //==========================================
+ // Create and configure the file source (yuv reader)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating source...");
+ m_pSource = new FileSource();
+ result = CheckError(m_pSource->Configure(
+ pConfig->nFrames, pConfig->nFramerate, pConfig->nFrameWidth,
+ pConfig->nFrameHeight, pConfig->nInBufferCount, SourceDeliveryFn,
+ pConfig->cInFileName, pConfig->nDVSXOffset, pConfig->nDVSYOffset,
+ pConfig->bProfileMode));
+ }
+
+ //==========================================
+ // Create and configure the file sink (m4v writer)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating sink...");
+ m_pSink = new FileSink();
+ result = CheckError(m_pSink->Configure(
+ pConfig->nFrames, pConfig->cOutFileName, nTestNum, SinkReleaseFn));
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pEncoder->EnableUseBufferModel(pConfig->bInUseBuffer, pConfig->bOutUseBuffer));
+ }
+
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ /* ppInputBuffers[i]->pAppPrivate = m_pEncoder; */ // set the encoder as the private app data
+ encoder_handle = m_pEncoder;
+ result = CheckError(m_pSource->SetFreeBuffer(ppInputBuffers[i])); // give ownership to source
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ /* ppOutputBuffers[i]->pAppPrivate = m_pEncoder; */ // set the encoder as the private app data
+ encoder_handle = m_pEncoder;
+ result = CheckError(m_pEncoder->DeliverOutput(
+ ppOutputBuffers[i])); // give ownership to encoder
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the sink ready to write m4v output
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("starting the sink thread...");
+ nStartTime = Time::GetTimeMicrosec();
+ result = CheckError(m_pSink->Start());
+ }
+
+ //==========================================
+ // Start reading and delivering frames
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("starting the source thread...");
+ result = CheckError(m_pSource->Start());
+ }
+
+ //==========================================
+ // Wait for the source to finish delivering all frames
+ if (m_pSource != NULL)
+ {
+ VENC_TEST_MSG_HIGH("waiting for source to finish...");
+ result = CheckError(m_pSource->Finish());
+ VENC_TEST_MSG_HIGH("source is finished");
+ }
+
+ //==========================================
+ // Wait for the sink to finish writing all frames
+ if (m_pSink != NULL)
+ {
+ VENC_TEST_MSG_HIGH("waiting for sink to finish...");
+ result = CheckError(m_pSink->Finish());
+ VENC_TEST_MSG_HIGH("sink is finished");
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ //==========================================
+ // Compute stats
+ nEndTime = Time::GetTimeMicrosec();
+ nRunTimeMillis = (nEndTime - nStartTime) / 1000; // convert to millis
+ nRunTimeSec = nRunTimeMillis / 1000; // convert to seconds
+
+ VENC_TEST_MSG_PROFILE("Time = %d millis, Encoded = %d, Dropped = %d",
+ (int) nRunTimeMillis,
+ (int) m_nFramesCoded,
+ (int) (pConfig->nFrames - m_nFramesCoded));
+
+ if (nRunTimeSec > 0) // ensure no divide by zero
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d",
+ (int) (m_nBits / nRunTimeSec),
+ (int) (pConfig->nFrames / nRunTimeSec),
+ (int) (m_nFramesCoded / nRunTimeSec));
+ }
+ else
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d", 0, 0, 0);
+ }
+
+ VENC_TEST_MSG_PROFILE("Avg encode time = %d millis per frame",
+ (int) (nRunTimeMillis / pConfig->nFrames));
+
+ // determine the test result
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->eControlRate != OMX_Video_ControlRateDisable &&
+ pConfig->bProfileMode == OMX_TRUE)
+ {
+ static const double errorThreshold = .15; // error percentage threshold
+
+ OMX_S32 nBitrateDelta = (OMX_S32) (pConfig->nBitrate - (m_nBits / nRunTimeSec));
+ if (nBitrateDelta < 0)
+ {
+ nBitrateDelta = -nBitrateDelta;
+ }
+ if ((double) nBitrateDelta > pConfig->nBitrate * errorThreshold)
+ {
+ VENC_TEST_MSG_ERROR("test failed with bitrate %d. bitrate delta is %d max allowed is approx %d",
+ (int) pConfig->nBitrate,
+ (int) nBitrateDelta,
+ (int) (pConfig->nBitrate * errorThreshold));
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ OMX_S32 nFramerateDelta = (OMX_S32) (pConfig->nFramerate - (pConfig->nFrames / nRunTimeSec));
+ if (nFramerateDelta < 0)
+ {
+ nFramerateDelta = -nFramerateDelta;
+ }
+ if ((double) nFramerateDelta > pConfig->nFramerate * errorThreshold)
+ {
+ VENC_TEST_MSG_ERROR("test failed with frame rate %d. frame rate delta is %d max allowed is approx %d",
+ (int) pConfig->nFramerate,
+ (int) nFramerateDelta,
+ (int) ((pConfig->nFrames / nRunTimeSec) * errorThreshold));
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pSource)
+ delete m_pSource;
+ if (m_pSink)
+ delete m_pSink;
+ if (m_pEncoder)
+ delete m_pEncoder;
+
+ return result;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ void TestEncode::SourceDeliveryFn(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ // Deliver YUV data from source to encoder
+ encoder_handle->DeliverInput(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ void TestEncode::SinkReleaseFn(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ // Deliver bitstream buffer from sink to encoder
+ encoder_handle->DeliverOutput(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEncode::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ TestEncode* pTester = (TestEncode*) pAppData;
+
+ // Deliver free yuv buffer to source
+ return pTester->m_pSource->SetFreeBuffer(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestEncode::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+
+ TestEncode* pTester = (TestEncode*) pAppData;
+
+ VENC_TEST_MSG_HIGH("FBD ...\n");
+ // get performance data
+ if (pBuffer->nFilledLen != 0)
+ {
+ // if it's only the syntax header don't count it as a frame
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0 &&
+ (pBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME))
+ {
+ ++pTester->m_nFramesCoded;
+ }
+
+ // always count the bits regarding whether or not its only syntax header
+ pTester->m_nBits = pTester->m_nBits + (OMX_S32) (pBuffer->nFilledLen * 8);
+ }
+
+ // Deliver encoded m4v output to sink for file write
+ return pTester->m_pSink->Write(pBuffer);
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestFlush.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestFlush.cpp
new file mode 100644
index 0000000..3eb7159
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestFlush.cpp
@@ -0,0 +1,380 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestFlush.h"
+#include "venctest_Time.h"
+#include "venctest_Encoder.h"
+#include "venctest_Queue.h"
+#include "venctest_File.h"
+
+namespace venctest
+{
+ static const OMX_S32 PORT_INDEX_IN = 0;
+ static const OMX_S32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestFlush::TestFlush()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL),
+ m_pInputQueue(NULL),
+ m_pOutputQueue(NULL),
+ m_pSource(NULL),
+ m_pSink(NULL),
+ m_nTimeStamp(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestFlush::~TestFlush()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestFlush::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestFlush::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pInputQueue = new Queue(pConfig->nInBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+
+ //==========================================
+ // Create output buffer queue
+ VENC_TEST_MSG_HIGH("Creating output buffer queue...");
+ m_pOutputQueue = new Queue(pConfig->nOutBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+ }
+
+ //==========================================
+ // Create and open yuv file
+ if (pConfig->cInFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file source...");
+ m_pSource = new File();
+ result = CheckError(m_pSource->Open(pConfig->cInFileName, OMX_TRUE));
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not reading from input file");
+ }
+
+ //==========================================
+ // Create and open m4v file
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->cOutFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file sink...");
+ m_pSink = new File();
+ result = CheckError(m_pSink->Open(pConfig->cOutFileName, OMX_FALSE));
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not writing to output file");
+ }
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pInputQueue->Push(
+ &ppInputBuffers[i], sizeof(ppInputBuffers[i]))); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pOutputQueue->Push(
+ &ppOutputBuffers[i], sizeof(ppOutputBuffers[i]))); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ static const OMX_S32 nState = 2;
+ for (OMX_S32 nState = 0; nState < 2; nState++)
+ {
+ static const OMX_S32 nRuns = 4;
+ static const OMX_BOOL bPortMap[nRuns][2] =
+ { {OMX_FALSE, OMX_FALSE}, // no input or output buffers
+ {OMX_TRUE, OMX_FALSE}, // input buffers only
+ {OMX_FALSE, OMX_TRUE}, // output buffers only
+ {OMX_TRUE, OMX_TRUE} }; // input and output buffers
+ for (OMX_S32 i = 0; i < nRuns; i++)
+ {
+ //==========================================
+ // Deliver buffers
+ VENC_TEST_MSG_HIGH("Deliver buffers %d", (int) i);
+ result = CheckError(DeliverBuffers(
+ bPortMap[i][0], bPortMap[i][1], pConfig));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver buffers %d", (int) i);
+ break;
+ }
+
+ //==========================================
+ // flush
+ VENC_TEST_MSG_HIGH("flushing %d", (int) i);
+ result = CheckError(m_pEncoder->Flush());
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error flushing");
+ break;
+ }
+
+ //==========================================
+ // make sure all buffers have been returned to us
+ result = CheckError(CheckBufferQueues(
+ pConfig->nInBufferCount, pConfig->nOutBufferCount));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("missing some buffers %d", (int) i);
+ break;
+ }
+ }
+
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+
+ if (nState == 0)
+ {
+ VENC_TEST_MSG_HIGH("going to pause state...");
+ result = CheckError(m_pEncoder->SetState(OMX_StatePause, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error going to pause state");
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ //==========================================
+ // Close the yuv file
+ if (m_pSource != NULL)
+ {
+ result = CheckError(m_pSource->Close());
+ }
+
+ //==========================================
+ // Close the m4v file
+ if (m_pSink != NULL)
+ {
+ result = CheckError(m_pSink->Close());
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pInputQueue)
+ delete m_pInputQueue;
+ if (m_pOutputQueue)
+ delete m_pOutputQueue;
+ if (m_pSource)
+ delete m_pSource;
+ if (m_pSink)
+ delete m_pSink;
+
+ return result;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestFlush::DeliverBuffers(OMX_BOOL bDeliverInput,
+ OMX_BOOL bDeliverOutput,
+ EncoderConfigType* pConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // deliver all input buffers
+ if (bDeliverInput == OMX_TRUE)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ OMX_S32 nSize = m_pInputQueue->GetSize();
+ for (OMX_S32 i = 0; i < nSize; i++)
+ {
+ result = CheckError(m_pInputQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer)));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop input");
+ break;
+ }
+
+ pBuffer->nTimeStamp = m_nTimeStamp;
+ m_nTimeStamp = m_nTimeStamp + 1000000 / pConfig->nFramerate;
+ pBuffer->nFilledLen = pConfig->nFrameWidth * pConfig->nFrameHeight * 3 / 2;
+ result = CheckError(m_pEncoder->DeliverInput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ break;
+ }
+ }
+ }
+
+ // deliver all output buffers
+ if (bDeliverOutput == OMX_TRUE)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ OMX_S32 nSize = m_pOutputQueue->GetSize();
+ for (OMX_S32 i = 0; i < nSize; i++)
+ {
+ result = CheckError(m_pOutputQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer)));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ break;
+ }
+
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestFlush::CheckBufferQueues(OMX_S32 nInputBuffers,
+ OMX_S32 nOutputBuffers)
+ {
+ OMX_S32 inSize = m_pInputQueue->GetSize();
+ OMX_S32 outSize = m_pOutputQueue->GetSize();
+
+ VENC_TEST_MSG_HIGH("queuedInput = %ld, queuedOutput = %ld", inSize, outSize);
+
+ if (inSize != nInputBuffers || outSize != nOutputBuffers)
+ {
+ VENC_TEST_MSG_ERROR("missing buffers %ld %ld", inSize, outSize);
+ }
+ return (inSize == nInputBuffers &&
+ outSize == nOutputBuffers) ? OMX_ErrorNone : OMX_ErrorUndefined;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestFlush::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_HIGH("queuing input buffer with size %ld", pBuffer->nFilledLen);
+ return ((TestFlush*) pAppData)->m_pInputQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestFlush::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_HIGH("queuing output buffer with size %ld", pBuffer->nFilledLen);
+ return ((TestFlush*) pAppData)->m_pOutputQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestGetSyntaxHdr.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestGetSyntaxHdr.cpp
new file mode 100644
index 0000000..3674214
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestGetSyntaxHdr.cpp
@@ -0,0 +1,260 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestGetSyntaxHdr.h"
+#include "venctest_Encoder.h"
+#include "venctest_SignalQueue.h"
+
+namespace venctest
+{
+ static const OMX_S32 PORT_INDEX_IN = 0;
+ static const OMX_S32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestGetSyntaxHdr::TestGetSyntaxHdr()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestGetSyntaxHdr::~TestGetSyntaxHdr()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestGetSyntaxHdr::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestGetSyntaxHdr::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ static const OMX_S32 nSyntaxHdrLen = 4096;
+
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ OMX_U8* pSyntaxHdr = NULL;
+ OMX_S32 nSyntaxHdrFilledLen;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create signal queue
+ VENC_TEST_MSG_HIGH("Creating signal queue...");
+ m_pSignalQueue = new SignalQueue(32, sizeof(OMX_BUFFERHEADERTYPE*)); // max 32 messages
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+ }
+
+ //==========================================
+ // Allocate the syntax header buffer
+ if (result == OMX_ErrorNone)
+ {
+ pSyntaxHdr = new OMX_U8[nSyntaxHdrLen];
+ }
+
+ //==========================================
+ // Get the out-of-band syntax hdr
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pEncoder->GetOutOfBandSyntaxHeader(
+ pSyntaxHdr, nSyntaxHdrLen, &nSyntaxHdrFilledLen));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to get syntax hdr");
+ }
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ if (result == OMX_ErrorNone)
+ {
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (OMX_S32 i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ }
+ }
+
+
+ //==========================================
+ // Get the in-band syntax hdr
+ if (result == OMX_ErrorNone)
+ {
+ // get the in band syntax header
+ result = CheckError(GetInBandSyntaxHeader(ppOutputBuffers[0]));
+
+ if (result == OMX_ErrorNone)
+ {
+ // are in-band and out-of-band headers the same size
+ if (nSyntaxHdrFilledLen > 0)
+ {
+ if (nSyntaxHdrFilledLen == (OMX_S32) ppOutputBuffers[0]->nFilledLen)
+ {
+ // are in-band and out-of-band headers bit-exact?
+ for (OMX_S32 i = 0; i < nSyntaxHdrFilledLen; i++)
+ {
+ if (pSyntaxHdr[i] != ppOutputBuffers[0]->pBuffer[i])
+ {
+ VENC_TEST_MSG_ERROR("Byte %ld does not match", i);
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Syntax header looks good with size of %ld",
+ nSyntaxHdrFilledLen);
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Syntax header sizes are different %ld != %ld",
+ nSyntaxHdrFilledLen, ppOutputBuffers[0]->nFilledLen);
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("Syntax header size is 0");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ if (pSyntaxHdr != NULL)
+ {
+ delete [] pSyntaxHdr;
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pSignalQueue)
+ delete m_pSignalQueue;
+
+ return result;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestGetSyntaxHdr::GetInBandSyntaxHeader(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ VENC_TEST_MSG_HIGH("waiting for syntax header...");
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pSignalQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer), 1000)); // wait for 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)
+ {
+ VENC_TEST_MSG_ERROR("expecting codeconfig flag");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed popping");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestGetSyntaxHdr::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return OMX_ErrorNone;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestGetSyntaxHdr::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestGetSyntaxHdr*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestIFrameRequest.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestIFrameRequest.cpp
new file mode 100644
index 0000000..529f89c
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestIFrameRequest.cpp
@@ -0,0 +1,579 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestIFrameRequest.h"
+#include "venctest_Time.h"
+#include "venctest_Encoder.h"
+#include "venctest_Queue.h"
+#include "venctest_SignalQueue.h"
+#include "venctest_File.h"
+
+namespace venctest
+{
+ static const OMX_U32 PORT_INDEX_IN = 0;
+ static const OMX_U32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestIFrameRequest::TestIFrameRequest()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL),
+ m_pInputQueue(NULL),
+ m_pOutputQueue(NULL),
+ m_pSignalQueue(NULL),
+ m_pSource(NULL),
+ m_pSink(NULL)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestIFrameRequest::~TestIFrameRequest()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestIFrameRequest::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pConfig->eControlRate == OMX_Video_ControlRateVariableSkipFrames ||
+ pConfig->eControlRate == OMX_Video_ControlRateConstantSkipFrames)
+ {
+ VENC_TEST_MSG_ERROR("Frame skip must be disabled for this to work");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nIFrameRequestPeriod <= 0)
+ {
+ VENC_TEST_MSG_ERROR("Need a valid iframe request period");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pDynamicConfig->nIFrameRequestPeriod > pConfig->nFrames)
+ {
+ VENC_TEST_MSG_ERROR("nIFrameRequestPeriod must be less than nFrames");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ if (pConfig->nIntraPeriod > pConfig->nFrames)
+ {
+ VENC_TEST_MSG_ERROR("nIntraPeriod must be less than nFrames");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestIFrameRequest::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create signal queue
+ VENC_TEST_MSG_HIGH("Creating signal queue...");
+ m_pSignalQueue = new SignalQueue(32, sizeof(OMX_BUFFERHEADERTYPE*)); // max 32 messages
+
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pInputQueue = new Queue(pConfig->nInBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+
+ //==========================================
+ // Create output buffer queue
+ VENC_TEST_MSG_HIGH("Creating output buffer queue...");
+ m_pOutputQueue = new Queue(pConfig->nOutBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+ }
+
+ //==========================================
+ // Create and open yuv file
+ if (pConfig->cInFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file source...");
+ m_pSource = new File();
+ result = m_pSource->Open(pConfig->cInFileName, OMX_TRUE);
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not reading from input file");
+ }
+
+ //==========================================
+ // Create and open m4v file
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->cOutFileName[0] != (char) 0)
+ {
+ VENC_TEST_MSG_HIGH("Creating file sink...");
+ m_pSink = new File();
+ result = m_pSink->Open(pConfig->cOutFileName, OMX_FALSE);
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("Not writing to output file");
+ }
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pEncoder->EnableUseBufferModel(pConfig->bInUseBuffer, pConfig->bOutUseBuffer);
+ }
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pInputQueue->Push(&ppInputBuffers[i], sizeof(ppInputBuffers[i])); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pOutputQueue->Push(&ppOutputBuffers[i], sizeof(ppOutputBuffers[i])); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Encode all frames
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(EncodeFrames(pConfig, pDynamicConfig));
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ //==========================================
+ // Close the yuv file
+ if (m_pSource != NULL)
+ {
+ result = m_pSource->Close();
+ }
+
+ //==========================================
+ // Close the m4v file
+ if (m_pSink != NULL)
+ {
+ result = m_pSink->Close();
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pInputQueue)
+ delete m_pInputQueue;
+ if (m_pOutputQueue)
+ delete m_pOutputQueue;
+ if (m_pSignalQueue)
+ delete m_pSignalQueue;
+ if (m_pSource)
+ delete m_pSource;
+ if (m_pSink)
+ delete m_pSink;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestIFrameRequest::ProcessSyntaxHeader()
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ VENC_TEST_MSG_HIGH("waiting for syntax header...");
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result == OMX_ErrorNone)
+ {
+ result = CheckError(m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 1000)); // wait for 1 second max
+ if (result == OMX_ErrorNone)
+ {
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0)
+ {
+ OMX_U32 nBytesWritten;
+ result = m_pSink->Write(pBuffer->pBuffer,
+ pBuffer->nFilledLen,
+ &nBytesWritten);
+ (void) m_pOutputQueue->Push((OMX_PTR) &pBuffer, sizeof(pBuffer));
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error writing to file");
+ result = OMX_ErrorUndefined;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("expecting codeconfig flag");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed popping");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestIFrameRequest::EncodeFrames(EncoderConfigType* pEncoderConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ OMX_BOOL bKeepRunning = OMX_TRUE;
+ OMX_S32 nInputDone = 0;
+ OMX_S32 nOutputDone = 0;
+ OMX_S32 nConsecIframes = 0;
+ OMX_BOOL bRequestedIFrame = OMX_FALSE;
+
+ OMX_TICKS nTimeStamp = 0;
+
+ // Let's get the syntax header unless H.263
+ if (pEncoderConfig->nFrames > 0 &&
+ pEncoderConfig->eCodec != OMX_VIDEO_CodingH263)
+ {
+ result = CheckError(ProcessSyntaxHeader());
+ }
+
+ while (bKeepRunning == OMX_TRUE && result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+
+ //==========================================
+ // see if we are finished
+ if (nInputDone == pEncoderConfig->nFrames &&
+ nOutputDone == pEncoderConfig->nFrames)
+ {
+ VENC_TEST_MSG_HIGH("Finished encoding %ld frames", pEncoderConfig->nFrames);
+ bKeepRunning = OMX_FALSE;
+ }
+
+ //==========================================
+ // See if both the input buffer and output buffer have been released.
+ // This will serialize the encoding.
+ else if (nInputDone == nOutputDone)
+ {
+
+ result = m_pInputQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ // shouldn't happen
+ VENC_TEST_MSG_ERROR("failed to pop input");
+ break;
+ }
+
+ OMX_S32 nBytesIn = pEncoderConfig->nFrameWidth * pEncoderConfig->nFrameHeight * 3 / 2;
+ if (m_pSource != NULL)
+ {
+ //==========================================
+ // read some yuv data
+ OMX_S32 nBytesOut = 0;
+ result = m_pSource->Read(pBuffer->pBuffer,
+ nBytesIn,
+ &nBytesOut);
+
+ if (nBytesIn != nBytesOut || result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("yuv file is too small. seeking to start.");
+ result = m_pSource->SeekStart(0);
+ if (result != OMX_ErrorNone)
+ {
+ // shouldn't happen
+ VENC_TEST_MSG_ERROR("failed to seek");
+ break;
+ }
+
+ result = m_pSource->Read(pBuffer->pBuffer,
+ nBytesIn,
+ &nBytesOut);
+ if (result != OMX_ErrorNone)
+ {
+ // shouldn't happen
+ VENC_TEST_MSG_ERROR("failed to read");
+ break;
+ }
+ }
+ }
+
+ if (nInputDone % pDynamicConfig->nIFrameRequestPeriod == 0 &&
+ nInputDone != 0)
+ {
+ VENC_TEST_MSG_HIGH("requesting iframe...");
+ bRequestedIFrame = OMX_TRUE;
+ result = CheckError(m_pEncoder->RequestIntraVOP());
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to request iframe");
+ break;
+ }
+ }
+
+ //==========================================
+ // deliver input
+ VENC_TEST_MSG_HIGH("Delivering input frame=%ld %p", nInputDone, pBuffer->pBuffer);
+ pBuffer->nTimeStamp = nTimeStamp;
+ pBuffer->nFilledLen = (OMX_U32) nBytesIn;
+ nTimeStamp = nTimeStamp + (1000000 / pEncoderConfig->nFramerate);
+ result = m_pEncoder->DeliverInput(pBuffer);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ break;
+ }
+
+ //==========================================
+ // deliver output
+ result = m_pOutputQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Delivering output frame=%ld %p", nOutputDone, pBuffer->pBuffer);
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ break;
+ }
+ }
+
+ if (bKeepRunning == OMX_TRUE)
+ {
+
+ //==========================================
+ // wait for a signal
+ result = CheckError(m_pSignalQueue->Pop((OMX_PTR) &pBuffer,
+ sizeof(pBuffer),
+ 0)); // wait infinitely
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed popping");
+ break;
+ }
+
+ if (pBuffer->nInputPortIndex == PORT_INDEX_IN)
+ {
+ //==========================================
+ // push the buffer on the back of the buffer queue
+ VENC_TEST_MSG_HIGH("Received input frame=%ld", nInputDone);
+ result = m_pInputQueue->Push(&pBuffer, sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed pushing");
+ break;
+ }
+ ++nInputDone;
+ }
+ else
+ {
+ // we are expecting an iframe
+ if (bRequestedIFrame == OMX_TRUE || // 1. we requested one
+ nOutputDone % pEncoderConfig->nIntraPeriod == 0) // 2. intra period expired
+ {
+ // is this an iframe?
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) == 0)
+ {
+ // perhaps we got an iframe the last frame which is why we did not get one
+ if (nConsecIframes == 0)
+ {
+ VENC_TEST_MSG_ERROR("got pframe but expecting an iframe");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+ }
+ else
+ {
+ VENC_TEST_MSG_HIGH("got iframe as expected");
+ }
+ }
+ else if ((pBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) != 0)
+ {
+ // we got an iframe but were not expecting one
+ VENC_TEST_MSG_ERROR("got iframe but not expecting one");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+
+ bRequestedIFrame = OMX_FALSE;
+
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) != 0)
+ {
+ ++nConsecIframes;
+ }
+ else
+ {
+ nConsecIframes = 0;
+ }
+
+ if (nConsecIframes > 1)
+ {
+ VENC_TEST_MSG_ERROR("got more than one consecutive iframe");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+
+ //==========================================
+ // push the buffer on the back of the buffer queue
+ VENC_TEST_MSG_HIGH("Received output frame=%ld", nOutputDone);
+ result = m_pOutputQueue->Push(&pBuffer, sizeof(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed pushing");
+ break;
+ }
+ ++nOutputDone;
+
+ //==========================================
+ // write to file
+ if (m_pSink != NULL)
+ {
+ OMX_U32 nBytesWritten;
+ result = m_pSink->Write(pBuffer->pBuffer,
+ pBuffer->nFilledLen,
+ &nBytesWritten);
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("error writing to file");
+ }
+ else if (nBytesWritten != pBuffer->nFilledLen)
+ {
+ VENC_TEST_MSG_ERROR("mismatched number of bytes in file write");
+ result = CheckError(OMX_ErrorUndefined);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestIFrameRequest::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestIFrameRequest*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestIFrameRequest::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return ((TestIFrameRequest*) pAppData)->m_pSignalQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestPmem.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestPmem.cpp
new file mode 100644
index 0000000..e2642c6
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestPmem.cpp
@@ -0,0 +1,179 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestPmem.h"
+#include "venctest_Time.h"
+#include "venctest_FileSource.h"
+#include "venctest_FileSink.h"
+#include "venctest_Encoder.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestPmem::TestPmem()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestPmem::~TestPmem()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestPmem::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestPmem::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = m_pEncoder->Configure(pConfig);
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ for (OMX_S32 i = 0; i < 2; i++)
+ {
+ //==========================================
+ // Allocate or UseBuffer model?
+ if (result == OMX_ErrorNone)
+ {
+ result = m_pEncoder->EnableUseBufferModel(i % 2 == 0 ? OMX_FALSE : OMX_TRUE, i % 2 == 0 ? OMX_FALSE : OMX_TRUE);
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = m_pEncoder->GoToExecutingState();
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Get the allocated input buffers
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ if (ppInputBuffers[i]->pBuffer == NULL ||
+ ppInputBuffers[i]->nAllocLen == 0)
+ {
+ result = OMX_ErrorUndefined;
+ break;
+ }
+ }
+
+
+ if (result = OMX_ErrorNone)
+ {
+ //==========================================
+ // Get the allocated output buffers
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ if (ppOutputBuffers[i]->pBuffer == NULL ||
+ ppOutputBuffers[i]->nAllocLen == 0)
+ {
+ result = OMX_ErrorUndefined;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = m_pEncoder->GoToLoadedState();
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("failed to go to loaded state");
+ break;
+ }
+
+ } // end of loop
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestPmem::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return OMX_ErrorNone;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestPmem::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ return OMX_ErrorNone;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestProfileEncode.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestProfileEncode.cpp
new file mode 100644
index 0000000..f1c62c4
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestProfileEncode.cpp
@@ -0,0 +1,338 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestProfileEncode.h"
+#include "venctest_Time.h"
+#include "venctest_FileSource.h"
+#include "venctest_FileSink.h"
+#include "venctest_Encoder.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestProfileEncode::TestProfileEncode()
+ : ITestCase(), // invoke the base class constructor
+ m_pSource(NULL),
+ m_pSink(NULL),
+ m_pEncoder(NULL),
+ m_nFramesCoded(0),
+ m_nBits(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestProfileEncode::~TestProfileEncode()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestProfileEncode::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestProfileEncode::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ OMX_TICKS nStartTime;
+ OMX_TICKS nEndTime;
+ OMX_TICKS nRunTimeSec;
+ OMX_TICKS nRunTimeMillis;
+
+ //==========================================
+ // Create and configure the file source (yuv reader)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating source...");
+ m_pSource = new FileSource();
+ result = m_pSource->Configure(pConfig->nFrames,
+ pConfig->nFramerate,
+ pConfig->nFrameWidth,
+ pConfig->nFrameHeight,
+ pConfig->nInBufferCount,
+ SourceDeliveryFn,
+ pConfig->cInFileName,
+ pConfig->nDVSXOffset,
+ pConfig->nDVSYOffset,
+ OMX_TRUE);
+ }
+
+ //==========================================
+ // Create and configure the file sink (m4v writer)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating sink...");
+ m_pSink = new FileSink();
+ result = m_pSink->Configure(pConfig->nFrames,
+ pConfig->cOutFileName,
+ SinkReleaseFn);
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = m_pEncoder->Configure(pConfig);
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = m_pEncoder->GoToExecutingState();
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pSource->SetFreeBuffer(ppInputBuffers[i]); // give ownership to source
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = m_pEncoder->DeliverOutput(ppOutputBuffers[i]); // give ownership to encoder
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the sink ready to write m4v output
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("starting the sink thread...");
+ nStartTime = Time::GetTimeMicrosec();
+ result = m_pSink->Start();
+ }
+
+ //==========================================
+ // Start reading and delivering frames
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("starting the source thread...");
+ result = m_pSource->Start();
+ }
+
+ //==========================================
+ // Wait for the source to finish delivering all frames
+ if (m_pSource != NULL)
+ {
+ VENC_TEST_MSG_HIGH("waiting for source to finish...");
+ result = m_pSource->Finish();
+ VENC_TEST_MSG_HIGH("source is finished");
+ }
+
+ //==========================================
+ // Wait for the sink to finish writing all frames
+ if (m_pSink != NULL)
+ {
+ VENC_TEST_MSG_HIGH("waiting for sink to finish...");
+ result = m_pSink->Finish();
+ VENC_TEST_MSG_HIGH("sink is finished");
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = m_pEncoder->GoToLoadedState();
+ }
+
+ //==========================================
+ // Compute stats
+ nEndTime = Time::GetTimeMicrosec();
+ nRunTimeMillis = (nEndTime - nStartTime) / 1000; // convert to millis
+ nRunTimeSec = nRunTimeMillis / 1000; // convert to seconds
+
+ VENC_TEST_MSG_PROFILE("Time = %d millis, Encoded = %d, Dropped = %d",
+ (int) nRunTimeMillis,
+ (int) m_nFramesCoded,
+ (int) (pConfig->nFrames - m_nFramesCoded));
+
+ if (nRunTimeSec > 0) // ensure no divide by zero
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d",
+ (int) (m_nBits / nRunTimeSec),
+ (int) (pConfig->nFrames / nRunTimeSec),
+ (int) (m_nFramesCoded / nRunTimeSec));
+ }
+ else
+ {
+ VENC_TEST_MSG_PROFILE("Bitrate = %d, InputFPS = %d, OutputFPS = %d");
+ }
+
+ VENC_TEST_MSG_PROFILE("Avg encode time = %d millis per frame",
+ (int) (nRunTimeMillis / pConfig->nFrames));
+
+ // determine the test result
+ if (result == OMX_ErrorNone)
+ {
+ if (pConfig->eControlRate != OMX_Video_ControlRateDisable)
+ {
+ static const double errorThreshold = .15; // error percentage threshold
+
+ OMX_S32 nBitrateDelta = (OMX_S32) (pConfig->nBitrate - (m_nBits / nRunTimeSec));
+ if (nBitrateDelta < 0)
+ {
+ nBitrateDelta = -nBitrateDelta;
+ }
+ if ((double) nBitrateDelta > pConfig->nBitrate * errorThreshold)
+ {
+ VENC_TEST_MSG_ERROR("test failed with bitrate %d. bitrate delta is %d max allowed is approx %d",
+ (int) pConfig->nBitrate,
+ (int) nBitrateDelta,
+ (int) (pConfig->nBitrate * errorThreshold));
+ result = OMX_ErrorUndefined;
+ }
+
+ OMX_S32 nFramerateDelta = (OMX_S32) (pConfig->nFramerate - (pConfig->nFrames / nRunTimeSec));
+ if (nFramerateDelta < 0)
+ {
+ nFramerateDelta = -nFramerateDelta;
+ }
+ if ((double) nFramerateDelta > pConfig->nFramerate * errorThreshold)
+ {
+ VENC_TEST_MSG_ERROR("test failed with frame rate %d. frame rate delta is %d max allowed is approx %d",
+ (int) pConfig->nFramerate,
+ (int) nFramerateDelta,
+ (int) ((pConfig->nFrames / nRunTimeSec) * errorThreshold));
+ result = OMX_ErrorUndefined;
+ }
+ }
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pSource)
+ delete m_pSource;
+ if (m_pSink)
+ delete m_pSink;
+ if (m_pEncoder)
+ delete m_pEncoder;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ void TestProfileEncode::SourceDeliveryFn(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ // Deliver YUV data from source to encoder
+ ((Encoder*) pBuffer->pAppPrivate)->DeliverInput(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ void TestProfileEncode::SinkReleaseFn(OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ // Deliver bitstream buffer from sink to encoder
+ ((Encoder*) pBuffer->pAppPrivate)->DeliverOutput(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestProfileEncode::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ TestProfileEncode* pTester = (TestProfileEncode*) pAppData;
+
+ // Deliver free yuv buffer to source
+ return pTester->m_pSource->SetFreeBuffer(pBuffer);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestProfileEncode::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+
+ TestProfileEncode* pTester = (TestProfileEncode*) pAppData;
+
+ // get performance data
+ if (pBuffer->nFilledLen != 0)
+ {
+ // if it's only the syntax header don't count it as a frame
+ if ((pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0 &&
+ (pBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME))
+ {
+ ++pTester->m_nFramesCoded;
+ }
+
+ // always count the bits regarding whether or not its only syntax header
+ pTester->m_nBits = pTester->m_nBits + (OMX_S32) (pBuffer->nFilledLen * 8);
+ }
+
+ // Deliver encoded m4v output to sink for file write
+ return pTester->m_pSink->Write(pBuffer);
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestStateExecutingToIdle.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestStateExecutingToIdle.cpp
new file mode 100644
index 0000000..257a987
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestStateExecutingToIdle.cpp
@@ -0,0 +1,307 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestStateExecutingToIdle.h"
+#include "venctest_Time.h"
+#include "venctest_Encoder.h"
+#include "venctest_Queue.h"
+#include "venctest_File.h"
+
+namespace venctest
+{
+ static const OMX_S32 PORT_INDEX_IN = 0;
+ static const OMX_S32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestStateExecutingToIdle::TestStateExecutingToIdle()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL),
+ m_pInputQueue(NULL),
+ m_pOutputQueue(NULL),
+ m_nTimeStamp(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestStateExecutingToIdle::~TestStateExecutingToIdle()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStateExecutingToIdle::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStateExecutingToIdle::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pInputQueue = new Queue(pConfig->nInBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+
+ //==========================================
+ // Create output buffer queue
+ VENC_TEST_MSG_HIGH("Creating output buffer queue...");
+ m_pOutputQueue = new Queue(pConfig->nOutBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pInputQueue->Push(
+ &ppInputBuffers[i], sizeof(ppInputBuffers[i]))); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pOutputQueue->Push(
+ &ppOutputBuffers[i], sizeof(ppOutputBuffers[i]))); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Deliver buffers and go to idle state
+ static const OMX_S32 nRuns = 4;
+ static const OMX_BOOL bPortMap[nRuns][2] =
+ { {OMX_FALSE, OMX_FALSE}, // no input or output buffers
+ {OMX_TRUE, OMX_FALSE}, // input buffers only
+ {OMX_FALSE, OMX_TRUE}, // output buffers only
+ {OMX_TRUE, OMX_TRUE} }; // input and output buffers
+ for (OMX_S32 i = 0; i < nRuns; i++)
+ {
+ VENC_TEST_MSG_HIGH("Deliver buffers %d", (int) i);
+ result = CheckError(DeliverBuffers(
+ bPortMap[i][0], bPortMap[i][1], pConfig));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver buffers %d", (int) i);
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Enter idle %d", (int) i);
+ result = CheckError(m_pEncoder->SetState(OMX_StateIdle, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter idle state %d", (int) i);
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Check queues %d", (int) i);
+ result = CheckError(CheckBufferQueues(
+ pConfig->nInBufferCount, pConfig->nOutBufferCount));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("missing some buffers %d", (int) i);
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Enter executing %d", (int) i);
+ result = CheckError(m_pEncoder->SetState(OMX_StateExecuting, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter executing state %d", (int) i);
+ break;
+ }
+ }
+
+ //==========================================
+ // Tear down the encoder (also deallocate buffers)
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Go to loaded state...");
+ result = CheckError(m_pEncoder->GoToLoadedState());
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pInputQueue)
+ delete m_pInputQueue;
+ if (m_pOutputQueue)
+ delete m_pOutputQueue;
+
+ return result;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStateExecutingToIdle::DeliverBuffers(OMX_BOOL bDeliverInput,
+ OMX_BOOL bDeliverOutput,
+ EncoderConfigType* pConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // deliver all input buffers
+ if (bDeliverInput == OMX_TRUE)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ OMX_S32 nSize = m_pInputQueue->GetSize();
+ for (OMX_S32 i = 0; i < nSize; i++)
+ {
+ result = CheckError(m_pInputQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer)));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop input");
+ break;
+ }
+
+ pBuffer->nTimeStamp = m_nTimeStamp;
+ m_nTimeStamp = m_nTimeStamp + 1000000 / pConfig->nFramerate;
+ pBuffer->nFilledLen = pConfig->nFrameWidth * pConfig->nFrameHeight * 3 / 2;
+ result = CheckError(m_pEncoder->DeliverInput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ break;
+ }
+ }
+ }
+
+ // deliver all output buffers
+ if (bDeliverOutput == OMX_TRUE)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ OMX_S32 nSize = m_pOutputQueue->GetSize();
+ for (OMX_S32 i = 0; i < nSize; i++)
+ {
+ result = CheckError(m_pOutputQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer)));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ break;
+ }
+
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStateExecutingToIdle::CheckBufferQueues(OMX_S32 nInputBuffers,
+ OMX_S32 nOutputBuffers)
+ {
+ return (m_pInputQueue->GetSize() == nInputBuffers &&
+ m_pOutputQueue->GetSize() == nOutputBuffers) ? OMX_ErrorNone : OMX_ErrorUndefined;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStateExecutingToIdle::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_HIGH("queuing input buffer with size %ld", pBuffer->nFilledLen);
+ return ((TestStateExecutingToIdle*) pAppData)->m_pInputQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStateExecutingToIdle::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_HIGH("queuing output buffer with size %ld", pBuffer->nFilledLen);
+ return ((TestStateExecutingToIdle*) pAppData)->m_pOutputQueue->Push(&pBuffer, sizeof(pBuffer));
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestStatePause.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestStatePause.cpp
new file mode 100644
index 0000000..12378ed
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_TestStatePause.cpp
@@ -0,0 +1,434 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_ComDef.h"
+#include "venctest_Debug.h"
+#include "venctest_TestStatePause.h"
+#include "venctest_Time.h"
+#include "venctest_Encoder.h"
+#include "venctest_Queue.h"
+#include "venctest_Mutex.h"
+
+namespace venctest
+{
+ static const OMX_S32 PORT_INDEX_IN = 0;
+ static const OMX_S32 PORT_INDEX_OUT = 1;
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestStatePause::TestStatePause()
+ : ITestCase(), // invoke the base class constructor
+ m_pEncoder(NULL),
+ m_pMutex(NULL),
+ m_pInputQueue(NULL),
+ m_pOutputQueue(NULL),
+ m_nTimeStamp(0)
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ TestStatePause::~TestStatePause()
+ {
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStatePause::ValidateAssumptions(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStatePause::Execute(EncoderConfigType* pConfig,
+ DynamicConfigType* pDynamicConfig,
+ OMX_S32 nTestNum)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pInputQueue = new Queue(pConfig->nInBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+
+ //==========================================
+ // Create output buffer queue
+ VENC_TEST_MSG_HIGH("Creating output buffer queue...");
+ m_pOutputQueue = new Queue(pConfig->nOutBufferCount,
+ sizeof(OMX_BUFFERHEADERTYPE*));
+ }
+
+ if (result == OMX_ErrorNone)
+ {
+ //==========================================
+ // Create input buffer queue
+ VENC_TEST_MSG_HIGH("Creating input buffer queue...");
+ m_pMutex = new Mutex();
+ }
+
+ //==========================================
+ // Create and configure the encoder
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Creating encoder...");
+ m_pEncoder = new Encoder(EBD,
+ FBD,
+ this, // set the test case object as the callback app data
+ pConfig->eCodec);
+ result = CheckError(m_pEncoder->Configure(pConfig));
+ }
+
+ //==========================================
+ // Go to executing state (also allocate buffers)
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Go to executing state...");
+ result = CheckError(m_pEncoder->GoToExecutingState());
+ }
+
+ //==========================================
+ // Get the allocated input buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppInputBuffers;
+ ppInputBuffers = m_pEncoder->GetBuffers(OMX_TRUE);
+ for (int i = 0; i < pConfig->nInBufferCount; i++)
+ {
+ ppInputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pInputQueue->Push(
+ &ppInputBuffers[i], sizeof(ppInputBuffers[i]))); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Get the allocated output buffers
+ if (result == OMX_ErrorNone)
+ {
+ OMX_BUFFERHEADERTYPE** ppOutputBuffers;
+ ppOutputBuffers = m_pEncoder->GetBuffers(OMX_FALSE);
+ for (int i = 0; i < pConfig->nOutBufferCount; i++)
+ {
+ ppOutputBuffers[i]->pAppPrivate = m_pEncoder; // set the encoder as the private app data
+ result = CheckError(m_pOutputQueue->Push(
+ &ppOutputBuffers[i], sizeof(ppOutputBuffers[i]))); // store buffers in queue
+ if (result != OMX_ErrorNone)
+ {
+ break;
+ }
+ }
+ }
+
+ //==========================================
+ // Deliver buffers and go to pause state
+ static const OMX_S32 nRuns = 4;
+ static const OMX_BOOL bPortMap[nRuns][2] =
+ { {OMX_FALSE, OMX_FALSE}, // no input or output buffers
+ {OMX_TRUE, OMX_FALSE}, // input buffers only
+ {OMX_FALSE, OMX_TRUE}, // output buffers only
+ {OMX_TRUE, OMX_TRUE} }; // input and output buffers
+ for (OMX_S32 i = 0; i < nRuns; i++)
+ {
+ VENC_TEST_MSG_HIGH("Deliver buffers %d", (int) i);
+ result = CheckError(DeliverBuffers(
+ bPortMap[i][0], bPortMap[i][1], pConfig));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver buffers %d", (int) i);
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Enter pause %d", (int) i);
+ result = CheckError(m_pEncoder->SetState(OMX_StatePause, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter pause state %d", (int) i);
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Check queues %ld: %ld %ld",
+ i, m_pInputQueue->GetSize(), m_pOutputQueue->GetSize());
+
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("missing some buffers %d", (int) i);
+ break;
+ }
+
+ VENC_TEST_MSG_HIGH("Enter executing %d", (int) i);
+ result = CheckError(m_pEncoder->SetState(OMX_StateExecuting, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter executing state %d", (int) i);
+ break;
+ }
+ }
+
+ //==========================================
+ // go back to pause state
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Enter pause");
+ result = CheckError(m_pEncoder->SetState(OMX_StatePause, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter pause state");
+ }
+ }
+
+ //==========================================
+ // verify we can transition from pause to idle
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Enter idle");
+ result = CheckError(m_pEncoder->SetState(OMX_StateIdle, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter idle state");
+ }
+ }
+
+ //==========================================
+ // ensure encoder has returned all buffers before finalizing idle transition
+ if (result == OMX_ErrorNone)
+ {
+ OMX_S32 in = m_pInputQueue->GetSize();
+ OMX_S32 out = m_pOutputQueue->GetSize();
+
+ if (in != pConfig->nInBufferCount ||
+ out != pConfig->nOutBufferCount)
+ {
+ VENC_TEST_MSG_ERROR("encoder did not return all buffers %ld %ld", in, out);
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+
+ //==========================================
+ // go back to executing state
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Enter executing");
+ result = CheckError(m_pEncoder->SetState(OMX_StateExecuting, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter executing state");
+ }
+ }
+
+ //==========================================
+ // go to pause state
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Enter pause");
+ result = CheckError(m_pEncoder->SetState(OMX_StatePause, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter pause state");
+ }
+ }
+
+ //==========================================
+ // verify we can deliver buffers in the pause state
+ if (result == OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_HIGH("Deliver buffers");
+ result = CheckError(DeliverBuffers(
+ OMX_TRUE, OMX_TRUE, pConfig));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver buffers in pause state");
+ }
+ }
+ //==========================================
+ // go to idle state
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Enter idle");
+ result = CheckError(m_pEncoder->SetState(OMX_StateIdle, OMX_TRUE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter idle state");
+ }
+ }
+
+ //==========================================
+ // ensure encoder has returned all buffers before finalizing idle transition
+ if (result == OMX_ErrorNone)
+ {
+ if (m_pInputQueue->GetSize() != pConfig->nInBufferCount ||
+ m_pOutputQueue->GetSize() != pConfig->nOutBufferCount)
+ {
+ VENC_TEST_MSG_ERROR("encoder did not return all buffers");
+ result = CheckError(OMX_ErrorUndefined);
+ }
+ }
+
+ //==========================================
+ // go to loaded state
+ if (m_pEncoder != NULL)
+ {
+ VENC_TEST_MSG_HIGH("Enter loaded");
+ result = CheckError(m_pEncoder->SetState(OMX_StateLoaded, OMX_FALSE));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed enter loaded state");
+ }
+
+ result = CheckError(m_pEncoder->FreeBuffers());
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to free buffers");
+ }
+
+ result = CheckError(m_pEncoder->WaitState(OMX_StateLoaded));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to wait for loaded");
+ }
+ }
+
+ //==========================================
+ // Free our helper classes
+ if (m_pEncoder)
+ delete m_pEncoder;
+ if (m_pInputQueue)
+ delete m_pInputQueue;
+ if (m_pOutputQueue)
+ delete m_pOutputQueue;
+ if (m_pMutex)
+ delete m_pMutex;
+
+ return result;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStatePause::DeliverBuffers(OMX_BOOL bDeliverInput,
+ OMX_BOOL bDeliverOutput,
+ EncoderConfigType* pConfig)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ // deliver all input buffers
+ if (bDeliverInput == OMX_TRUE)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ OMX_S32 nSize = m_pInputQueue->GetSize();
+ for (OMX_S32 i = 0; i < nSize; i++)
+ {
+ m_pMutex->Lock();
+ result = CheckError(m_pInputQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer)));
+ m_pMutex->UnLock();
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop input");
+ break;
+ }
+
+ pBuffer->nTimeStamp = m_nTimeStamp;
+ m_nTimeStamp = m_nTimeStamp + 1000000 / pConfig->nFramerate;
+ pBuffer->nFilledLen = pConfig->nFrameWidth * pConfig->nFrameHeight * 3 / 2;
+ result = CheckError(m_pEncoder->DeliverInput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver input");
+ break;
+ }
+ }
+ }
+
+ // deliver all output buffers
+ if (bDeliverOutput == OMX_TRUE)
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ OMX_S32 nSize = m_pOutputQueue->GetSize();
+ for (OMX_S32 i = 0; i < nSize; i++)
+ {
+ m_pMutex->Lock();
+ result = CheckError(m_pOutputQueue->Pop(
+ (OMX_PTR) &pBuffer, sizeof(pBuffer)));
+ m_pMutex->UnLock();
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to pop output");
+ break;
+ }
+
+ result = CheckError(m_pEncoder->DeliverOutput(pBuffer));
+ if (result != OMX_ErrorNone)
+ {
+ VENC_TEST_MSG_ERROR("failed to deliver output");
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStatePause::EBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_HIGH("queuing input buffer with size %ld", pBuffer->nFilledLen);
+ ((TestStatePause*) pAppData)->m_pMutex->Lock();
+ OMX_ERRORTYPE result = ((TestStatePause*) pAppData)->m_pInputQueue->Push(&pBuffer, sizeof(pBuffer));
+ ((TestStatePause*) pAppData)->m_pMutex->UnLock();
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE TestStatePause::FBD(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+ {
+ VENC_TEST_MSG_HIGH("queuing output buffer with size %ld", pBuffer->nFilledLen);
+ ((TestStatePause*) pAppData)->m_pMutex->Lock();
+ OMX_ERRORTYPE result = ((TestStatePause*) pAppData)->m_pOutputQueue->Push(&pBuffer, sizeof(pBuffer));
+ ((TestStatePause*) pAppData)->m_pMutex->UnLock();
+ return result;
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Thread.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Thread.cpp
new file mode 100644
index 0000000..5c21cbe
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Thread.cpp
@@ -0,0 +1,123 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Debug.h"
+#include "venctest_Thread.h"
+#include "venc_thread.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Thread::Thread()
+ : m_pFn(NULL),
+ m_nPriority(0),
+ m_pThread(NULL),
+ m_pThreadArgs(NULL)
+ {
+ VENC_TEST_MSG_LOW("constructor");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ Thread::~Thread()
+ {
+ VENC_TEST_MSG_LOW("destructor");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Thread::Start(StartFnType pFn,
+ OMX_PTR pThreadArgs,
+ OMX_S32 nPriority)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ VENC_TEST_MSG_LOW("Start");
+ m_pThreadArgs = pThreadArgs;
+ m_pFn = pFn;
+
+ if (venc_thread_create(&m_pThread, ThreadEntry, this, (int) nPriority) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to create thread");
+ result = OMX_ErrorUndefined;
+ }
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_ERRORTYPE Thread::Join(OMX_ERRORTYPE* pThreadResult)
+ {
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ int thread_result;
+
+ VENC_TEST_MSG_LOW("Join");
+
+ if (venc_thread_destroy(m_pThread, &thread_result) != 0)
+ {
+ VENC_TEST_MSG_ERROR("failed to destroy thread");
+ }
+
+ if (pThreadResult != NULL)
+ {
+ *pThreadResult = (OMX_ERRORTYPE) thread_result;
+ }
+
+ m_pThread = NULL;
+
+ return result;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ int Thread::ThreadEntry(void* pThreadData)
+ {
+ Thread* pThread = (Thread*) pThreadData;
+ VENC_TEST_MSG_LOW("ThreadEntry");
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+
+ if (pThread != NULL)
+ {
+ result = pThread->m_pFn(pThread->m_pThreadArgs);
+ }
+ else
+ {
+ VENC_TEST_MSG_ERROR("failed to create thread");
+ result = OMX_ErrorUndefined;
+ }
+
+
+ return (int) result;
+ }
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/common/src/venctest_Time.cpp b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Time.cpp
new file mode 100644
index 0000000..bdd7e4e
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/common/src/venctest_Time.cpp
@@ -0,0 +1,45 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*========================================================================
+ Include Files
+ ==========================================================================*/
+#include "venctest_Time.h"
+#include "venc_time.h"
+
+namespace venctest
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////
+ OMX_TICKS Time::GetTimeMicrosec()
+ {
+ return (OMX_TICKS) venc_time_microsec();
+ }
+
+} // namespace venctest
diff --git a/omx/mm-video/qdsp6/venc/test/etc/venctest_Config.cfg b/omx/mm-video/qdsp6/venc/test/etc/venctest_Config.cfg
new file mode 100644
index 0000000..be67356
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/etc/venctest_Config.cfg
@@ -0,0 +1,79 @@
+#--------------------------------------------------------------------------
+#Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#--------------------------------------------------------------------------
+
+##############################################
+############ COMMON STATIC CONFIG ############
+##############################################
+FrameWidth = 1280 ## Frame width
+FrameHeight = 720 ## Frame height
+OutputFrameWidth = 1280 ## DVS Frame width
+OutputFrameHeight = 720 ## DVS Frame height
+DVSXOffset = 0 ## DVS Frame width
+DVSYOffset = 0 ## DVS Frame height
+Codec = MP4 ## MP4 | H263 | H264
+FPS = 30 ## Frame rate
+RC = RC_OFF ## RC_OFF | RC_VBR_VFR | RC_VBR_CFR | RC_CBR_VFR
+InBufferCount = 6 ## Number of input buffers
+OutBufferCount = 6 ## Number of output buffers
+Rotation = 0 ## Rotation in degrees 0 | 90 | 180 | 270
+Bitrate = 68000 ## Bits per second
+ResyncMarkerType = NONE ## NONE | BITS | MB | GOB
+ResyncMarkerSpacing = 0 ## Resync marker spacing (valid only if resyncmarkertype != none)
+EnableIntraRefresh = 0 ## Intra refresh enable (0 for disable, 1 for enable)
+InFile = clips/enc_720p.yuv ## Input yuv file
+OutFile = 720p_i.m4v ## Output bitstream file (leave blank for no output)
+NumFrames = 300 ## Number of frames to encode
+IntraPeriod = 60 ## The iframe interval in units of frames
+MinQp = 2 ## The minimum qp
+MaxQp = 31 ## The maximum qp
+
+##############################################
+############ MPEG4 STATIC CONFIG ############
+##############################################
+HECInterval = 0 ## Header extension coding interval (0 for disable)
+TimeIncRes = 30 ## MPEG4 time increment resolution
+EnableShortHeader = 0 ## MPEG4 SVH enable
+
+##############################################
+############ H.263 STATIC CONFIG ############
+##############################################
+
+##############################################
+############ H.264 STATIC CONFIG ############
+##############################################
+
+##############################################
+########### COMMON DYNAMIC CONFIG ############
+##############################################
+IFrameRequestPeriod = 5 ## Dynmically request an iframe every N frames
+UpdatedFPS = 15 ## The new frame rate for change quality
+UpdatedMinQp = 2 ## The new minimum qp for change quality
+UpdatedMaxQp = 31 ## The new maximum qp for change quality
+UpdatedBitrate = 98000 ## The new bitrate for change quality
+UpdatedNumFrames = 90 ## The new number of frames to encode
+UpdatedIntraPeriod = 30 ## The new intra period
diff --git a/omx/mm-video/qdsp6/venc/test/etc/venctest_Script.cfg b/omx/mm-video/qdsp6/venc/test/etc/venctest_Script.cfg
new file mode 100644
index 0000000..6e07cc1
--- /dev/null
+++ b/omx/mm-video/qdsp6/venc/test/etc/venctest_Script.cfg
@@ -0,0 +1,46 @@
+#--------------------------------------------------------------------------
+#Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#--------------------------------------------------------------------------
+
+##############################################################################
+# Supported Test Types:
+# 1. SERIAL_ENCODE
+# 2. PROFILE_ENCODE
+# 3. IFRAME_REQUEST
+# 4. PMEM
+#
+# Script File Syntax:
+# <SCRIPT_NAME> <ENCODER_CONFIG_FILE_NAME> <NUM_SESSIONS>
+##############################################################################
+
+SERIAL_ENCODE venctest_Config.cfg 1
+
+# PROFILE_ENCODE venctest_Config.cfg 1
+
+# IFRAME_REQUEST venctest_Config.cfg 1
+
+# PMEM venctest_Config.cfg 1
diff --git a/omx/mm-video/vidc/vdec/Android.mk b/omx/mm-video/vidc/vdec/Android.mk
new file mode 100644
index 0000000..d02d0cb
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/Android.mk
@@ -0,0 +1,122 @@
+#--------------------------------------------------------------------------
+#Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#--------------------------------------------------------------------------
+
+ifneq ($(BUILD_TINY_ANDROID),true)
+
+ROOT_DIR := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PATH:= $(ROOT_DIR)
+
+# ---------------------------------------------------------------------------------
+# Common definitons
+# ---------------------------------------------------------------------------------
+
+libOmxVdec-def := -D__alignx\(x\)=__attribute__\(\(__aligned__\(x\)\)\)
+libOmxVdec-def += -D__align=__alignx
+libOmxVdec-def += -Dinline=__inline
+libOmxVdec-def += -g -O3
+libOmxVdec-def += -DIMAGE_APPS_PROC
+libOmxVdec-def += -D_ANDROID_
+libOmxVdec-def += -DCDECL
+libOmxVdec-def += -DT_ARM
+libOmxVdec-def += -DNO_ARM_CLZ
+libOmxVdec-def += -UENABLE_DEBUG_LOW
+libOmxVdec-def += -DENABLE_DEBUG_HIGH
+libOmxVdec-def += -DENABLE_DEBUG_ERROR
+libOmxVdec-def += -UMULTI_DEC_INST
+ifeq "$(findstring msm7630,$(TARGET_PRODUCT))" "msm7630"
+libOmxVdec-def += -DMAX_RES_720P
+endif
+ifeq "$(findstring msm8660,$(TARGET_PRODUCT))" "msm8660"
+libOmxVdec-def += -DMAX_RES_1080P
+endif
+# ---------------------------------------------------------------------------------
+# Make the Shared library (libOmxVdec)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+LOCAL_PATH:= $(ROOT_DIR)
+
+libmm-vdec-inc := $(LOCAL_PATH)/inc
+libmm-vdec-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore
+
+LOCAL_MODULE := libOmxVdec
+LOCAL_CFLAGS := $(libOmxVdec-def)
+LOCAL_C_INCLUDES := $(libmm-vdec-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog libutils libbinder
+
+LOCAL_SRC_FILES := src/frameparser.cpp
+LOCAL_SRC_FILES += src/h264_utils.cpp
+LOCAL_SRC_FILES += src/omx_vdec.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
+# ---------------------------------------------------------------------------------
+# Make the apps-test (mm-vdec-omx-test)
+# ---------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+
+mm-vdec-test-inc := $(TARGET_OUT_HEADERS)/mm-core/omxcore
+mm-vdec-test-inc += $(LOCAL_PATH)/inc
+
+LOCAL_MODULE := mm-vdec-omx-test
+LOCAL_CFLAGS := $(libOmxVdec-def)
+LOCAL_C_INCLUDES := $(mm-vdec-test-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libutils libOmxCore libOmxVdec libbinder
+
+LOCAL_SRC_FILES := src/queue.c
+LOCAL_SRC_FILES += test/omx_vdec_test.cpp
+
+include $(BUILD_EXECUTABLE)
+
+# ---------------------------------------------------------------------------------
+# Make the driver-test (mm-video-driver-test)
+# ---------------------------------------------------------------------------------
+include $(CLEAR_VARS)
+
+mm-vdec-drv-test-inc := $(TARGET_OUT_HEADERS)/mm-core/omxcore
+mm-vdec-drv-test-inc += $(LOCAL_PATH)/inc
+
+LOCAL_MODULE := mm-video-driver-test
+LOCAL_CFLAGS := $(libOmxVdec-def)
+LOCAL_C_INCLUDES := $(mm-vdec-drv-test-inc)
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := src/message_queue.c
+LOCAL_SRC_FILES += test/decoder_driver_test.c
+
+include $(BUILD_EXECUTABLE)
+
+endif #BUILD_TINY_ANDROID
+
+# ---------------------------------------------------------------------------------
+# END
+# ---------------------------------------------------------------------------------
diff --git a/omx/mm-video/vidc/vdec/inc/Map.h b/omx/mm-video/vidc/vdec/inc/Map.h
new file mode 100644
index 0000000..87cf6de
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/Map.h
@@ -0,0 +1,237 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _MAP_H_
+#define _MAP_H_
+
+#include <stdio.h>
+using namespace std;
+
+template <typename T,typename T2>
+class Map
+{
+ struct node
+ {
+ T data;
+ T2 data2;
+ node* prev;
+ node* next;
+ node(T t, T2 t2,node* p, node* n) :
+ data(t), data2(t2), prev(p), next(n) {}
+ };
+ node* head;
+ node* tail;
+ node* tmp;
+ unsigned size_of_list;
+ static Map<T,T2> *m_self;
+public:
+ Map() : head( NULL ), tail ( NULL ),tmp(head),size_of_list(0) {}
+ bool empty() const { return ( !head || !tail ); }
+ operator bool() const { return !empty(); }
+ void insert(T,T2);
+ void show();
+ int size();
+ T2 find(T); // Return VALUE
+ T find_ele(T);// Check if the KEY is present or not
+ T2 begin(); //give the first ele
+ bool erase(T);
+ bool eraseall();
+ bool isempty();
+ ~Map()
+ {
+ while(head)
+ {
+ node* temp(head);
+ head=head->next;
+ size_of_list--;
+ delete temp;
+ }
+ }
+};
+
+template <typename T,typename T2>
+T2 Map<T,T2>::find(T d1)
+{
+ tmp = head;
+ while(tmp)
+ {
+ if(tmp->data == d1)
+ {
+ return tmp->data2;
+ }
+ tmp = tmp->next;
+ }
+ return 0;
+}
+
+template <typename T,typename T2>
+T Map<T,T2>::find_ele(T d1)
+{
+ tmp = head;
+ while(tmp)
+ {
+ if(tmp->data == d1)
+ {
+ return tmp->data;
+ }
+ tmp = tmp->next;
+ }
+ return 0;
+}
+
+template <typename T,typename T2>
+T2 Map<T,T2>::begin()
+{
+ tmp = head;
+ if(tmp)
+ {
+ return (tmp->data2);
+ }
+ return 0;
+}
+
+template <typename T,typename T2>
+void Map<T,T2>::show()
+{
+ tmp = head;
+ while(tmp)
+ {
+ printf("%d-->%d\n",tmp->data,tmp->data2);
+ tmp = tmp->next;
+ }
+}
+
+template <typename T,typename T2>
+int Map<T,T2>::size()
+{
+ int count =0;
+ tmp = head;
+ while(tmp)
+ {
+ tmp = tmp->next;
+ count++;
+ }
+ return count;
+}
+
+template <typename T,typename T2>
+void Map<T,T2>::insert(T data, T2 data2)
+{
+ tail = new node(data, data2,tail, NULL);
+ if( tail->prev )
+ tail->prev->next = tail;
+
+ if( empty() )
+ {
+ head = tail;
+ tmp=head;
+ }
+ tmp = head;
+ size_of_list++;
+}
+
+template <typename T,typename T2>
+bool Map<T,T2>::erase(T d)
+{
+ bool found = false;
+ tmp = head;
+ node* prevnode = tmp;
+ node *tempnode;
+
+ while(tmp)
+ {
+ if((head == tail) && (head->data == d))
+ {
+ found = true;
+ tempnode = head;
+ head = tail = NULL;
+ delete tempnode;
+ break;
+ }
+ if((tmp ==head) && (tmp->data ==d))
+ {
+ found = true;
+ tempnode = tmp;
+ tmp = tmp->next;
+ tmp->prev = NULL;
+ head = tmp;
+ tempnode->next = NULL;
+ delete tempnode;
+ break;
+ }
+ if((tmp == tail) && (tmp->data ==d))
+ {
+ found = true;
+ tempnode = tmp;
+ prevnode->next = NULL;
+ tmp->prev = NULL;
+ tail = prevnode;
+ delete tempnode;
+ break;
+ }
+ if(tmp->data == d)
+ {
+ found = true;
+ prevnode->next = tmp->next;
+ tmp->next->prev = prevnode->next;
+ tempnode = tmp;
+ //tmp = tmp->next;
+ delete tempnode;
+ break;
+ }
+ prevnode = tmp;
+ tmp = tmp->next;
+ }
+ if(found)size_of_list--;
+ return found;
+}
+
+template <typename T,typename T2>
+bool Map<T,T2>::eraseall()
+{
+ node *tempnode;
+ tmp = head;
+ while(head)
+ {
+ tempnode = head;
+ tempnode->next = NULL;
+ head = head->next;
+ delete tempnode;
+ }
+ tail = head = NULL;
+ return true;
+}
+
+
+template <typename T,typename T2>
+bool Map<T,T2>::isempty()
+{
+ if(!size_of_list) return true;
+ else return false;
+}
+
+#endif // _MAP_H_
diff --git a/omx/mm-video/vidc/vdec/inc/decoder_driver_test.h b/omx/mm-video/vidc/vdec/inc/decoder_driver_test.h
new file mode 100644
index 0000000..11822db
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/decoder_driver_test.h
@@ -0,0 +1,69 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include "message_queue.h"
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/msm_vidc_dec.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+struct video_decoder_context
+{
+ enum vdec_codec decoder_format;
+ enum vdec_output_fromat output_format;
+ struct vdec_picsize video_resoultion;
+ struct vdec_allocatorproperty input_buffer;
+ struct vdec_allocatorproperty output_buffer;
+ struct vdec_bufferpayload **ptr_inputbuffer;
+ struct vdec_bufferpayload **ptr_outputbuffer;
+ struct vdec_output_frameinfo **ptr_respbuffer;
+ struct video_queue_context queue_context;
+ int video_driver_fd;
+
+ FILE * inputBufferFile;
+ FILE * outputBufferFile;
+
+ pthread_t videothread_id;
+ pthread_t asyncthread_id;
+ sem_t sem_synchronize;
+};
+
+int init_decoder ( struct video_decoder_context *init_decode );
+int allocate_buffer ( enum vdec_buffer,
+ struct video_decoder_context *decode_context
+ );
+int free_buffer ( enum vdec_buffer,
+ struct video_decoder_context *decode_context
+ );
+int start_decoding (struct video_decoder_context *decode_context);
+int stop_decoding (struct video_decoder_context *decode_context);
+int deinit_decoder (struct video_decoder_context *init_decode);
diff --git a/omx/mm-video/vidc/vdec/inc/frameparser.h b/omx/mm-video/vidc/vdec/inc/frameparser.h
new file mode 100644
index 0000000..e3bd557
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/frameparser.h
@@ -0,0 +1,94 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef FRAMEPARSER_H
+#define FRAMEPARSER_H
+
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+#include "h264_utils.h"
+//#include <stdlib.h>
+
+
+enum codec_type
+{
+ CODEC_TYPE_MPEG4 = 0,
+ CODEC_TYPE_H263 = 1,
+ CODEC_TYPE_H264 = 2,
+ CODEC_TYPE_VC1 = 3
+};
+
+enum state_start_code_parse
+{
+ A0,
+ A1,
+ A2,
+ A3,
+ A4
+};
+
+enum state_nal_parse
+{
+ NAL_LENGTH_ACC,
+ NAL_PARSING
+};
+
+class frame_parse
+{
+
+public:
+ H264_Utils *mutils;
+ int init_start_codes (codec_type codec_type_parse);
+ int parse_mpeg4_frame (OMX_BUFFERHEADERTYPE *source,
+ OMX_BUFFERHEADERTYPE *dest ,
+ OMX_U32 *partialframe);
+ int init_nal_length (unsigned int nal_length);
+ int parse_h264_nallength (OMX_BUFFERHEADERTYPE *source,
+ OMX_BUFFERHEADERTYPE *dest ,
+ OMX_U32 *partialframe);
+ void flush ();
+ void update_metadata (unsigned int time_stamp ,unsigned int flags);
+ frame_parse ();
+ ~frame_parse ();
+
+private:
+ /*Variables for Start code based Parsing*/
+ enum state_start_code_parse parse_state;
+ unsigned char start_code[4];
+ char mask_code[4];
+ unsigned char last_byte,prev_one;
+
+ /*Variables for NAL Length Parsing*/
+ enum state_nal_parse state_nal;
+ unsigned int nal_length;
+ unsigned int accum_length;
+ unsigned int bytes_tobeparsed;
+ unsigned int time_stamp;
+ unsigned int flags;
+};
+
+#endif /* FRAMEPARSER_H */
diff --git a/omx/mm-video/vidc/vdec/inc/h264_utils.h b/omx/mm-video/vidc/vdec/inc/h264_utils.h
new file mode 100644
index 0000000..9c28caa
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/h264_utils.h
@@ -0,0 +1,209 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef H264_UTILS_H
+#define H264_UTILS_H
+
+/*========================================================================
+
+ O p e n M M
+ U t i l i t i e s a n d H e l p e r R o u t i n e s
+
+*//** @file H264_Utils.h
+This module contains H264 video decoder utilities and helper routines.
+
+*//*====================================================================== */
+
+/* =======================================================================
+
+ INCLUDE FILES FOR MODULE
+
+========================================================================== */
+#include <stdio.h>
+#include "Map.h"
+#include "qtypes.h"
+#include "OMX_Core.h"
+
+#define STD_MIN(x,y) (((x) < (y)) ? (x) : (y))
+
+#define OMX_CORE_720P_HEIGHT 720
+#define OMX_CORE_720P_WIDTH 1280
+
+/* =======================================================================
+
+ DATA DECLARATIONS
+
+========================================================================== */
+
+/* -----------------------------------------------------------------------
+** Constant / Define Declarations
+** ----------------------------------------------------------------------- */
+// Common format block header definitions
+#define MT_VIDEO_META_STREAM_HEADER 0x00
+#define MT_VIDEO_MEDIA_STREAM_HEADER 0x01
+#define MT_VIDEO_META_MEDIA_STREAM_HEADER 0x02
+
+// H.264 format block header definitions
+#define MT_VIDEO_H264_ACCESS_UNIT_FORMAT 0x00
+#define MT_VIDEO_H264_NAL_FORMT 0x01
+#define MT_VIDEO_H264_BYTE_FORMAT 0x02
+#define MT_VIDEO_H264_BYTE_STREAM_FORMAT 0x00
+#define MT_VIDEO_H264_NAL_UNIT_STREAM_FORMAT 0x01
+#define MT_VIDEO_H264_FORMAT_BLOCK_HEADER_SIZE 18
+
+// MPEG-4 format block header definitions
+#define MT_VIDEO_MPEG4_VOP_FORMAT 0x00
+#define MT_VIDEO_MPEG4_SLICE_FORMAT 0x01
+#define MT_VIDEO_MPEG4_BYTE_FORMAT 0x02
+#define MT_VIDEO_MPEG4_FORMAT_BLOCK_HEADER_SIZE 15
+
+// H.263 format block header definitions
+#define MT_VIDEO_H263_PICTURE_FORMAT 0x00
+#define MT_VIDEO_H263_GOB_FORMAT 0x01
+#define MT_VIDEO_H263_SLICE_STRUCTURED_FORMAT 0x02
+#define MT_VIDEO_H263_BYTE_FORMAT 0x03
+#define MT_VIDEO_H263_FORMAT_BLOCK_HEADER_SIZE 16
+
+/* =======================================================================
+** Function Declarations
+** ======================================================================= */
+
+/* -----------------------------------------------------------------------
+** Type Declarations
+** ----------------------------------------------------------------------- */
+
+// This type is used when parsing an H.264 bitstream to collect H.264 NAL
+// units that need to go in the meta data.
+struct H264ParamNalu {
+ uint32 picSetID;
+ uint32 seqSetID;
+ uint32 picOrderCntType;
+ bool frameMbsOnlyFlag;
+ bool picOrderPresentFlag;
+ uint32 picWidthInMbsMinus1;
+ uint32 picHeightInMapUnitsMinus1;
+ uint32 log2MaxFrameNumMinus4;
+ uint32 log2MaxPicOrderCntLsbMinus4;
+ bool deltaPicOrderAlwaysZeroFlag;
+ //std::vector<uint8> nalu;
+ uint32 nalu;
+ uint32 crop_left;
+ uint32 crop_right;
+ uint32 crop_top;
+ uint32 crop_bot;
+};
+//typedef map<uint32, H264ParamNalu> H264ParamNaluSet;
+typedef Map<uint32, H264ParamNalu *> H264ParamNaluSet;
+
+typedef enum {
+ NALU_TYPE_UNSPECIFIED = 0,
+ NALU_TYPE_NON_IDR,
+ NALU_TYPE_PARTITION_A,
+ NALU_TYPE_PARTITION_B,
+ NALU_TYPE_PARTITION_C,
+ NALU_TYPE_IDR,
+ NALU_TYPE_SEI,
+ NALU_TYPE_SPS,
+ NALU_TYPE_PPS,
+ NALU_TYPE_ACCESS_DELIM,
+ NALU_TYPE_EOSEQ,
+ NALU_TYPE_EOSTREAM,
+ NALU_TYPE_FILLER_DATA,
+ NALU_TYPE_RESERVED,
+} NALU_TYPE;
+
+// NAL header information
+typedef struct {
+ uint32 nal_ref_idc;
+ uint32 nalu_type;
+ uint32 forbidden_zero_bit;
+} NALU;
+
+// This structure contains persistent information about an H.264 stream as it
+// is parsed.
+//struct H264StreamInfo {
+// H264ParamNaluSet pic;
+// H264ParamNaluSet seq;
+//};
+
+class RbspParser
+/******************************************************************************
+ ** This class is used to convert an H.264 NALU (network abstraction layer
+ ** unit) into RBSP (raw byte sequence payload) and extract bits from it.
+ *****************************************************************************/
+{
+public:
+ RbspParser (const uint8 *begin, const uint8 *end);
+
+ virtual ~RbspParser ();
+
+ uint32 next ();
+ void advance ();
+ uint32 u (uint32 n);
+ uint32 ue ();
+ int32 se ();
+
+private:
+ const uint8 *begin, *end;
+ int32 pos;
+ uint32 bit;
+ uint32 cursor;
+ bool advanceNeeded;
+};
+
+class H264_Utils
+{
+public:
+ H264_Utils();
+ ~H264_Utils();
+ void initialize_frame_checking_environment();
+ void allocate_rbsp_buffer(uint32 inputBufferSize);
+ bool isNewFrame(OMX_IN OMX_U8 *bitstream,
+ OMX_IN OMX_U32 bitstream_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_BOOL &isNewFrame);
+
+private:
+ boolean extract_rbsp(OMX_IN OMX_U8 *buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_U8 *rbsp_bistream,
+ OMX_OUT OMX_U32 *rbsp_length,
+ OMX_OUT NALU *nal_unit);
+
+ unsigned m_height;
+ unsigned m_width;
+ H264ParamNaluSet pic;
+ H264ParamNaluSet seq;
+ uint8 *m_rbspBytes;
+ NALU m_prv_nalu;
+ bool m_forceToStichNextNAL;
+ bool m_au_data;
+};
+
+
+#endif /* H264_UTILS_H */
diff --git a/omx/mm-video/vidc/vdec/inc/message_queue.h b/omx/mm-video/vidc/vdec/inc/message_queue.h
new file mode 100644
index 0000000..b303784
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/message_queue.h
@@ -0,0 +1,78 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Message Queue structure */
+struct video_msgq
+{
+ /* Command to be executed */
+ unsigned int cmd;
+
+ unsigned int status;
+
+ /* Client-specific data */
+ void *clientdata;
+};
+
+
+/* Thread & Message Queue information */
+struct video_queue_context
+{
+ /* Message Queue related members */
+ pthread_mutex_t mutex;
+ sem_t sem_message;
+ int commandq_size;
+ int dataq_size;
+ struct video_msgq *ptr_dataq;
+ struct video_msgq *ptr_cmdq;
+ int write_dataq ;
+ int read_dataq;
+ int write_comq ;
+ int read_comq ;
+
+};
+
+int check_if_queue_empty ( unsigned int queuetocheck,void* queuecontext );
+
+struct video_msgq * queue_get_cmd ( void* queuecontext );
+
+int queue_post_cmdq ( void *queuecontext,
+ struct video_msgq *post_msg
+ );
+
+int queue_post_dataq ( void *queuecontext,
+ struct video_msgq *post_msg
+ );
+
+#endif /* QUEUE_H */
diff --git a/omx/mm-video/vidc/vdec/inc/omx_vdec.h b/omx/mm-video/vidc/vdec/inc/omx_vdec.h
new file mode 100644
index 0000000..557dedd
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/omx_vdec.h
@@ -0,0 +1,615 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef __OMX_VDEC_H__
+#define __OMX_VDEC_H__
+/*============================================================================
+ O p e n M A X Component
+ Video Decoder
+
+*//** @file comx_vdec.h
+ This module contains the class definition for openMAX decoder component.
+
+*//*========================================================================*/
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include<stdlib.h>
+
+#include <stdio.h>
+
+#ifdef _ANDROID_
+#include <binder/MemoryHeapBase.h>
+extern "C"{
+#include<utils/Log.h>
+}
+#define LOG_TAG "OMX-VDEC-720P"
+#ifdef ENABLE_DEBUG_LOW
+#define DEBUG_PRINT_LOW LOGE
+#else
+#define DEBUG_PRINT_LOW
+#endif
+#ifdef ENABLE_DEBUG_HIGH
+#define DEBUG_PRINT_HIGH LOGE
+#else
+#define DEBUG_PRINT_HIGH
+#endif
+#ifdef ENABLE_DEBUG_ERROR
+#define DEBUG_PRINT_ERROR LOGE
+#else
+#define DEBUG_PRINT_ERROR
+#endif
+#endif // _ANDROID_
+
+#include <pthread.h>
+#ifndef PC_DEBUG
+#include <semaphore.h>
+#endif
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+//#include "vdec.h"
+#include "qc_omx_component.h"
+//#include "Map.h"
+//#include "OmxUtils.h"
+#include <linux/msm_vidc_dec.h>
+#include "frameparser.h"
+#include <linux/android_pmem.h>
+
+extern "C" {
+ OMX_API void * get_omx_component_factory_fn(void);
+}
+
+
+#ifdef _ANDROID_
+ using namespace android;
+ // local pmem heap object
+ class VideoHeap : public MemoryHeapBase
+ {
+ public:
+ VideoHeap(int fd, size_t size, void* base);
+ virtual ~VideoHeap() {}
+ };
+#endif // _ANDROID_
+//////////////////////////////////////////////////////////////////////////////
+// Module specific globals
+//////////////////////////////////////////////////////////////////////////////
+#define OMX_SPEC_VERSION 0x00000101
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros
+//////////////////////////////////////////////////////////////////////////////
+#define PrintFrameHdr(bufHdr) DEBUG_PRINT("bufHdr %x buf %x size %d TS %d\n",\
+ (unsigned) bufHdr,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp)
+
+// BitMask Management logic
+#define BITS_PER_BYTE 32
+#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE)
+#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_BYTE)
+#define BITMASK_FLAG(mIndex) (1 << ((mIndex) % BITS_PER_BYTE))
+#define BITMASK_CLEAR(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \
+ &= ~(BITMASK_FLAG(mIndex))
+#define BITMASK_SET(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \
+ |= BITMASK_FLAG(mIndex)
+#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex))
+#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex)) == 0x0)
+#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex))
+#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex)) == 0x0)
+
+#define OMX_VIDEO_DEC_NUM_INPUT_BUFFERS 2
+#define OMX_VIDEO_DEC_NUM_OUTPUT_BUFFERS 2
+
+#ifdef FEATURE_QTV_WVGA_ENABLE
+#define OMX_VIDEO_DEC_INPUT_BUFFER_SIZE (256*1024)
+#else
+#define OMX_VIDEO_DEC_INPUT_BUFFER_SIZE (128*1024)
+#endif
+
+#define OMX_CORE_CONTROL_CMDQ_SIZE 100
+#define OMX_CORE_QCIF_HEIGHT 144
+#define OMX_CORE_QCIF_WIDTH 176
+#define OMX_CORE_VGA_HEIGHT 480
+#define OMX_CORE_VGA_WIDTH 640
+#define OMX_CORE_WVGA_HEIGHT 480
+#define OMX_CORE_WVGA_WIDTH 800
+
+
+struct video_driver_context
+{
+ int video_driver_fd;
+ enum vdec_codec decoder_format;
+ enum vdec_output_fromat output_format;
+ struct vdec_picsize video_resoultion;
+ struct vdec_allocatorproperty input_buffer;
+ struct vdec_allocatorproperty output_buffer;
+ struct vdec_bufferpayload *ptr_inputbuffer;
+ struct vdec_bufferpayload *ptr_outputbuffer;
+ struct vdec_output_frameinfo *ptr_respbuffer;
+ char kind[128];
+};
+
+class OmxUtils;
+
+// OMX video decoder class
+class omx_vdec: public qc_omx_component
+{
+
+public:
+ omx_vdec(); // constructor
+ virtual ~omx_vdec(); // destructor
+
+ static int async_message_process (void *context, void* message);
+ static void process_event_cb(void *ctxt,unsigned char id);
+
+ OMX_ERRORTYPE allocate_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes
+ );
+
+
+ OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp);
+
+ OMX_ERRORTYPE component_init(OMX_STRING role);
+
+ OMX_ERRORTYPE component_role_enum(
+ OMX_HANDLETYPE hComp,
+ OMX_U8 *role,
+ OMX_U32 index
+ );
+
+ OMX_ERRORTYPE component_tunnel_request(
+ OMX_HANDLETYPE hComp,
+ OMX_U32 port,
+ OMX_HANDLETYPE peerComponent,
+ OMX_U32 peerPort,
+ OMX_TUNNELSETUPTYPE *tunnelSetup
+ );
+
+ OMX_ERRORTYPE empty_this_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+
+
+ OMX_ERRORTYPE fill_this_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+
+ OMX_ERRORTYPE free_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_U32 port,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+ OMX_ERRORTYPE get_component_version(
+ OMX_HANDLETYPE hComp,
+ OMX_STRING componentName,
+ OMX_VERSIONTYPE *componentVersion,
+ OMX_VERSIONTYPE *specVersion,
+ OMX_UUIDTYPE *componentUUID
+ );
+
+ OMX_ERRORTYPE get_config(
+ OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData
+ );
+
+ OMX_ERRORTYPE get_extension_index(
+ OMX_HANDLETYPE hComp,
+ OMX_STRING paramName,
+ OMX_INDEXTYPE *indexType
+ );
+
+ OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData);
+
+ OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp,
+ OMX_STATETYPE *state);
+
+
+
+ OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param1,
+ OMX_PTR cmdData);
+
+
+ OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp,
+ OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData);
+
+ OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData);
+
+ OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData);
+
+ OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes,
+ OMX_U8 *buffer);
+
+
+ OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ void * eglImage);
+
+
+
+ struct video_driver_context driver_context;
+ int m_pipe_in;
+ int m_pipe_out;
+ pthread_t msg_thread_id;
+ pthread_t async_thread_id;
+
+private:
+ // Bit Positions
+ enum flags_bit_positions
+ {
+ // Defer transition to IDLE
+ OMX_COMPONENT_IDLE_PENDING =0x1,
+ // Defer transition to LOADING
+ OMX_COMPONENT_LOADING_PENDING =0x2,
+ // First Buffer Pending
+ OMX_COMPONENT_FIRST_BUFFER_PENDING =0x3,
+ // Second Buffer Pending
+ OMX_COMPONENT_SECOND_BUFFER_PENDING =0x4,
+ // Defer transition to Enable
+ OMX_COMPONENT_INPUT_ENABLE_PENDING =0x5,
+ // Defer transition to Enable
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x6,
+ // Defer transition to Disable
+ OMX_COMPONENT_INPUT_DISABLE_PENDING =0x7,
+ // Defer transition to Disable
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x8,
+ //defer flush notification
+ OMX_COMPONENT_OUTPUT_FLUSH_PENDING =0x9,
+ OMX_COMPONENT_INPUT_FLUSH_PENDING =0xA,
+ OMX_COMPONENT_PAUSE_PENDING =0xB,
+ OMX_COMPONENT_EXECUTE_PENDING =0xC
+
+ };
+
+ // Deferred callback identifiers
+ enum
+ {
+ //Event Callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_EVENT = 0x1,
+ //Buffer Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2,
+ //Frame Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_FRAME_DONE = 0x3,
+ //Buffer Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_FTB = 0x4,
+ //Frame Done callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_ETB = 0x5,
+ //Command
+ OMX_COMPONENT_GENERATE_COMMAND = 0x6,
+ //Push-Pending Buffers
+ OMX_COMPONENT_PUSH_PENDING_BUFS = 0x7,
+ // Empty Buffer Done callbacks
+ OMX_COMPONENT_GENERATE_EBD = 0x8,
+ //Flush Event Callbacks from the vdec component thread context
+ OMX_COMPONENT_GENERATE_EVENT_FLUSH = 0x9,
+ OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH = 0x0A,
+ OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH = 0x0B,
+ OMX_COMPONENT_GENERATE_FBD = 0xc,
+ OMX_COMPONENT_GENERATE_START_DONE = 0xD,
+ OMX_COMPONENT_GENERATE_PAUSE_DONE = 0xE,
+ OMX_COMPONENT_GENERATE_RESUME_DONE = 0xF,
+ OMX_COMPONENT_GENERATE_STOP_DONE = 0x10,
+ OMX_COMPONENT_GENERATE_HARDWARE_ERROR = 0x11,
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARY = 0x12
+ };
+
+ enum port_indexes
+ {
+ OMX_CORE_INPUT_PORT_INDEX =0,
+ OMX_CORE_OUTPUT_PORT_INDEX =1
+ };
+
+ enum vc1_profile_type
+ {
+ VC1_SP_MP_RCV = 1,
+ VC1_AP = 2
+ };
+
+ struct omx_event
+ {
+ unsigned param1;
+ unsigned param2;
+ unsigned id;
+ };
+
+ struct omx_cmd_queue
+ {
+ omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE];
+ unsigned m_read;
+ unsigned m_write;
+ unsigned m_size;
+
+ omx_cmd_queue();
+ ~omx_cmd_queue();
+ bool insert_entry(unsigned p1, unsigned p2, unsigned id);
+ bool pop_entry(unsigned *p1,unsigned *p2, unsigned *id);
+ // get msgtype of the first ele from the queue
+ unsigned get_q_msg_type();
+
+ };
+
+ OMX_ERRORTYPE omx_vdec_check_port_settings(bool *port_setting_changed);
+ OMX_ERRORTYPE omx_vdec_validate_port_param(int height, int width);
+
+
+ bool allocate_done(void);
+ bool allocate_input_done(void);
+ bool allocate_output_done(void);
+
+ OMX_ERRORTYPE free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
+ OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
+
+ OMX_ERRORTYPE allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes);
+
+
+ OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes);
+
+ OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,OMX_PTR appData,
+ OMX_U32 bytes);
+
+ OMX_ERRORTYPE use_input_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes,
+ OMX_U8 *buffer);
+
+ OMX_ERRORTYPE use_output_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes,
+ OMX_U8 *buffer);
+
+ bool execute_omx_flush(OMX_U32);
+ bool execute_output_flush(OMX_U32);
+ bool execute_input_flush(OMX_U32);
+ bool register_output_buffers();
+ OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+
+ OMX_ERRORTYPE fill_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+ OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ OMX_ERRORTYPE empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+ OMX_ERRORTYPE push_input_buffer (OMX_HANDLETYPE hComp);
+ OMX_ERRORTYPE push_input_sc_codec (OMX_HANDLETYPE hComp);
+ OMX_ERRORTYPE push_input_h264 (OMX_HANDLETYPE hComp);
+ OMX_ERRORTYPE push_input_vc1 (OMX_HANDLETYPE hComp);
+
+ OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer);
+ bool release_done();
+
+ bool release_output_done();
+ bool release_input_done();
+
+ bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
+ OMX_U32 alignment);
+
+ OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param1,
+ OMX_PTR cmdData);
+ bool post_event( unsigned int p1,
+ unsigned int p2,
+ unsigned int id
+ );
+ inline int clip2(int x)
+ {
+ x = x -1;
+ x = x | x >> 1;
+ x = x | x >> 2;
+ x = x | x >> 4;
+ x = x | x >> 16;
+ x = x + 1;
+ return x;
+ }
+
+ inline void omx_report_error ()
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Sending OMX_EventError to Client");
+ if (m_cb.EventHandler && !m_error_propogated)
+ {
+ m_error_propogated = true;
+ m_cb.EventHandler(&m_cmp,m_app_data,
+ OMX_EventError,OMX_ErrorHardware,0,NULL);
+ }
+ }
+
+
+ //*************************************************************
+ //*******************MEMBER VARIABLES *************************
+ //*************************************************************
+ pthread_mutex_t m_lock;
+ //sem to handle the minimum procesing of commands
+ sem_t m_cmd_lock;
+ bool m_error_propogated;
+ // compression format
+ OMX_VIDEO_CODINGTYPE eCompressionFormat;
+ // OMX State
+ OMX_STATETYPE m_state;
+ // Application data
+ OMX_PTR m_app_data;
+ // Application callbacks
+ OMX_CALLBACKTYPE m_cb;
+ OMX_COLOR_FORMATTYPE m_color_format;
+ OMX_PRIORITYMGMTTYPE m_priority_mgm ;
+ OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier;
+ // fill this buffer queue
+ omx_cmd_queue m_ftb_q;
+ // Command Q for rest of the events
+ omx_cmd_queue m_cmd_q;
+ omx_cmd_queue m_etb_q;
+ // Input memory pointer
+ OMX_BUFFERHEADERTYPE *m_inp_mem_ptr;
+ // Output memory pointer
+ OMX_BUFFERHEADERTYPE *m_out_mem_ptr;
+
+ bool input_flush_progress;
+ bool output_flush_progress;
+ bool input_use_buffer;
+ bool output_use_buffer;
+ int pending_input_buffers;
+ int pending_output_buffers;
+ int m_ineos_reached;
+ int m_outeos_pending;
+ int m_outeos_reached;
+ // bitmask array size for output side
+ unsigned int m_out_bm_count;
+ // Number of Output Buffers
+ unsigned int m_out_buf_count;
+ unsigned int m_out_buf_count_min;
+ unsigned int m_out_buf_size;
+ // Number of Input Buffers
+ unsigned int m_inp_buf_count;
+ unsigned int m_inp_buf_count_min;
+ // Size of Input Buffers
+ unsigned int m_inp_buf_size;
+ // bitmask array size for input side
+ unsigned int m_inp_bm_count;
+ //Input port Populated
+ OMX_BOOL m_inp_bPopulated;
+ //Output port Populated
+ OMX_BOOL m_out_bPopulated;
+ //Height
+ unsigned int m_height;
+ // Width
+ unsigned int m_width;
+ unsigned int stride;
+ unsigned int scan_lines;
+ // Storage of HxW during dynamic port reconfig
+ unsigned int m_port_height;
+ unsigned int m_port_width;
+
+ unsigned int m_crop_x;
+ unsigned int m_crop_y;
+ unsigned int m_crop_dx;
+ unsigned int m_crop_dy;
+ // encapsulate the waiting states.
+ unsigned int m_flags;
+
+#ifdef _ANDROID_
+ // Heap pointer to frame buffers
+ sp<MemoryHeapBase> m_heap_ptr;
+#endif //_ANDROID_
+ // store I/P PORT state
+ OMX_BOOL m_inp_bEnabled;
+ // store O/P PORT state
+ OMX_BOOL m_out_bEnabled;
+ // to know whether Event Port Settings change has been triggered or not.
+ bool m_event_port_settings_sent;
+ OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE];
+ // Platform specific details
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *m_platform_list;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *m_platform_entry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *m_pmem_info;
+ // SPS+PPS sent as part of set_config
+ OMX_VENDOR_EXTRADATATYPE m_vendor_config;
+
+ /*Variables for arbitrary Byte parsing support*/
+ frame_parse m_frame_parser;
+ omx_cmd_queue m_input_pending_q;
+ omx_cmd_queue m_input_free_q;
+ bool arbitrary_bytes;
+ OMX_BUFFERHEADERTYPE h264_scratch;
+ OMX_BUFFERHEADERTYPE *psource_frame;
+ OMX_BUFFERHEADERTYPE *pdest_frame;
+ OMX_BUFFERHEADERTYPE *m_inp_heap_ptr;
+ OMX_BUFFERHEADERTYPE **m_phdr_pmem_ptr;
+ unsigned int m_heap_inp_bm_count;
+ codec_type codec_type_parse;
+ bool first_frame_meta;
+ unsigned frame_count;
+ unsigned nal_count;
+ unsigned nal_length;
+ bool look_ahead_nal;
+ int first_frame;
+ unsigned char *first_buffer;
+ int first_frame_size;
+ unsigned int mp4h263_flags;
+ unsigned int mp4h263_timestamp;
+ bool set_seq_header_done;
+ bool gate_output_buffers;
+ bool gate_input_buffers;
+ bool sent_first_frame;
+ unsigned int m_out_buf_count_recon;
+ unsigned int m_out_buf_count_min_recon;
+ unsigned int m_out_buf_size_recon;
+ unsigned char m_hwdevice_name[80];
+ FILE *m_device_file_ptr;
+ enum vc1_profile_type m_vc1_profile;
+};
+
+#endif // __OMX_VDEC_H__
diff --git a/omx/mm-video/vidc/vdec/inc/qtypes.h b/omx/mm-video/vidc/vdec/inc/qtypes.h
new file mode 100644
index 0000000..8fc7a86
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/qtypes.h
@@ -0,0 +1,90 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef QTYPES_H
+#define QTYPES_H
+/*===========================================================================
+
+ Data Declarations
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------------------------------------------------------------------
+** Constants
+** ------------------------------------------------------------------------ */
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define TRUE 1 /* Boolean true value. */
+#define FALSE 0 /* Boolean false value. */
+
+
+
+/* -----------------------------------------------------------------------
+** Standard Types
+** ----------------------------------------------------------------------- */
+
+/* The following definitions are the same accross platforms. This first
+** group are the sanctioned types.
+*/
+
+typedef unsigned char boolean; /* Boolean value type. */
+
+typedef unsigned long int uint32; /* Unsigned 32 bit value */
+typedef unsigned short uint16; /* Unsigned 16 bit value */
+typedef unsigned char uint8; /* Unsigned 8 bit value */
+
+typedef signed long int int32; /* Signed 32 bit value */
+typedef signed short int16; /* Signed 16 bit value */
+typedef signed char int8; /* Signed 8 bit value */
+
+/* This group are the deprecated types. Their use should be
+** discontinued and new code should use the types above
+*/
+typedef unsigned char byte; /* Unsigned 8 bit value type. */
+typedef unsigned short word; /* Unsinged 16 bit value type. */
+typedef unsigned long dword; /* Unsigned 32 bit value type. */
+
+typedef long long int64;
+typedef unsigned long long uint64;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* QTYPES_H */
diff --git a/omx/mm-video/vidc/vdec/inc/queue.h b/omx/mm-video/vidc/vdec/inc/queue.h
new file mode 100644
index 0000000..2a7d331
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/inc/queue.h
@@ -0,0 +1,39 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef QUEUE_H
+#define QUEUE_H
+
+typedef struct Queue Queue;
+
+Queue *alloc_queue();
+void free_queue(Queue *q);
+void free_queue_and_qelement(Queue *q);
+int push(Queue *q, void * element);
+void *pop(Queue *q);
+
+#endif
diff --git a/omx/mm-video/vidc/vdec/src/frameparser.cpp b/omx/mm-video/vidc/vdec/src/frameparser.cpp
new file mode 100644
index 0000000..8f3e90d
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/src/frameparser.cpp
@@ -0,0 +1,506 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "frameparser.h"
+#include "omx_vdec.h"
+
+#ifdef _ANDROID_
+ extern "C"{
+ #include<utils/Log.h>
+ }
+#endif//_ANDROID_
+
+static unsigned char H264_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
+static unsigned char H264_start_code[4] = {0x00,0x00,0x00,0x01};
+
+static unsigned char MPEG4_start_code[4] = {0x00,0x00,0x01,0xB6};
+static unsigned char MPEG4_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
+
+static unsigned char H263_start_code[4] = {0x00,0x00,0x80,0x00};
+static unsigned char H263_mask_code[4] = {0xFF,0xFF,0xFC,0x00};
+
+static unsigned char VC1_AP_start_code[4] = {0x00,0x00,0x01,0x0D};
+static unsigned char VC1_AP_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
+
+frame_parse::frame_parse():parse_state(A0),
+ last_byte(0),
+ prev_one(0),
+ state_nal(NAL_LENGTH_ACC),
+ nal_length(0),
+ accum_length(0),
+ bytes_tobeparsed(0),
+ mutils(NULL),
+ time_stamp (0),
+ flags (0)
+{
+ memset (start_code,0,sizeof (start_code));
+ memset (mask_code,0,sizeof (mask_code));
+}
+
+frame_parse::~frame_parse ()
+{
+ if (mutils)
+ delete mutils;
+
+ mutils = NULL;
+}
+
+int frame_parse::init_start_codes (codec_type codec_type_parse)
+{
+ /*Check if Codec Type is proper and we are in proper state*/
+ if (codec_type_parse > CODEC_TYPE_VC1 || parse_state != A0)
+ {
+ return -1;
+ }
+
+ switch (codec_type_parse)
+ {
+ case CODEC_TYPE_MPEG4:
+ memcpy (start_code,MPEG4_start_code,4);
+ memcpy (mask_code,MPEG4_mask_code,4);
+ break;
+ case CODEC_TYPE_H263:
+ memcpy (start_code,H263_start_code,4);
+ memcpy (mask_code,H263_mask_code,4);
+ break;
+ case CODEC_TYPE_H264:
+ memcpy (start_code,H264_start_code,4);
+ memcpy (mask_code,H264_mask_code,4);
+ break;
+ case CODEC_TYPE_VC1:
+ memcpy (start_code,VC1_AP_start_code,4);
+ memcpy (mask_code,VC1_AP_mask_code,4);
+ break;
+ }
+ return 1;
+}
+
+
+int frame_parse::init_nal_length (unsigned int nal_len)
+{
+ if (nal_len == 0 || nal_len > 4 || state_nal != NAL_LENGTH_ACC)
+ {
+ return -1;
+ }
+ nal_length = nal_len;
+
+ return 1;
+}
+
+int frame_parse::parse_mpeg4_frame ( OMX_BUFFERHEADERTYPE *source,
+ OMX_BUFFERHEADERTYPE *dest ,
+ OMX_U32 *partialframe)
+{
+ OMX_U8 *pdest = NULL,*psource = NULL;
+ OMX_U32 dest_len =0, source_len = 0, temp_len = 0;
+ OMX_U32 parsed_length = 0,i=0;
+ int residue_byte = 0;
+
+ if (source == NULL || dest == NULL || partialframe == NULL)
+ {
+ return -1;
+ }
+
+ /*Calculate how many bytes are left in source and destination*/
+ dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
+ psource = source->pBuffer + source->nOffset;
+ pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
+ source_len = source->nFilledLen;
+
+ /*Need Minimum of 4 for destination to copy atleast Start code*/
+ if (dest_len < 4 || source_len == 0)
+ {
+ DEBUG_PRINT_LOW("\n Dest_len %d source_len %d",dest_len,source_len);
+ if (source_len == 0 && (source->nFlags & 0x01))
+ {
+ DEBUG_PRINT_LOW("\n EOS condition Inform Client that it is complete frame");
+ *partialframe = 0;
+ return 1;
+ }
+ DEBUG_PRINT_LOW("\n Error in Parsing bitstream");
+ return -1;
+ }
+
+ /*Check if State of the previous find is a Start code*/
+ if (parse_state == A4)
+ {
+ /*Check for minimun size should be 4*/
+ dest->nFlags = flags;
+ dest->nTimeStamp = time_stamp;
+ update_metadata(source->nTimeStamp,source->nFlags);
+ memcpy (pdest,start_code,4);
+ pdest [2] = prev_one;
+ pdest [3] = last_byte;
+ dest->nFilledLen += 4;
+ pdest += 4;
+ parse_state = A0;
+ }
+
+ /*Entry State Machine*/
+ while ( source->nFilledLen > 0 && parse_state != A0
+ && parse_state != A4 && dest_len > 0
+ )
+ {
+ //printf ("\n In the Entry Loop");
+ switch (parse_state)
+ {
+ case A3:
+ /*If fourth Byte is matching then start code is found*/
+ if ((*psource & mask_code [3]) == start_code [3])
+ {
+ last_byte = *psource;
+ parse_state = A4;
+ source->nFilledLen--;
+ source->nOffset++;
+ psource++;
+ }
+ else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1]))
+ {
+ parse_state = A2;
+ memcpy (pdest,start_code,1);
+ pdest++;
+ dest->nFilledLen++;
+ dest_len--;
+ }
+ else if (start_code [2] == start_code [0])
+ {
+ parse_state = A1;
+ memcpy (pdest,start_code,2);
+ pdest += 2;
+ dest->nFilledLen += 2;
+ dest_len -= 2;
+ }
+ else
+ {
+ parse_state = A0;
+ memcpy (pdest,start_code,3);
+ pdest += 3;
+ dest->nFilledLen +=3;
+ dest_len -= 3;
+ }
+ break;
+
+ case A2:
+ if ((*psource & mask_code [2]) == start_code [2])
+ {
+ prev_one = *psource;
+ parse_state = A3;
+ source->nFilledLen--;
+ source->nOffset++;
+ psource++;
+ }
+ else if ( start_code [1] == start_code [0])
+ {
+ parse_state = A1;
+ memcpy (pdest,start_code,1);
+ dest->nFilledLen +=1;
+ dest_len--;
+ pdest++;
+ }
+ else
+ {
+ parse_state = A0;
+ memcpy (pdest,start_code,2);
+ dest->nFilledLen +=2;
+ dest_len -= 2;
+ pdest += 2;
+ }
+ break;
+
+ case A1:
+ if ((*psource & mask_code [1]) == start_code [1])
+ {
+ parse_state = A2;
+ source->nFilledLen--;
+ source->nOffset++;
+ psource++;
+ }
+ else
+ {
+ memcpy (pdest,start_code,1);
+ dest->nFilledLen +=1;
+ pdest++;
+ dest_len--;
+ parse_state = A0;
+ }
+ break;
+ case A4:
+ case A0:
+ break;
+ }
+ dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
+ }
+
+ if (parse_state == A4)
+ {
+ *partialframe = 0;
+ DEBUG_PRINT_LOW("\n Nal Found length is %d",dest->nFilledLen);
+ return 1;
+ }
+
+ /*Partial Frame is true*/
+ *partialframe = 1;
+
+ /*Calculate how many bytes are left in source and destination*/
+ dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
+ psource = source->pBuffer + source->nOffset;
+ pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
+ source_len = source->nFilledLen;
+
+ temp_len = (source_len < dest_len)?source_len:dest_len;
+
+ /*Check if entry state machine consumed source or destination*/
+ if (temp_len == 0)
+ {
+ return 1;
+ }
+
+ /*Parsing State Machine*/
+ while (parsed_length < temp_len)
+ {
+ switch (parse_state)
+ {
+ case A0:
+ if ((psource [parsed_length] & mask_code [0]) == start_code[0])
+ {
+ parse_state = A1;
+ }
+ parsed_length++;
+ break;
+ case A1:
+ if ((psource [parsed_length] & mask_code [1]) == start_code [1])
+ {
+ parsed_length++;
+ parse_state = A2;
+ }
+ else
+ {
+ parse_state = A0;
+ }
+ break;
+ case A2:
+ if ((psource [parsed_length] & mask_code [2]) == start_code [2])
+ {
+ prev_one = psource [parsed_length];
+ parsed_length++;
+ parse_state = A3;
+ }
+ else if (start_code [1] == start_code [0])
+ {
+ parse_state = A1;
+ }
+ else
+ {
+ parse_state = A0;
+ }
+ break;
+ case A3:
+ if ((psource [parsed_length] & mask_code [3]) == start_code [3])
+ {
+ last_byte = psource [parsed_length];
+ parsed_length++;
+ parse_state = A4;
+ }
+ else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1]))
+ {
+ parse_state = A2;
+ }
+ else if (start_code [2] == start_code [0])
+ {
+ parse_state = A1;
+ }
+ else
+ {
+ parse_state = A0;
+ }
+ break;
+ }
+
+ /*Found the code break*/
+ if (parse_state == A4)
+ {
+ break;
+ }
+ }
+
+ /*Exit State Machine*/
+ psource = source->pBuffer + source->nOffset;
+ switch (parse_state)
+ {
+ case A4:
+ *partialframe = 0;
+ if (parsed_length > 4)
+ {
+ memcpy (pdest,psource,(parsed_length-4));
+ dest->nFilledLen += (parsed_length-4);
+ }
+ break;
+ case A3:
+ if (parsed_length > 3)
+ {
+ memcpy (pdest,psource,(parsed_length-3));
+ dest->nFilledLen += (parsed_length-3);
+ }
+ break;
+ case A2:
+ if (parsed_length > 2)
+ {
+ memcpy (pdest,psource,(parsed_length-2));
+ dest->nFilledLen += (parsed_length-2);
+ }
+ break;
+ case A1:
+ if (parsed_length > 1)
+ {
+ memcpy (pdest,psource,(parsed_length-1));
+ dest->nFilledLen += (parsed_length-1);
+ }
+ break;
+ case A0:
+ memcpy (pdest,psource,(parsed_length));
+ dest->nFilledLen += (parsed_length);
+ break;
+ }
+
+ if (source->nFilledLen < parsed_length)
+ {
+ printf ("\n FATAL Error");
+ return -1;
+ }
+ source->nFilledLen -= parsed_length;
+ source->nOffset += parsed_length;
+
+ return 1;
+}
+
+
+int frame_parse::parse_h264_nallength (OMX_BUFFERHEADERTYPE *source,
+ OMX_BUFFERHEADERTYPE *dest ,
+ OMX_U32 *partialframe)
+{
+ OMX_U8 *pdest = NULL,*psource = NULL;
+ OMX_U32 dest_len =0, source_len = 0, temp_len = 0,parsed_length = 0;
+
+ if (source == NULL || dest == NULL || partialframe == NULL)
+ {
+ return -1;
+ }
+
+ /*Calculate the length's*/
+ dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
+ source_len = source->nFilledLen;
+
+ if (dest_len < 4 || source_len == 0 || nal_length == 0)
+ {
+ DEBUG_PRINT_LOW("\n Destination %d source %d nal length %d",\
+ dest_len,source_len,nal_length);
+ return -1;
+ }
+ *partialframe = 1;
+ temp_len = (source_len < dest_len)?source_len:dest_len;
+ psource = source->pBuffer + source->nOffset;
+ pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
+
+ /* Find the Bytes to Accumalte*/
+ if (state_nal == NAL_LENGTH_ACC)
+ {
+ while (parsed_length < temp_len )
+ {
+ bytes_tobeparsed |= (((OMX_U32)(*psource))) << (((nal_length-accum_length-1) << 3));
+
+ /*COPY THE DATA FOR C-SIM TO BE REOMVED ON TARGET*/
+ //*pdest = *psource;
+ accum_length++;
+ source->nFilledLen--;
+ source->nOffset++;
+ psource++;
+ //dest->nFilledLen++;
+ //pdest++;
+ parsed_length++;
+
+ if (accum_length == nal_length)
+ {
+ accum_length = 0;
+ state_nal = NAL_PARSING;
+ memcpy (pdest,H264_start_code,4);
+ dest->nFilledLen += 4;
+ break;
+ }
+ }
+ }
+
+ dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
+ source_len = source->nFilledLen;
+ temp_len = (source_len < dest_len)?source_len:dest_len;
+
+ psource = source->pBuffer + source->nOffset;
+ pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
+
+ /*Already in Parsing state go ahead and copy*/
+ if(state_nal == NAL_PARSING && temp_len > 0)
+ {
+ if (temp_len < bytes_tobeparsed)
+ {
+ memcpy (pdest,psource,temp_len);
+ dest->nFilledLen += temp_len;
+ source->nOffset += temp_len;
+ source->nFilledLen -= temp_len;
+ bytes_tobeparsed -= temp_len;
+ }
+ else
+ {
+ memcpy (pdest,psource,bytes_tobeparsed);
+ temp_len -= bytes_tobeparsed;
+ dest->nFilledLen += bytes_tobeparsed;
+ source->nOffset += bytes_tobeparsed;
+ source->nFilledLen -= bytes_tobeparsed;
+ bytes_tobeparsed = 0;
+ }
+ }
+
+ if (bytes_tobeparsed == 0 && state_nal == NAL_PARSING)
+ {
+ *partialframe = 0;
+ state_nal = NAL_LENGTH_ACC;
+ }
+
+ return 1;
+}
+
+void frame_parse::flush ()
+{
+ parse_state = A0;
+ state_nal = NAL_LENGTH_ACC;
+ accum_length = 0;
+ bytes_tobeparsed = 0;
+}
+
+void frame_parse::update_metadata (unsigned int ts ,unsigned int flgs)
+{
+ time_stamp = ts;
+ flags = flgs;
+}
diff --git a/omx/mm-video/vidc/vdec/src/h264_utils.cpp b/omx/mm-video/vidc/vdec/src/h264_utils.cpp
new file mode 100644
index 0000000..ff9f080
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/src/h264_utils.cpp
@@ -0,0 +1,455 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*========================================================================
+
+ O p e n M M
+ V i d e o U t i l i t i e s
+
+*//** @file VideoUtils.cpp
+ This module contains utilities and helper routines.
+
+@par EXTERNALIZED FUNCTIONS
+
+@par INITIALIZATION AND SEQUENCING REQUIREMENTS
+ (none)
+
+*//*====================================================================== */
+
+/* =======================================================================
+
+ INCLUDE FILES FOR MODULE
+
+========================================================================== */
+#include "h264_utils.h"
+#include "omx_vdec.h"
+#include <string.h>
+#include <stdlib.h>
+
+/* =======================================================================
+
+ DEFINITIONS AND DECLARATIONS FOR MODULE
+
+This section contains definitions for constants, macros, types, variables
+and other items needed by this module.
+
+========================================================================== */
+
+#define SIZE_NAL_FIELD_MAX 4
+#define BASELINE_PROFILE 66
+#define MAIN_PROFILE 77
+#define HIGH_PROFILE 100
+
+#define MAX_SUPPORTED_LEVEL 32
+
+
+RbspParser::RbspParser (const uint8 *_begin, const uint8 *_end)
+: begin (_begin), end(_end), pos (- 1), bit (0),
+cursor (0xFFFFFF), advanceNeeded (true)
+{
+}
+
+// Destructor
+/*lint -e{1540} Pointer member neither freed nor zeroed by destructor
+ * No problem
+ */
+RbspParser::~RbspParser () {}
+
+// Return next RBSP byte as a word
+uint32 RbspParser::next ()
+{
+ if (advanceNeeded) advance ();
+ //return static_cast<uint32> (*pos);
+ return static_cast<uint32> (begin[pos]);
+}
+
+// Advance RBSP decoder to next byte
+void RbspParser::advance ()
+{
+ ++pos;
+ //if (pos >= stop)
+ if (begin + pos == end)
+ {
+ /*lint -e{730} Boolean argument to function
+ * I don't see a problem here
+ */
+ //throw false;
+ DEBUG_PRINT_LOW("H264Parser-->NEED TO THROW THE EXCEPTION...\n");
+ }
+ cursor <<= 8;
+ //cursor |= static_cast<uint32> (*pos);
+ cursor |= static_cast<uint32> (begin[pos]);
+ if ((cursor & 0xFFFFFF) == 0x000003)
+ {
+ advance ();
+ }
+ advanceNeeded = false;
+}
+
+// Decode unsigned integer
+uint32 RbspParser::u (uint32 n)
+{
+ uint32 i, s, x = 0;
+ for (i = 0; i < n; i += s)
+ {
+ s = static_cast<uint32>STD_MIN(static_cast<int>(8 - bit),
+ static_cast<int>(n - i));
+ x <<= s;
+
+ x |= ((next () >> ((8 - static_cast<uint32>(bit)) - s)) &
+ ((1 << s) - 1));
+
+ bit = (bit + s) % 8;
+ if (!bit)
+ {
+ advanceNeeded = true;
+ }
+ }
+ return x;
+}
+
+// Decode unsigned integer Exp-Golomb-coded syntax element
+uint32 RbspParser::ue ()
+{
+ int leadingZeroBits = -1;
+ for (uint32 b = 0; !b; ++leadingZeroBits)
+ {
+ b = u (1);
+ }
+ return ((1 << leadingZeroBits) - 1) +
+ u (static_cast<uint32>(leadingZeroBits));
+}
+
+// Decode signed integer Exp-Golomb-coded syntax element
+int32 RbspParser::se ()
+{
+ const uint32 x = ue ();
+ if (!x) return 0;
+ else if (x & 1) return static_cast<int32> ((x >> 1) + 1);
+ else return - static_cast<int32> (x >> 1);
+}
+
+void H264_Utils::allocate_rbsp_buffer(uint32 inputBufferSize)
+{
+ m_rbspBytes = (byte *) calloc(1,inputBufferSize);
+ m_prv_nalu.nal_ref_idc = 0;
+ m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
+}
+
+H264_Utils::H264_Utils(): m_height(0),
+ m_width(0),
+ m_rbspBytes(NULL),
+ m_au_data (false)
+{
+ initialize_frame_checking_environment();
+}
+
+H264_Utils::~H264_Utils()
+{
+/* if(m_pbits)
+ {
+ delete(m_pbits);
+ m_pbits = NULL;
+ }
+*/
+ if (m_rbspBytes)
+ {
+ free(m_rbspBytes);
+ m_rbspBytes = NULL;
+ }
+}
+
+/***********************************************************************/
+/*
+FUNCTION:
+ H264_Utils::initialize_frame_checking_environment
+
+DESCRIPTION:
+ Extract RBSP data from a NAL
+
+INPUT/OUTPUT PARAMETERS:
+ None
+
+RETURN VALUE:
+ boolean
+
+SIDE EFFECTS:
+ None.
+*/
+/***********************************************************************/
+void H264_Utils::initialize_frame_checking_environment()
+{
+ m_forceToStichNextNAL = false;
+ m_au_data = false;
+ m_prv_nalu.nal_ref_idc = 0;
+ m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
+}
+
+/***********************************************************************/
+/*
+FUNCTION:
+ H264_Utils::extract_rbsp
+
+DESCRIPTION:
+ Extract RBSP data from a NAL
+
+INPUT/OUTPUT PARAMETERS:
+ <In>
+ buffer : buffer containing start code or nal length + NAL units
+ buffer_length : the length of the NAL buffer
+ start_code : If true, start code is detected,
+ otherwise size nal length is detected
+ size_of_nal_length_field: size of nal length field
+
+ <Out>
+ rbsp_bistream : extracted RBSP bistream
+ rbsp_length : the length of the RBSP bitstream
+ nal_unit : decoded NAL header information
+
+RETURN VALUE:
+ boolean
+
+SIDE EFFECTS:
+ None.
+*/
+/***********************************************************************/
+
+boolean H264_Utils::extract_rbsp(OMX_IN OMX_U8 *buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_U8 *rbsp_bistream,
+ OMX_OUT OMX_U32 *rbsp_length,
+ OMX_OUT NALU *nal_unit)
+{
+ byte coef1, coef2, coef3;
+ uint32 pos = 0;
+ uint32 nal_len = buffer_length;
+ uint32 sizeofNalLengthField = 0;
+ uint32 zero_count;
+ boolean eRet = true;
+ boolean start_code = (size_of_nal_length_field==0)?true:false;
+
+ DEBUG_PRINT_LOW("extract_rbsp\n");
+
+ if(start_code) {
+ // Search start_code_prefix_one_3bytes (0x000001)
+ coef2 = buffer[pos++];
+ coef3 = buffer[pos++];
+ do {
+ if(pos >= buffer_length)
+ {
+ DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
+ return false;
+ }
+
+ coef1 = coef2;
+ coef2 = coef3;
+ coef3 = buffer[pos++];
+ } while(coef1 || coef2 || coef3 != 1);
+ }
+ else if (size_of_nal_length_field)
+ {
+ /* This is the case to play multiple NAL units inside each access unit*/
+ /* Extract the NAL length depending on sizeOfNALength field */
+ sizeofNalLengthField = size_of_nal_length_field;
+ nal_len = 0;
+ while(size_of_nal_length_field--)
+ {
+ nal_len |= buffer[pos++]<<(size_of_nal_length_field<<3);
+ }
+ if (nal_len >= buffer_length)
+ {
+ DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
+ return false;
+ }
+ }
+
+ if (nal_len > buffer_length)
+ {
+ DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
+ return false;
+ }
+ if(pos + 1 > (nal_len + sizeofNalLengthField))
+ {
+ DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
+ return false;
+ }
+ if (nal_unit->forbidden_zero_bit = (buffer[pos] & 0x80))
+ {
+ DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
+ }
+ nal_unit->nal_ref_idc = (buffer[pos] & 0x60) >> 5;
+ nal_unit->nalu_type = buffer[pos++] & 0x1f;
+ DEBUG_PRINT_LOW("\n@#@# Pos = %x NalType = %x buflen = %d",pos-1,nal_unit->nalu_type,buffer_length);
+ *rbsp_length = 0;
+
+
+ if( nal_unit->nalu_type == NALU_TYPE_EOSEQ ||
+ nal_unit->nalu_type == NALU_TYPE_EOSTREAM)
+ return (nal_len + sizeofNalLengthField);
+
+ zero_count = 0;
+ while (pos < (nal_len+sizeofNalLengthField)) //similar to for in p-42
+ {
+ if( zero_count == 2 ) {
+ if( buffer[pos] == 0x03 ) {
+ pos ++;
+ zero_count = 0;
+ continue;
+ }
+ if( buffer[pos] <= 0x01 ) {
+ if( start_code ) {
+ *rbsp_length -= 2;
+ pos -= 2;
+ return pos;
+ }
+ }
+ zero_count = 0;
+ }
+ zero_count ++;
+ if( buffer[pos] != 0 )
+ zero_count = 0;
+
+ rbsp_bistream[(*rbsp_length)++] = buffer[pos++];
+ }
+
+ return eRet;
+}
+
+/*===========================================================================
+FUNCTION:
+ H264_Utils::iSNewFrame
+
+DESCRIPTION:
+ Returns true if NAL parsing successfull otherwise false.
+
+INPUT/OUTPUT PARAMETERS:
+ <In>
+ buffer : buffer containing start code or nal length + NAL units
+ buffer_length : the length of the NAL buffer
+ start_code : If true, start code is detected,
+ otherwise size nal length is detected
+ size_of_nal_length_field: size of nal length field
+ <out>
+ isNewFrame: true if the NAL belongs to a differenet frame
+ false if the NAL belongs to a current frame
+
+RETURN VALUE:
+ boolean true, if nal parsing is successful
+ false, if the nal parsing has errors
+
+SIDE EFFECTS:
+ None.
+===========================================================================*/
+bool H264_Utils::isNewFrame(OMX_IN OMX_U8 *buffer,
+ OMX_IN OMX_U32 buffer_length,
+ OMX_IN OMX_U32 size_of_nal_length_field,
+ OMX_OUT OMX_BOOL &isNewFrame)
+{
+ NALU nal_unit;
+ uint16 first_mb_in_slice = 0;
+ uint32 numBytesInRBSP = 0;
+ bool eRet = true;
+
+ DEBUG_PRINT_LOW("get_h264_nal_type %p nal_length %d nal_length_field %d\n",
+ buffer, buffer_length, size_of_nal_length_field);
+
+ if ( false == extract_rbsp(buffer, buffer_length, size_of_nal_length_field,
+ m_rbspBytes, &numBytesInRBSP, &nal_unit) )
+ {
+ DEBUG_PRINT_ERROR("ERROR: In %s() - extract_rbsp() failed", __func__);
+ isNewFrame = OMX_FALSE;
+ eRet = false;
+ }
+ else
+ {
+ switch (nal_unit.nalu_type)
+ {
+ case NALU_TYPE_IDR:
+ case NALU_TYPE_NON_IDR:
+ {
+ DEBUG_PRINT_LOW("\n Found a AU Boundary %d ",nal_unit.nalu_type);
+ if (m_forceToStichNextNAL)
+ {
+ isNewFrame = OMX_FALSE;
+ }
+ else
+ {
+ RbspParser rbsp_parser(m_rbspBytes, (m_rbspBytes+numBytesInRBSP));
+ first_mb_in_slice = rbsp_parser.ue();
+
+ if((!first_mb_in_slice) || /*(slice.prv_frame_num != slice.frame_num ) ||*/
+ ( (m_prv_nalu.nal_ref_idc != nal_unit.nal_ref_idc) && ( nal_unit.nal_ref_idc * m_prv_nalu.nal_ref_idc == 0 ) ) ||
+ /*( ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) && (nal_unit.nalu_type == NALU_TYPE_IDR)) && (slice.idr_pic_id != slice.prv_idr_pic_id) ) || */
+ ( (m_prv_nalu.nalu_type != nal_unit.nalu_type ) && ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) || (nal_unit.nalu_type == NALU_TYPE_IDR)) ) )
+ {
+ //DEBUG_PRINT_LOW("Found a New Frame due to NALU_TYPE_IDR/NALU_TYPE_NON_IDR");
+ isNewFrame = OMX_TRUE;
+ }
+ else
+ {
+ isNewFrame = OMX_FALSE;
+ }
+ }
+ m_au_data = true;
+ m_forceToStichNextNAL = false;
+ break;
+ }
+ case NALU_TYPE_SPS:
+ case NALU_TYPE_PPS:
+ case NALU_TYPE_SEI:
+ case NALU_TYPE_UNSPECIFIED:
+ case NALU_TYPE_EOSEQ:
+ case NALU_TYPE_EOSTREAM:
+ {
+ DEBUG_PRINT_LOW("\n Non AU boundary NAL %d",nal_unit.nalu_type);
+ if(m_au_data)
+ {
+ isNewFrame = OMX_TRUE;
+ m_au_data = false;
+ }
+ else
+ {
+ isNewFrame = OMX_FALSE;
+ }
+
+ m_forceToStichNextNAL = true;
+ break;
+ }
+ case NALU_TYPE_ACCESS_DELIM:
+ default:
+ {
+ isNewFrame = OMX_FALSE;
+ // Do not update m_forceToStichNextNAL
+ break;
+ }
+ } // end of switch
+ } // end of if
+ m_prv_nalu = nal_unit;
+ DEBUG_PRINT_LOW("get_h264_nal_type - newFrame value %d\n",isNewFrame);
+ return eRet;
+}
diff --git a/omx/mm-video/vidc/vdec/src/message_queue.c b/omx/mm-video/vidc/vdec/src/message_queue.c
new file mode 100644
index 0000000..55af903
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/src/message_queue.c
@@ -0,0 +1,174 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "message_queue.h"
+
+int check_if_queue_empty ( unsigned int queuetocheck, void* queuecontext )
+{
+ struct video_queue_context *ptr_q = NULL;
+ /*
+ * queuetocheck - 0 command queue
+ * queuetocheck - 1 data queue
+ */
+ if ( queuecontext == NULL || (queuetocheck > 1 ) )
+ {
+ return 1;
+ }
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ if (queuetocheck == 0)
+ {
+ if (ptr_q->read_comq == ptr_q->write_comq)
+ {
+ return 1;
+ }
+ }
+ else if (queuetocheck == 1)
+ {
+ if (ptr_q->write_dataq == ptr_q->read_dataq)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+
+struct video_msgq * queue_get_cmd (void* queuecontext )
+{
+ struct video_queue_context *ptr_q = NULL;
+ struct video_msgq *pitem = NULL;
+
+ if( NULL == queuecontext )
+ {
+ printf("\n queue_get_cmd: Invalid Input parameter\n");
+ return NULL;
+ }
+
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ /* Wait on the semaphore till it is released */
+ sem_wait(&ptr_q->sem_message);
+
+ /* Lock the mutex to protect the critical section */
+ pthread_mutex_lock(&ptr_q->mutex);
+
+ if (ptr_q->read_comq != ptr_q->write_comq)
+ {
+ pitem = &ptr_q->ptr_cmdq [ptr_q->read_comq];
+ ptr_q->read_comq = (ptr_q->read_comq + 1) % \
+ ptr_q->commandq_size;
+ }
+ else if (ptr_q->write_dataq != ptr_q->read_dataq)
+ {
+ pitem = &ptr_q->ptr_dataq [ptr_q->read_dataq];
+ ptr_q->read_dataq = (ptr_q->read_dataq + 1) % \
+ ptr_q->dataq_size;
+ }
+
+ /* Unlock the mutex to release the critical section */
+ pthread_mutex_unlock(&ptr_q->mutex);
+
+ return pitem;
+}
+
+
+int queue_post_cmdq ( void* queuecontext,
+ struct video_msgq *pitem
+ )
+{
+ struct video_queue_context *ptr_q = NULL;
+
+ if (pitem == NULL || queuecontext == NULL)
+ {
+ return -1;
+ }
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ /* Lock the mutex to protect the critical section */
+ pthread_mutex_lock(&ptr_q->mutex);
+
+ if ((ptr_q->write_comq + 1) % ptr_q->commandq_size == ptr_q->read_comq)
+ {
+ printf("\n QUEUE is FULL");
+ return 0;
+ }
+ else
+ {
+ /* Store the command in the Message Queue & increment write offset */
+ memcpy ( &ptr_q->ptr_cmdq [ptr_q->write_comq],pitem, \
+ sizeof (struct video_msgq));
+ ptr_q->write_comq = (ptr_q->write_comq + 1) % ptr_q->commandq_size;
+ }
+
+ /* Unlock the mutex to release the critical section */
+ pthread_mutex_unlock(&ptr_q->mutex);
+
+ /* Post the semaphore */
+ sem_post(&ptr_q->sem_message);
+ return 1;
+}
+
+
+int queue_post_dataq ( void *queuecontext,
+ struct video_msgq *pitem
+ )
+{
+ struct video_queue_context *ptr_q = NULL;
+
+ if (pitem == NULL || queuecontext == NULL)
+ {
+ return -1;
+ }
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ /* Lock the mutex to protect the critical section */
+ pthread_mutex_lock(&ptr_q->mutex);
+
+ if ((ptr_q->write_dataq + 1) % ptr_q->dataq_size == ptr_q->read_dataq)
+ {
+ printf("\n QUEUE is FULL");
+ return 0;
+ }
+ else
+ {
+ /* Store the command in the Message Queue & increment write offset */
+ memcpy ( &ptr_q->ptr_dataq [ptr_q->write_dataq],pitem, \
+ sizeof (struct video_msgq));
+ ptr_q->write_dataq = (ptr_q->write_dataq + 1) % ptr_q->dataq_size;
+ }
+
+ /* Unlock the mutex to release the critical section */
+ pthread_mutex_unlock(&ptr_q->mutex);
+
+ /* Post the semaphore */
+ sem_post(&ptr_q->sem_message);
+ return 1;
+
+}
diff --git a/omx/mm-video/vidc/vdec/src/omx_vdec.cpp b/omx/mm-video/vidc/vdec/src/omx_vdec.cpp
new file mode 100644
index 0000000..3315066
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/src/omx_vdec.cpp
@@ -0,0 +1,6193 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+/*============================================================================
+ O p e n M A X w r a p p e r s
+ O p e n M A X C o r e
+
+*//** @file omx_vdec.cpp
+ This module contains the implementation of the OpenMAX core & component.
+
+*//*========================================================================*/
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include <string.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include "omx_vdec.h"
+#include <fcntl.h>
+
+#define BITSTREAM_LOG 0
+
+#if BITSTREAM_LOG
+FILE *outputBufferFile1;
+char filename [] = "/data/input-bitstream.m4v";
+#endif
+
+#define H264_SUPPORTED_WIDTH (480)
+#define H264_SUPPORTED_HEIGHT (368)
+
+#define MPEG4_SUPPORTED_WIDTH (480)
+#define MPEG4_SUPPORTED_HEIGHT (368)
+
+#define VC1_SP_MP_START_CODE 0xC5000000
+#define VC1_SP_MP_START_CODE_MASK 0xFF000000
+#define VC1_AP_SEQ_START_CODE 0x0F010000
+#define VC1_STRUCT_C_PROFILE_MASK 0xF0
+#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
+#define VC1_SIMPLE_PROFILE 0
+#define VC1_MAIN_PROFILE 1
+#define VC1_ADVANCE_PROFILE 3
+#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
+#define VC1_SIMPLE_PROFILE_MED_LEVEL 2
+#define VC1_STRUCT_C_LEN 4
+#define VC1_STRUCT_C_POS 8
+#define VC1_STRUCT_A_POS 12
+#define VC1_STRUCT_B_POS 24
+#define VC1_SEQ_LAYER_SIZE 36
+
+#ifdef _ANDROID_
+ extern "C"{
+ #include<utils/Log.h>
+ }
+#endif//_ANDROID_
+
+void* async_message_thread (void *input)
+{
+ struct vdec_ioctl_msg ioctl_msg;
+ struct vdec_msginfo vdec_msg;
+ omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
+
+ DEBUG_PRINT_HIGH("omx_vdec: Async thread start\n");
+ while (1)
+ {
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&vdec_msg;
+
+ /*Wait for a message from the video decoder driver*/
+ if (ioctl ( omx->driver_context.video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Error in ioctl read next msg");
+ break;
+ }
+ else
+ {
+ /*Call Instance specific process function*/
+ if (omx->async_message_process(input,&vdec_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Wrong ioctl message");
+ }
+ }
+ }
+ DEBUG_PRINT_HIGH("omx_vdec: Async thread stop\n");
+ return NULL;
+}
+
+void* message_thread(void *input)
+{
+ omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
+ unsigned char id;
+ int n;
+
+ DEBUG_PRINT_HIGH("omx_vdec: message thread start\n");
+ while (1)
+ {
+
+ n = read(omx->m_pipe_in, &id, 1);
+
+ if(0 == n)
+ {
+ break;
+ }
+
+ if (1 == n)
+ {
+ omx->process_event_cb(omx, id);
+ }
+ if ((n < 0) && (errno != EINTR))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: read from pipe failed, ret %d errno %d", n, errno);
+ break;
+ }
+ }
+ DEBUG_PRINT_HIGH("omx_vdec: message thread stop\n");
+ return 0;
+}
+
+void post_message(omx_vdec *omx, unsigned char id)
+{
+ int ret_value;
+ DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d\n", id,omx->m_pipe_out);
+ ret_value = write(omx->m_pipe_out, &id, 1);
+ DEBUG_PRINT_LOW("post_message to pipe done %d\n",ret_value);
+}
+
+// omx_cmd_queue destructor
+omx_vdec::omx_cmd_queue::~omx_cmd_queue()
+{
+ // Nothing to do
+}
+
+// omx cmd queue constructor
+omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
+{
+ memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
+}
+
+// omx cmd queue insert
+bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id)
+{
+ bool ret = true;
+ if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE)
+ {
+ m_q[m_write].id = id;
+ m_q[m_write].param1 = p1;
+ m_q[m_write].param2 = p2;
+ m_write++;
+ m_size ++;
+ if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE)
+ {
+ m_write = 0;
+ }
+ }
+ else
+ {
+ ret = false;
+ DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full\n", __func__);
+ }
+ return ret;
+}
+
+// omx cmd queue pop
+bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id)
+{
+ bool ret = true;
+ if (m_size > 0)
+ {
+ *id = m_q[m_read].id;
+ *p1 = m_q[m_read].param1;
+ *p2 = m_q[m_read].param2;
+ // Move the read pointer ahead
+ ++m_read;
+ --m_size;
+ if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE)
+ {
+ m_read = 0;
+ }
+ }
+ else
+ {
+ ret = false;
+ }
+ return ret;
+}
+
+// Retrieve the first mesg type in the queue
+unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
+{
+ return m_q[m_read].id;
+}
+
+// factory function executed by the core to create instances
+void *get_omx_component_factory_fn(void)
+{
+ return (new omx_vdec);
+}
+
+#ifdef _ANDROID_
+VideoHeap::VideoHeap(int fd, size_t size, void* base)
+{
+ // dup file descriptor, map once, use pmem
+ init(dup(fd), base, size, 0 , "/dev/pmem_adsp");
+}
+#endif // _ANDROID_
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec
+
+DESCRIPTION
+ Constructor
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None.
+========================================================================== */
+omx_vdec::omx_vdec(): m_state(OMX_StateInvalid),
+ m_app_data(NULL),
+ m_color_format(OMX_COLOR_FormatYUV420Planar),
+ m_inp_mem_ptr(NULL),
+ m_out_mem_ptr(NULL),
+ pending_input_buffers(0),
+ pending_output_buffers(0),
+ m_out_buf_count(0),
+ m_out_bm_count(0),
+ m_inp_buf_count(OMX_VIDEO_DEC_NUM_INPUT_BUFFERS),
+ m_inp_buf_size(OMX_VIDEO_DEC_INPUT_BUFFER_SIZE),
+ m_inp_bm_count(0),
+ m_inp_bPopulated(OMX_FALSE),
+ m_out_bPopulated(OMX_FALSE),
+ m_height(0),
+ m_width(0),
+ m_port_height(0),
+ m_port_width(0),
+ m_crop_x(0),
+ m_crop_y(0),
+ m_crop_dx(0),
+ m_crop_dy(0),
+ m_flags(0),
+ m_inp_bEnabled(OMX_TRUE),
+ m_out_bEnabled(OMX_TRUE),
+ m_event_port_settings_sent(false),
+ m_platform_list(NULL),
+ m_platform_entry(NULL),
+ m_pmem_info(NULL),
+ output_flush_progress (false),
+ input_flush_progress (false),
+ input_use_buffer (false),
+ output_use_buffer (false),
+ m_ineos_reached (0),
+ m_outeos_pending (0),
+ m_outeos_reached (0),
+ arbitrary_bytes (true),
+ psource_frame (NULL),
+ pdest_frame (NULL),
+ m_inp_heap_ptr (NULL),
+ m_heap_inp_bm_count (0),
+ codec_type_parse ((codec_type)0),
+ first_frame_meta (true),
+ frame_count (0),
+ nal_length(0),
+ nal_count (0),
+ look_ahead_nal (false),
+ first_frame(0),
+ first_buffer(NULL),
+ first_frame_size (0),
+ set_seq_header_done(false),
+ gate_output_buffers(true),
+ gate_input_buffers(false),
+ sent_first_frame(false),
+ stride(0),
+ scan_lines(0),
+ m_error_propogated(false),
+ m_device_file_ptr(NULL),
+ m_vc1_profile((vc1_profile_type)0)
+{
+ /* Assumption is that , to begin with , we have all the frames with decoder */
+ DEBUG_PRINT_HIGH("\n In OMX vdec Constuctor");
+ memset(&m_cmp,0,sizeof(m_cmp));
+ memset(&m_cb,0,sizeof(m_cb));
+ memset (&driver_context,0,sizeof(driver_context));
+ memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
+ memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
+ driver_context.video_driver_fd = -1;
+ m_vendor_config.pData = NULL;
+ pthread_mutex_init(&m_lock, NULL);
+ sem_init(&m_cmd_lock,0,0);
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::~omx_vdec
+
+DESCRIPTION
+ Destructor
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None.
+========================================================================== */
+omx_vdec::~omx_vdec()
+{
+ m_pmem_info = NULL;
+ m_port_width = m_port_height = 0;
+ DEBUG_PRINT_HIGH("\n In OMX vdec Destructor");
+ if(m_pipe_in) close(m_pipe_in);
+ if(m_pipe_out) close(m_pipe_out);
+ m_pipe_in = -1;
+ m_pipe_out = -1;
+ DEBUG_PRINT_HIGH("\n Waiting on OMX Msg Thread exit");
+ pthread_join(msg_thread_id,NULL);
+ DEBUG_PRINT_HIGH("\n Waiting on OMX Async Thread exit");
+ pthread_join(async_thread_id,NULL);
+ pthread_mutex_destroy(&m_lock);
+ sem_destroy(&m_cmd_lock);
+ DEBUG_PRINT_HIGH("\n Exit OMX vdec Destructor");
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::OMXCntrlProcessMsgCb
+
+DESCRIPTION
+ IL Client callbacks are generated through this routine. The decoder
+ provides the thread context for this routine.
+
+PARAMETERS
+ ctxt -- Context information related to the self.
+ id -- Event identifier. This could be any of the following:
+ 1. Command completion event
+ 2. Buffer done callback event
+ 3. Frame done callback event
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+void omx_vdec::process_event_cb(void *ctxt, unsigned char id)
+{
+ unsigned p1; // Parameter - 1
+ unsigned p2; // Parameter - 2
+ unsigned ident;
+ unsigned qsize=0; // qsize
+ omx_vdec *pThis = (omx_vdec *) ctxt;
+
+ if(!pThis)
+ {
+ DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out\n",
+ __func__);
+ return;
+ }
+
+ // Protect the shared queue data structure
+ do
+ {
+ /*Read the message id's from the queue*/
+ pthread_mutex_lock(&pThis->m_lock);
+ qsize = pThis->m_cmd_q.m_size;
+ if(qsize)
+ {
+ pThis->m_cmd_q.pop_entry(&p1,&p2,&ident);
+ }
+
+ if (qsize == 0 && !pThis->gate_output_buffers)
+ {
+ qsize = pThis->m_ftb_q.m_size;
+ if (qsize)
+ {
+ pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
+ }
+ }
+
+ if (qsize == 0)
+ {
+ qsize = pThis->m_etb_q.m_size;
+ if (qsize)
+ {
+ pThis->m_etb_q.pop_entry(&p1,&p2,&ident);
+ }
+ }
+ pthread_mutex_unlock(&pThis->m_lock);
+
+ /*process message if we have one*/
+ if(qsize > 0)
+ {
+ id = ident;
+ switch (id)
+ {
+ case OMX_COMPONENT_GENERATE_EVENT:
+ if (pThis->m_cb.EventHandler)
+ {
+ switch (p1)
+ {
+ case OMX_CommandStateSet:
+ pThis->m_state = (OMX_STATETYPE) p2;
+ DEBUG_PRINT_HIGH("\n OMX_CommandStateSet complete, m_state = %d",
+ pThis->m_state);
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete, p1, p2, NULL);
+ break;
+
+ case OMX_EventError:
+ if(p2 == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_EventError: p2 is OMX_StateInvalid");
+ pThis->m_state = (OMX_STATETYPE) p2;
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
+ }
+ else if (p2 == OMX_ErrorHardware)
+ {
+ pThis->omx_report_error();
+ }
+ else
+ {
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError, p2, NULL, NULL );
+ }
+ break;
+
+ case OMX_CommandPortDisable:
+ DEBUG_PRINT_HIGH("\n OMX_CommandPortDisable complete for port [%d]", p2);
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete, p1, p2, NULL );
+ //TODO: Check if output port is one that got disabled
+ pThis->gate_output_buffers = false;
+ break;
+ case OMX_CommandPortEnable:
+ DEBUG_PRINT_HIGH("\n OMX_CommandPortEnable complete for port [%d]", p2);
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
+ OMX_EventCmdComplete, p1, p2, NULL );
+ break;
+
+ default:
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete, p1, p2, NULL );
+ break;
+
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL\n", __func__);
+ }
+ break;
+ case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
+ if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
+ (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
+ pThis->omx_report_error ();
+ }
+ break;
+ case OMX_COMPONENT_GENERATE_ETB:
+ if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
+ (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_FTB:
+ if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
+ (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_COMMAND:
+ pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
+ (OMX_U32)p2,(OMX_PTR)NULL);
+ break;
+
+ case OMX_COMPONENT_GENERATE_EBD:
+
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EBD failure");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ if ( pThis->empty_buffer_done(&pThis->m_cmp,
+ (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n empty_buffer_done failure");
+ pThis->omx_report_error ();
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_FBD:
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_FBD failure");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ if ( pThis->fill_buffer_done(&pThis->m_cmp,
+ (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
+ {
+ DEBUG_PRINT_ERROR("\n fill_buffer_done failure");
+ pThis->omx_report_error ();
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
+ DEBUG_PRINT_HIGH("\n Flush i/p Port complete");
+ pThis->input_flush_progress = false;
+ DEBUG_PRINT_LOW("\n Input flush done pending input %d",
+ pThis->pending_input_buffers);
+
+ if (pThis->m_cb.EventHandler)
+ {
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\nOMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ /*Check if we need generate event for Flush done*/
+ if(BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_INPUT_FLUSH_PENDING))
+ {
+ BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
+ DEBUG_PRINT_LOW("\n Input Flush completed - Notify Client");
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandFlush,
+ OMX_CORE_INPUT_PORT_INDEX,NULL );
+ }
+ if (BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_IDLE_PENDING))
+ {
+ if (!pThis->output_flush_progress)
+ {
+ DEBUG_PRINT_LOW("\n Output flush done hence issue stop");
+ if (ioctl (pThis->driver_context.video_driver_fd,
+ VDEC_IOCTL_CMD_STOP,NULL ) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
+ DEBUG_PRINT_HIGH("\n Flush o/p Port complete");
+ pThis->output_flush_progress = false;
+ DEBUG_PRINT_LOW("\n Output flush done pending buf %d",pThis->pending_output_buffers);
+
+ if (pThis->m_cb.EventHandler)
+ {
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ /*Check if we need generate event for Flush done*/
+ if(BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_OUTPUT_FLUSH_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n Notify Output Flush done");
+ BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
+
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandFlush,
+ OMX_CORE_OUTPUT_PORT_INDEX,NULL );
+ }
+ if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING))
+ {
+ if (!pThis->input_flush_progress)
+ {
+ DEBUG_PRINT_LOW("\n Input flush done hence issue stop");
+ if (ioctl (pThis->driver_context.video_driver_fd,
+ VDEC_IOCTL_CMD_STOP,NULL ) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_START_DONE:
+ DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_START_DONE");
+
+ if (pThis->m_cb.EventHandler)
+ {
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_START_DONE Failure");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success");
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n Move to executing");
+ // Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
+ pThis->m_state = OMX_StateExecuting;
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StateExecuting, NULL);
+ }
+ else if (BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_PAUSE_PENDING))
+ {
+ if (ioctl (pThis->driver_context.video_driver_fd,
+ VDEC_IOCTL_CMD_PAUSE,NULL ) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_PAUSE failed");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Event Handler callback is NULL");
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_PAUSE_DONE:
+ DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
+ if (pThis->m_cb.EventHandler)
+ {
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
+ //Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
+ pThis->m_state = OMX_StatePause;
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StatePause, NULL);
+ }
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_RESUME_DONE:
+ DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
+ if (pThis->m_cb.EventHandler)
+ {
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_RESUME_DONE failed");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n Moving the decoder to execute state");
+ // Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
+ pThis->m_state = OMX_StateExecuting;
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StateExecuting,NULL);
+ }
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_STOP_DONE:
+ DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
+ if (pThis->m_cb.EventHandler)
+ {
+ if (p2 != VDEC_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
+ pThis->omx_report_error ();
+ }
+ else
+ {
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE Success");
+ // Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
+ pThis->m_state = OMX_StateIdle;
+ DEBUG_PRINT_LOW("\n Move to Idle State");
+ pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StateIdle,NULL);
+ }
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
+ DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
+ pThis->omx_report_error ();
+ break;
+
+ default:
+ break;
+ }
+ }
+ pthread_mutex_lock(&pThis->m_lock);
+ if(!pThis->gate_output_buffers)
+ {
+ qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\
+ pThis->m_etb_q.m_size;
+ }
+ else
+ {
+ qsize = pThis->m_cmd_q.m_size + pThis->m_etb_q.m_size;
+ }
+ pthread_mutex_unlock(&pThis->m_lock);
+ }
+ while(qsize>0);
+
+}
+
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentInit
+
+DESCRIPTION
+ Initialize the component.
+
+PARAMETERS
+ ctxt -- Context information related to the self.
+ id -- Event identifier. This could be any of the following:
+ 1. Command completion event
+ 2. Buffer done callback event
+ 3. Frame done callback event
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
+{
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned int alignment = 0,buffer_size = 0;
+ int fds[2];
+ int r;
+ bool is_fluid = false;
+
+ if (!m_device_file_ptr) {
+ int bytes_read = 0,count = 0;
+ unsigned min_size;
+ m_device_file_ptr = fopen("/sys/devices/system/soc/soc0/hw_platform","rb");
+ if (m_device_file_ptr) {
+ (void)fgets((char *)m_hwdevice_name,sizeof(m_hwdevice_name),m_device_file_ptr);
+ DEBUG_PRINT_HIGH ("\n Name of the device is %s",m_hwdevice_name);
+ min_size = strnlen((const char *)m_hwdevice_name,sizeof(m_hwdevice_name));
+ if (strlen("Fluid") < min_size) {
+ min_size = strnlen("Fluid",sizeof("Fluid"));
+ }
+ if (!strncmp("Fluid",(const char *)m_hwdevice_name,min_size)) {
+ is_fluid = true;
+ }
+ fclose (m_device_file_ptr);
+ } else {
+ DEBUG_PRINT_HIGH("\n Could not open hw_platform file");
+ }
+ }
+
+ DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Start of New Playback");
+ driver_context.video_driver_fd = open ("/dev/msm_vidc_dec",\
+ O_RDWR|O_NONBLOCK);
+
+ DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Open returned fd %d",
+ driver_context.video_driver_fd);
+
+ if(driver_context.video_driver_fd == 0){
+ driver_context.video_driver_fd = open ("/dev/msm_vidc_dec",\
+ O_RDWR|O_NONBLOCK);
+ }
+
+ if(driver_context.video_driver_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure\n");
+ return OMX_ErrorInsufficientResources;
+ }
+
+#ifndef MULTI_DEC_INST
+ unsigned int instance_count = 0;
+ if (!is_fluid) {
+ ioctl_msg.outputparam = &instance_count;
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_GET_NUMBER_INSTANCES,
+ (void*)&ioctl_msg) < 0){
+ DEBUG_PRINT_ERROR("\n Instance Query Failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ if (instance_count > 1) {
+ close(driver_context.video_driver_fd);
+ DEBUG_PRINT_ERROR("\n Reject Second instance of Decoder");
+ driver_context.video_driver_fd = -1;
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+#endif
+
+#if BITSTREAM_LOG
+ outputBufferFile1 = fopen (filename, "ab");
+#endif
+
+ // Copy the role information which provides the decoder kind
+ strncpy(driver_context.kind,role,128);
+
+ if(!strncmp(driver_context.kind,"OMX.qcom.video.decoder.mpeg4",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_decoder.mpeg4",\
+ OMX_MAX_STRINGNAME_SIZE);
+ driver_context.decoder_format = VDEC_CODECTYPE_MPEG4;
+ eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ /*Initialize Start Code for MPEG4*/
+ codec_type_parse = CODEC_TYPE_MPEG4;
+ m_frame_parser.init_start_codes (codec_type_parse);
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.h263",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("\n H263 Decoder selected");
+ driver_context.decoder_format = VDEC_CODECTYPE_H263;
+ eCompressionFormat = OMX_VIDEO_CodingH263;
+ codec_type_parse = CODEC_TYPE_H263;
+ m_frame_parser.init_start_codes (codec_type_parse);
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.avc",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ driver_context.decoder_format = VDEC_CODECTYPE_H264;
+ eCompressionFormat = OMX_VIDEO_CodingAVC;
+ codec_type_parse = CODEC_TYPE_H264;
+ m_frame_parser.init_start_codes (codec_type_parse);
+ m_frame_parser.init_nal_length(nal_length);
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.vc1",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
+ driver_context.decoder_format = VDEC_CODECTYPE_VC1;
+ eCompressionFormat = OMX_VIDEO_CodingWMV;
+ codec_type_parse = CODEC_TYPE_VC1;
+ m_frame_parser.init_start_codes (codec_type_parse);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Unknown Component\n");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+
+ if (eRet == OMX_ErrorNone)
+ {
+ driver_context.output_format = VDEC_YUV_FORMAT_NV12;
+
+ if (is_fluid) {
+
+ FILE * pFile;
+ char disable_overlay = '0';
+ pFile = fopen
+ ("/data/data/com.arcsoft.videowall/files/disableoverlay.txt", "rb" );
+ if (pFile == NULL) {
+ DEBUG_PRINT_HIGH(" fopen FAiLED for disableoverlay.txt\n");
+ } else {
+ int count = fread(&disable_overlay, 1, 1, pFile);
+ fclose(pFile);
+ }
+
+ if(disable_overlay == '1') {
+ DEBUG_PRINT_HIGH(" vdec : TILE format \n");
+ driver_context.output_format = VDEC_YUV_FORMAT_TILE_4x2;
+ } else {
+ DEBUG_PRINT_HIGH(" vdec : NV 12 format \n");
+ driver_context.output_format = VDEC_YUV_FORMAT_NV12;
+ }
+ }
+
+ /*Initialize Decoder with codec type and resolution*/
+ ioctl_msg.inputparam = &driver_context.decoder_format;
+ ioctl_msg.outputparam = NULL;
+
+ if ( (eRet == OMX_ErrorNone) &&
+ ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_CODEC,
+ (void*)&ioctl_msg) < 0)
+
+ {
+ DEBUG_PRINT_ERROR("\n Set codec type failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ /*Set the output format*/
+ ioctl_msg.inputparam = &driver_context.output_format;
+ ioctl_msg.outputparam = NULL;
+
+ if ( (eRet == OMX_ErrorNone) &&
+ ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set output format failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+#ifdef MAX_RES_720P
+ driver_context.video_resoultion.frame_height = 720;
+ driver_context.video_resoultion.frame_width = 1280;
+ driver_context.video_resoultion.stride = 1280;
+ driver_context.video_resoultion.scan_lines = 720;
+#endif
+#ifdef MAX_RES_1080P
+ driver_context.video_resoultion.frame_height = 1088;
+ driver_context.video_resoultion.frame_width = 1920;
+ driver_context.video_resoultion.stride = 1920;
+ driver_context.video_resoultion.scan_lines = 1088;
+#endif
+
+ ioctl_msg.inputparam = &driver_context.video_resoultion;
+ ioctl_msg.outputparam = NULL;
+
+ if ( (eRet == OMX_ErrorNone) &&
+ ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_PICRES,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set Resolution failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ /*Get the Buffer requirements for input and output ports*/
+ driver_context.input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.input_buffer;
+
+ if ( (eRet == OMX_ErrorNone) &&
+ ioctl (driver_context.video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Requesting for input buffer requirements failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ m_inp_buf_count = driver_context.input_buffer.actualcount;
+ buffer_size = driver_context.input_buffer.buffer_size;
+ alignment = driver_context.input_buffer.alignment;
+ m_inp_buf_size = ((buffer_size + alignment -1 ) & (~(alignment -1)));
+ m_inp_buf_count_min = driver_context.input_buffer.mincount;
+
+ /*Get the Buffer requirements for input and output ports*/
+ driver_context.input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ ioctl_msg.inputparam = &driver_context.input_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ m_inp_buf_count_min = m_inp_buf_count = driver_context.input_buffer.actualcount =
+ driver_context.input_buffer.mincount + 3;
+
+ if ( (eRet == OMX_ErrorNone) &&
+ ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set input buffer requirements failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+
+ driver_context.output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.output_buffer;
+
+ if ((eRet == OMX_ErrorNone) &&
+ ioctl (driver_context.video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Requesting for output buffer requirements failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ m_out_buf_count_recon = m_out_buf_count = driver_context.output_buffer.actualcount;
+ m_out_buf_count_min_recon = m_out_buf_count_min = driver_context.output_buffer.mincount;
+
+ alignment = driver_context.output_buffer.alignment;
+ buffer_size = driver_context.output_buffer.buffer_size;
+ m_out_buf_size_recon = m_out_buf_size =
+ ((buffer_size + alignment - 1) & (~(alignment -1)));
+#ifdef MAX_RES_720P
+ scan_lines = m_crop_dy = m_height = 720;
+ stride = m_crop_dx = m_width = 1280;
+#endif
+#ifdef MAX_RES_1080P
+ scan_lines = m_crop_dy = m_height = 1088;
+ stride = m_crop_dx = m_width = 1920;
+#endif
+ m_port_height = m_height;
+ m_port_width = m_width;
+ m_state = OMX_StateLoaded;
+
+ if(pipe(fds))
+ {
+ DEBUG_PRINT_ERROR("pipe creation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ else
+ {
+ int temp1[2];
+ if(fds[0] == 0 || fds[1] == 0)
+ {
+ if (pipe (temp1))
+ {
+ DEBUG_PRINT_ERROR("pipe creation failed\n");
+ return OMX_ErrorInsufficientResources;
+ }
+ //close (fds[0]);
+ //close (fds[1]);
+ fds[0] = temp1 [0];
+ fds[1] = temp1 [1];
+ }
+ m_pipe_in = fds[0];
+ m_pipe_out = fds[1];
+ r = pthread_create(&msg_thread_id,0,message_thread,this);
+
+ if(r < 0)
+ {
+ DEBUG_PRINT_ERROR("\n component_init(): message_thread creation failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ else
+ {
+ r = pthread_create(&async_thread_id,0,async_message_thread,this);
+ if(r < 0)
+ {
+ DEBUG_PRINT_ERROR("\n component_init(): async_message_thread creation failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ }
+ }
+
+ if (eRet != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n Component Init Failed");
+ DEBUG_PRINT_HIGH("\n Calling VDEC_IOCTL_STOP_NEXT_MSG");
+ (void)ioctl(driver_context.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
+ NULL);
+ DEBUG_PRINT_HIGH("\n Calling close() on Video Driver");
+ close (driver_context.video_driver_fd);
+ driver_context.video_driver_fd = -1;
+ }
+ else
+ {
+ DEBUG_PRINT_HIGH("\n omx_vdec::component_init() success");
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetComponentVersion
+
+DESCRIPTION
+ Returns the component version.
+
+PARAMETERS
+ TBD.
+
+RETURN VALUE
+ OMX_ErrorNone.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_component_version
+ (
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_STRING componentName,
+ OMX_OUT OMX_VERSIONTYPE* componentVersion,
+ OMX_OUT OMX_VERSIONTYPE* specVersion,
+ OMX_OUT OMX_UUIDTYPE* componentUUID
+ )
+{
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ /* TBD -- Return the proper version */
+ return OMX_ErrorNone;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::SendCommand
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_COMMANDTYPE cmd,
+ OMX_IN OMX_U32 param1,
+ OMX_IN OMX_PTR cmdData
+ )
+{
+ DEBUG_PRINT_LOW("\n send_command: Recieved a Command from Client");
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
+ sem_wait(&m_cmd_lock);
+ DEBUG_PRINT_LOW("\n send_command: Command Processed\n");
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SendCommand
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_COMMANDTYPE cmd,
+ OMX_IN OMX_U32 param1,
+ OMX_IN OMX_PTR cmdData
+ )
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_STATETYPE eState = (OMX_STATETYPE) param1;
+ int bFlag = 1,sem_posted = 0;;
+
+ DEBUG_PRINT_LOW("\n send_command_proxy(): cmd = %d", cmd);
+ DEBUG_PRINT_HIGH("\n send_command_proxy(): Current State %d, Expected State %d",
+ m_state, eState);
+
+ if(cmd == OMX_CommandStateSet)
+ {
+ DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandStateSet issued");
+ DEBUG_PRINT_HIGH("\n Current State %d, Expected State %d", m_state, eState);
+ /***************************/
+ /* Current State is Loaded */
+ /***************************/
+ if(m_state == OMX_StateLoaded)
+ {
+ if(eState == OMX_StateIdle)
+ {
+ //if all buffers are allocated or all ports disabled
+ if(allocate_done() ||
+ (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE))
+ {
+ DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle\n");
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Loaded to Loaded */
+ else if(eState == OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded\n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Loaded to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition */
+ DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources\n");
+ }
+ /* Requesting transition from Loaded to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Loaded to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Loaded to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid\n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)\n",\
+ eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /***************************/
+ /* Current State is IDLE */
+ /***************************/
+ else if(m_state == OMX_StateIdle)
+ {
+ if(eState == OMX_StateLoaded)
+ {
+ if(release_done())
+ {
+ /*
+ Since error is None , we will post an event at the end
+ of this function definition
+ */
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded\n");
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Idle to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
+ post_event (NULL,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_START_DONE);
+ bFlag = 0;
+ }
+ /* Requesting transition from Idle to Idle */
+ else if(eState == OMX_StateIdle)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle\n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Idle to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Idle to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ /*To pause the Video core we need to start the driver*/
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_CMD_START,
+ NULL) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED");
+ omx_report_error ();
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause\n");
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Idle to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /******************************/
+ /* Current State is Executing */
+ /******************************/
+ else if(m_state == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_LOW("\n Command Recieved in OMX_StateExecuting");
+ /* Requesting transition from Executing to Idle */
+ if(eState == OMX_StateIdle)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition
+ */
+ DEBUG_PRINT_LOW("\n send_command_proxy(): Executing --> Idle \n");
+ BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
+ if(!sem_posted)
+ {
+ sem_posted = 1;
+ sem_post (&m_cmd_lock);
+ execute_omx_flush(OMX_ALL);
+ }
+ bFlag = 0;
+ }
+ /* Requesting transition from Executing to Paused */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_LOW("\n PAUSE Command Issued");
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_CMD_PAUSE,
+ NULL) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Error In Pause State");
+ post_event(OMX_EventError,OMX_ErrorHardware,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
+ DEBUG_PRINT_LOW("send_command_proxy(): Pause-->Executing\n");
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Executing to Loaded */
+ else if(eState == OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Loaded \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Executing to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> WaitForResources \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Executing to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Executing \n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Executing to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Invalid \n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled\n",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /***************************/
+ /* Current State is Pause */
+ /***************************/
+ else if(m_state == OMX_StatePause)
+ {
+ /* Requesting transition from Pause to Executing */
+ if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_LOW("\n Pause --> Executing \n");
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_CMD_RESUME,
+ NULL) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_RESUME failed");
+ post_event(OMX_EventError,OMX_ErrorHardware,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n");
+ post_event (NULL,VDEC_S_SUCCESS,\
+ OMX_COMPONENT_GENERATE_RESUME_DONE);
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Pause to Idle */
+ else if(eState == OMX_StateIdle)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition */
+ DEBUG_PRINT_LOW("\n Pause --> Idle \n");
+ BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
+ if(!sem_posted)
+ {
+ sem_posted = 1;
+ sem_post (&m_cmd_lock);
+ execute_omx_flush(OMX_ALL);
+ }
+ bFlag = 0;
+ }
+ /* Requesting transition from Pause to loaded */
+ else if(eState == OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("\n Pause --> loaded \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Pause to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("\n Pause --> WaitForResources \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Pause to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("\n Pause --> Pause \n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Pause to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("\n Pause --> Invalid \n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled\n",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /***************************/
+ /* Current State is WaitForResources */
+ /***************************/
+ else if(m_state == OMX_StateWaitForResources)
+ {
+ /* Requesting transition from WaitForResources to Loaded */
+ if(eState == OMX_StateLoaded)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition */
+ DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded\n");
+ }
+ /* Requesting transition from WaitForResources to WaitForResources */
+ else if (eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources\n");
+ post_event(OMX_EventError,OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from WaitForResources to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from WaitForResources to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from WaitForResources to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid\n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ /* Requesting transition from WaitForResources to Loaded -
+ is NOT tested by Khronos TS */
+
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)\n",m_state,eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /********************************/
+ /* Current State is Invalid */
+ /*******************************/
+ else if(m_state == OMX_StateInvalid)
+ {
+ /* State Transition from Inavlid to any state */
+ if(eState == (OMX_StateLoaded || OMX_StateWaitForResources
+ || OMX_StateIdle || OMX_StateExecuting
+ || OMX_StatePause || OMX_StateInvalid))
+ {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded\n");
+ post_event(OMX_EventError,OMX_ErrorInvalidState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ }
+ else if (cmd == OMX_CommandFlush)
+ {
+ DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued"
+ "with param1: %d", param1);
+ if(0 == param1 || OMX_ALL == param1)
+ {
+ BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
+ }
+ if(1 == param1 || OMX_ALL == param1)
+ {
+ //generate output flush event only.
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
+ }
+ if (!sem_posted){
+ sem_posted = 1;
+ DEBUG_PRINT_LOW("\n Set the Semaphore");
+ sem_post (&m_cmd_lock);
+ execute_omx_flush(param1);
+ }
+ bFlag = 0;
+ }
+ else if ( cmd == OMX_CommandPortEnable)
+ {
+ DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortEnable issued"
+ "with param1: %d", param1);
+ if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
+ {
+ m_inp_bEnabled = OMX_TRUE;
+
+ if( (m_state == OMX_StateLoaded &&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ || allocate_input_done())
+ {
+ post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
+ {
+ DEBUG_PRINT_LOW("\n Enable output Port command recieved");
+ m_out_bEnabled = OMX_TRUE;
+
+ if( (m_state == OMX_StateLoaded &&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ || (allocate_output_done()))
+ {
+ post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ }
+ else if (cmd == OMX_CommandPortDisable)
+ {
+ DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued"
+ "with param1: %d", param1);
+ if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL)
+ {
+ m_inp_bEnabled = OMX_FALSE;
+ if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
+ && release_input_done())
+ {
+ post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ else
+ {
+ BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
+ {
+ if(!sem_posted)
+ {
+ sem_posted = 1;
+ sem_post (&m_cmd_lock);
+ execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
+ }
+ }
+
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL)
+ {
+ m_out_bEnabled = OMX_FALSE;
+ DEBUG_PRINT_LOW("\n Disable output Port command recieved");
+ if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
+ && release_output_done())
+ {
+ post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ else
+ {
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+ if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
+ {
+ if(!sem_posted)
+ {
+ sem_posted = 1;
+ sem_post (&m_cmd_lock);
+ execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
+ }
+ }
+ // Skip the event notification
+ bFlag = 0;
+
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd);
+ eRet = OMX_ErrorNotImplemented;
+ }
+ if(eRet == OMX_ErrorNone && bFlag)
+ {
+ post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
+ }
+ if(!sem_posted)
+ {
+ sem_post(&m_cmd_lock);
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ExecuteOmxFlush
+
+DESCRIPTION
+ Executes the OMX flush.
+
+PARAMETERS
+ flushtype - input flush(1)/output flush(0)/ both.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
+{
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ enum vdec_bufferflush flush_dir = VDEC_FLUSH_TYPE_ALL;
+ bool bRet = false;
+
+ if(flushType == 0 || flushType == OMX_ALL)
+ {
+ input_flush_progress = true;
+ //flush input only
+ bRet = execute_input_flush(flushType);
+ }
+ if(flushType == 1 || flushType == OMX_ALL)
+ {
+ //flush output only
+ output_flush_progress = true;
+ bRet = execute_output_flush(flushType);
+ }
+
+ if(flushType == OMX_ALL)
+ {
+ /*Check if there are buffers with the Driver*/
+ DEBUG_PRINT_LOW("\n Flush ALL ioctl issued");
+ ioctl_msg.inputparam = &flush_dir;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(driver_context.video_driver_fd,VDEC_IOCTL_CMD_FLUSH,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Flush ALL Failed ");
+ return false;
+ }
+ }
+
+ return bRet;
+}
+/*=========================================================================
+FUNCTION : execute_output_flush
+
+DESCRIPTION
+ Executes the OMX flush at OUTPUT PORT.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+==========================================================================*/
+bool omx_vdec::execute_output_flush(OMX_U32 flushType)
+{
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ enum vdec_bufferflush flush_dir = VDEC_FLUSH_TYPE_OUTPUT;
+ unsigned p1 = 0; // Parameter - 1
+ unsigned p2 = 0; // Parameter - 2
+ unsigned ident = 0;
+ bool bRet = true;
+
+ /*Generate FBD for all Buffers in the FTBq*/
+ pthread_mutex_lock(&m_lock);
+ DEBUG_PRINT_LOW("\n Initiate Output Flush");
+ while (m_ftb_q.m_size)
+ {
+ DEBUG_PRINT_LOW("\n Buffer queue size %d pending buf cnt %d",
+ m_ftb_q.m_size,pending_output_buffers);
+ m_ftb_q.pop_entry(&p1,&p2,&ident);
+
+ if(ident == OMX_COMPONENT_GENERATE_FTB )
+ {
+ DEBUG_PRINT_LOW("\n Inside Flush Buffer OMX_COMPONENT_GENERATE_FTB");
+ pending_output_buffers++;
+ fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
+ }
+ else if (ident == OMX_COMPONENT_GENERATE_FBD)
+ {
+ fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
+ }
+ }
+ pthread_mutex_unlock(&m_lock);
+
+ if(gate_output_buffers)
+ {
+ DEBUG_PRINT_LOW("\n Output Buffers gated Check flush response");
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n Notify Output Flush done");
+ BITMASK_CLEAR (&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
+ m_cb.EventHandler(&m_cmp,m_app_data,OMX_EventCmdComplete,OMX_CommandFlush,
+ OMX_CORE_OUTPUT_PORT_INDEX,NULL );
+ }
+ output_flush_progress = false;
+ return bRet;
+ }
+
+ DEBUG_PRINT_LOW("\n output buffers count = %d",pending_output_buffers);
+
+ if(flushType == 1)
+ {
+ /*Check if there are buffers with the Driver*/
+ DEBUG_PRINT_LOW("\n ioctl command flush for output");
+ ioctl_msg.inputparam = &flush_dir;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(driver_context.video_driver_fd,VDEC_IOCTL_CMD_FLUSH,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n output flush failed");
+ return false;
+ }
+ }
+
+ return bRet;
+}
+/*=========================================================================
+FUNCTION : execute_input_flush
+
+DESCRIPTION
+ Executes the OMX flush at INPUT PORT.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+==========================================================================*/
+bool omx_vdec::execute_input_flush(OMX_U32 flushType)
+{
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ enum vdec_bufferflush flush_dir = VDEC_FLUSH_TYPE_INPUT;
+ unsigned i =0;
+ unsigned p1 = 0; // Parameter - 1
+ unsigned p2 = 0; // Parameter - 2
+ unsigned ident = 0;
+ bool bRet = true;
+
+ /*Generate EBD for all Buffers in the ETBq*/
+ DEBUG_PRINT_LOW("\n Initiate Input Flush \n");
+
+ pthread_mutex_lock(&m_lock);
+ DEBUG_PRINT_LOW("\n Check if the Queue is empty \n");
+ while (m_etb_q.m_size)
+ {
+ m_etb_q.pop_entry(&p1,&p2,&ident);
+
+ if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)
+ {
+ DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
+ m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
+ }
+ else if(ident == OMX_COMPONENT_GENERATE_ETB)
+ {
+ pending_input_buffers++;
+ empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
+ }
+ else if (ident == OMX_COMPONENT_GENERATE_EBD)
+ {
+ empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
+ }
+ }
+
+ /*Check if Heap Buffers are to be flushed*/
+ if (arbitrary_bytes)
+ {
+ DEBUG_PRINT_LOW("\n Reset all the variables before flusing");
+ h264_scratch.nFilledLen = 0;
+ nal_count = 0;
+ look_ahead_nal = false;
+ frame_count = 0;
+ DEBUG_PRINT_LOW("\n Initialize parser");
+ if (m_frame_parser.mutils)
+ {
+ m_frame_parser.mutils->initialize_frame_checking_environment();
+ }
+
+ while (m_input_pending_q.m_size)
+ {
+ m_input_pending_q.pop_entry(&p1,&p2,&ident);
+ m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
+ }
+
+ if (psource_frame)
+ {
+ m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
+ psource_frame = NULL;
+ }
+
+ if (pdest_frame)
+ {
+ pdest_frame->nFilledLen = 0;
+ m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
+ pdest_frame = NULL;
+ }
+ m_frame_parser.flush();
+ }
+
+ pthread_mutex_unlock(&m_lock);
+ DEBUG_PRINT_LOW("\n Value of pending input buffers %d \n",pending_input_buffers);
+
+ if(flushType == 0)
+ {
+ /*Check if there are buffers with the Driver*/
+ DEBUG_PRINT_LOW("\n Input Flush ioctl issued");
+ ioctl_msg.inputparam = &flush_dir;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(driver_context.video_driver_fd,VDEC_IOCTL_CMD_FLUSH,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Input Flush Failed ");
+ return false;
+ }
+ }
+
+ return bRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SendCommandEvent
+
+DESCRIPTION
+ Send the event to decoder pipe. This is needed to generate the callbacks
+ in decoder thread context.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::post_event(unsigned int p1,
+ unsigned int p2,
+ unsigned int id)
+{
+ bool bRet = false;
+
+
+ pthread_mutex_lock(&m_lock);
+
+ if( id == OMX_COMPONENT_GENERATE_FTB || \
+ (id == OMX_COMPONENT_GENERATE_FBD)||
+ (id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH))
+ {
+ m_ftb_q.insert_entry(p1,p2,id);
+ }
+ else if((id == OMX_COMPONENT_GENERATE_ETB) \
+ || (id == OMX_COMPONENT_GENERATE_EBD)||
+ (id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY)||
+ (id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH))
+ {
+ m_etb_q.insert_entry(p1,p2,id);
+ }
+ else
+ {
+ m_cmd_q.insert_entry(p1,p2,id);
+ }
+
+ bRet = true;
+ DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this);
+ post_message(this, id);
+
+ pthread_mutex_unlock(&m_lock);
+
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetParameter
+
+DESCRIPTION
+ OMX Get Parameter method implementation
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_INOUT OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned int height=0,width = 0;
+
+ DEBUG_PRINT_LOW("get_parameter: \n");
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Get Param in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if(paramData == NULL)
+ {
+ DEBUG_PRINT_LOW("Get Param in Invalid paramData \n");
+ return OMX_ErrorBadParameter;
+ }
+ switch(paramIndex)
+ {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n");
+
+ portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
+ portDefn->nSize = sizeof(portDefn);
+ portDefn->eDomain = OMX_PortDomainVideo;
+ portDefn->format.video.nFrameHeight = m_crop_dy;
+ portDefn->format.video.nFrameWidth = m_crop_dx;
+ portDefn->format.video.nStride = m_width;
+ portDefn->format.video.nSliceHeight = m_height;
+ portDefn->format.video.xFramerate= 25;
+
+ if (0 == portDefn->nPortIndex)
+ {
+ portDefn->eDir = OMX_DirInput;
+ /*Actual count is based on input buffer count*/
+ portDefn->nBufferCountActual = m_inp_buf_count;
+ /*Set the Min count*/
+ portDefn->nBufferCountMin = m_inp_buf_count_min;
+ portDefn->nBufferSize = m_inp_buf_size;
+ portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ portDefn->format.video.eCompressionFormat = eCompressionFormat;
+ portDefn->bEnabled = m_inp_bEnabled;
+ portDefn->bPopulated = m_inp_bPopulated;
+ }
+ else if (1 == portDefn->nPortIndex)
+ {
+ m_out_buf_count = m_out_buf_count_recon;
+ m_out_buf_count_min = m_out_buf_count_min_recon;
+ m_out_buf_size = m_out_buf_size_recon;
+ portDefn->eDir = OMX_DirOutput;
+ portDefn->nBufferCountActual = m_out_buf_count;
+ portDefn->nBufferCountMin = m_out_buf_count_min;
+ portDefn->nBufferSize = m_out_buf_size;
+ portDefn->bEnabled = m_out_bEnabled;
+ portDefn->bPopulated = m_out_bPopulated;
+ height = driver_context.video_resoultion.frame_height;
+ width = driver_context.video_resoultion.frame_width;
+
+ portDefn->format.video.nFrameHeight = height;
+ portDefn->format.video.nFrameWidth = width;
+ portDefn->format.video.nStride = stride;
+ portDefn->format.video.nSliceHeight = scan_lines;
+ DEBUG_PRINT_LOW("\n Get Param Slice Height %d Slice Width %d",
+ scan_lines,stride);
+ //TODO: Need to add color format
+ portDefn->format.video.eColorFormat = m_color_format;
+ portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ DEBUG_PRINT_LOW("\n Output Actual %d Output Min %d",
+ portDefn->nBufferCountActual,portDefn->nBufferCountMin);
+ }
+ else
+ {
+ portDefn->eDir = OMX_DirMax;
+ DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+ case OMX_IndexParamVideoInit:
+ {
+ OMX_PORT_PARAM_TYPE *portParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n");
+
+ portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ portParamType->nSize = sizeof(portParamType);
+ portParamType->nPorts = 2;
+ portParamType->nStartPortNumber = 0;
+ break;
+ }
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n");
+
+ portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
+ portFmt->nSize = sizeof(portFmt);
+
+ if (0 == portFmt->nPortIndex)
+ {
+ if (0 == portFmt->nIndex)
+ {
+ portFmt->eColorFormat = OMX_COLOR_FormatUnused;
+ portFmt->eCompressionFormat = eCompressionFormat;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
+ " NoMore compression formats\n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if (1 == portFmt->nPortIndex)
+ {
+ if (0 == portFmt->nIndex)
+ {
+ if (driver_context.output_format == VDEC_YUV_FORMAT_NV12)
+ portFmt->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ else
+ portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)0x7F000000;
+
+ portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
+ " NoMore Color formats\n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n",
+ (int)portFmt->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamAudioInit:
+ {
+ OMX_PORT_PARAM_TYPE *audioPortParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n");
+ audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ audioPortParamType->nSize = sizeof(audioPortParamType);
+ audioPortParamType->nPorts = 0;
+ audioPortParamType->nStartPortNumber = 0;
+ break;
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamImageInit:
+ {
+ OMX_PORT_PARAM_TYPE *imagePortParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n");
+ imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ imagePortParamType->nSize = sizeof(imagePortParamType);
+ imagePortParamType->nPorts = 0;
+ imagePortParamType->nStartPortNumber = 0;
+ break;
+
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamOtherInit:
+ {
+ DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x\n",
+ paramIndex);
+ eRet =OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
+ comp_role->nSize = sizeof(*comp_role);
+
+ DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",
+ paramIndex);
+ strncpy((char*)comp_role->cRole,(const char*)m_cRole,
+ OMX_MAX_STRINGNAME_SIZE);
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamPriorityMgmt:
+ {
+
+ OMX_PRIORITYMGMTTYPE *priorityMgmType =
+ (OMX_PRIORITYMGMTTYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n");
+ priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
+ priorityMgmType->nSize = sizeof(priorityMgmType);
+
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
+ (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n");
+
+ bufferSupplierType->nSize = sizeof(bufferSupplierType);
+ bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
+ if(0 == bufferSupplierType->nPortIndex)
+ bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
+ else if (1 == bufferSupplierType->nPortIndex)
+ bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
+ else
+ eRet = OMX_ErrorBadPortIndex;
+
+
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x\n",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x\n",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x\n",
+ paramIndex);
+ break;
+ }
+ default:
+ {
+ DEBUG_PRINT_ERROR("get_parameter: unknown param %08x\n", paramIndex);
+ eRet =OMX_ErrorUnsupportedIndex;
+ }
+
+ }
+
+ DEBUG_PRINT_LOW("\n get_parameter returning Height %d , Width %d \n",
+ m_height, m_width);
+ return eRet;
+
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::Setparameter
+
+DESCRIPTION
+ OMX Set Parameter method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_IN OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned int alignment = 0,buffer_size = 0;
+ int i;
+
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Set Param in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if(paramData == NULL)
+ {
+ DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n");
+ return OMX_ErrorBadParameter;
+ }
+ switch(paramIndex)
+ {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+
+ /*set_parameter can be called in loaded state
+ or disabled port */
+
+ /* When the component is in Loaded state and IDLE Pending*/
+ if(((m_state == OMX_StateLoaded)&&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ /* Or while the I/P or the O/P port or disabled */
+ ||((OMX_DirInput == portDefn->eDir && m_inp_bEnabled == OMX_FALSE)||
+ (OMX_DirOutput == portDefn->eDir && m_out_bEnabled == OMX_FALSE)))
+ {
+ DEBUG_PRINT_LOW("Set Parameter called in valid state");
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
+ (int)portDefn->format.video.nFrameHeight,
+ (int)portDefn->format.video.nFrameWidth);
+
+ eRet = omx_vdec_validate_port_param(portDefn->format.video.nFrameHeight,
+ portDefn->format.video.nFrameWidth);
+ if(eRet != OMX_ErrorNone)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ if(OMX_DirOutput == portDefn->eDir)
+ {
+ if ( portDefn->nBufferCountActual < m_out_buf_count_min ||
+ portDefn->nBufferSize != m_out_buf_size
+ )
+ {
+ return OMX_ErrorBadParameter;
+ }
+ driver_context.output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.output_buffer;
+
+ if (ioctl (driver_context.video_driver_fd,
+ VDEC_IOCTL_GET_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Request output buffer requirements failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ driver_context.output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ driver_context.output_buffer.actualcount =
+ portDefn->nBufferCountActual;
+ ioctl_msg.inputparam = &driver_context.output_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (driver_context.video_driver_fd,
+ VDEC_IOCTL_SET_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Request output buffer requirements failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_out_buf_count = portDefn->nBufferCountActual;
+ m_out_buf_count_recon = m_out_buf_count;
+ DEBUG_PRINT_LOW("set_parameter:OMX_IndexParamPortDefinition output port\n");
+ }
+ else if(OMX_DirInput == portDefn->eDir)
+ {
+ if(m_height != portDefn->format.video.nFrameHeight ||
+ m_width != portDefn->format.video.nFrameWidth)
+ {
+ DEBUG_PRINT_LOW("set_parameter ip port: stride %d\n",
+ (int)portDefn->format.video.nStride);
+ // set the HxW only if non-zero
+ if((portDefn->format.video.nFrameHeight != 0x0)
+ && (portDefn->format.video.nFrameWidth != 0x0))
+ {
+ m_crop_x = m_crop_y = 0;
+ m_crop_dy = m_port_height = m_height =
+ portDefn->format.video.nFrameHeight;
+ m_crop_dx = m_port_width = m_width =
+ portDefn->format.video.nFrameWidth;
+ scan_lines = portDefn->format.video.nSliceHeight;
+ stride = portDefn->format.video.nStride;
+ DEBUG_PRINT_LOW("\n SetParam with new H %d and W %d\n",
+ m_height, m_width );
+ driver_context.video_resoultion.frame_height = m_height;
+ driver_context.video_resoultion.frame_width = m_width;
+ driver_context.video_resoultion.stride = stride;
+ driver_context.video_resoultion.scan_lines = scan_lines;
+ ioctl_msg.inputparam = &driver_context.video_resoultion;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_PICRES,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set Resolution failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ driver_context.output_buffer.buffer_type =
+ VDEC_BUFFER_TYPE_OUTPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.output_buffer;
+
+ if (ioctl (driver_context.video_driver_fd,
+ VDEC_IOCTL_GET_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Request output buffer requirements failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ m_out_buf_count_recon = m_out_buf_count = driver_context.output_buffer.actualcount;
+ m_out_buf_count_min_recon = m_out_buf_count_min = driver_context.output_buffer.mincount;
+
+ alignment = driver_context.output_buffer.alignment;
+ buffer_size = driver_context.output_buffer.buffer_size;
+ m_out_buf_size_recon = m_out_buf_size =
+ ((buffer_size + alignment - 1) & (~(alignment - 1)));
+ }
+ }
+ else
+ {
+ /*
+ If actual buffer count is greater than the Min buffer
+ count,change the actual count.
+ m_inp_buf_count is initialized to OMX_CORE_NUM_INPUT_BUFFERS
+ in the constructor
+ */
+ if ( portDefn->nBufferCountActual < m_inp_buf_count_min ||
+ portDefn->nBufferSize != m_inp_buf_size
+ )
+ {
+ return OMX_ErrorBadParameter;
+ }
+ /*Get the Buffer requirements for input and output ports*/
+ driver_context.input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.input_buffer;
+
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Request input buffer requirements failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ driver_context.input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ driver_context.input_buffer.actualcount =
+ portDefn->nBufferCountActual;
+ ioctl_msg.inputparam = &driver_context.input_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Request input buffer requirements failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ m_inp_buf_count = portDefn->nBufferCountActual;
+ DEBUG_PRINT_LOW("\n set_parameter: Image Dimensions same \n");
+ }
+
+ }
+ else if (portDefn->eDir == OMX_DirMax)
+ {
+ DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ }
+ break;
+
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
+ portFmt->eColorFormat);
+
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
+ portFmt->eColorFormat);
+ if(1 == portFmt->nPortIndex)
+ {
+
+ m_color_format = portFmt->eColorFormat;
+ }
+ }
+ break;
+
+ case OMX_QcomIndexPortDefn:
+ {
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
+ (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d\n",
+ portFmt->nFramePackingFormat);
+
+ /* Input port */
+ if (portFmt->nPortIndex == 0)
+ {
+ if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary)
+ {
+ arbitrary_bytes = true;
+ }
+ else if (portFmt->nFramePackingFormat ==
+ OMX_QCOM_FramePacking_OnlyOneCompleteFrame)
+ {
+ arbitrary_bytes = false;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %d\n",
+ portFmt->nFramePackingFormat);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ }
+ break;
+
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n",
+ comp_role->cRole);
+
+ if((m_state == OMX_StateLoaded)&&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ DEBUG_PRINT_LOW("Set Parameter called in valid state");
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown param %s\n", driver_context.kind);
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ break;
+ }
+
+ case OMX_IndexParamPriorityMgmt:
+ {
+ if(m_state != OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n",
+ priorityMgmtype->nGroupID);
+
+ DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n",
+ priorityMgmtype->nGroupPriority);
+
+ m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
+ m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
+
+ break;
+ }
+
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
+ bufferSupplierType->eBufferSupplier);
+ if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
+ m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
+
+ else
+
+ eRet = OMX_ErrorBadPortIndex;
+
+ break;
+
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d\n",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d\n",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d\n",
+ paramIndex);
+ break;
+ }
+
+ default:
+ {
+ DEBUG_PRINT_ERROR("Setparameter: unknown param %d\n", paramIndex);
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetConfig
+
+DESCRIPTION
+ OMX Get Config Method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_INOUT OMX_PTR configData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ switch (configIndex)
+ {
+ case OMX_QcomIndexConfigInterlaced:
+ {
+ OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
+ (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
+ if (configFmt->nPortIndex == 1)
+ {
+ if (configFmt->nIndex == 0)
+ {
+ configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
+ }
+ else if (configFmt->nIndex == 1)
+ {
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
+ }
+ else if (configFmt->nIndex == 2)
+ {
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
+ " NoMore Interlaced formats\n");
+ eRet = OMX_ErrorNoMore;
+ }
+
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port\n",
+ (int)configFmt->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_QcomIndexQueryNumberOfVideoDecInstance:
+ {
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
+ (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
+ ioctl_msg.outputparam = (void*)&decoderinstances->nNumOfInstances;
+ (void)(ioctl(driver_context.video_driver_fd,
+ VDEC_IOCTL_GET_NUMBER_INSTANCES,&ioctl_msg));
+ break;
+ }
+ default:
+ {
+ DEBUG_PRINT_ERROR("get_config: unknown param %d\n",configIndex);
+ eRet = OMX_ErrorBadParameter;
+ }
+
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SetConfig
+
+DESCRIPTION
+ OMX Set Config method implementation
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_IN OMX_PTR configData)
+{
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Get Config in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ OMX_VIDEO_CONFIG_NALSIZE *pNal;
+
+ DEBUG_PRINT_LOW("\n Set Config Called");
+
+ if (m_state == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n");
+ return ret;
+ }
+
+ if (configIndex == OMX_IndexVendorVideoExtraData)
+ {
+ OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData;
+ DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData called");
+ if (!strcmp(driver_context.kind, "OMX.qcom.video.decoder.avc"))
+ {
+ DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData AVC");
+ OMX_U32 extra_size;
+ // Parsing done here for the AVC atom is definitely not generic
+ // Currently this piece of code is working, but certainly
+ // not tested with all .mp4 files.
+ // Incase of failure, we might need to revisit this
+ // for a generic piece of code.
+
+ // Retrieve size of NAL length field
+ // byte #4 contains the size of NAL lenght field
+ nal_length = (config->pData[4] & 0x03) + 1;
+
+ extra_size = 0;
+ if (nal_length > 2)
+ {
+ /* Presently we assume that only one SPS and one PPS in AvC1 Atom */
+ extra_size = (nal_length - 2) * 2;
+ }
+
+ // SPS starts from byte #6
+ OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
+ OMX_U8 *pDestBuf;
+ m_vendor_config.nPortIndex = config->nPortIndex;
+
+ // minus 6 --> SPS starts from byte #6
+ // minus 1 --> picture param set byte to be ignored from avcatom
+ m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size;
+ m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize);
+ OMX_U32 len;
+ OMX_U8 index = 0;
+ // case where SPS+PPS is sent as part of set_config
+ pDestBuf = m_vendor_config.pData;
+
+ DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]\n",
+ m_vendor_config.nPortIndex,
+ m_vendor_config.nDataSize,
+ m_vendor_config.pData);
+ while (index < 2)
+ {
+ uint8 *psize;
+ len = *pSrcBuf;
+ len = len << 8;
+ len |= *(pSrcBuf + 1);
+ psize = (uint8 *) & len;
+ memcpy(pDestBuf + nal_length, pSrcBuf + 2,len);
+ for (int i = 0; i < nal_length; i++)
+ {
+ pDestBuf[i] = psize[nal_length - 1 - i];
+ }
+ //memcpy(pDestBuf,pSrcBuf,(len+2));
+ pDestBuf += len + nal_length;
+ pSrcBuf += len + 2;
+ index++;
+ pSrcBuf++; // skip picture param set
+ len = 0;
+ }
+ }
+ else if (!strcmp(driver_context.kind, "OMX.qcom.video.decoder.mpeg4"))
+ {
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize));
+ memcpy(m_vendor_config.pData, config->pData,config->nDataSize);
+ }
+ else if (!strcmp(driver_context.kind, "OMX.qcom.video.decoder.vc1"))
+ {
+ if(m_vendor_config.pData)
+ {
+ free(m_vendor_config.pData);
+ m_vendor_config.pData = NULL;
+ m_vendor_config.nDataSize = 0;
+ }
+
+ if (((*((OMX_U32 *) config->pData)) &
+ VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE)
+ {
+ DEBUG_PRINT_LOW("set_config - VC1 simple/main profile\n");
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc(config->nDataSize);
+ memcpy(m_vendor_config.pData, config->pData,
+ config->nDataSize);
+ m_vc1_profile = VC1_SP_MP_RCV;
+ }
+ else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE)
+ {
+ DEBUG_PRINT_LOW("set_config - VC1 Advance profile\n");
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData =
+ (OMX_U8 *) malloc((config->nDataSize));
+ memcpy(m_vendor_config.pData, config->pData,
+ config->nDataSize);
+ m_vc1_profile = VC1_AP;
+ }
+ else if ((config->nDataSize == VC1_STRUCT_C_LEN))
+ {
+ DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only\n");
+ m_vendor_config.nPortIndex = config->nPortIndex;
+ m_vendor_config.nDataSize = config->nDataSize;
+ m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
+ memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
+ m_vc1_profile = VC1_SP_MP_RCV;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile\n");
+ }
+ }
+ return ret;
+ }
+ else if (configIndex == OMX_IndexConfigVideoNalSize)
+ {
+
+ pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
+ nal_length = pNal->nNaluBytes;
+ m_frame_parser.init_nal_length(nal_length);
+ DEBUG_PRINT_LOW("\n Nal Length option called with Size %d",nal_length);
+ return ret;
+ }
+
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetExtensionIndex
+
+DESCRIPTION
+ OMX GetExtensionIndex method implementaion. <TBD>
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_STRING paramName,
+ OMX_OUT OMX_INDEXTYPE* indexType)
+{
+ DEBUG_PRINT_ERROR("get_extension_index: Error, Not implemented\n");
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::GetState
+
+DESCRIPTION
+ Returns the state information back to the caller.<TBD>
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Error None if everything is successful.
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_STATETYPE* state)
+{
+ *state = m_state;
+ DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentTunnelRequest
+
+DESCRIPTION
+ OMX Component Tunnel Request method implementation. <TBD>
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_HANDLETYPE peerComponent,
+ OMX_IN OMX_U32 peerPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
+{
+ DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n");
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseInputBuffer
+
+DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_input_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct vdec_setbuffer_cmd setbuffers;
+ OMX_BUFFERHEADERTYPE *input = NULL;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned i = 0;
+ unsigned char *buf_addr = NULL;
+ int pmem_fd = -1;
+
+ if(bytes != m_inp_buf_size)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ if(!m_inp_mem_ptr)
+ {
+ DEBUG_PRINT_HIGH("\n Use i/p buffer case - Header List allocation");
+ input_use_buffer = true;
+ m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_inp_buf_count);
+
+ if (m_inp_mem_ptr == NULL)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ driver_context.ptr_inputbuffer = (struct vdec_bufferpayload *) \
+ calloc ((sizeof (struct vdec_bufferpayload)),m_inp_buf_count);
+
+ if (driver_context.ptr_inputbuffer == NULL)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ for (i=0; i < m_inp_buf_count; i++)
+ {
+ driver_context.ptr_inputbuffer [i].pmem_fd = -1;
+ }
+ }
+
+ for(i=0; i< m_inp_buf_count; i++)
+ {
+ if(BITMASK_ABSENT(&m_inp_bm_count,i))
+ {
+ break;
+ }
+ }
+
+ if(i < m_inp_buf_count)
+ {
+ pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (pmem_fd < 0)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if(pmem_fd == 0)
+ {
+ pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+ if (pmem_fd < 0)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if(!align_pmem_buffers(pmem_fd, m_inp_buf_size,
+ driver_context.input_buffer.alignment))
+ {
+ DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
+ close(pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ buf_addr = (unsigned char *)mmap(NULL,m_inp_buf_size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,pmem_fd,0);
+
+ if (buf_addr == MAP_FAILED)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ driver_context.ptr_inputbuffer [i].bufferaddr = buf_addr;
+ driver_context.ptr_inputbuffer [i].pmem_fd = pmem_fd;
+ driver_context.ptr_inputbuffer [i].mmaped_size = m_inp_buf_size;
+ driver_context.ptr_inputbuffer [i].offset = 0;
+
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ memcpy (&setbuffers.buffer,&driver_context.ptr_inputbuffer [i],
+ sizeof (vdec_bufferpayload));
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ *bufferHdr = (m_inp_mem_ptr + i);
+ input = *bufferHdr;
+ BITMASK_SET(&m_inp_bm_count,i);
+
+ input->pBuffer = (OMX_U8 *)buffer;
+ input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ input->nVersion.nVersion = OMX_SPEC_VERSION;
+ input->nAllocLen = m_inp_buf_size;
+ input->pAppPrivate = appData;
+ input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
+ input->pInputPortPrivate = (void *)&driver_context.ptr_inputbuffer [i];
+ }
+ else
+ {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseOutputBuffer
+
+DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_output_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
+ unsigned i= 0; // Temporary counter
+
+ if(!m_out_mem_ptr)
+ {
+ DEBUG_PRINT_HIGH("\n Use o/p buffer case - Header List allocation");
+ output_use_buffer = true;
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_out_buf_count);
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+
+ nPMEMInfoSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+
+ DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize,
+ sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize,
+ nPlatformListSize);
+ DEBUG_PRINT_LOW("PE %d bmSize %d \n",nPlatformEntrySize,
+ m_out_bm_count);
+
+ /*
+ * Memory for output side involves the following:
+ * 1. Array of Buffer Headers
+ * 2. Platform specific information List
+ * 3. Platform specific Entry List
+ * 4. PMem Information entries
+ * 5. Bitmask array to hold the buffer allocation details
+ * In order to minimize the memory management entire allocation
+ * is done in one step.
+ */
+ m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
+ // Alloc mem for platform specific info
+ char *pPtr=NULL;
+ pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize,1);
+ driver_context.ptr_outputbuffer = (struct vdec_bufferpayload *) \
+ calloc (sizeof(struct vdec_bufferpayload),m_out_buf_count);
+ driver_context.ptr_respbuffer = (struct vdec_output_frameinfo *)\
+ calloc (sizeof (struct vdec_output_frameinfo),m_out_buf_count);
+
+ if(m_out_mem_ptr && pPtr && driver_context.ptr_outputbuffer
+ && driver_context.ptr_respbuffer)
+ {
+ bufHdr = m_out_mem_ptr;
+ m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
+ m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *) m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *) m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+
+ DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr, m_out_mem_ptr,pPlatformEntry);
+ DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo);
+ for(i=0; i < m_out_buf_count ; i++)
+ {
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = bytes;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ // Platform specific PMEM Information
+ // Initialize the Platform Entry
+ //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d\n",i);
+ pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+ // Keep pBuffer NULL till vdec is opened
+ bufHdr->pBuffer = NULL;
+
+ pPMEMInfo->offset = 0;
+ pPMEMInfo->pmem_fd = 0;
+ bufHdr->pPlatformPrivate = pPlatformList;
+
+ driver_context.ptr_outputbuffer[i].pmem_fd = -1;
+
+ /*Create a mapping between buffers*/
+ bufHdr->pOutputPortPrivate = &driver_context.ptr_respbuffer[i];
+ driver_context.ptr_respbuffer[i].client_data = (void *) \
+ &driver_context.ptr_outputbuffer[i];
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\
+ m_out_mem_ptr, pPtr);
+ if(m_out_mem_ptr)
+ {
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if(pPtr)
+ {
+ free(pPtr);
+ pPtr = NULL;
+ }
+ if(driver_context.ptr_outputbuffer)
+ {
+ free(driver_context.ptr_outputbuffer);
+ driver_context.ptr_outputbuffer = NULL;
+ }
+ if(driver_context.ptr_respbuffer)
+ {
+ free(driver_context.ptr_respbuffer);
+ driver_context.ptr_respbuffer = NULL;
+ }
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ for(i=0; i< m_out_buf_count; i++)
+ {
+ if(BITMASK_ABSENT(&m_out_bm_count,i))
+ {
+ break;
+ }
+ }
+
+ if (eRet == OMX_ErrorNone)
+ {
+ if(i < m_out_buf_count)
+ {
+ driver_context.ptr_outputbuffer[i].pmem_fd = \
+ open ("/dev/pmem_adsp",O_RDWR);
+
+ if (driver_context.ptr_outputbuffer[i].pmem_fd < 0)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if(driver_context.ptr_outputbuffer[i].pmem_fd == 0)
+ {
+ driver_context.ptr_outputbuffer[i].pmem_fd = \
+ open ("/dev/pmem_adsp",O_RDWR);
+
+ if (driver_context.ptr_outputbuffer[i].pmem_fd < 0)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if(!align_pmem_buffers(driver_context.ptr_outputbuffer[i].pmem_fd,
+ m_out_buf_size, driver_context.output_buffer.alignment))
+ {
+ DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
+ close(driver_context.ptr_outputbuffer[i].pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ driver_context.ptr_outputbuffer[i].bufferaddr =
+ (unsigned char *)mmap(NULL,m_out_buf_size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,driver_context.ptr_outputbuffer[i].pmem_fd,0);
+
+ if (driver_context.ptr_outputbuffer[i].bufferaddr == MAP_FAILED)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+ driver_context.ptr_outputbuffer[i].offset = 0;
+ m_pmem_info[i].offset = driver_context.ptr_outputbuffer[i].offset;
+ m_pmem_info[i].pmem_fd = driver_context.ptr_outputbuffer[i].pmem_fd;
+
+ // found an empty buffer at i
+ *bufferHdr = (m_out_mem_ptr + i );
+ (*bufferHdr)->pBuffer = buffer;
+ (*bufferHdr)->pAppPrivate = appData;
+ BITMASK_SET(&m_out_bm_count,i);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient \n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseBuffer
+
+DESCRIPTION
+ OMX Use Buffer method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None , if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Use Buffer in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if(port == OMX_CORE_INPUT_PORT_INDEX)
+ {
+ eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
+ }
+ else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
+ {
+ eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, eRet);
+
+ if(eRet == OMX_ErrorNone)
+ {
+ if(allocate_done())
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet,OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ }
+ else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ return eRet;
+}
+
+OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
+{
+ unsigned int index = 0;
+
+ if (bufferHdr == NULL || m_inp_mem_ptr == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ index = bufferHdr - m_inp_mem_ptr;
+ DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index);
+
+ if (index < m_inp_buf_count && driver_context.ptr_inputbuffer)
+ {
+ DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index);
+ if (driver_context.ptr_inputbuffer[index].pmem_fd > 0)
+ {
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct vdec_setbuffer_cmd setbuffers;
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ memcpy (&setbuffers.buffer,&driver_context.ptr_inputbuffer[index],
+ sizeof (vdec_bufferpayload));
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+ int ioctl_r = ioctl (driver_context.video_driver_fd,
+ VDEC_IOCTL_FREE_BUFFER, &ioctl_msg);
+ if (ioctl_r < 0)
+ {
+ DEBUG_PRINT_ERROR("\nVDEC_IOCTL_FREE_BUFFER returned error %d", ioctl_r);
+ }
+
+ DEBUG_PRINT_LOW("\n unmap the input buffer fd=%d",
+ driver_context.ptr_inputbuffer[index].pmem_fd);
+ DEBUG_PRINT_LOW("\n unmap the input buffer size=%d address = %d",
+ driver_context.ptr_inputbuffer[index].mmaped_size,
+ driver_context.ptr_inputbuffer[index].bufferaddr);
+ munmap (driver_context.ptr_inputbuffer[index].bufferaddr,
+ driver_context.ptr_inputbuffer[index].mmaped_size);
+ close (driver_context.ptr_inputbuffer[index].pmem_fd);
+ driver_context.ptr_inputbuffer[index].pmem_fd = -1;
+ }
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
+{
+ unsigned int index = 0;
+
+ if (bufferHdr == NULL || m_out_mem_ptr == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ index = bufferHdr - m_out_mem_ptr;
+ DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d",index);
+
+ if (index < m_out_buf_count && driver_context.ptr_outputbuffer)
+ {
+ DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d addr = %x", index,
+ driver_context.ptr_outputbuffer[index].bufferaddr);
+
+ if (!gate_output_buffers)
+ {
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct vdec_setbuffer_cmd setbuffers;
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ memcpy (&setbuffers.buffer,&driver_context.ptr_outputbuffer[index],
+ sizeof (vdec_bufferpayload));
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+ DEBUG_PRINT_LOW("\nRelease the Output Buffer");
+ if (ioctl (driver_context.video_driver_fd, VDEC_IOCTL_FREE_BUFFER,
+ &ioctl_msg) < 0)
+ DEBUG_PRINT_ERROR("\nRelease output buffer failed in VCD");
+ }
+
+ if (driver_context.ptr_outputbuffer[0].pmem_fd > 0)
+ {
+ DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d",
+ driver_context.ptr_outputbuffer[0].pmem_fd);
+ DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %d",
+ driver_context.ptr_outputbuffer[0].mmaped_size,
+ driver_context.ptr_outputbuffer[0].bufferaddr);
+ munmap (driver_context.ptr_outputbuffer[0].bufferaddr,
+ driver_context.ptr_outputbuffer[0].mmaped_size);
+ close (driver_context.ptr_outputbuffer[0].pmem_fd);
+ driver_context.ptr_outputbuffer[0].pmem_fd = -1;
+ }
+ }
+
+ return OMX_ErrorNone;
+
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes)
+{
+ OMX_BUFFERHEADERTYPE *input = NULL;
+ unsigned char *buf_addr = NULL;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned i = 0;
+
+ /* Sanity Check*/
+ if (bufferHdr == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_inp_heap_ptr == NULL)
+ {
+ m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_inp_buf_count);
+ m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), m_inp_buf_count);
+
+ if (m_inp_heap_ptr == NULL)
+ {
+ DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ h264_scratch.nAllocLen = m_inp_buf_size;
+ h264_scratch.pBuffer = (OMX_U8 *)malloc (m_inp_buf_size);
+ h264_scratch.nFilledLen = 0;
+ h264_scratch.nOffset = 0;
+
+ if (h264_scratch.pBuffer == NULL)
+ {
+ DEBUG_PRINT_ERROR("\n h264_scratch.pBuffer Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (m_frame_parser.mutils == NULL)
+ {
+ m_frame_parser.mutils = new H264_Utils();
+
+ if (m_frame_parser.mutils == NULL)
+ {
+ DEBUG_PRINT_ERROR("\n parser utils Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ m_frame_parser.mutils->initialize_frame_checking_environment();
+ m_frame_parser.mutils->allocate_rbsp_buffer (m_inp_buf_size);
+ }
+ }
+
+ /*Find a Free index*/
+ for(i=0; i< m_inp_buf_count; i++)
+ {
+ if(BITMASK_ABSENT(&m_heap_inp_bm_count,i))
+ {
+ DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i);
+ break;
+ }
+ }
+
+ if (i < m_inp_buf_count)
+ {
+ buf_addr = (unsigned char *)malloc (m_inp_buf_size);
+
+ if (buf_addr == NULL)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ *bufferHdr = (m_inp_heap_ptr + i);
+ input = *bufferHdr;
+ BITMASK_SET(&m_heap_inp_bm_count,i);
+
+ input->pBuffer = (OMX_U8 *)buf_addr;
+ input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ input->nVersion.nVersion = OMX_SPEC_VERSION;
+ input->nAllocLen = m_inp_buf_size;
+ input->pAppPrivate = appData;
+ input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
+ DEBUG_PRINT_LOW("\n Address of Heap Buffer %p",*bufferHdr );
+ eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
+ DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",m_phdr_pmem_ptr [i] );
+ /*Add the Buffers to freeq*/
+ if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr [i],NULL,NULL))
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Free_q is full");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ return eRet;
+
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateInputBuffer
+
+DESCRIPTION
+ Helper function for allocate buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct vdec_setbuffer_cmd setbuffers;
+ OMX_BUFFERHEADERTYPE *input = NULL;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned i = 0;
+ unsigned char *buf_addr = NULL;
+ int pmem_fd = -1;
+
+ if(bytes != m_inp_buf_size)
+ {
+ DEBUG_PRINT_LOW("\n Requested Size is wrong %d epected is %d",bytes,m_inp_buf_size);
+ //return OMX_ErrorBadParameter;
+ }
+
+ if(!m_inp_mem_ptr)
+ {
+ DEBUG_PRINT_HIGH("\n Allocate i/p buffer case - Header List allocation");
+ DEBUG_PRINT_LOW("\n Allocating input buffer count %d ",m_inp_buf_count);
+ DEBUG_PRINT_LOW("\n Size of input buffer is %d",m_inp_buf_size);
+
+ m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_inp_buf_count);
+
+ if (m_inp_mem_ptr == NULL)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ driver_context.ptr_inputbuffer = (struct vdec_bufferpayload *) \
+ calloc ((sizeof (struct vdec_bufferpayload)),m_inp_buf_count);
+
+ if (driver_context.ptr_inputbuffer == NULL)
+ {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ for (i=0; i < m_inp_buf_count; i++)
+ {
+ driver_context.ptr_inputbuffer [i].pmem_fd = -1;
+ }
+ }
+
+ for(i=0; i< m_inp_buf_count; i++)
+ {
+ if(BITMASK_ABSENT(&m_inp_bm_count,i))
+ {
+ DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i);
+ break;
+ }
+ }
+
+ if(i < m_inp_buf_count)
+ {
+ DEBUG_PRINT_LOW("\n Allocate input Buffer");
+ pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (pmem_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (pmem_fd == 0)
+ {
+ pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (pmem_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if(!align_pmem_buffers(pmem_fd, m_inp_buf_size,
+ driver_context.input_buffer.alignment))
+ {
+ DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
+ close(pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ buf_addr = (unsigned char *)mmap(NULL,m_inp_buf_size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,pmem_fd,0);
+
+ if (buf_addr == MAP_FAILED)
+ {
+ DEBUG_PRINT_ERROR("\n Map Failed to allocate input buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ driver_context.ptr_inputbuffer [i].bufferaddr = buf_addr;
+ driver_context.ptr_inputbuffer [i].pmem_fd = pmem_fd;
+ driver_context.ptr_inputbuffer [i].buffer_len = m_inp_buf_size;
+ driver_context.ptr_inputbuffer [i].mmaped_size = m_inp_buf_size;
+ driver_context.ptr_inputbuffer [i].offset = 0;
+
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ memcpy (&setbuffers.buffer,&driver_context.ptr_inputbuffer [i],
+ sizeof (vdec_bufferpayload));
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set Buffers Failed");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ *bufferHdr = (m_inp_mem_ptr + i);
+ input = *bufferHdr;
+ BITMASK_SET(&m_inp_bm_count,i);
+ DEBUG_PRINT_LOW("\n Buffer address %p of pmem",*bufferHdr);
+
+ input->pBuffer = (OMX_U8 *)buf_addr;
+ input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ input->nVersion.nVersion = OMX_SPEC_VERSION;
+ input->nAllocLen = m_inp_buf_size;
+ input->pAppPrivate = appData;
+ input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
+ input->pInputPortPrivate = (void *)&driver_context.ptr_inputbuffer [i];
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Input Buffer Index not found");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateOutputBuffer
+
+DESCRIPTION
+ Helper fn for AllocateBuffer in the output pin
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything went well.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
+ unsigned i= 0; // Temporary counter
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct vdec_setbuffer_cmd setbuffers;
+
+ if(!m_out_mem_ptr)
+ {
+ DEBUG_PRINT_HIGH("\n Allocate o/p buffer case - Header List allocation");
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ int pmem_fd = -1;
+ unsigned char *pmem_baseaddress = NULL;
+
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_out_buf_count);
+ nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
+
+ nPMEMInfoSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = m_out_buf_count *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+
+ DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize,
+ sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize,
+ nPlatformListSize);
+ DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d \n",nPlatformEntrySize,
+ m_out_buf_count);
+
+ pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (pmem_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d",m_out_buf_size);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if(pmem_fd == 0)
+ {
+ pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (pmem_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d",m_out_buf_size);
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if(!align_pmem_buffers(pmem_fd, m_out_buf_size * m_out_buf_count,
+ driver_context.output_buffer.alignment))
+ {
+ DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed");
+ close(pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ pmem_baseaddress = (unsigned char *)mmap(NULL,(m_out_buf_size * m_out_buf_count),
+ PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
+ m_heap_ptr = new VideoHeap (pmem_fd,
+ m_out_buf_size*m_out_buf_count,
+ pmem_baseaddress);
+
+
+ if (pmem_baseaddress == MAP_FAILED)
+ {
+ DEBUG_PRINT_ERROR("\n MMAP failed for Size %d",m_out_buf_size);
+ return OMX_ErrorInsufficientResources;
+ }
+ m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
+ // Alloc mem for platform specific info
+ char *pPtr=NULL;
+ pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize,1);
+ driver_context.ptr_outputbuffer = (struct vdec_bufferpayload *) \
+ calloc (sizeof(struct vdec_bufferpayload),m_out_buf_count);
+ driver_context.ptr_respbuffer = (struct vdec_output_frameinfo *)\
+ calloc (sizeof (struct vdec_output_frameinfo),m_out_buf_count);
+
+ if(m_out_mem_ptr && pPtr && driver_context.ptr_outputbuffer
+ && driver_context.ptr_respbuffer)
+ {
+ driver_context.ptr_outputbuffer[0].mmaped_size =
+ (m_out_buf_size * m_out_buf_count);
+ bufHdr = m_out_mem_ptr;
+ m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
+ m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *) m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *) m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+
+ DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr, m_out_mem_ptr,pPlatformEntry);
+ DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo);
+ for(i=0; i < m_out_buf_count ; i++)
+ {
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = bytes;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ // Platform specific PMEM Information
+ // Initialize the Platform Entry
+ //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d\n",i);
+ pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+ // Keep pBuffer NULL till vdec is opened
+ bufHdr->pBuffer = NULL;
+ bufHdr->nOffset = 0;
+
+ pPMEMInfo->offset = m_out_buf_size*i;
+ pPMEMInfo->pmem_fd = 0;
+ bufHdr->pPlatformPrivate = pPlatformList;
+
+ driver_context.ptr_outputbuffer[i].pmem_fd = pmem_fd;
+
+ /*Create a mapping between buffers*/
+ bufHdr->pOutputPortPrivate = &driver_context.ptr_respbuffer[i];
+ driver_context.ptr_respbuffer[i].client_data = (void *) \
+ &driver_context.ptr_outputbuffer[i];
+ driver_context.ptr_outputbuffer[i].offset = m_out_buf_size*i;
+ driver_context.ptr_outputbuffer[i].bufferaddr = \
+ pmem_baseaddress + (m_out_buf_size*i);
+
+ DEBUG_PRINT_LOW("\n pmem_fd = %d offset = %d address = %p",\
+ pmem_fd,driver_context.ptr_outputbuffer[i].offset,driver_context.ptr_outputbuffer[i].bufferaddr);
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\
+ m_out_mem_ptr, pPtr);
+ if(m_out_mem_ptr)
+ {
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if(pPtr)
+ {
+ free(pPtr);
+ pPtr = NULL;
+ }
+ if(driver_context.ptr_outputbuffer)
+ {
+ free(driver_context.ptr_outputbuffer);
+ driver_context.ptr_outputbuffer = NULL;
+ }
+ if(driver_context.ptr_respbuffer)
+ {
+ free(driver_context.ptr_respbuffer);
+ driver_context.ptr_respbuffer = NULL;
+ }
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ for(i=0; i< m_out_buf_count; i++)
+ {
+ if(BITMASK_ABSENT(&m_out_bm_count,i))
+ {
+ DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i);
+ break;
+ }
+ }
+
+ if (eRet == OMX_ErrorNone)
+ {
+ if(i < m_out_buf_count)
+ {
+ m_pmem_info[i].offset = driver_context.ptr_outputbuffer[i].offset;
+ m_pmem_info[i].pmem_fd = (OMX_U32) m_heap_ptr.get ();
+ driver_context.ptr_outputbuffer[i].buffer_len = m_out_buf_size;
+ //driver_context.ptr_outputbuffer[i].mmaped_size = m_out_buf_size;
+ if(!gate_output_buffers)
+ {
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ memcpy (&setbuffers.buffer,&driver_context.ptr_outputbuffer [i],
+ sizeof (vdec_bufferpayload));
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("\n Set the Output Buffer");
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set output buffer failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ // found an empty buffer at i
+ *bufferHdr = (m_out_mem_ptr + i );
+ (*bufferHdr)->pBuffer = driver_context.ptr_outputbuffer[i].bufferaddr;
+ (*bufferHdr)->pAppPrivate = appData;
+ BITMASK_SET(&m_out_bm_count,i);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient \n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ return eRet;
+}
+
+
+// AllocateBuffer -- API Call
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateBuffer
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+ unsigned i = 0;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
+
+ DEBUG_PRINT_LOW("\n Allocate buffer on port %d \n", (int)port);
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if(port == OMX_CORE_INPUT_PORT_INDEX)
+ {
+ if (arbitrary_bytes)
+ {
+ eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
+ }
+ else
+ {
+ eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
+ }
+ }
+ else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
+ {
+ eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
+ if(eRet == OMX_ErrorNone)
+ {
+ if(allocate_done()){
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet,OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet);
+ return eRet;
+}
+
+// Free Buffer - API call
+/* ======================================================================
+FUNCTION
+ omx_vdec::FreeBuffer
+
+DESCRIPTION
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned int nPortIndex;
+
+ DEBUG_PRINT_LOW("In for decoder free_buffer \n");
+
+ if(m_state == OMX_StateIdle &&
+ (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
+ {
+ DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n");
+ }
+ else if((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
+ (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX))
+ {
+ DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port);
+ }
+ else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled\n");
+ post_event(OMX_EventError,
+ OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ return eRet;
+ }
+ else if (m_state != OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers\n");
+ post_event(OMX_EventError,
+ OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ if(port == OMX_CORE_INPUT_PORT_INDEX)
+ {
+ /*Check if arbitrary bytes*/
+ if (!arbitrary_bytes)
+ {
+ // check if the buffer is valid
+ nPortIndex = buffer - m_inp_mem_ptr;
+ }
+ else
+ {
+ nPortIndex = buffer - m_inp_heap_ptr;
+ }
+
+ DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d \n", nPortIndex);
+ if(nPortIndex < m_inp_buf_count)
+ {
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
+
+ if (arbitrary_bytes)
+ {
+ if (m_inp_heap_ptr[nPortIndex].pBuffer)
+ {
+ BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
+ DEBUG_PRINT_LOW("\n Free Heap Buffer index %d",nPortIndex);
+ free (m_inp_heap_ptr[nPortIndex].pBuffer);
+ m_inp_heap_ptr[nPortIndex].pBuffer = NULL;
+ }
+ if (m_phdr_pmem_ptr[nPortIndex])
+ {
+ DEBUG_PRINT_LOW("\n Free pmem Buffer index %d",nPortIndex);
+ free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
+ }
+ }
+ else
+ {
+ free_input_buffer(buffer);
+ }
+
+ m_inp_bPopulated = OMX_FALSE;
+
+ /*Free the Buffer Header*/
+ if (release_input_done())
+ {
+ DEBUG_PRINT_HIGH("\n ALL input buffers are freed/released");
+ input_use_buffer = false;
+ if (arbitrary_bytes)
+ {
+ if (m_frame_parser.mutils)
+ {
+ DEBUG_PRINT_LOW("\n Free utils parser");
+ delete (m_frame_parser.mutils);
+ m_frame_parser.mutils = NULL;
+ }
+
+ if (m_inp_heap_ptr)
+ {
+ DEBUG_PRINT_LOW("\n Free input Heap Pointer");
+ free (m_inp_heap_ptr);
+ m_inp_heap_ptr = NULL;
+ }
+
+ if (m_phdr_pmem_ptr)
+ {
+ DEBUG_PRINT_LOW("\n Free input pmem header Pointer");
+ free (m_phdr_pmem_ptr);
+ m_phdr_pmem_ptr = NULL;
+ }
+ }
+ if (m_inp_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("\n Free input pmem Pointer area");
+ free (m_inp_mem_ptr);
+ m_inp_mem_ptr = NULL;
+ }
+
+ if (driver_context.ptr_inputbuffer)
+ {
+ DEBUG_PRINT_LOW("\n Free Driver Context pointer");
+ free (driver_context.ptr_inputbuffer);
+ driver_context.ptr_inputbuffer = NULL;
+ }
+ }
+
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
+ && release_input_done())
+ {
+ DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
+ {
+ // check if the buffer is valid
+ nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
+ if(nPortIndex < m_out_buf_count)
+ {
+ DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d \n", nPortIndex);
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
+ m_out_bPopulated = OMX_FALSE;
+ free_output_buffer (buffer);
+
+ if (release_output_done())
+ {
+ DEBUG_PRINT_HIGH("\n ALL output buffers are freed/released");
+ output_use_buffer = false;
+ if (m_out_mem_ptr)
+ {
+ free (m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if (driver_context.ptr_respbuffer)
+ {
+ free (driver_context.ptr_respbuffer);
+ driver_context.ptr_respbuffer = NULL;
+ }
+ if (driver_context.ptr_outputbuffer)
+ {
+ free (driver_context.ptr_outputbuffer);
+ driver_context.ptr_outputbuffer = NULL;
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
+ && release_output_done() )
+ {
+ DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n");
+
+ DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ else
+ {
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if((eRet == OMX_ErrorNone) &&
+ (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
+ {
+ if(release_done())
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateLoaded,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::EmptyThisBuffer
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_ERRORTYPE ret1 = OMX_ErrorNone;
+ unsigned int nBufferIndex = m_inp_buf_count;
+
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (buffer == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:ETB Buffer is NULL");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (arbitrary_bytes)
+ {
+ nBufferIndex = buffer - m_inp_heap_ptr;
+ }
+ else
+ {
+ nBufferIndex = buffer - m_inp_mem_ptr;
+ }
+
+ if (nBufferIndex > m_inp_buf_count )
+ {
+ DEBUG_PRINT_ERROR("\nERROR:ETB nBufferIndex is invalid");
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("\n ETB: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ if (arbitrary_bytes)
+ {
+ post_event ((unsigned)hComp,(unsigned)buffer,
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
+ }
+ else
+ {
+ post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
+ }
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::empty_this_buffer_proxy
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ int push_cnt = 0,i=0;
+ unsigned nPortIndex = 0;
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ struct vdec_input_frameinfo frameinfo;
+ struct vdec_bufferpayload *temp_buffer;
+ struct vdec_ioctl_msg ioctl_msg;
+ struct vdec_seqheader seq_header;
+ bool port_setting_changed = true;
+
+ /*Should we generate a Aync error event*/
+ if (buffer == NULL || buffer->pInputPortPrivate == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy is invalid");
+ return OMX_ErrorBadParameter;
+ }
+
+ nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
+
+ if (nPortIndex > m_inp_buf_count)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
+ nPortIndex);
+ return OMX_ErrorBadParameter;
+ }
+
+ pending_input_buffers++;
+
+ if( input_flush_progress == true || m_ineos_reached == 1)
+ {
+ DEBUG_PRINT_LOW("\n Flush in progress return buffer ");
+ post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
+ OMX_COMPONENT_GENERATE_EBD);
+ return OMX_ErrorNone;
+ }
+
+ if(m_event_port_settings_sent && !arbitrary_bytes)
+ {
+ post_event((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
+ return OMX_ErrorNone;
+ }
+
+ temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
+
+ if ((temp_buffer - driver_context.ptr_inputbuffer) > m_inp_buf_count)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("\n ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ /*for use buffer we need to memcpy the data*/
+ temp_buffer->buffer_len = buffer->nFilledLen;
+
+ if (input_use_buffer)
+ {
+ if (buffer->nFilledLen <= temp_buffer->buffer_len)
+ {
+ memcpy (temp_buffer->bufferaddr,(buffer->pBuffer + buffer->nOffset),
+ buffer->nFilledLen);
+ }
+ else
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ }
+
+ if (!arbitrary_bytes && first_frame < 2 && codec_type_parse == CODEC_TYPE_MPEG4)
+ {
+
+ if (first_frame == 0)
+ {
+ first_buffer = (unsigned char *)malloc (m_inp_buf_size);
+ DEBUG_PRINT_LOW("\n Copied the first buffer data size %d ",
+ temp_buffer->buffer_len);
+ first_frame = 1;
+ memcpy (first_buffer,temp_buffer->bufferaddr,temp_buffer->buffer_len);
+ first_frame_size = buffer->nFilledLen;
+ buffer->nFilledLen = 0;
+ post_event ((unsigned int)buffer,VDEC_S_SUCCESS,
+ OMX_COMPONENT_GENERATE_EBD);
+ return OMX_ErrorNone;
+ }
+ else if (first_frame == 1)
+ {
+ first_frame = 2;
+ DEBUG_PRINT_LOW("\n Second buffer copy the header size %d frame size %d",
+ first_frame_size,temp_buffer->buffer_len);
+ memcpy (&first_buffer [first_frame_size],temp_buffer->bufferaddr,
+ temp_buffer->buffer_len);
+ first_frame_size += temp_buffer->buffer_len;
+ memcpy (temp_buffer->bufferaddr,first_buffer,first_frame_size);
+ temp_buffer->buffer_len = first_frame_size;
+ free (first_buffer);
+ }
+ }
+
+ frameinfo.bufferaddr = temp_buffer->bufferaddr;
+ frameinfo.client_data = (void *) buffer;
+ frameinfo.datalen = temp_buffer->buffer_len;
+ frameinfo.flags = 0;
+ frameinfo.offset = buffer->nOffset;
+ frameinfo.pmem_fd = temp_buffer->pmem_fd;
+ frameinfo.pmem_offset = temp_buffer->offset;
+ frameinfo.timestamp = buffer->nTimeStamp;
+
+#if BITSTREAM_LOG
+ int bytes_written;
+ bytes_written = fwrite((const char *)temp_buffer->bufferaddr,
+ temp_buffer->buffer_len,1,outputBufferFile1);
+
+#endif
+
+ if(!set_seq_header_done)
+ {
+ set_seq_header_done = true;
+ DEBUG_PRINT_HIGH("\n Set Sequence Header");
+ seq_header.ptr_seqheader = frameinfo.bufferaddr;
+ seq_header.seq_header_len = frameinfo.datalen;
+ seq_header.pmem_fd = frameinfo.pmem_fd;
+ seq_header.pmem_offset = frameinfo.pmem_offset;
+ ioctl_msg.inputparam = &seq_header;
+ ioctl_msg.outputparam = NULL;
+ if (ioctl(driver_context.video_driver_fd,VDEC_IOCTL_SET_SEQUENCE_HEADER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set Sequence Header Failed");
+ /*Generate an async error and move to invalid state*/
+ return OMX_ErrorBadParameter;
+ }
+ if(omx_vdec_check_port_settings (&port_setting_changed) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n Check port setting failed");
+ return OMX_ErrorBadParameter;
+ }
+
+ if(port_setting_changed)
+ {
+ DEBUG_PRINT_HIGH("\n Port settings changed");
+ m_event_port_settings_sent = true;
+ m_cb.EventHandler(&m_cmp, m_app_data,OMX_EventPortSettingsChanged,
+ OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL );
+ DEBUG_PRINT_HIGH("\n EventHandler for Port Setting changed done");
+ return OMX_ErrorNone;
+ }
+ else
+ {
+ if(!register_output_buffers())
+ {
+ DEBUG_PRINT_ERROR("\n register output failed");
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_HIGH("\n Port settings Not changed");
+ }
+ }
+
+ if (temp_buffer->buffer_len == 0 || (buffer->nFlags & 0x01))
+ {
+ DEBUG_PRINT_HIGH("\n Rxd i/p EOS, Notify Driver that EOS has been reached");
+ frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
+ m_ineos_reached = 1;
+ }
+
+ sent_first_frame = true;
+ DEBUG_PRINT_LOW("\n Decode Input Frame Size %d",frameinfo.datalen);
+ ioctl_msg.inputparam = &frameinfo;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(driver_context.video_driver_fd,VDEC_IOCTL_DECODE_FRAME,
+ &ioctl_msg) < 0)
+ {
+ /*Generate an async error and move to invalid state*/
+ return OMX_ErrorBadParameter;
+ }
+
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::FillThisBuffer
+
+DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("FTB in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (buffer == NULL || ((buffer - m_out_mem_ptr) > m_out_buf_size))
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("\n FTB: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB);
+ return OMX_ErrorNone;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::fill_this_buffer_proxy
+
+DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
+{
+ OMX_ERRORTYPE nRet = OMX_ErrorNone;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
+ struct vdec_fillbuffer_cmd fillbuffer;
+ struct vdec_bufferpayload *ptr_outputbuffer = NULL;
+ struct vdec_output_frameinfo *ptr_respbuffer = NULL;
+
+
+ if (bufferAdd == NULL || ((buffer - m_out_mem_ptr) > m_out_buf_count) )
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("\n FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
+ bufferAdd, bufferAdd->pBuffer);
+ /*Return back the output buffer to client*/
+ if( (m_event_port_settings_sent == true) || (m_out_bEnabled != OMX_TRUE)
+ || output_flush_progress == true || m_outeos_reached == 1)
+ {
+ DEBUG_PRINT_LOW("\n Output Buffers return in EOS condition");
+ buffer->nFlags |= m_outeos_reached;
+ m_cb.FillBufferDone (hComp,m_app_data,buffer);
+ return OMX_ErrorNone;
+ }
+ pending_output_buffers++;
+ ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
+ if (ptr_respbuffer)
+ {
+ ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
+ }
+
+ if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ memcpy (&fillbuffer.buffer,ptr_outputbuffer,\
+ sizeof(struct vdec_bufferpayload));
+ fillbuffer.client_data = bufferAdd;
+
+ ioctl_msg.inputparam = &fillbuffer;
+ ioctl_msg.outputparam = NULL;
+ if (ioctl (driver_context.video_driver_fd,
+ VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Decoder frame failed");
+ m_cb.FillBufferDone (hComp,m_app_data,buffer);
+ return OMX_ErrorBadParameter;
+ }
+
+ if(gate_input_buffers)
+ {
+ gate_input_buffers = false;
+ if(pdest_frame)
+ {
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::SetCallbacks
+
+DESCRIPTION
+ Set the callbacks.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_CALLBACKTYPE* callbacks,
+ OMX_IN OMX_PTR appData)
+{
+
+ m_cb = *callbacks;
+ DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
+ m_cb.EventHandler,m_cb.FillBufferDone);
+ m_app_data = appData;
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentDeInit
+
+DESCRIPTION
+ Destroys the component and release memory allocated to the heap.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
+{
+ int i = 0;
+ if (OMX_StateLoaded != m_state)
+ {
+ DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\
+ m_state);
+ DEBUG_PRINT_ERROR("\nPlayback Ended - FAILED");
+ }
+ else
+ {
+ DEBUG_PRINT_HIGH("\n Playback Ended - PASSED");
+ }
+
+ /*Check if the output buffers have to be cleaned up*/
+ if(m_out_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("Freeing the Output Memory\n");
+ for (i=0; i<m_out_buf_count; i++ )
+ {
+ free_output_buffer (&m_out_mem_ptr[i]);
+ }
+ if (driver_context.ptr_outputbuffer)
+ {
+ free (driver_context.ptr_outputbuffer);
+ driver_context.ptr_outputbuffer = NULL;
+ }
+
+ if (driver_context.ptr_respbuffer)
+ {
+ free (driver_context.ptr_respbuffer);
+ driver_context.ptr_respbuffer = NULL;
+ }
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+
+ /*Check if the input buffers have to be cleaned up*/
+ if(m_inp_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("Freeing the Input Memory\n");
+ for (i=0; i<m_inp_buf_count; i++ )
+ {
+ free_input_buffer (&m_inp_mem_ptr[i]);
+ }
+
+ if (driver_context.ptr_inputbuffer)
+ {
+ free (driver_context.ptr_inputbuffer);
+ driver_context.ptr_inputbuffer = NULL;
+ }
+
+ free(m_inp_mem_ptr);
+ m_inp_mem_ptr = NULL;
+ }
+
+ if(h264_scratch.pBuffer)
+ {
+ free(h264_scratch.pBuffer);
+ h264_scratch.pBuffer = NULL;
+ }
+
+ if(m_platform_list)
+ {
+ free(m_platform_list);
+ m_platform_list = NULL;
+ }
+ if(m_vendor_config.pData)
+ {
+ free(m_vendor_config.pData);
+ m_vendor_config.pData = NULL;
+ }
+
+ // Reset counters in mesg queues
+ m_ftb_q.m_size=0;
+ m_cmd_q.m_size=0;
+ m_etb_q.m_size=0;
+ m_ftb_q.m_read = m_ftb_q.m_write =0;
+ m_cmd_q.m_read = m_cmd_q.m_write =0;
+ m_etb_q.m_read = m_etb_q.m_write =0;
+
+ DEBUG_PRINT_LOW("\n Calling VDEC_IOCTL_STOP_NEXT_MSG");
+ (void)ioctl(driver_context.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
+ NULL);
+ DEBUG_PRINT_HIGH("\n Close the driver instance");
+ close(driver_context.video_driver_fd);
+
+#if BITSTREAM_LOG
+ fclose (outputBufferFile1);
+#endif
+#ifdef _ANDROID_
+ //for (i=0; i<m_out_buf_count; i++ )
+ {
+ // Clear the strong reference
+ m_heap_ptr.clear();
+ }
+#endif // _ANDROID_
+ DEBUG_PRINT_HIGH("\n omx_vdec::component_deinit() complete");
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::UseEGLImage
+
+DESCRIPTION
+ OMX Use EGL Image method implementation <TBD>.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Not Implemented error.
+
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN void* eglImage)
+{
+ DEBUG_PRINT_ERROR("Error : use_EGL_image: Not Implemented \n");
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ComponentRoleEnum
+
+DESCRIPTION
+ OMX Component Role Enum method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything is successful.
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_U8* role,
+ OMX_IN OMX_U32 index)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp(driver_context.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Querying Role on Unknown Component\n");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ return eRet;
+}
+
+
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateDone
+
+DESCRIPTION
+ Checks if entire buffer pool is allocated by IL Client or not.
+ Need this to move to IDLE state.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_vdec::allocate_done(void)
+{
+ bool bRet = false;
+ bool bRet_In = false;
+ bool bRet_Out = false;
+
+ bRet_In = allocate_input_done();
+ bRet_Out = allocate_output_done();
+
+ if(bRet_In && bRet_Out)
+ {
+ bRet = true;
+ }
+
+ return bRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateInputDone
+
+DESCRIPTION
+ Checks if I/P buffer pool is allocated by IL Client or not.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_vdec::allocate_input_done(void)
+{
+ bool bRet = false;
+ unsigned i=0;
+
+ if (m_inp_mem_ptr == NULL)
+ {
+ return bRet;
+ }
+ if(m_inp_mem_ptr )
+ {
+ for(;i<m_inp_buf_count;i++)
+ {
+ if(BITMASK_ABSENT(&m_inp_bm_count,i))
+ {
+ break;
+ }
+ }
+ }
+ if(i==m_inp_buf_count)
+ {
+ bRet = true;
+ DEBUG_PRINT_HIGH("\n Allocate done for all i/p buffers");
+ }
+ if(i==m_inp_buf_count && m_inp_bEnabled)
+ {
+ m_inp_bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::AllocateOutputDone
+
+DESCRIPTION
+ Checks if entire O/P buffer pool is allocated by IL Client or not.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_vdec::allocate_output_done(void)
+{
+ bool bRet = false;
+ unsigned j=0;
+
+ if (m_out_mem_ptr == NULL)
+ {
+ return bRet;
+ }
+
+ if(m_out_mem_ptr )
+ {
+ for(;j<m_out_buf_count;j++)
+ {
+ if(BITMASK_ABSENT(&m_out_bm_count,j))
+ {
+ break;
+ }
+ }
+ }
+
+ if(j==m_out_buf_count)
+ {
+ bRet = true;
+ DEBUG_PRINT_HIGH("\n Allocate done for all o/p buffers");
+ }
+
+ if(j==m_out_buf_count && m_out_bEnabled)
+ {
+ m_out_bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ReleaseDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::release_done(void)
+{
+ bool bRet = false;
+
+ if(release_input_done())
+ {
+ if(release_output_done())
+ {
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::ReleaseOutputDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::release_output_done(void)
+{
+ bool bRet = false;
+ unsigned i=0,j=0;
+
+ DEBUG_PRINT_LOW("\n Value of m_out_mem_ptr %p",m_inp_mem_ptr);
+ if(m_out_mem_ptr)
+ {
+ for(;j<m_out_buf_count;j++)
+ {
+ if(BITMASK_PRESENT(&m_out_bm_count,j))
+ {
+ break;
+ }
+ }
+ if(j==m_out_buf_count)
+ {
+ m_out_bm_count = 0;
+ bRet = true;
+ }
+ }
+ else
+ {
+ m_out_bm_count = 0;
+ bRet = true;
+ }
+ return bRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_vdec::ReleaseInputDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_vdec::release_input_done(void)
+{
+ bool bRet = false;
+ unsigned i=0,j=0;
+
+ DEBUG_PRINT_LOW("\n Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
+ if(m_inp_mem_ptr)
+ {
+ for(;j<m_inp_buf_count;j++)
+ {
+ if( BITMASK_PRESENT(&m_inp_bm_count,j))
+ {
+ break;
+ }
+ }
+ if(j==m_inp_buf_count)
+ {
+ bRet = true;
+ }
+ }
+ else
+ {
+ bRet = true;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_check_port_settings
+
+DESCRIPTION
+ Parse meta data to check the height and width param
+ Check the level and profile
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX_ErrorNone, if profile and level are supported
+ OMX_ErrorUnsupportedSetting, if profile and level are not supported
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::omx_vdec_check_port_settings(bool *port_setting_changed)
+{
+ struct vdec_ioctl_msg ioctl_msg;
+ unsigned int alignment = 0,buffer_size = 0;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ *port_setting_changed = false;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.video_resoultion;
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_GET_PICRES,&ioctl_msg))
+ {
+ DEBUG_PRINT_ERROR("\n Error in VDEC_IOCTL_GET_PICRES in port_setting");
+ return OMX_ErrorHardware;
+ }
+
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &driver_context.output_buffer;
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ,
+ &ioctl_msg))
+ {
+ DEBUG_PRINT_ERROR("\n Error in VDEC_IOCTL_GET_BUFFER_REQ in port_setting");
+ return OMX_ErrorHardware;
+ }
+ DEBUG_PRINT_HIGH("\n Queried Dimensions H=%d W=%d Act H=%d W=%d",
+ driver_context.video_resoultion.frame_height,
+ driver_context.video_resoultion.frame_width,
+ m_height,m_width);
+ DEBUG_PRINT_HIGH("\n Queried Buffer ACnt=%d BSiz=%d Act Acnt=%d Bsiz=%d",
+ driver_context.output_buffer.actualcount,
+ driver_context.output_buffer.buffer_size,
+ m_out_buf_count,m_out_buf_size);
+
+ DEBUG_PRINT_HIGH("\n Queried stride cuur Str=%d cur scan=%d Act str=%d act scan =%d",
+ driver_context.video_resoultion.stride,driver_context.video_resoultion.scan_lines,
+ stride,scan_lines);
+
+
+ if(driver_context.video_resoultion.frame_height != m_height ||
+ driver_context.video_resoultion.frame_width != m_width ||
+ driver_context.video_resoultion.scan_lines != scan_lines ||
+ driver_context.video_resoultion.stride != stride ||
+ driver_context.output_buffer.actualcount != m_out_buf_count ||
+ driver_context.output_buffer.buffer_size > m_out_buf_size)
+ {
+ *port_setting_changed = true;
+ ioctl_msg.inputparam = &driver_context.output_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER_REQ,
+ &ioctl_msg))
+ {
+ DEBUG_PRINT_ERROR("\n Error in VDEC_IOCTL_GET_BUFFER_REQ in port_setting");
+ return OMX_ErrorHardware;
+ }
+ m_out_buf_size_recon = driver_context.output_buffer.buffer_size;
+ m_out_buf_count_recon = driver_context.output_buffer.actualcount;
+ m_out_buf_count_min_recon = driver_context.output_buffer.mincount;
+
+ alignment = driver_context.output_buffer.alignment;
+ buffer_size = driver_context.output_buffer.buffer_size;
+ m_out_buf_size_recon =
+ ((buffer_size + alignment - 1) & (~(alignment - 1)));
+ m_crop_dy = m_height = driver_context.video_resoultion.frame_height;
+ m_crop_dx = m_width = driver_context.video_resoultion.frame_width;
+ scan_lines = driver_context.video_resoultion.scan_lines;
+ stride = driver_context.video_resoultion.stride;
+ m_port_height = m_height;
+ m_port_width = m_width;
+ }
+
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_vdec::omx_vdec_validate_port_param
+
+DESCRIPTION
+ Get the PMEM area from video decoder
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ None
+========================================================================== */
+OMX_ERRORTYPE omx_vdec::omx_vdec_validate_port_param(int height, int width)
+{
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ long hxw = height*width;
+ long lmt_hxw = 0;
+
+ return ret;
+}
+
+static FILE * outputBufferFile = NULL;
+
+OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer)
+{
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
+
+ if (buffer == NULL || ((buffer - m_out_mem_ptr) > m_out_buf_count))
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("\n fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
+ buffer, buffer->pBuffer);
+ pending_output_buffers --;
+
+ if (buffer->nFlags & 0x01)
+ {
+ DEBUG_PRINT_LOW("\n Output EOS has been reached");
+
+ m_outeos_reached = 0;
+ m_ineos_reached = 0;
+ h264_scratch.nFilledLen = 0;
+ nal_count = 0;
+ look_ahead_nal = false;
+ frame_count = 0;
+
+ if (m_frame_parser.mutils)
+ {
+ m_frame_parser.mutils->initialize_frame_checking_environment();
+ }
+ if (psource_frame)
+ {
+ m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
+ psource_frame = NULL;
+ }
+
+ if (pdest_frame)
+ {
+ pdest_frame->nFilledLen = 0;
+ m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL);
+ pdest_frame = NULL;
+ }
+ m_frame_parser.flush();
+ }
+
+ DEBUG_PRINT_LOW("\n In fill Buffer done call address %p ",buffer);
+
+ if (outputBufferFile == NULL)
+ {
+ outputBufferFile = fopen ("/data/output.yuv","wb");
+ }
+ if (outputBufferFile)
+ {
+ /*fwrite (buffer->pBuffer,1,buffer->nFilledLen,
+ outputBufferFile); */
+ }
+ /* For use buffer we need to copy the data */
+ if (m_cb.FillBufferDone)
+ {
+ pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
+ buffer->pPlatformPrivate)->entryList->entry;
+ DEBUG_PRINT_LOW("\n Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd);
+ m_cb.FillBufferDone (hComp,m_app_data,buffer);
+ DEBUG_PRINT_LOW("\n After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd);
+ }
+ else
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE* buffer)
+{
+
+ if (buffer == NULL || ((buffer - m_inp_mem_ptr) > m_inp_buf_count))
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("\n empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p",
+ buffer, buffer->pBuffer);
+ pending_input_buffers--;
+
+ if (arbitrary_bytes)
+ {
+ if (pdest_frame == NULL && input_flush_progress == false)
+ {
+ DEBUG_PRINT_LOW("\n Push input from buffer done address of Buffer %p",buffer);
+ pdest_frame = buffer;
+ buffer->nFilledLen = 0;
+ push_input_buffer (hComp);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Push buffer into freeq address of Buffer %p",buffer);
+ buffer->nFilledLen = 0;
+ if (!m_input_free_q.insert_entry((unsigned)buffer,NULL,NULL))
+ {
+ DEBUG_PRINT_ERROR("\nERROR:i/p free Queue is FULL Error");
+ }
+ }
+ }
+ else if(m_cb.EmptyBufferDone)
+ {
+ buffer->nFilledLen = 0;
+ m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
+ }
+ return OMX_ErrorNone;
+}
+
+
+int omx_vdec::async_message_process (void *context, void* message)
+{
+ omx_vdec* omx = NULL;
+ struct vdec_msginfo *vdec_msg = NULL;
+ OMX_BUFFERHEADERTYPE* omxhdr = NULL;
+ struct vdec_output_frameinfo *output_respbuf = NULL;
+
+ if (context == NULL || message == NULL)
+ {
+ DEBUG_PRINT_ERROR("\n FATAL ERROR in omx_vdec::async_message_process NULL Check");
+ return -1;
+ }
+ vdec_msg = (struct vdec_msginfo *)message;
+
+ omx = reinterpret_cast<omx_vdec*>(context);
+ switch (vdec_msg->msgcode)
+ {
+
+ case VDEC_MSG_EVT_HW_ERROR:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
+ break;
+
+ case VDEC_MSG_RESP_START_DONE:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_START_DONE);
+ break;
+
+ case VDEC_MSG_RESP_STOP_DONE:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_STOP_DONE);
+ break;
+
+ case VDEC_MSG_RESP_RESUME_DONE:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_RESUME_DONE);
+ break;
+
+ case VDEC_MSG_RESP_PAUSE_DONE:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_PAUSE_DONE);
+ break;
+
+ case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
+ break;
+ case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
+ omx->post_event (NULL,vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
+ break;
+ case VDEC_MSG_RESP_INPUT_FLUSHED:
+ case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
+
+ omxhdr = (OMX_BUFFERHEADERTYPE* )\
+ vdec_msg->msgdata.input_frame_clientdata;
+
+
+ if (omxhdr == NULL ||
+ ((omxhdr - omx->m_inp_mem_ptr) > omx->m_inp_buf_count) )
+ {
+ omxhdr = NULL;
+ vdec_msg->status_code = VDEC_S_EFATAL;
+ }
+
+ omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_EBD);
+ break;
+ case VDEC_MSG_RESP_OUTPUT_FLUSHED:
+ case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
+ omxhdr = (OMX_BUFFERHEADERTYPE*)vdec_msg->msgdata.output_frame.client_data;
+ DEBUG_PRINT_LOW("\n Got Buffer back from Driver %p omxhdr time stamp = %d " ,omxhdr,vdec_msg->msgdata.output_frame.time_stamp);
+
+ if ( (omxhdr != NULL) &&
+ ((omxhdr - omx->m_out_mem_ptr) < omx->m_out_buf_count) &&
+ (omxhdr->pOutputPortPrivate != NULL) &&
+ ( ((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
+ - omx->driver_context.ptr_respbuffer) < omx->m_out_buf_count)
+ )
+ {
+ if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen)
+ {
+ omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
+ omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
+ omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
+ omxhdr->nFlags = (vdec_msg->msgdata.output_frame.flags & 0x01);
+
+ output_respbuf = (struct vdec_output_frameinfo *)\
+ omxhdr->pOutputPortPrivate;
+ output_respbuf->framesize.n_bottom = \
+ vdec_msg->msgdata.output_frame.framesize.n_bottom;
+ output_respbuf->framesize.n_left = \
+ vdec_msg->msgdata.output_frame.framesize.n_left;
+ output_respbuf->framesize.n_right = \
+ vdec_msg->msgdata.output_frame.framesize.n_right;
+ output_respbuf->framesize.n_top = \
+ vdec_msg->msgdata.output_frame.framesize.n_top;
+ output_respbuf->len = vdec_msg->msgdata.output_frame.len;
+ output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
+ output_respbuf->time_stamp = vdec_msg->msgdata.output_frame.time_stamp;
+ output_respbuf->flags = vdec_msg->msgdata.output_frame.flags;
+
+ /*Use buffer case*/
+ if (omx->output_use_buffer)
+ {
+ if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen)
+ {
+ memcpy ( omxhdr->pBuffer,
+ (vdec_msg->msgdata.output_frame.bufferaddr +
+ vdec_msg->msgdata.output_frame.offset),
+ vdec_msg->msgdata.output_frame.len );
+ }
+ else
+ {
+ omxhdr->nFilledLen = 0;
+ }
+ }
+ }
+ else
+ {
+ omxhdr->nFilledLen = 0;
+ }
+
+ }
+ else
+ {
+ omxhdr = NULL;
+ vdec_msg->status_code = VDEC_S_EFATAL;
+ }
+
+ DEBUG_PRINT_LOW("\n Driver returned a output Buffer status %d",
+ vdec_msg->status_code);
+ omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_FBD);
+ break;
+ default:
+ break;
+ }
+ return 1;
+}
+
+OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ )
+{
+ unsigned address,p2,id;
+ DEBUG_PRINT_LOW("\n Empty this arbitrary");
+
+ if (buffer == NULL)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_LOW("\n ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ DEBUG_PRINT_LOW("\n ETBProxyArb: nFilledLen %u, flags %d, timestamp %u",
+ buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp);
+
+ if( input_flush_progress == true || m_ineos_reached == 1)
+ {
+ DEBUG_PRINT_LOW("\n Flush in progress return buffer ");
+ m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
+ return OMX_ErrorNone;
+ }
+
+ if (psource_frame == NULL)
+ {
+ DEBUG_PRINT_LOW("\n Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp);
+ psource_frame = buffer;
+ DEBUG_PRINT_LOW("\n Try to Push One Input Buffer ");
+ push_input_buffer (hComp);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Push the source buffer into pendingq %p",buffer);
+ if (!m_input_pending_q.insert_entry((unsigned)buffer,NULL,NULL))
+ {
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
+{
+ unsigned address,p2,id;
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+
+ if (pdest_frame == NULL || psource_frame == NULL)
+ {
+ /*Check if we have a destination buffer*/
+ if (pdest_frame == NULL)
+ {
+ DEBUG_PRINT_LOW("\n Get a Destination buffer from the queue");
+ if (m_input_free_q.m_size && !gate_input_buffers)
+ {
+ m_input_free_q.pop_entry(&address,&p2,&id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
+ pdest_frame->nFilledLen = 0;
+ DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",pdest_frame);
+ }
+ }
+
+ /*Check if we have a destination buffer*/
+ if (psource_frame == NULL)
+ {
+ DEBUG_PRINT_LOW("\n Get a source buffer from the queue");
+ if (m_input_pending_q.m_size && !gate_input_buffers)
+ {
+ m_input_pending_q.pop_entry(&address,&p2,&id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *)address;
+ DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame,
+ psource_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d",
+ psource_frame->nFlags,psource_frame->nFilledLen);
+
+ }
+ }
+
+ }
+
+ while ((pdest_frame != NULL) && (psource_frame != NULL)&& !gate_input_buffers)
+ {
+ switch (codec_type_parse)
+ {
+ case CODEC_TYPE_MPEG4:
+ case CODEC_TYPE_H263:
+ ret = push_input_sc_codec(hComp);
+ break;
+ case CODEC_TYPE_H264:
+ ret = push_input_h264(hComp);
+ break;
+ case CODEC_TYPE_VC1:
+ ret = push_input_vc1(hComp);
+ break;
+ }
+ if (ret != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n Pushing input Buffer Failed");
+ omx_report_error ();
+ break;
+ }
+ }
+
+ return ret;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
+{
+ OMX_U32 partial_frame = 1;
+ OMX_BOOL genarte_edb = OMX_TRUE,generate_eos = OMX_TRUE;
+ unsigned address,p2,id;
+
+ DEBUG_PRINT_LOW("\n Start Parsing the bit stream address %p TimeStamp %d",
+ psource_frame,psource_frame->nTimeStamp);
+ if (m_frame_parser.parse_mpeg4_frame(psource_frame,
+ pdest_frame,&partial_frame) == -1)
+ {
+ DEBUG_PRINT_ERROR("\n Error In Parsing Return Error");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (partial_frame == 0)
+ {
+ DEBUG_PRINT_LOW("\n Frame size %d source %p frame count %d",
+ pdest_frame->nFilledLen,psource_frame,frame_count);
+
+
+ DEBUG_PRINT_LOW("\n TimeStamp updated %d",pdest_frame->nTimeStamp);
+ /*First Parsed buffer will have only header Hence skip*/
+ if (frame_count == 0)
+ {
+ DEBUG_PRINT_LOW("\n H263/MPEG4 Codec First Frame ");
+ mp4h263_flags = psource_frame->nFlags;
+ mp4h263_timestamp = psource_frame->nTimeStamp;
+ frame_count++;
+ }
+ else
+ {
+ pdest_frame->nTimeStamp = mp4h263_timestamp;
+ mp4h263_timestamp = psource_frame->nTimeStamp;
+ pdest_frame->nFlags = mp4h263_flags;
+ mp4h263_flags = psource_frame->nFlags;
+
+ if(psource_frame->nFilledLen == 0)
+ {
+ pdest_frame->nFlags = mp4h263_flags;
+ generate_eos = OMX_FALSE;
+ }
+
+
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ if(m_event_port_settings_sent)
+ {
+ gate_input_buffers = true;
+ return OMX_ErrorNone;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+
+ if (m_input_free_q.m_size && !gate_input_buffers)
+ {
+ m_input_free_q.pop_entry(&address,&p2,&id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
+ pdest_frame->nFilledLen = 0;
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Not a Complete Frame %d",pdest_frame->nFilledLen);
+ /*Check if Destination Buffer is full*/
+ if (pdest_frame->nAllocLen ==
+ pdest_frame->nFilledLen + pdest_frame->nOffset)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Frame Not found though Destination Filled");
+ return OMX_ErrorStreamCorrupt;
+ }
+ }
+
+ if (psource_frame->nFilledLen == 0)
+ {
+ if ((psource_frame->nFlags & 0x01) && generate_eos)
+ {
+ if (pdest_frame)
+ {
+ pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
+ pdest_frame->nFlags = psource_frame->nFlags;
+ DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
+ pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
+ pdest_frame->nFilledLen,frame_count++);
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Last frame in else dest addr") ;
+ genarte_edb = OMX_FALSE;
+ }
+ }
+ if(genarte_edb)
+ {
+ DEBUG_PRINT_LOW("\n Buffer Consumed return back to client %p",psource_frame);
+ m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
+ psource_frame = NULL;
+
+ if (m_input_pending_q.m_size)
+ {
+ DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame);
+ m_input_pending_q.pop_entry(&address,&p2,&id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame,
+ psource_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d",
+ psource_frame->nFlags,psource_frame->nFilledLen);
+ }
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
+{
+ OMX_U32 partial_frame = 1;
+ unsigned address,p2,id;
+ OMX_BOOL isNewFrame = OMX_FALSE;
+ OMX_BOOL genarte_edb = OMX_TRUE;
+ OMX_BOOL skip_parsing = OMX_FALSE;
+
+ if (h264_scratch.pBuffer == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR:H.264 Scratch Buffer not allocated");
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_LOW("\n Values of h264_scratch.nFilledLen %d look_ahead_nal %d",
+ h264_scratch.nFilledLen,look_ahead_nal);
+ DEBUG_PRINT_LOW("\n pdest_frame->nFilledLen %d",pdest_frame->nFilledLen);
+ if (h264_scratch.nFilledLen && look_ahead_nal)
+ {
+ look_ahead_nal = false;
+ DEBUG_PRINT_LOW("\n Copy the previous NAL into Buffer %d ",
+ h264_scratch.nFilledLen);
+ if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen)
+ {
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ DEBUG_PRINT_LOW("\n Total filled length %d",pdest_frame->nFilledLen);
+ h264_scratch.nFilledLen = 0;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ if(psource_frame->nFlags & 0x01)
+ {
+ DEBUG_PRINT_LOW("\n EOS has been reached no parsing required");
+ skip_parsing = OMX_TRUE;
+ if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ psource_frame->nFilledLen)
+ {
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ (psource_frame->pBuffer+psource_frame->nOffset),
+ psource_frame->nFilledLen);
+ pdest_frame->nFilledLen += psource_frame->nFilledLen;
+ DEBUG_PRINT_LOW("\n Total filled length %d",pdest_frame->nFilledLen);
+ psource_frame->nFilledLen = 0;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ if(!skip_parsing)
+ {
+ if (nal_length == 0)
+ {
+ DEBUG_PRINT_LOW("\n NAL length Zero hence parse using start code");
+ if (m_frame_parser.parse_mpeg4_frame(psource_frame,
+ &h264_scratch,&partial_frame) == -1)
+ {
+ DEBUG_PRINT_ERROR("\n Error In Parsing Return Error");
+ return OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n NAL length %d hence parse with NAL length %d",nal_length);
+ if (m_frame_parser.parse_h264_nallength(psource_frame,
+ &h264_scratch,&partial_frame) == -1)
+ {
+ DEBUG_PRINT_ERROR("\n Error In Parsing NAL Return Error");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ if (partial_frame == 0)
+ {
+
+ if (nal_count == 0 && h264_scratch.nFilledLen == 0)
+ {
+ DEBUG_PRINT_LOW("\n First NAL with Zero Length Hence Skip");
+ nal_count++;
+ h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
+ h264_scratch.nFlags = psource_frame->nFlags;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Length of New NAL is %d",h264_scratch.nFilledLen);
+
+ m_frame_parser.mutils->isNewFrame(h264_scratch.pBuffer,
+ h264_scratch.nFilledLen,0,isNewFrame);
+ nal_count++;
+
+ if (!isNewFrame)
+ {
+ if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen)
+ {
+ DEBUG_PRINT_LOW("\n Not a NewFrame Copy into Dest len %d",
+ h264_scratch.nFilledLen);
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ h264_scratch.nFilledLen = 0;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ look_ahead_nal = true;
+ pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
+ pdest_frame->nFlags = h264_scratch.nFlags;
+ h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
+ h264_scratch.nFlags = psource_frame->nFlags;
+
+ DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
+ pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
+ pdest_frame->nFilledLen,frame_count++);
+
+ if (pdest_frame->nFilledLen == 0)
+ {
+ DEBUG_PRINT_LOW("\n Copy the Current Frame since and push it");
+ look_ahead_nal = false;
+ if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen)
+ {
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ h264_scratch.nFilledLen = 0;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ }
+ else
+ {
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ if(m_event_port_settings_sent)
+ {
+ gate_input_buffers = true;
+ return OMX_ErrorNone;
+ }
+ //frame_count++;
+ pdest_frame = NULL;
+ if (m_input_free_q.m_size && !gate_input_buffers)
+ {
+ m_input_free_q.pop_entry(&address,&p2,&id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("\n Pop the next pdest_buffer %p",pdest_frame);
+ pdest_frame->nFilledLen = 0;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Not a Complete Frame %d",pdest_frame->nFilledLen);
+ /*Check if Destination Buffer is full*/
+ if (h264_scratch.nAllocLen ==
+ h264_scratch.nFilledLen + h264_scratch.nOffset)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Frame Not found though Destination Filled");
+ return OMX_ErrorStreamCorrupt;
+ }
+ }
+ }
+
+ if (psource_frame->nFilledLen == 0)
+ {
+ DEBUG_PRINT_LOW("\n Buffer Consumed return back to client %p",psource_frame);
+
+ if (psource_frame->nFlags & 0x01)
+ {
+ if (pdest_frame)
+ {
+ DEBUG_PRINT_LOW("\n EOS Reached Pass Last Buffer");
+ if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen)
+ {
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ h264_scratch.nFilledLen = 0;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR:Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
+ pdest_frame->nFlags = psource_frame->nFlags;
+
+ DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x",
+ pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d",
+ pdest_frame->nFilledLen,frame_count++);
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone)
+ {
+ return OMX_ErrorBadParameter;
+ }
+ if(m_event_port_settings_sent)
+ {
+ gate_input_buffers = true;
+ return OMX_ErrorNone;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Last frame in else dest addr %p size %d",
+ pdest_frame,h264_scratch.nFilledLen);
+ genarte_edb = OMX_FALSE;
+ }
+ }
+ if(genarte_edb)
+ {
+ m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
+ psource_frame = NULL;
+ if (m_input_pending_q.m_size && !gate_input_buffers)
+ {
+ DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame);
+ m_input_pending_q.pop_entry(&address,&p2,&id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("\nNext source Buffer flag %d length %d",
+ psource_frame->nFlags,psource_frame->nFilledLen);
+ }
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp)
+{
+ OMX_U8 *buf, *pdest;
+ OMX_U32 partial_frame = 1;
+ OMX_U32 buf_len, dest_len;
+
+ if(frame_count == 0)
+ {
+ DEBUG_PRINT_LOW("\nFirst i/p buffer for VC1 arbitrary bytes\n");
+ if(!m_vendor_config.pData)
+ {
+ DEBUG_PRINT_LOW("\nCheck profile type in 1st source buffer\n");
+ buf = psource_frame->pBuffer;
+ buf_len = psource_frame->nFilledLen;
+
+ if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE)
+ {
+ m_vc1_profile = VC1_SP_MP_RCV;
+ }
+ else if(*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE)
+ {
+ m_vc1_profile = VC1_AP;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nInvalid sequence layer in first buffer\n");
+ return OMX_ErrorStreamCorrupt;
+ }
+ }
+ else
+ {
+ pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
+ pdest_frame->nOffset;
+ dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
+ pdest_frame->nOffset);
+
+ if(dest_len < m_vendor_config.nDataSize)
+ {
+ DEBUG_PRINT_ERROR("\nDestination buffer full\n");
+ return OMX_ErrorBadParameter;
+ }
+ else
+ {
+ memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
+ pdest_frame->nFilledLen += m_vendor_config.nDataSize;
+ }
+ }
+ }
+
+ switch(m_vc1_profile)
+ {
+ case VC1_AP:
+ DEBUG_PRINT_LOW("\n VC1 AP, hence parse using frame start code");
+ if (push_input_sc_codec(hComp) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n Error In Parsing VC1 AP start code");
+ return OMX_ErrorBadParameter;
+ }
+ break;
+
+ case VC1_SP_MP_RCV:
+ default:
+ DEBUG_PRINT_ERROR("\n Unsupported VC1 profile in ArbitraryBytes Mode\n");
+ return OMX_ErrorBadParameter;
+ }
+ return OMX_ErrorNone;
+}
+
+bool omx_vdec::register_output_buffers()
+{
+ struct vdec_ioctl_msg ioctl_msg;
+ struct vdec_setbuffer_cmd setbuffers;
+ int i = 0;
+ unsigned p1 =0,p2 = 0,ident = 0;
+
+ for(i=0;i<m_out_buf_count;i++)
+ {
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ memcpy (&setbuffers.buffer,&driver_context.ptr_outputbuffer [i],
+ sizeof (vdec_bufferpayload));
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("\n Set the Output Buffer");
+ if (ioctl (driver_context.video_driver_fd,VDEC_IOCTL_SET_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Set output buffer failed");
+ return false;
+ }
+ }
+ if(gate_output_buffers)
+ {
+ /*Generate FBD for all Buffers in the FTBq*/
+ pthread_mutex_lock(&m_lock);
+ DEBUG_PRINT_LOW("\n Initiate Pushing Output Buffers");
+ while (m_ftb_q.m_size)
+ {
+ m_ftb_q.pop_entry(&p1,&p2,&ident);
+ if(ident == OMX_COMPONENT_GENERATE_FTB )
+ {
+ if (fill_this_buffer_proxy ((OMX_HANDLETYPE)p1,
+ (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure");
+ omx_report_error ();
+ return false;
+ }
+ }
+ else if (ident == OMX_COMPONENT_GENERATE_FBD)
+ {
+ fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
+ }
+ }
+ gate_output_buffers = false;
+ pthread_mutex_unlock(&m_lock);
+ }
+ return true;
+}
+
+bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
+ OMX_U32 alignment)
+{
+ struct pmem_allocation allocation;
+ allocation.size = buffer_size;
+ allocation.align = clip2(alignment);
+ if (allocation.align < 4096)
+ {
+ allocation.align = 4096;
+ }
+ if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0)
+ {
+ DEBUG_PRINT_ERROR("\n Aligment failed with pmem driver");
+ return false;
+ }
+ return true;
+}
+
diff --git a/omx/mm-video/vidc/vdec/src/queue.c b/omx/mm-video/vidc/vdec/src/queue.c
new file mode 100644
index 0000000..aefb681
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/src/queue.c
@@ -0,0 +1,128 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*
+ Queue with Linked list
+*/
+
+#include "queue.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+
+typedef struct Node
+{
+ void *element;
+ struct Node *next;
+} Node;
+
+struct Queue
+{
+ Node *head;
+ Node *tail;
+ int current_size;
+};
+
+Queue *alloc_queue()
+{
+ Queue *q = (Queue *) malloc(sizeof(Queue));
+ if (q)
+ {
+ q->head = q->tail = NULL;
+ q->current_size = 0;
+ }
+ return q;
+}
+
+void free_queue(Queue *q)
+{
+ while (q->current_size)
+ {
+ pop(q);
+ }
+}
+
+void free_queue_and_qelement(Queue *q)
+{
+ while (q->current_size)
+ {
+ void *element = pop(q);
+ if (element)
+ free(element);
+ }
+}
+
+int push(Queue *q, void * element)
+{
+ Node *new_node = (Node *) malloc(sizeof(Node));
+
+ if (new_node == NULL)
+ return -1;
+
+ new_node->element = element;
+ new_node->next = NULL;
+
+ if (q->current_size == 0)
+ {
+ q->head = new_node;
+ }
+ else
+ {
+ q->tail->next = new_node;
+ }
+
+ q->tail = new_node;
+ q->current_size++;
+
+ return 0;
+}
+
+void *pop(Queue *q)
+{
+ Node *temp;
+ void *element;
+
+ if (q->current_size == 0)
+ return NULL;
+
+ temp = q->head;
+ element = temp->element;
+
+ if (q->current_size == 1)
+ {
+ q->head = q->tail = NULL;
+ }
+ else
+ {
+ q->head = q->head->next;
+ }
+
+ free(temp);
+ q->current_size--;
+ return element;
+}
+
diff --git a/omx/mm-video/vidc/vdec/test/decoder_driver_test.c b/omx/mm-video/vidc/vdec/test/decoder_driver_test.c
new file mode 100644
index 0000000..8112a2d
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/test/decoder_driver_test.c
@@ -0,0 +1,1189 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "decoder_driver_test.h"
+
+#define DEBUG_PRINT printf
+/************************************************************************/
+/* #DEFINES */
+/************************************************************************/
+
+#define VOP_START_CODE 0x000001B6
+#define SHORT_HEADER_START_CODE 0x00008000
+#define H264_START_CODE 0x00000001
+
+/************************************************************************/
+/* STATIC VARIABLES */
+/************************************************************************/
+
+static int Code_type;
+static int total_frames = 0;
+static unsigned int header_code = 0;
+static pthread_mutex_t read_lock;
+
+static unsigned int read_frame ( unsigned char *dataptr,unsigned int length,
+ FILE * inputBufferFile
+ );
+static int Read_Buffer_From_DAT_File( unsigned char *dataptr, unsigned int length,
+ FILE * inputBufferFile
+ );
+
+static unsigned clp2(unsigned x)
+{
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >>16);
+ return x + 1;
+}
+
+static void* video_thread (void *);
+static void* async_thread (void *);
+
+int main (int argc, char **argv)
+{
+ struct video_decoder_context *decoder_context = NULL;
+ char *file_name = NULL;
+ FILE *file_ptr = NULL;
+ int temp1 =0,temp2 =0;
+ int error = 1;
+ unsigned int i = 0;
+
+ file_name = argv [1];
+ file_ptr = fopen (file_name,"rb");
+
+ if (file_ptr == NULL)
+ {
+ DEBUG_PRINT("\n File is not located ");
+ return -1;
+ }
+
+
+ decoder_context = (struct video_decoder_context *) \
+ calloc (sizeof (struct video_decoder_context),1);
+
+ decoder_context->outputBufferFile = NULL;
+ decoder_context->inputBufferFile = NULL;
+ decoder_context->video_driver_fd = -1;
+
+ if (decoder_context == NULL)
+ {
+ return -1;
+ }
+
+ decoder_context->inputBufferFile = file_ptr;
+
+ file_ptr = fopen ("/data/output.yuv","wb");
+ if (file_ptr == NULL)
+ {
+ DEBUG_PRINT("\n File can't be created");
+ return -1;
+ }
+ decoder_context->outputBufferFile = file_ptr;
+
+ switch (atoi(argv[2]))
+ {
+ case 0:
+ DEBUG_PRINT("\n MPEG4 codec selected");
+ decoder_context->decoder_format = VDEC_CODECTYPE_MPEG4;
+ Code_type = 0;
+ break;
+ case 1:
+ DEBUG_PRINT("\n H.263");
+ decoder_context->decoder_format = VDEC_CODECTYPE_H263;
+ Code_type = 0;
+ break;
+ case 2:
+ DEBUG_PRINT("\n H.264");
+ decoder_context->decoder_format = VDEC_CODECTYPE_H264;
+ Code_type = 1;
+ break;
+ default:
+ DEBUG_PRINT("\n Wrong codec type");
+ error = -1;
+ break;
+ }
+
+ if (error != -1)
+ {
+ temp1 = atoi(argv[3]);
+ temp2 = atoi(argv[4]);
+
+ if (((temp1%16) != 0) || ((temp2%16) != 0))
+ {
+ error = -1;
+ }
+ else
+ {
+ decoder_context->video_resoultion.frame_height = temp1;
+ decoder_context->video_resoultion.frame_width = temp2;
+ }
+ }
+
+ switch (atoi(argv[5]))
+ {
+ case 0:
+ DEBUG_PRINT("\n No Sink");
+ decoder_context->outputBufferFile = NULL;
+ break;
+ }
+
+ if ( error != -1 && (init_decoder (decoder_context) == -1 ))
+ {
+ DEBUG_PRINT("\n Init decoder fails ");
+ error = -1;
+ }
+ DEBUG_PRINT("\n Decoder open successfull");
+
+
+ /*Allocate input and output buffers*/
+ if (error != -1 && (allocate_buffer (VDEC_BUFFER_TYPE_INPUT,
+ decoder_context)== -1))
+ {
+ DEBUG_PRINT("\n Error in input Buffer allocation");
+ error = -1;
+ }
+
+ if (error != -1 && (allocate_buffer (VDEC_BUFFER_TYPE_OUTPUT,
+ decoder_context)== -1))
+ {
+ DEBUG_PRINT("\n Error in output Buffer allocation");
+ error = -1;
+ }
+
+
+ if (error != -1 && (start_decoding (decoder_context) == -1))
+ {
+ DEBUG_PRINT("\n Error in start decoding call");
+ error = -1;
+ }
+
+ if (error != -1 && (stop_decoding (decoder_context) == -1))
+ {
+ DEBUG_PRINT("\n Error in stop decoding call");
+ error = -1;
+ }
+
+ DEBUG_PRINT("\n De-init the decoder");
+ if ((deinit_decoder (decoder_context) == -1))
+ {
+ error = -1;
+ }
+
+
+ (void)free_buffer (VDEC_BUFFER_TYPE_INPUT,decoder_context);
+ (void)free_buffer (VDEC_BUFFER_TYPE_OUTPUT,decoder_context);
+
+ if (decoder_context->inputBufferFile != NULL)
+ {
+ fclose (decoder_context->inputBufferFile);
+ }
+ if (decoder_context->outputBufferFile != NULL)
+ {
+ fclose (decoder_context->outputBufferFile);
+ }
+ DEBUG_PRINT ("\n Total Number of frames decoded %d",total_frames);
+ DEBUG_PRINT("\n closing the driver");
+ free (decoder_context);
+
+ return error;
+}
+
+int init_decoder ( struct video_decoder_context *init_decode )
+{
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct video_queue_context *queue_ptr = NULL;
+ enum vdec_output_fromat output_format = VDEC_YUV_FORMAT_NV12;
+ pthread_mutexattr_t init_values;
+
+ DEBUG_PRINT("\n Before calling the open");
+
+ init_decode->video_driver_fd = open ("/dev/msm_vidc_dec", \
+ O_RDWR | O_NONBLOCK);
+
+
+
+ if (init_decode->video_driver_fd < 0)
+ {
+ DEBUG_PRINT("\n Open failed");
+ return -1;
+ }
+
+
+ /*Initialize Decoder with codec type and resolution*/
+ ioctl_msg.inputparam = &init_decode->decoder_format;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_CODEC,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set codec type failed");
+ return -1;
+ }
+
+ /*Set the output format*/
+ ioctl_msg.inputparam = &output_format;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set output format failed");
+ return -1;
+ }
+
+ ioctl_msg.inputparam = &init_decode->video_resoultion;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_PICRES,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set Resolution failed");
+ return -1;
+ }
+ DEBUG_PRINT("\n After Set Resolution");
+
+ DEBUG_PRINT("\n Query Input bufffer requirements");
+ /*Get the Buffer requirements for input and output ports*/
+
+ init_decode->input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &init_decode->input_buffer;
+
+ if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Requesting for input buffer requirements failed");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n input Size=%d min count =%d actual count = %d", \
+ init_decode->input_buffer.buffer_size,\
+ init_decode->input_buffer.mincount,\
+ init_decode->input_buffer.actualcount);
+
+
+ init_decode->input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ ioctl_msg.inputparam = &init_decode->input_buffer;
+ ioctl_msg.outputparam = NULL;
+ init_decode->input_buffer.actualcount = init_decode->input_buffer.mincount + 2;
+
+ if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set Buffer Requirements Failed");
+ return -1;
+ }
+
+
+ DEBUG_PRINT("\n Query output bufffer requirements");
+ init_decode->output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &init_decode->output_buffer;
+
+ if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Requesting for output buffer requirements failed");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n output Size=%d min count =%d actual count = %d", \
+ init_decode->output_buffer.buffer_size,\
+ init_decode->output_buffer.mincount,\
+ init_decode->output_buffer.actualcount);
+
+ /*Create Queue related data structures*/
+ queue_ptr = &init_decode->queue_context;
+ queue_ptr->commandq_size = 50;
+ queue_ptr->dataq_size = 50;
+
+ sem_init(&queue_ptr->sem_message,0, 0);
+ sem_init(&init_decode->sem_synchronize,0, 0);
+
+ pthread_mutexattr_init (&init_values);
+ pthread_mutex_init (&queue_ptr->mutex,&init_values);
+ pthread_mutex_init (&read_lock,&init_values);
+ DEBUG_PRINT("\n create Queues");
+ queue_ptr->ptr_cmdq = (struct video_msgq*) \
+ calloc (sizeof (struct video_msgq),
+ queue_ptr->commandq_size);
+ queue_ptr->ptr_dataq = (struct video_msgq*) \
+ calloc (sizeof (struct video_msgq),
+ queue_ptr->dataq_size
+ );
+
+ if ( queue_ptr->ptr_cmdq == NULL ||
+ queue_ptr->ptr_dataq == NULL
+ )
+ {
+ return -1;
+ }
+ DEBUG_PRINT("\n create Threads");
+ /*Create two threads*/
+ if ( (pthread_create (&init_decode->videothread_id,NULL,video_thread,
+ init_decode) < 0) ||
+ (pthread_create (&init_decode->asyncthread_id,NULL,async_thread,
+ init_decode) < 0)
+ )
+ {
+ return -1;
+ }
+
+ return 1;
+}
+
+
+
+int free_buffer ( enum vdec_buffer buffer_dir,
+ struct video_decoder_context *decode_context
+ )
+{
+ unsigned int buffercount = 0,i=0;
+ struct vdec_bufferpayload **ptemp = NULL;
+
+ if (decode_context == NULL)
+ {
+ return -1;
+ }
+
+ if (buffer_dir == VDEC_BUFFER_TYPE_INPUT && decode_context->ptr_inputbuffer)
+ {
+ buffercount = decode_context->input_buffer.actualcount;
+ ptemp = decode_context->ptr_inputbuffer;
+
+ for (i=0;i<buffercount;i++)
+ {
+ if (ptemp [i])
+ {
+ if (ptemp [i]->pmem_fd != -1)
+ {
+ munmap ( ptemp [i]->bufferaddr,ptemp [i]->mmaped_size);
+ ptemp [i]->bufferaddr = NULL;
+ close (ptemp [i]->pmem_fd);
+ }
+ free (ptemp [i]);
+ ptemp [i] = NULL;
+ }
+ }
+ free (decode_context->ptr_inputbuffer);
+ decode_context->ptr_inputbuffer = NULL;
+ }
+ else if ( buffer_dir == VDEC_BUFFER_TYPE_OUTPUT )
+ {
+ buffercount = decode_context->output_buffer.actualcount;
+ ptemp = decode_context->ptr_outputbuffer;
+
+ if (decode_context->ptr_respbuffer)
+ {
+ for (i=0;i<buffercount;i++)
+ {
+ if (decode_context->ptr_respbuffer [i])
+ {
+ free (decode_context->ptr_respbuffer[i]);
+ decode_context->ptr_respbuffer [i] = NULL;
+ }
+ }
+ free (decode_context->ptr_respbuffer);
+ decode_context->ptr_respbuffer = NULL;
+ }
+
+ if (ptemp)
+ {
+ for (i=0;i<buffercount;i++)
+ {
+ if (ptemp [i])
+ {
+ if (ptemp [i]->pmem_fd != -1)
+ {
+ munmap ( ptemp [i]->bufferaddr,ptemp [i]->mmaped_size);
+ ptemp [i]->bufferaddr = NULL;
+ close (ptemp [i]->pmem_fd);
+ }
+ free (ptemp [i]);
+ ptemp [i] = NULL;
+ }
+ }
+ free (ptemp);
+ decode_context->ptr_outputbuffer = NULL;
+ }
+ }
+
+ return 1;
+}
+
+int allocate_buffer ( enum vdec_buffer buffer_dir,
+ struct video_decoder_context *decode_context
+ )
+{
+ struct vdec_setbuffer_cmd setbuffers;
+ struct vdec_bufferpayload **ptemp = NULL;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned int buffercount = 0,i=0,alignedsize=0;
+ unsigned int buffersize = 0;
+
+ if ( decode_context == NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: context is NULL");
+ return -1;
+ }
+
+ if ( buffer_dir == VDEC_BUFFER_TYPE_INPUT )
+ {
+ /*Check if buffers are allocated*/
+ if (decode_context->ptr_inputbuffer != NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: decode_context->ptr_inputbuffer is set");
+ return -1;
+ }
+
+ buffercount = decode_context->input_buffer.actualcount;
+ alignedsize = decode_context->input_buffer.alignment;
+ buffersize = decode_context->input_buffer.buffer_size;
+ buffersize = (buffersize + alignedsize) & (~alignedsize);
+ }
+ else if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT)
+ {
+ /*Check if buffers are allocated*/
+ if (decode_context->ptr_outputbuffer != NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Double allcoate output");
+ return -1;
+ }
+
+ buffercount = decode_context->output_buffer.actualcount;
+ alignedsize = decode_context->output_buffer.alignment;
+ buffersize = decode_context->output_buffer.buffer_size;
+ buffersize = (buffersize + alignedsize) & (~alignedsize);
+
+ decode_context->ptr_respbuffer = (struct vdec_output_frameinfo **)\
+ calloc (sizeof (struct vdec_output_frameinfo *),buffercount);
+
+ if (decode_context->ptr_respbuffer == NULL)
+ {
+ DEBUG_PRINT ("\n Allocate failure ptr_respbuffer");
+ }
+
+ for (i=0; i< buffercount; i++)
+ {
+ decode_context->ptr_respbuffer [i] = (struct vdec_output_frameinfo *)\
+ calloc (sizeof (struct vdec_output_frameinfo),buffercount);
+ if (decode_context->ptr_respbuffer [i] == NULL)
+ {
+ DEBUG_PRINT ("\nfailed to allocate vdec_output_frameinfo");
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Wrong buffer directions");
+ return -1;
+ }
+
+ ptemp = (struct vdec_bufferpayload **)\
+ calloc (sizeof (struct vdec_bufferpayload *),buffercount);
+
+ if (ptemp == NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: vdec_bufferpayload failure");
+ return -1;
+ }
+
+
+ if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: OUT");
+ decode_context->ptr_outputbuffer = ptemp;
+ }
+ else
+ {
+ DEBUG_PRINT ("\nallocate_buffer: IN");
+ decode_context->ptr_inputbuffer = ptemp;
+ }
+
+ /*Allocate buffer headers*/
+ for (i=0; i< buffercount; i++)
+ {
+ ptemp [i] = (struct vdec_bufferpayload*)\
+ calloc (sizeof (struct vdec_bufferpayload),1);
+
+ if (ptemp [i] == NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: ptemp [i] calloc failure");
+ return -1;
+ }
+
+ if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT)
+ {
+ decode_context->ptr_respbuffer [i]->client_data = \
+ (void *) ptemp [i];
+ }
+ ptemp [i]->pmem_fd = -1;
+
+ }
+
+ for (i=0; i< buffercount; i++)
+ {
+ ptemp [i]->pmem_fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (ptemp [i]->pmem_fd < 0)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: open pmem_adsp failed");
+ return -1;
+ }
+
+ ptemp [i]->bufferaddr = mmap(NULL,clp2(buffersize),PROT_READ|PROT_WRITE,
+ MAP_SHARED,ptemp [i]->pmem_fd,0);
+ DEBUG_PRINT ("\n pmem fd = %d virt addr = %p",ptemp [i]->pmem_fd,\
+ ptemp [i]->bufferaddr);
+ if (ptemp [i]->bufferaddr == MAP_FAILED)
+ {
+ ptemp [i]->bufferaddr = NULL;
+ DEBUG_PRINT ("\nallocate_buffer: MMAP failed");
+ return -1;
+ }
+ ptemp [i]->buffer_len = buffersize;
+ ptemp [i]->mmaped_size = clp2 (buffersize);
+
+ setbuffers.buffer_type = buffer_dir;
+ memcpy (&setbuffers.buffer,ptemp [i],sizeof (struct vdec_bufferpayload));
+
+ ioctl_msg.inputparam = &setbuffers;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_SET_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Set Buffer IOCTL failed");
+ return -1;
+ }
+
+ }
+ DEBUG_PRINT ("\nallocate_buffer: Success");
+ return 1;
+}
+
+
+
+int start_decoding (struct video_decoder_context *decode_context)
+{
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct vdec_input_frameinfo frameinfo;
+ struct vdec_fillbuffer_cmd fillbuffer;
+ unsigned int i = 0;
+ unsigned int data_len =0;
+
+ memset ((unsigned char*)&frameinfo,0,sizeof (struct vdec_input_frameinfo));
+ memset ((unsigned char*)&fillbuffer,0,sizeof (struct vdec_fillbuffer_cmd));
+
+ if (decode_context == NULL)
+ {
+ return -1;
+ }
+
+ if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_CMD_START,
+ NULL) < 0)
+ {
+ DEBUG_PRINT("\n Start failed");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n Start Issued successfully waiting for Start Done");
+ /*Wait for Start command response*/
+ sem_wait (&decode_context->sem_synchronize);
+
+ /*Push output Buffers*/
+ i = 0;
+ while (i < decode_context->output_buffer.mincount)
+ {
+ fillbuffer.buffer.buffer_len =
+ decode_context->ptr_outputbuffer [i]->buffer_len;
+ fillbuffer.buffer.bufferaddr =
+ decode_context->ptr_outputbuffer [i]->bufferaddr;
+ fillbuffer.buffer.offset =
+ decode_context->ptr_outputbuffer [i]->offset;
+ fillbuffer.buffer.pmem_fd =
+ decode_context->ptr_outputbuffer [i]->pmem_fd;
+ fillbuffer.client_data = (void *)decode_context->ptr_respbuffer [i];
+ DEBUG_PRINT ("\n Client Data on output = %p",fillbuffer.client_data);
+ ioctl_msg.inputparam = &fillbuffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (decode_context->video_driver_fd,
+ VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Decoder frame failed");
+ return -1;
+ }
+ i++;
+ }
+
+
+ /*push input buffers*/
+ i = 0;
+ while (i < decode_context->input_buffer.mincount)
+ {
+ DEBUG_PRINT("\n Read Frame from File");
+ data_len = read_frame ( decode_context->ptr_inputbuffer [i]->bufferaddr,
+ decode_context->ptr_inputbuffer [i]->buffer_len,
+ decode_context->inputBufferFile);
+ if (data_len == 0)
+ {
+ DEBUG_PRINT("\n Length is zero error");
+ return -1;
+ }
+ DEBUG_PRINT("\n Read Frame from File szie = %u",data_len);
+ frameinfo.bufferaddr =
+ decode_context->ptr_inputbuffer [i]->bufferaddr;
+ frameinfo.offset = 0;
+ frameinfo.pmem_fd = decode_context->ptr_inputbuffer [i]->pmem_fd;
+ frameinfo.pmem_offset = decode_context->ptr_inputbuffer [i]->offset;
+ frameinfo.datalen = data_len;
+ frameinfo.client_data = (struct vdec_bufferpayload *)\
+ decode_context->ptr_inputbuffer [i];
+ /*TODO: Time stamp needs to be updated*/
+ ioctl_msg.inputparam = &frameinfo;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_DECODE_FRAME,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Decoder frame failed");
+ return -1;
+ }
+ total_frames++;
+ i++;
+ }
+ DEBUG_PRINT ("\n Wait for EOS");
+ /*Wait for EOS or Error condition*/
+ sem_wait (&decode_context->sem_synchronize);
+ DEBUG_PRINT ("\n Reached EOS");
+
+ return 1;
+}
+
+int stop_decoding (struct video_decoder_context *decode_context)
+{
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ enum vdec_bufferflush flush_dir = VDEC_FLUSH_TYPE_INPUT;
+
+ if (decode_context == NULL)
+ {
+ return -1;
+ }
+
+ ioctl_msg.inputparam = &flush_dir;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_FLUSH,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Flush input failed");
+ }
+ else
+ {
+ sem_wait (&decode_context->sem_synchronize);
+ }
+
+ flush_dir = VDEC_FLUSH_TYPE_OUTPUT;
+ ioctl_msg.inputparam = &flush_dir;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_FLUSH,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Flush output failed");
+ }
+ else
+ {
+ sem_wait (&decode_context->sem_synchronize);
+ }
+
+ DEBUG_PRINT("\n Stop VDEC_IOCTL_CMD_STOP");
+ if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_STOP,
+ NULL) < 0)
+ {
+ DEBUG_PRINT("\n Stop failed");
+ }
+ else
+ {
+ sem_wait (&decode_context->sem_synchronize);
+ }
+ return 1;
+}
+
+int deinit_decoder (struct video_decoder_context *init_decode)
+{
+ if (init_decode == NULL)
+ {
+ return -1;
+ }
+
+ /*Close the driver*/
+ if (init_decode->video_driver_fd != -1)
+ {
+ close (init_decode->video_driver_fd);
+ }
+
+ if (init_decode->queue_context.ptr_cmdq)
+ {
+ free (init_decode->queue_context.ptr_cmdq);
+ init_decode->queue_context.ptr_cmdq = NULL;
+ }
+
+ if (init_decode->queue_context.ptr_dataq)
+ {
+ free (init_decode->queue_context.ptr_dataq);
+ init_decode->queue_context.ptr_dataq = NULL;
+ }
+
+ sem_destroy (&init_decode->queue_context.sem_message);
+ sem_destroy (&init_decode->sem_synchronize);
+
+ pthread_mutex_destroy(&init_decode->queue_context.mutex);
+ pthread_mutex_destroy (&read_lock);
+
+ return 1;
+}
+
+static void* video_thread (void *context)
+{
+ struct video_decoder_context *decode_context = NULL;
+ struct video_msgq *queueitem = NULL;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct vdec_input_frameinfo frameinfo;
+ struct vdec_fillbuffer_cmd fillbuffer;
+ struct vdec_output_frameinfo *outputbuffer = NULL;
+ struct vdec_bufferpayload *tempbuffer = NULL;
+ unsigned int data_len =0;
+
+
+ if (context == NULL)
+ {
+ DEBUG_PRINT("\n video thread recieved NULL context");
+ return NULL;
+ }
+ decode_context = (struct video_decoder_context *) context;
+
+ /* Thread function which will accept commands from async thread
+ * or main thread
+ */
+ while (1)
+ {
+ queueitem = queue_get_cmd (&decode_context ->queue_context);
+ if (queueitem != NULL)
+ {
+ switch (queueitem->cmd)
+ {
+ case VDEC_MSG_EVT_HW_ERROR:
+ DEBUG_PRINT("\n FATAL ERROR ");
+ break;
+ case VDEC_MSG_RESP_INPUT_FLUSHED:
+ DEBUG_PRINT("\n Input Buffer Flushed");
+ break;
+ case VDEC_MSG_RESP_OUTPUT_FLUSHED:
+ DEBUG_PRINT("\n Output buffer Flushed");
+ break;
+ case VDEC_MSG_RESP_START_DONE:
+ DEBUG_PRINT("\n recived start done command");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+
+ case VDEC_MSG_RESP_STOP_DONE:
+ DEBUG_PRINT("\n recieved stop done");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+
+ case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
+
+ tempbuffer = (struct vdec_bufferpayload *)queueitem->clientdata;
+ if (tempbuffer == NULL)
+ {
+ DEBUG_PRINT("\n FATAL ERROR input buffer address is bad");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+ }
+ data_len = read_frame ( tempbuffer->bufferaddr,
+ tempbuffer->buffer_len,
+ decode_context->inputBufferFile
+ );
+
+ if (data_len == 0)
+ {
+ DEBUG_PRINT ("\n End of stream reached");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+ }
+
+ frameinfo.bufferaddr = tempbuffer->bufferaddr;
+ frameinfo.offset = 0;
+ frameinfo.pmem_fd = tempbuffer->pmem_fd;
+ frameinfo.pmem_offset = tempbuffer->offset;
+ frameinfo.datalen = data_len;
+ frameinfo.client_data = (struct vdec_bufferpayload *)\
+ tempbuffer;
+ /*TODO: Time stamp needs to be updated*/
+ ioctl_msg.inputparam = &frameinfo;
+ ioctl_msg.outputparam = NULL;
+ total_frames++;
+ if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_DECODE_FRAME,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Decoder frame failed");
+ sem_post (&decode_context->sem_synchronize);
+ }
+ DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\
+ total_frames);
+ break;
+
+ case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
+
+ outputbuffer = (struct vdec_output_frameinfo *)\
+ queueitem->clientdata;
+ DEBUG_PRINT("\n Value of client Data in VT %p",queueitem->clientdata);
+ if (outputbuffer == NULL || outputbuffer->bufferaddr == NULL ||
+ outputbuffer->client_data == NULL
+ )
+ {
+ DEBUG_PRINT("\n FATAL ERROR output buffer is bad");
+ DEBUG_PRINT("\nValues outputbuffer = %p",outputbuffer);
+ DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\
+ outputbuffer->bufferaddr);
+ DEBUG_PRINT("\nValues outputbuffer->client_data = %p",\
+ outputbuffer->client_data);
+ sem_post (&decode_context->sem_synchronize);
+ break;
+ }
+
+
+ if (outputbuffer->len == 0)
+ {
+ DEBUG_PRINT("\n Filled Length is zero Close decoding");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+ }
+
+ if (decode_context->outputBufferFile != NULL)
+ {
+ fwrite (outputbuffer->bufferaddr,1,outputbuffer->len,
+ decode_context->outputBufferFile);
+ }
+
+ tempbuffer = (struct vdec_bufferpayload *)\
+ outputbuffer->client_data;
+
+ DEBUG_PRINT("\n recieved output buffer consume outbuffer");
+ DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\
+ outputbuffer->bufferaddr);
+ DEBUG_PRINT ("\n Vir address of allocated buffer %p",\
+ tempbuffer->bufferaddr);
+ fillbuffer.buffer.buffer_len = tempbuffer->buffer_len;
+ fillbuffer.buffer.bufferaddr = tempbuffer->bufferaddr;
+ fillbuffer.buffer.offset = tempbuffer->offset;
+ fillbuffer.buffer.pmem_fd = tempbuffer->pmem_fd;
+ fillbuffer.client_data = (void *)outputbuffer;
+
+ ioctl_msg.inputparam = &fillbuffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (decode_context->video_driver_fd,
+ VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Decoder frame failed");
+ return NULL;
+ }
+
+ break;
+
+ case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
+ DEBUG_PRINT("\n Flush input complete");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+
+ case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
+ DEBUG_PRINT("\n Flush output complete");
+ sem_post (&decode_context->sem_synchronize);
+ break;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT("\n Error condition recieved NULL from Queue");
+ }
+
+ if (queueitem->cmd == VDEC_MSG_RESP_STOP_DONE)
+ {
+ DEBUG_PRINT("\n Playback has ended thread will exit");
+ return NULL;
+ }
+ }
+}
+
+static void* async_thread (void *context)
+{
+ struct video_decoder_context *decode_context = NULL;
+ struct vdec_output_frameinfo *outputframe = NULL;
+ struct video_msgq queueitem ;
+ struct vdec_msginfo vdec_msg;
+ struct vdec_ioctl_msg ioctl_msg = {NULL,NULL};
+ int result = -1;
+
+ if (context == NULL)
+ {
+ DEBUG_PRINT("\n aynsc thread recieved NULL context");
+ return NULL;
+ }
+ decode_context = (struct video_decoder_context *) context;
+ DEBUG_PRINT("\n Entering the async thread");
+
+ while (1)
+ {
+ ioctl_msg.inputparam = NULL;
+
+ ioctl_msg.outputparam = (void*)&vdec_msg;
+ DEBUG_PRINT ("\n Sizeof vdec_msginfo = %d ",sizeof (vdec_msg));
+ DEBUG_PRINT("\n Address of Vdec msg in async thread %p",\
+ ioctl_msg.outputparam);
+ if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG,\
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Error in ioctl read next msg");
+ }
+ else
+ {
+ switch (vdec_msg.msgcode)
+ {
+ case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
+ case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
+ case VDEC_MSG_RESP_START_DONE:
+ case VDEC_MSG_RESP_STOP_DONE:
+ case VDEC_MSG_EVT_HW_ERROR:
+ DEBUG_PRINT("\nioctl read next msg");
+ queueitem.cmd = vdec_msg.msgcode;
+ queueitem.status = vdec_msg.status_code;
+ queueitem.clientdata = NULL;
+ break;
+
+ case VDEC_MSG_RESP_INPUT_FLUSHED:
+ case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
+
+ queueitem.cmd = vdec_msg.msgcode;
+ queueitem.status = vdec_msg.status_code;
+ queueitem.clientdata = (void *)\
+ vdec_msg.msgdata.input_frame_clientdata;
+ break;
+
+ case VDEC_MSG_RESP_OUTPUT_FLUSHED:
+ case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
+ queueitem.cmd = vdec_msg.msgcode;
+ queueitem.status = vdec_msg.status_code;
+ outputframe = (struct vdec_output_frameinfo *)\
+ vdec_msg.msgdata.output_frame.client_data;
+ DEBUG_PRINT ("\n Client Data value in %p", \
+ vdec_msg.msgdata.output_frame.client_data);
+ outputframe->bufferaddr = vdec_msg.msgdata.output_frame.bufferaddr;
+ outputframe->framesize.n_bottom = \
+ vdec_msg.msgdata.output_frame.framesize.n_bottom;
+ outputframe->framesize.n_left = \
+ vdec_msg.msgdata.output_frame.framesize.n_left;
+ outputframe->framesize.n_right = \
+ vdec_msg.msgdata.output_frame.framesize.n_right;
+ outputframe->framesize.n_top = \
+ vdec_msg.msgdata.output_frame.framesize.n_top;
+ outputframe->framesize = vdec_msg.msgdata.output_frame.framesize;
+ outputframe->len = vdec_msg.msgdata.output_frame.len;
+ outputframe->time_stamp = vdec_msg.msgdata.output_frame.time_stamp;
+ queueitem.clientdata = (void *)outputframe;
+ DEBUG_PRINT ("\n Client Data value Copy %p",queueitem.clientdata);
+ break;
+
+ default:
+ DEBUG_PRINT("\nIn Default of get next message %d",vdec_msg.msgcode);
+ queueitem.cmd = vdec_msg.msgcode;
+ queueitem.status = vdec_msg.status_code;
+ queueitem.clientdata = NULL;
+ break;
+ }
+ result = queue_post_cmdq (&decode_context->queue_context,&queueitem);
+ while (result == 0)
+ {
+ result = queue_post_cmdq (&decode_context->queue_context,
+ &queueitem);
+ }
+
+ if (result == -1)
+ {
+ DEBUG_PRINT("\n FATAL ERROR WITH Queue");
+ }
+ }
+ if (vdec_msg.msgcode == VDEC_MSG_RESP_STOP_DONE)
+ {
+ /*Thread can exit at this point*/
+ return NULL;
+ }
+ }
+}
+
+
+static unsigned int read_frame (unsigned char *dataptr, unsigned int length,
+ FILE * inputBufferFile)
+{
+
+ unsigned int readOffset = 0;
+ int bytes_read = 0;
+ unsigned int code = 0;
+ int found = 0;
+
+ DEBUG_PRINT ("\n Inside the readframe");
+
+ if (dataptr == NULL && length == 0)
+ {
+ DEBUG_PRINT ("\n dataptr = %p length = %u",dataptr,length);
+ return 0;
+ }
+
+ if (!Code_type)
+ {
+ /* Start of Critical Section*/
+ pthread_mutex_lock(&read_lock);
+ do
+ {
+ //Start codes are always byte aligned.
+ bytes_read = fread(&dataptr[readOffset],1, 1,inputBufferFile);
+ if( !bytes_read)
+ {
+ DEBUG_PRINT("\n Bytes read Zero \n");
+ break;
+ }
+ code <<= 8;
+ code |= (0x000000FF & dataptr[readOffset]);
+ //VOP start code comparision
+ if (readOffset>3)
+ {
+ if(!header_code )
+ {
+ if( VOP_START_CODE == code)
+ {
+ DEBUG_PRINT ("\n Found VOP Code");
+ header_code = VOP_START_CODE;
+ }
+ else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE )
+ {
+ header_code = SHORT_HEADER_START_CODE;
+ }
+ }
+ if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=4;
+ found = 1;
+ break;
+
+ }
+ else if (( header_code == SHORT_HEADER_START_CODE ) &&
+ ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00)))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=4;
+ found = 1;
+ break;
+ }
+ }
+ readOffset++;
+ }while (readOffset < length);
+ pthread_mutex_unlock(&read_lock);
+ /* End of Critical Section*/
+ if (found == 1)
+ {
+ //DEBUG_PRINT ("Found a Frame");
+ return (readOffset+1);
+ }
+ else
+ {
+ //DEBUG_PRINT ("No Frames detected");
+ return 0;
+ }
+ }
+ else
+ {
+
+ readOffset = Read_Buffer_From_DAT_File(dataptr,length,inputBufferFile);
+ if (total_frames == 0)
+ {
+ bytes_read = Read_Buffer_From_DAT_File(&dataptr[readOffset],
+ (length-readOffset),
+ inputBufferFile);
+ readOffset += bytes_read;
+ }
+ return (readOffset);
+ }
+
+}
+
+static int Read_Buffer_From_DAT_File(unsigned char *dataptr, unsigned int length,
+ FILE * inputBufferFile)
+{
+
+
+ long frameSize=0;
+ char temp_buffer[10];
+ char temp_byte;
+ int bytes_read=0;
+ int i=0;
+ unsigned char *read_buffer=NULL;
+ char c = '1'; //initialize to anything except '\0'(0)
+ char inputFrameSize[10];
+ int count =0; char cnt =0;
+ memset(temp_buffer, 0, sizeof(temp_buffer));
+
+ while (cnt < 10)
+ /* Check the input file format, may result in infinite loop */
+ {
+ count = fread(&inputFrameSize[cnt],1,1,inputBufferFile);
+ if(inputFrameSize[cnt] == '\0' )
+ break;
+ cnt++;
+ }
+ inputFrameSize[cnt]='\0';
+ frameSize = atoi(inputFrameSize);
+ //length = 0;
+ DEBUG_PRINT ("\n Frame Size is %d",frameSize);
+
+ /* get the frame length */
+ fseek(inputBufferFile, -1, SEEK_CUR);
+ bytes_read = fread(dataptr, 1, frameSize, inputBufferFile);
+
+ if(bytes_read == 0 || bytes_read < frameSize ) {
+ return 0;
+ }
+ return bytes_read;
+}
diff --git a/omx/mm-video/vidc/vdec/test/omx_vdec_test.cpp b/omx/mm-video/vidc/vdec/test/omx_vdec_test.cpp
new file mode 100644
index 0000000..a7c0cc5
--- /dev/null
+++ b/omx/mm-video/vidc/vdec/test/omx_vdec_test.cpp
@@ -0,0 +1,2613 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*
+ An Open max test application ....
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include "OMX_QCOMExtns.h"
+
+#ifdef _ANDROID_
+#include <binder/MemoryHeapBase.h>
+
+extern "C"{
+#include<utils/Log.h>
+}
+#define LOG_TAG "OMX-VDEC-TEST"
+#define DEBUG_PRINT
+#define DEBUG_PRINT_ERROR
+
+#else
+#define DEBUG_PRINT printf
+#define DEBUG_PRINT_ERROR printf
+#endif /* _ANDROID_ */
+
+#include "OMX_Core.h"
+#include "OMX_Component.h"
+#include "OMX_QCOMExtns.h"
+extern "C" {
+#include "queue.h"
+}
+
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+//#include "qutility.h"
+
+
+/************************************************************************/
+/* #DEFINES */
+/************************************************************************/
+#define DELAY 66
+#define false 0
+#define true 1
+#define VOP_START_CODE 0x000001B6
+#define SHORT_HEADER_START_CODE 0x00008000
+#define VC1_START_CODE 0x00000100
+#define VC1_FRAME_START_CODE 0x0000010D
+#define NUMBER_OF_ARBITRARYBYTES_READ (4 * 1024)
+#define VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32
+#define VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16
+
+#define CONFIG_VERSION_SIZE(param) \
+ param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\
+ param.nSize = sizeof(param);
+
+#define FAILED(result) (result != OMX_ErrorNone)
+
+#define SUCCEEDED(result) (result == OMX_ErrorNone)
+#define SWAPBYTES(ptrA, ptrB) { char t = *ptrA; *ptrA = *ptrB; *ptrB = t;}
+#define SIZE_NAL_FIELD_MAX 4
+#define MDP_DEINTERLACE 0x80000000
+
+/************************************************************************/
+/* GLOBAL DECLARATIONS */
+/************************************************************************/
+#ifdef _ANDROID_
+using namespace android;
+#endif
+
+typedef enum {
+ CODEC_FORMAT_H264 = 1,
+ CODEC_FORMAT_MP4,
+ CODEC_FORMAT_H263,
+ CODEC_FORMAT_VC1,
+ CODEC_FORMAT_MAX = CODEC_FORMAT_VC1
+} codec_format;
+
+typedef enum {
+ FILE_TYPE_DAT_PER_AU = 1,
+ FILE_TYPE_ARBITRARY_BYTES,
+ FILE_TYPE_COMMON_CODEC_MAX,
+
+ FILE_TYPE_START_OF_H264_SPECIFIC = 10,
+ FILE_TYPE_264_NAL_SIZE_LENGTH = FILE_TYPE_START_OF_H264_SPECIFIC,
+
+ FILE_TYPE_START_OF_MP4_SPECIFIC = 20,
+ FILE_TYPE_PICTURE_START_CODE = FILE_TYPE_START_OF_MP4_SPECIFIC,
+
+ FILE_TYPE_START_OF_VC1_SPECIFIC = 30,
+ FILE_TYPE_RCV = FILE_TYPE_START_OF_VC1_SPECIFIC,
+ FILE_TYPE_VC1
+} file_type;
+
+typedef enum {
+ GOOD_STATE = 0,
+ PORT_SETTING_CHANGE_STATE,
+ ERROR_STATE,
+ INVALID_STATE
+} test_status;
+
+typedef enum {
+ FREE_HANDLE_AT_LOADED = 1,
+ FREE_HANDLE_AT_IDLE,
+ FREE_HANDLE_AT_EXECUTING,
+ FREE_HANDLE_AT_PAUSE
+} freeHandle_test;
+
+static int (*Read_Buffer)(OMX_BUFFERHEADERTYPE *pBufHdr );
+
+FILE * inputBufferFile;
+FILE * outputBufferFile;
+FILE * seqFile;
+int takeYuvLog = 0;
+int displayYuv = 0;
+int displayWindow = 0;
+int realtime_display = 0;
+struct timeval t_avsync={0};
+
+Queue *etb_queue = NULL;
+Queue *fbd_queue = NULL;
+
+pthread_t ebd_thread_id;
+pthread_t fbd_thread_id;
+void* ebd_thread(void*);
+void* fbd_thread(void*);
+
+pthread_mutex_t etb_lock;
+pthread_mutex_t fbd_lock;
+pthread_mutex_t lock;
+pthread_cond_t cond;
+pthread_mutex_t elock;
+pthread_cond_t econd;
+pthread_cond_t fcond;
+pthread_mutex_t eos_lock;
+pthread_cond_t eos_cond;
+
+sem_t etb_sem;
+sem_t fbd_sem;
+sem_t seq_sem;
+sem_t in_flush_sem, out_flush_sem;
+
+OMX_PARAM_PORTDEFINITIONTYPE portFmt;
+OMX_PORT_PARAM_TYPE portParam;
+OMX_ERRORTYPE error;
+
+#define CLR_KEY 0xe8fd
+#define COLOR_BLACK_RGBA_8888 0x00000000
+#define FRAMEBUFFER_32
+
+static int fb_fd = -1;
+static struct fb_var_screeninfo vinfo;
+static struct fb_fix_screeninfo finfo;
+static struct mdp_overlay overlay, *overlayp;
+static struct msmfb_overlay_data ov_front;
+static int vid_buf_front_id;
+int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr);
+void overlay_set();
+void overlay_unset();
+void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr);
+
+/************************************************************************/
+/* GLOBAL INIT */
+/************************************************************************/
+int input_buf_cnt = 0;
+int height =0, width =0;
+int sliceheight = 0, stride = 0;
+int used_ip_buf_cnt = 0;
+volatile int event_is_done = 0;
+int ebd_cnt, fbd_cnt;
+int bInputEosReached = 0;
+int bOutputEosReached = 0;
+char in_filename[512];
+char seq_file_name[512];
+unsigned char seq_enabled = 0, flush_in_progress = 0;
+unsigned int cmd_data = 0, etb_count = 0;;
+
+char curr_seq_command[100];
+int timeStampLfile = 0;
+int timestampInterval = 33333;
+codec_format codec_format_option;
+file_type file_type_option;
+freeHandle_test freeHandle_option;
+int nalSize;
+int sent_disabled = 0;
+int waitForPortSettingsChanged = 1;
+test_status currentStatus = GOOD_STATE;
+
+//* OMX Spec Version supported by the wrappers. Version = 1.1 */
+const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101;
+OMX_COMPONENTTYPE* dec_handle = 0;
+
+OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL;
+OMX_BUFFERHEADERTYPE **pOutYUVBufHdrs= NULL;
+
+int rcv_v1=0;
+
+/* Performance related variable*/
+//QPERF_INIT(render_fb);
+//QPERF_INIT(client_decode);
+
+/************************************************************************/
+/* GLOBAL FUNC DECL */
+/************************************************************************/
+int Init_Decoder();
+int Play_Decoder();
+int run_tests();
+
+/**************************************************************************/
+/* STATIC DECLARATIONS */
+/**************************************************************************/
+static int video_playback_count = 1;
+static int open_video_file ();
+static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr );
+static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr);
+
+static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle,
+ OMX_BUFFERHEADERTYPE ***pBufHdrs,
+ OMX_U32 nPortIndex,
+ long bufCntMin, long bufSize);
+
+
+static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+static OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+
+static void do_freeHandle_and_clean_up(bool isDueToError);
+
+/*static usecs_t get_time(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return ((usecs_t)tv.tv_usec) +
+ (((usecs_t)tv.tv_sec) * ((usecs_t)1000000));
+}*/
+
+
+void wait_for_event(void)
+{
+ DEBUG_PRINT("Waiting for event\n");
+ pthread_mutex_lock(&lock);
+ while (event_is_done == 0) {
+ pthread_cond_wait(&cond, &lock);
+ }
+ event_is_done = 0;
+ pthread_mutex_unlock(&lock);
+ DEBUG_PRINT("Running .... get the event\n");
+}
+
+void event_complete(void )
+{
+ pthread_mutex_lock(&lock);
+ if (event_is_done == 0) {
+ event_is_done = 1;
+ pthread_cond_broadcast(&cond);
+ }
+ pthread_mutex_unlock(&lock);
+}
+int get_next_command(FILE *seq_file)
+{
+ int i = -1;
+ do{
+ i++;
+ if(fread(&curr_seq_command[i], 1, 1, seq_file) != 1)
+ return -1;
+ }while(curr_seq_command[i] != '\n');
+ curr_seq_command[i] = 0;
+ printf("\n cmd_str = %s", curr_seq_command);
+ return 0;
+}
+
+void process_current_command(const char *seq_command)
+{
+ char *data_str = NULL;
+ unsigned int data = 0, bufCnt = 0, i = 0;
+ int frameSize;
+ OMX_ERRORTYPE ret;
+
+ if(strstr(seq_command, "pause") == seq_command)
+ {
+ printf("\n\n $$$$$ PAUSE $$$$$");
+ data_str = (char*)seq_command + strlen("pause") + 1;
+ data = atoi(data_str);
+ printf("\n After frame number %u", data);
+ cmd_data = data;
+ sem_wait(&seq_sem);
+ printf("\n Sending PAUSE cmd to OMX compt");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0);
+ wait_for_event();
+ printf("\n EventHandler for PAUSE DONE");
+ }
+ else if(strstr(seq_command, "sleep") == seq_command)
+ {
+ printf("\n\n $$$$$ SLEEP $$$$$");
+ data_str = (char*)seq_command + strlen("sleep") + 1;
+ data = atoi(data_str);
+ printf("\n Sleep Time = %u ms", data);
+ usleep(data*1000);
+ }
+ else if(strstr(seq_command, "resume") == seq_command)
+ {
+ printf("\n\n $$$$$ RESUME $$$$$");
+ printf("\n Immediate effect", data);
+ printf("\n Sending PAUSE cmd to OMX compt");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0);
+ wait_for_event();
+ printf("\n EventHandler for RESUME DONE");
+ }
+ else if(strstr(seq_command, "flush") == seq_command)
+ {
+ printf("\n\n $$$$$ FLUSH $$$$$");
+ data_str = (char*)seq_command + strlen("flush") + 1;
+ data = atoi(data_str);
+ printf("\n After frame number %u", data);
+ cmd_data = data;
+ sem_wait(&seq_sem);
+ printf("\n Sending FLUSH cmd to OMX compt");
+ flush_in_progress = 1;
+ OMX_SendCommand(dec_handle, OMX_CommandFlush, OMX_ALL, 0);
+ wait_for_event();
+ flush_in_progress = 0;
+ printf("\n EventHandler for FLUSH DONE");
+ printf("\n Post EBD_thread flush sem");
+ sem_post(&in_flush_sem);
+ printf("\n Post FBD_thread flush sem");
+ sem_post(&out_flush_sem);
+ }
+ else
+ {
+ printf("\n\n $$$$$ INVALID CMD $$$$$");
+ printf("\n seq_command[%s] is invalid", seq_command);
+ seq_enabled = 0;
+ }
+}
+
+void* ebd_thread(void* pArg)
+{
+ while(currentStatus != INVALID_STATE)
+ {
+ int readBytes =0;
+ OMX_BUFFERHEADERTYPE* pBuffer = NULL;
+
+ if(flush_in_progress)
+ {
+ printf("\n EBD_thread flush wait start");
+ sem_wait(&in_flush_sem);
+ printf("\n EBD_thread flush wait complete");
+ }
+
+ sem_wait(&etb_sem);
+ pthread_mutex_lock(&etb_lock);
+ pBuffer = (OMX_BUFFERHEADERTYPE *) pop(etb_queue);
+ pthread_mutex_unlock(&etb_lock);
+ if(pBuffer == NULL)
+ {
+ DEBUG_PRINT_ERROR("Error - No etb pBuffer to dequeue\n");
+ continue;
+ }
+
+ pBuffer->nOffset = 0;
+ if((readBytes = Read_Buffer(pBuffer)) > 0) {
+ pBuffer->nFilledLen = readBytes;
+ OMX_EmptyThisBuffer(dec_handle,pBuffer);
+ etb_count++;
+ if(cmd_data == etb_count)
+ {
+ sem_post(&seq_sem);
+ printf("\n Posted seq_sem");
+ }
+ }
+ else
+ {
+ pBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
+ bInputEosReached = true;
+ pBuffer->nFilledLen = readBytes;
+ OMX_EmptyThisBuffer(dec_handle,pBuffer);
+ DEBUG_PRINT("EBD::Either EOS or Some Error while reading file\n");
+ etb_count++;
+ if(cmd_data == etb_count)
+ {
+ sem_post(&seq_sem);
+ printf("\n Posted seq_sem");
+ }
+ break;
+ }
+ }
+ return NULL;
+}
+
+void* fbd_thread(void* pArg)
+{
+ while(currentStatus != INVALID_STATE)
+ {
+ long current_avsync_time = 0, delta_time = 0;
+ int canDisplay = 1;
+ static int contigous_drop_frame = 0;
+ static long base_avsync_time = 0;
+ static long base_timestamp = 0;
+ long lipsync_time = 250000;
+ int bytes_written = 0;
+ OMX_BUFFERHEADERTYPE *pBuffer;
+
+ if(flush_in_progress)
+ {
+ printf("\n FBD_thread flush wait start");
+ sem_wait(&out_flush_sem);
+ printf("\n FBD_thread flush wait complete");
+ }
+
+ sem_wait(&fbd_sem);
+ DEBUG_PRINT("Inside %s fbd_cnt[%d] \n", __FUNCTION__, fbd_cnt);
+
+ fbd_cnt++;
+ pthread_mutex_lock(&fbd_lock);
+ pBuffer = (OMX_BUFFERHEADERTYPE *) pop(fbd_queue);
+ pthread_mutex_unlock(&fbd_lock);
+ if (pBuffer == NULL)
+ {
+ DEBUG_PRINT("Error - No pBuffer to dequeue\n");
+ continue;
+ }
+
+ /*********************************************
+ Write the output of the decoder to the file.
+ *********************************************/
+
+ if (sent_disabled)
+ {
+ DEBUG_PRINT("Ignoring FillBufferDone\n");
+ continue;
+ }
+
+ if (realtime_display)
+ {
+ if(!gettimeofday(&t_avsync,NULL))
+ {
+ current_avsync_time =(t_avsync.tv_sec*1000000)+t_avsync.tv_usec;
+ }
+
+ if (base_avsync_time != 0)
+ {
+ pthread_mutex_lock(&fbd_lock);
+ delta_time = (current_avsync_time - base_avsync_time) - ((long)pBuffer->nTimeStamp - base_timestamp);
+ if (delta_time < 0 )
+ {
+ DEBUG_PRINT_ERROR("Sleep %d us. AV Sync time is left behind\n",
+ -delta_time);
+ usleep(-delta_time);
+ canDisplay = 1;
+ }
+ else if ((delta_time>lipsync_time) && (contigous_drop_frame < 6))
+ {
+ DEBUG_PRINT_ERROR("Error - Drop the frame at the renderer. Video frame with ts %lu usec behind by %ld usec"
+ ", pBuffer->nFilledLen %u\n",
+ (unsigned long)pBuffer->nTimeStamp, delta_time, pBuffer->nFilledLen);
+ canDisplay = 0;
+ contigous_drop_frame++;
+ }
+ else
+ {
+ canDisplay = 1;
+ }
+ pthread_mutex_unlock(&fbd_lock);
+ }
+ else
+ {
+ base_avsync_time = current_avsync_time;
+ base_timestamp = (long)pBuffer->nTimeStamp;
+ }
+ }
+
+ if (!flush_in_progress && displayYuv && canDisplay && pBuffer->nFilledLen > 0)
+ {
+ if(overlay_fb(pBuffer))
+ break;
+ contigous_drop_frame = 0;
+ }
+
+ if (!flush_in_progress && takeYuvLog) {
+ pthread_mutex_lock(&fbd_lock);
+ bytes_written = fwrite((const char *)pBuffer->pBuffer,
+ pBuffer->nFilledLen,1,outputBufferFile);
+ pthread_mutex_unlock(&fbd_lock);
+ if (bytes_written < 0) {
+ DEBUG_PRINT("\nFillBufferDone: Failed to write to the file\n");
+ }
+ else {
+ DEBUG_PRINT("\nFillBufferDone: Wrote %d YUV bytes to the file\n",
+ bytes_written);
+ }
+ }
+
+ /********************************************************************/
+ /* De-Initializing the open max and relasing the buffers and */
+ /* closing the files.*/
+ /********************************************************************/
+ if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS ) {
+ DEBUG_PRINT("***************************************************\n");
+ DEBUG_PRINT("FillBufferDone: End Of Stream Reached\n");
+ DEBUG_PRINT("***************************************************\n");
+ pthread_mutex_lock(&eos_lock);
+ bOutputEosReached = true;
+ pthread_cond_broadcast(&eos_cond);
+ pthread_mutex_unlock(&eos_lock);
+ //QPERF_END(client_decode);
+ //QPERF_SET_ITERATION(client_decode, fbd_cnt);
+ DEBUG_PRINT("***************************************************\n");
+ DEBUG_PRINT("FBD_THREAD bOutputEosReached %d\n",bOutputEosReached);
+ break;
+ }
+ OMX_FillThisBuffer(dec_handle, pBuffer);
+ }
+ return NULL;
+}
+
+OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+ DEBUG_PRINT("Function %s \n", __FUNCTION__);
+
+ switch(eEvent) {
+ case OMX_EventCmdComplete:
+ DEBUG_PRINT("\n OMX_EventCmdComplete \n");
+ // check nData1 for DISABLE event
+ if(OMX_CommandPortDisable == (OMX_COMMANDTYPE)nData1)
+ {
+ DEBUG_PRINT("*********************************************\n");
+ DEBUG_PRINT("Recieved DISABLE Event Command Complete[%d]\n",nData2);
+ DEBUG_PRINT("*********************************************\n");
+ sent_disabled = 0;
+ }
+ else if(OMX_CommandPortEnable == (OMX_COMMANDTYPE)nData1)
+ {
+ DEBUG_PRINT("*********************************************\n");
+ DEBUG_PRINT("Recieved ENABLE Event Command Complete[%d]\n",nData2);
+ DEBUG_PRINT("*********************************************\n");
+ }
+ currentStatus = GOOD_STATE;
+ event_complete();
+ break;
+
+ case OMX_EventError:
+ DEBUG_PRINT("OMX_EventError \n");
+ currentStatus = ERROR_STATE;
+ if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)nData1 ||
+ OMX_ErrorHardware == (OMX_ERRORTYPE)nData1)
+ {
+ DEBUG_PRINT("Invalid State or hardware error \n");
+ currentStatus = INVALID_STATE;
+ if(event_is_done == 0)
+ {
+ DEBUG_PRINT("Event error in the middle of Decode \n");
+ pthread_mutex_lock(&eos_lock);
+ bOutputEosReached = true;
+ pthread_cond_broadcast(&eos_cond);
+ pthread_mutex_unlock(&eos_lock);
+
+ }
+ }
+
+ event_complete();
+ break;
+ case OMX_EventPortSettingsChanged:
+ DEBUG_PRINT("OMX_EventPortSettingsChanged port[%d]\n",nData1);
+ waitForPortSettingsChanged = 0;
+ currentStatus = PORT_SETTING_CHANGE_STATE;
+ // reset the event
+ event_complete();
+ break;
+
+ default:
+ DEBUG_PRINT_ERROR("ERROR - Unknown Event \n");
+ break;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ int readBytes =0; int bufCnt=0;
+ OMX_ERRORTYPE result;
+
+ DEBUG_PRINT("Function %s cnt[%d]\n", __FUNCTION__, ebd_cnt);
+ ebd_cnt++;
+
+
+ if(bInputEosReached) {
+ DEBUG_PRINT("*****EBD:Input EoS Reached************\n");
+ return OMX_ErrorNone;
+ }
+
+ pthread_mutex_lock(&etb_lock);
+ if(push(etb_queue, (void *) pBuffer) < 0)
+ {
+ DEBUG_PRINT_ERROR("Error in enqueue ebd data\n");
+ return OMX_ErrorUndefined;
+ }
+ pthread_mutex_unlock(&etb_lock);
+ sem_post(&etb_sem);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ DEBUG_PRINT("Inside %s callback_count[%d] \n", __FUNCTION__, fbd_cnt);
+
+ /* Test app will assume there is a dynamic port setting
+ * In case that there is no dynamic port setting, OMX will not call event cb,
+ * instead OMX will send empty this buffer directly and we need to clear an event here
+ */
+ if(waitForPortSettingsChanged)
+ {
+ currentStatus = GOOD_STATE;
+ waitForPortSettingsChanged = 0;
+
+ if(displayYuv)
+ {
+ overlay_set();
+ }
+ event_complete();
+ }
+
+ if(!sent_disabled)
+ {
+ pthread_mutex_lock(&fbd_lock);
+ if(push(fbd_queue, (void *)pBuffer) < 0)
+ {
+ DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n");
+ return OMX_ErrorUndefined;
+ }
+ pthread_mutex_unlock(&fbd_lock);
+ sem_post(&fbd_sem);
+ }
+ return OMX_ErrorNone;
+}
+
+int main(int argc, char **argv)
+{
+ int i=0;
+ int bufCnt=0;
+ int num=0;
+ int outputOption = 0;
+ int test_option = 0;
+ OMX_ERRORTYPE result;
+
+ if (argc < 2)
+ {
+ printf("To use it: ./mm-vdec-omx-test <clip location> \n");
+ printf("Command line argument is also available\n");
+ return -1;
+ }
+
+ strncpy(in_filename, argv[1], strlen(argv[1])+1);
+
+ if(argc > 5)
+ {
+ codec_format_option = (codec_format)atoi(argv[2]);
+ file_type_option = (file_type)atoi(argv[3]);
+ }
+ else
+ {
+ printf("Command line argument is available\n");
+ printf("To use it: ./mm-vdec-omx-test <clip location> <codec_type> \n");
+ printf(" <input_type: 1. per AU(.dat), 2. arbitrary, 3.per NAL/frame>\n");
+ printf(" <output_type> <test_case> <size_nal if H264>\n\n\n");
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1--> H264\n");
+ printf(" 2--> MP4\n");
+ printf(" 3--> H263\n");
+ printf(" 4--> VC1\n");
+ fflush(stdin);
+ scanf("%d", &codec_format_option);
+ fflush(stdin);
+
+ if (codec_format_option > CODEC_FORMAT_MAX)
+ {
+ printf(" Wrong test case...[%d] \n", codec_format_option);
+ return -1;
+ }
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1--> PER ACCESS UNIT CLIP (.dat). Clip only available for H264 and Mpeg4\n");
+ printf(" 2--> ARBITRARY BYTES (need .264/.264c/.mv4/.263/.rcv/.vc1)\n");
+ if (codec_format_option == CODEC_FORMAT_H264)
+ {
+ printf(" 3--> NAL LENGTH SIZE CLIP (.264c)\n");
+ }
+ else if ( (codec_format_option == CODEC_FORMAT_MP4) || (codec_format_option == CODEC_FORMAT_H263) )
+ {
+ printf(" 3--> MP4 VOP or H263 P0 SHORT HEADER START CODE CLIP (.m4v or .263)\n");
+ }
+ else if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ printf(" 3--> VC1 clip Simple/Main Profile (.rcv)\n");
+ printf(" 4--> VC1 clip Advance Profile (.vc1)\n");
+ }
+ fflush(stdin);
+ scanf("%d", &file_type_option);
+ fflush(stdin);
+ }
+
+ if (file_type_option >= FILE_TYPE_COMMON_CODEC_MAX)
+ {
+ switch (codec_format_option)
+ {
+ case CODEC_FORMAT_H264:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_H264_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ case CODEC_FORMAT_MP4:
+ case CODEC_FORMAT_H263:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_MP4_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ case CODEC_FORMAT_VC1:
+ file_type_option = (file_type)(FILE_TYPE_START_OF_VC1_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX);
+ break;
+ default:
+ printf("Error: Unknown code %d\n", codec_format_option);
+ }
+ }
+
+ if(argc > 5)
+ {
+ outputOption = atoi(argv[4]);
+ test_option = atoi(argv[5]);
+ if (argc > 6)
+ {
+ nalSize = atoi(argv[6]);
+ }
+ else
+ {
+ nalSize = 0;
+ }
+
+ if(argc > 7)
+ {
+ displayWindow = atoi(argv[7]);
+ if(displayWindow > 0)
+ {
+ printf(" Curently display window 0 only supported; ignoring other values\n");
+ displayWindow = 0;
+ }
+ }
+ else
+ {
+ displayWindow = 0;
+ }
+
+ if((file_type_option == FILE_TYPE_PICTURE_START_CODE) ||
+ (file_type_option == FILE_TYPE_RCV) ||
+ (file_type_option == FILE_TYPE_VC1) && argc > 8)
+ {
+ realtime_display = atoi(argv[8]);
+ }
+
+ if(realtime_display)
+ {
+ takeYuvLog = 0;
+ if(argc > 9)
+ {
+ int fps = atoi(argv[9]);
+ timestampInterval = 1000000/fps;
+ }
+ else if(argc > 10)
+ {
+ strncpy(seq_file_name, argv[10], strlen(argv[10])+1);
+ }
+ }
+ else
+ {
+ if(argc > 9)
+ {
+ strncpy(seq_file_name, argv[9], strlen(argv[9])+1);
+ }
+ }
+ height=144;width=176; // Assume Default as QCIF
+ sliceheight = 144;
+ stride = 176;
+ printf("Executing DynPortReconfig QCIF 144 x 176 \n");
+ }
+ else
+ {
+ int fps = 30;
+ switch(file_type_option)
+ {
+ case FILE_TYPE_DAT_PER_AU:
+ case FILE_TYPE_ARBITRARY_BYTES:
+ case FILE_TYPE_264_NAL_SIZE_LENGTH:
+ case FILE_TYPE_PICTURE_START_CODE:
+ case FILE_TYPE_RCV:
+ case FILE_TYPE_VC1:
+ {
+ nalSize = 0;
+ if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) ||
+ ((codec_format_option == CODEC_FORMAT_H264) && (file_type_option == FILE_TYPE_ARBITRARY_BYTES)))
+ {
+ printf(" Enter Nal length size [2 or 4] \n");
+ if (file_type_option == FILE_TYPE_ARBITRARY_BYTES)
+ {
+ printf(" Enter 0 if it is a start code based clip\n");
+ }
+ scanf("%d", &nalSize);
+ if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) &&
+ (nalSize == 0))
+ {
+ printf("Error - Can't pass NAL length size = 0\n");
+ return -1;
+ }
+ }
+
+ height=144;width=176; // Assume Default as QCIF
+ printf("Executing DynPortReconfig QCIF 144 x 176 \n");
+ break;
+ }
+
+ default:
+ {
+ printf(" Wrong test case...[%d] \n",file_type_option);
+ return -1;
+ }
+ }
+
+ printf(" *********************************************\n");
+ printf(" Output buffer option:\n");
+ printf(" *********************************************\n");
+ printf(" 0 --> No display and no YUV log\n");
+ printf(" 1 --> Diplay YUV\n");
+ printf(" 2 --> Take YUV log\n");
+ printf(" 3 --> Display YUV and take YUV log\n");
+ fflush(stdin);
+ scanf("%d", &outputOption);
+ fflush(stdin);
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1 --> Play the clip till the end\n");
+ printf(" 2 --> Run compliance test. Do NOT expect any display for most option. \n");
+ printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n");
+ fflush(stdin);
+ scanf("%d", &test_option);
+ fflush(stdin);
+
+ printf(" *********************************************\n");
+ printf(" ENTER THE PORTION OF DISPLAY TO USE\n");
+ printf(" *********************************************\n");
+ printf(" 0 --> Entire Screen\n");
+ printf(" 1 --> 1/4 th of the screen starting from top left corner to middle \n");
+ printf(" 2 --> 1/4 th of the screen starting from middle to top right corner \n");
+ printf(" 3 --> 1/4 th of the screen starting from middle to bottom left \n");
+ printf(" 4 --> 1/4 th of the screen starting from middle to bottom right \n");
+ printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n");
+ fflush(stdin);
+ scanf("%d", &displayWindow);
+ fflush(stdin);
+
+ if(displayWindow > 0)
+ {
+ printf(" Curently display window 0 only supported; ignoring other values\n");
+ displayWindow = 0;
+ }
+
+ if((file_type_option == FILE_TYPE_PICTURE_START_CODE) ||
+ (file_type_option == FILE_TYPE_RCV) ||
+ (file_type_option == FILE_TYPE_VC1))
+ {
+ printf(" *********************************************\n");
+ printf(" DO YOU WANT TEST APP TO RENDER in Real time \n");
+ printf(" 0 --> NO\n 1 --> YES\n");
+ printf(" Warning: For H264, it require one NAL per frame clip.\n");
+ printf(" For Arbitrary bytes option, Real time display is not recommended\n");
+ printf(" *********************************************\n");
+ fflush(stdin);
+ scanf("%d", &realtime_display);
+ fflush(stdin);
+ }
+
+
+ if (realtime_display)
+ {
+ printf(" *********************************************\n");
+ printf(" ENTER THE CLIP FPS\n");
+ printf(" Exception: Timestamp extracted from clips will be used.\n");
+ printf(" *********************************************\n");
+ fflush(stdin);
+ scanf("%d", &fps);
+ fflush(stdin);
+ timestampInterval = 1000000/fps;
+ }
+ printf(" *********************************************\n");
+ printf(" ENTER THE SEQ FILE NAME\n");
+ printf(" *********************************************\n");
+ fflush(stdin);
+ scanf("%[^\n]", &seq_file_name);
+ fflush(stdin);
+ }
+
+ if (outputOption == 0)
+ {
+ displayYuv = 0;
+ takeYuvLog = 0;
+ realtime_display = 0;
+ }
+ else if (outputOption == 1)
+ {
+ displayYuv = 1;
+ }
+ else if (outputOption == 2)
+ {
+ takeYuvLog = 1;
+ realtime_display = 0;
+ }
+ else if (outputOption == 3)
+ {
+ displayYuv = 1;
+ takeYuvLog = !realtime_display;
+ }
+ else
+ {
+ printf("Wrong option. Assume you want to see the YUV display\n");
+ displayYuv = 1;
+ }
+
+ if (test_option == 2)
+ {
+ printf(" *********************************************\n");
+ printf(" ENTER THE COMPLIANCE TEST YOU WOULD LIKE TO EXECUTE\n");
+ printf(" *********************************************\n");
+ printf(" 1 --> Call Free Handle at the OMX_StateLoaded\n");
+ printf(" 2 --> Call Free Handle at the OMX_StateIdle\n");
+ printf(" 3 --> Call Free Handle at the OMX_StateExecuting\n");
+ printf(" 4 --> Call Free Handle at the OMX_StatePause\n");
+ fflush(stdin);
+ scanf("%d", &freeHandle_option);
+ fflush(stdin);
+ }
+ else
+ {
+ freeHandle_option = (freeHandle_test)0;
+ }
+
+ printf("Input values: inputfilename[%s]\n", in_filename);
+ printf("*******************************************************\n");
+ pthread_cond_init(&cond, 0);
+ pthread_cond_init(&eos_cond, 0);
+ pthread_mutex_init(&eos_lock, 0);
+ pthread_mutex_init(&lock, 0);
+ pthread_mutex_init(&etb_lock, 0);
+ pthread_mutex_init(&fbd_lock, 0);
+ if (-1 == sem_init(&etb_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+ if (-1 == sem_init(&fbd_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+ if (-1 == sem_init(&seq_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+ if (-1 == sem_init(&in_flush_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+ if (-1 == sem_init(&out_flush_sem, 0, 0))
+ {
+ printf("Error - sem_init failed %d\n", errno);
+ }
+ etb_queue = alloc_queue();
+ if (etb_queue == NULL)
+ {
+ printf("\n Error in Creating etb_queue\n");
+ return -1;
+ }
+
+ fbd_queue = alloc_queue();
+ if (fbd_queue == NULL)
+ {
+ printf("\n Error in Creating fbd_queue\n");
+ free_queue(etb_queue);
+ return -1;
+ }
+
+ if(0 != pthread_create(&fbd_thread_id, NULL, fbd_thread, NULL))
+ {
+ printf("\n Error in Creating fbd_thread \n");
+ free_queue(etb_queue);
+ free_queue(fbd_queue);
+ return -1;
+ }
+
+ if (displayYuv)
+ {
+ //QPERF_RESET(render_fb);
+#ifdef _ANDROID_
+ DEBUG_PRINT("\n Opening /dev/graphics/fb0");
+ fb_fd = open("/dev/graphics/fb0", O_RDWR);
+#else
+ DEBUG_PRINT("\n Opening /dev/fb0");
+ fb_fd = open("/dev/fb0", O_RDWR);
+#endif
+ if (fb_fd < 0) {
+ printf("[omx_vdec_test] - ERROR - can't open framebuffer!\n");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n fb_fd = %d", fb_fd);
+ if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0)
+ {
+ printf("[omx_vdec_test] - ERROR - can't retrieve fscreenInfo!\n");
+ close(fb_fd);
+ return -1;
+ }
+ if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
+ {
+ printf("[omx_vdec_test] - ERROR - can't retrieve vscreenInfo!\n");
+ close(fb_fd);
+ return -1;
+ }
+ }
+
+ run_tests();
+ pthread_cond_destroy(&cond);
+ pthread_mutex_destroy(&lock);
+ pthread_mutex_destroy(&etb_lock);
+ pthread_mutex_destroy(&fbd_lock);
+ pthread_cond_destroy(&eos_cond);
+ pthread_mutex_destroy(&eos_lock);
+ if (-1 == sem_destroy(&etb_sem))
+ {
+ DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno);
+ }
+ if (-1 == sem_destroy(&fbd_sem))
+ {
+ DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno);
+ }
+ if (-1 == sem_destroy(&seq_sem))
+ {
+ DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno);
+ }
+ if (-1 == sem_destroy(&in_flush_sem))
+ {
+ DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno);
+ }
+ if (-1 == sem_destroy(&out_flush_sem))
+ {
+ DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno);
+ }
+ if (displayYuv)
+ {
+ overlay_unset();
+ close(fb_fd);
+ fb_fd = -1;
+ //QPERF_TERMINATE(render_fb);
+ }
+ //QPERF_TERMINATE(client_decode);
+ return 0;
+}
+
+int run_tests()
+{
+ DEBUG_PRINT("Inside %s\n", __FUNCTION__);
+ waitForPortSettingsChanged = 1;
+ currentStatus = GOOD_STATE;
+
+ if(file_type_option == FILE_TYPE_DAT_PER_AU) {
+ Read_Buffer = Read_Buffer_From_DAT_File;
+ }
+ else if(file_type_option == FILE_TYPE_ARBITRARY_BYTES) {
+ Read_Buffer = Read_Buffer_ArbitraryBytes;
+ }
+ else if(codec_format_option == CODEC_FORMAT_H264) {
+ Read_Buffer = Read_Buffer_From_Size_Nal;
+ }
+ else if((codec_format_option == CODEC_FORMAT_H263) ||
+ (codec_format_option == CODEC_FORMAT_MP4)) {
+ Read_Buffer = Read_Buffer_From_Vop_Start_Code_File;
+ }
+ else if(file_type_option == FILE_TYPE_RCV) {
+ Read_Buffer = Read_Buffer_From_RCV_File;
+ }
+ else if(file_type_option == FILE_TYPE_VC1) {
+ Read_Buffer = Read_Buffer_From_VC1_File;
+ }
+
+ DEBUG_PRINT("file_type_option %d!\n", file_type_option);
+
+ switch(file_type_option)
+ {
+ case FILE_TYPE_DAT_PER_AU:
+ case FILE_TYPE_ARBITRARY_BYTES:
+ case FILE_TYPE_264_NAL_SIZE_LENGTH:
+ case FILE_TYPE_PICTURE_START_CODE:
+ case FILE_TYPE_RCV:
+ case FILE_TYPE_VC1:
+ if(Init_Decoder()!= 0x00)
+ {
+ DEBUG_PRINT_ERROR("Error - Decoder Init failed\n");
+ return -1;
+ }
+ if(Play_Decoder() != 0x00)
+ {
+ return -1;
+ }
+ break;
+ default:
+ DEBUG_PRINT_ERROR("Error - Invalid Entry...%d\n",file_type_option);
+ break;
+ }
+
+ if(strlen(seq_file_name))
+ {
+ seqFile = fopen (seq_file_name, "rb");
+ if (seqFile == NULL)
+ {
+ DEBUG_PRINT_ERROR("Error - Seq file %s could NOT be opened\n",
+ seq_file_name);
+ }
+ else
+ {
+ DEBUG_PRINT("Seq file %s is opened \n", seq_file_name);
+ seq_enabled = 1;
+ }
+ }
+
+ pthread_mutex_lock(&eos_lock);
+ while (bOutputEosReached == false)
+ {
+ if(seq_enabled)
+ {
+ if(!get_next_command(seqFile))
+ {
+ process_current_command(curr_seq_command);
+ }
+ else
+ {
+ printf("\n Error in get_next_cmd or EOF");
+ seq_enabled = 0;
+ }
+ }
+ else
+ {
+ pthread_cond_wait(&eos_cond, &eos_lock);
+ }
+ }
+ pthread_mutex_unlock(&eos_lock);
+
+ // Wait till EOS is reached...
+ if(bOutputEosReached)
+ {
+ int bufCnt = 0;
+
+ DEBUG_PRINT("Moving the decoder to idle state \n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0);
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return 0;
+ }
+
+ DEBUG_PRINT("Moving the decoder to loaded state \n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateLoaded,0);
+
+ DEBUG_PRINT("[OMX Vdec Test] - Deallocating i/p and o/p buffers \n");
+ for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]);
+ }
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]);
+ }
+
+ fbd_cnt = 0; ebd_cnt=0;
+ bInputEosReached = false;
+ bOutputEosReached = false;
+
+ wait_for_event();
+
+ DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n");
+ OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle);
+ if (result != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("[OMX Vdec Test] - Terminate: OMX_FreeHandle error. Error code: %d\n", result);
+ }
+ dec_handle = NULL;
+
+ /* Deinit OpenMAX */
+ DEBUG_PRINT("[OMX Vdec Test] - Terminate: De-initializing OMX \n");
+ OMX_Deinit();
+
+ DEBUG_PRINT("[OMX Vdec Test] - Terminate: closing all files\n");
+ if(inputBufferFile)
+ {
+ fclose(inputBufferFile);
+ inputBufferFile = NULL;
+ }
+
+
+ if (takeYuvLog && outputBufferFile) {
+ fclose(outputBufferFile);
+ outputBufferFile = NULL;
+ }
+
+ if(etb_queue)
+ {
+ free_queue(etb_queue);
+ etb_queue = NULL;
+ }
+ if(fbd_queue)
+ {
+ free_queue(fbd_queue);
+ fbd_queue = NULL;
+ }
+
+ printf("*****************************************\n");
+ printf("******...TEST SUCCESSFULL...*******\n");
+ printf("*****************************************\n");
+
+ }
+
+ return 0;
+}
+
+int Init_Decoder()
+{
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE omxresult;
+ OMX_U32 total = 0;
+ char vdecCompNames[50];
+ typedef OMX_U8* OMX_U8_PTR;
+ char *role ="video_decoder";
+
+ static OMX_CALLBACKTYPE call_back = {&EventHandler, &EmptyBufferDone, &FillBufferDone};
+
+ int i = 0;
+ long bufCnt = 0;
+
+ /* Init. the OpenMAX Core */
+ DEBUG_PRINT("\nInitializing OpenMAX Core....\n");
+ omxresult = OMX_Init();
+
+ if(OMX_ErrorNone != omxresult) {
+ DEBUG_PRINT_ERROR("\n Failed to Init OpenMAX core");
+ return -1;
+ }
+ else {
+ DEBUG_PRINT_ERROR("\nOpenMAX Core Init Done\n");
+ }
+
+ /* Query for video decoders*/
+ OMX_GetComponentsOfRole(role, &total, 0);
+ DEBUG_PRINT("\nTotal components of role=%s :%d", role, total);
+
+ if(total)
+ {
+ /* Allocate memory for pointers to component name */
+ OMX_U8** vidCompNames = (OMX_U8**)malloc((sizeof(OMX_U8*))*total);
+
+ for (i = 0; i < total; ++i) {
+ vidCompNames[i] = (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_MAX_STRINGNAME_SIZE);
+ }
+ OMX_GetComponentsOfRole(role, &total, vidCompNames);
+ DEBUG_PRINT("\nComponents of Role:%s\n", role);
+ for (i = 0; i < total; ++i) {
+ DEBUG_PRINT("\nComponent Name [%s]\n",vidCompNames[i]);
+ free(vidCompNames[i]);
+ }
+ free(vidCompNames);
+ }
+ else {
+ DEBUG_PRINT_ERROR("No components found with Role:%s", role);
+ }
+
+ if (codec_format_option == CODEC_FORMAT_H264)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.avc", 27);
+ }
+ else if (codec_format_option == CODEC_FORMAT_MP4)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg4", 29);
+ }
+ else if (codec_format_option == CODEC_FORMAT_H263)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.h263", 28);
+ }
+ else if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ strncpy(vdecCompNames, "OMX.qcom.video.decoder.vc1", 27);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option);
+ return -1;
+ }
+
+ omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&dec_handle),
+ (OMX_STRING)vdecCompNames, NULL, &call_back);
+ if (FAILED(omxresult)) {
+ DEBUG_PRINT_ERROR("\nFailed to Load the component:%s\n", vdecCompNames);
+ return -1;
+ }
+ else
+ {
+ DEBUG_PRINT("\nComponent %s is in LOADED state\n", vdecCompNames);
+ }
+
+ QOMX_VIDEO_QUERY_DECODER_INSTANCES decoder_instances;
+ omxresult = OMX_GetConfig(dec_handle,
+ (OMX_INDEXTYPE)OMX_QcomIndexQueryNumberOfVideoDecInstance,
+ &decoder_instances);
+ DEBUG_PRINT("\n Number of decoder instances %d",
+ decoder_instances.nNumOfInstances);
+
+ /* Get the port information */
+ CONFIG_VERSION_SIZE(portParam);
+ omxresult = OMX_GetParameter(dec_handle, OMX_IndexParamVideoInit,
+ (OMX_PTR)&portParam);
+
+ if(FAILED(omxresult)) {
+ DEBUG_PRINT_ERROR("ERROR - Failed to get Port Param\n");
+ return -1;
+ }
+ else
+ {
+ DEBUG_PRINT("portParam.nPorts:%d\n", portParam.nPorts);
+ DEBUG_PRINT("portParam.nStartPortNumber:%d\n", portParam.nStartPortNumber);
+ }
+
+ DEBUG_PRINT("Set parameter immediately followed by getparameter");
+ omxresult = OMX_SetParameter(dec_handle,
+ OMX_IndexParamPortDefinition,
+ &portFmt);
+
+ if(OMX_ErrorNone != omxresult)
+ {
+ DEBUG_PRINT_ERROR("ERROR - Set parameter failed");
+ }
+
+ /* Set the compression format on i/p port */
+ if (codec_format_option == CODEC_FORMAT_H264)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ }
+ else if (codec_format_option == CODEC_FORMAT_MP4)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ }
+ else if (codec_format_option == CODEC_FORMAT_H263)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
+ }
+ else if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option);
+ }
+
+
+ return 0;
+}
+
+int Play_Decoder()
+{
+ int i, bufCnt;
+ int frameSize=0;
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE ret;
+
+ DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE));
+
+ /* open the i/p and o/p files based on the video file format passed */
+ if(open_video_file()) {
+ DEBUG_PRINT_ERROR("Error in opening video file\n");
+ return -1;
+ }
+
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE inputPortFmt;
+ memset(&inputPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE));
+ CONFIG_VERSION_SIZE(inputPortFmt);
+ inputPortFmt.nPortIndex = 0; // input port
+ switch (file_type_option)
+ {
+ case FILE_TYPE_DAT_PER_AU:
+ case FILE_TYPE_PICTURE_START_CODE:
+ case FILE_TYPE_RCV:
+ case FILE_TYPE_VC1:
+ {
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame;
+ break;
+ }
+
+ case FILE_TYPE_ARBITRARY_BYTES:
+ case FILE_TYPE_264_NAL_SIZE_LENGTH:
+ {
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary;
+ break;
+ }
+
+ default:
+ inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Unspecified;
+ }
+ OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn,
+ (OMX_PTR)&inputPortFmt);
+
+ /* Query the decoder outport's min buf requirements */
+ CONFIG_VERSION_SIZE(portFmt);
+
+ /* Port for which the Client needs to obtain info */
+ portFmt.nPortIndex = portParam.nStartPortNumber;
+
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt);
+ DEBUG_PRINT("\nDec: Min Buffer Count %d\n", portFmt.nBufferCountMin);
+ DEBUG_PRINT("\nDec: Buffer Size %d\n", portFmt.nBufferSize);
+
+ if(OMX_DirInput != portFmt.eDir) {
+ printf ("\nDec: Expect Input Port\n");
+ return -1;
+ }
+
+ bufCnt = 0;
+ portFmt.format.video.nFrameHeight = height;
+ portFmt.format.video.nFrameWidth = width;
+ OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition,
+ (OMX_PTR)&portFmt);
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,
+ &portFmt);
+ DEBUG_PRINT("\nDec: New Min Buffer Count %d", portFmt.nBufferCountMin);
+
+
+ DEBUG_PRINT("\nVideo format, height = %d", portFmt.format.video.nFrameHeight);
+ DEBUG_PRINT("\nVideo format, height = %d\n", portFmt.format.video.nFrameWidth);
+ if(codec_format_option == CODEC_FORMAT_H264)
+ {
+ OMX_VIDEO_CONFIG_NALSIZE naluSize;
+ naluSize.nNaluBytes = nalSize;
+ DEBUG_PRINT("\n Nal length is %d index %d",nalSize,OMX_IndexConfigVideoNalSize);
+ OMX_SetConfig(dec_handle,OMX_IndexConfigVideoNalSize,(OMX_PTR)&naluSize);
+ DEBUG_PRINT("SETTING THE NAL SIZE to %d\n",naluSize.nNaluBytes);
+ }
+ DEBUG_PRINT("\nOMX_SendCommand Decoder -> IDLE\n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0);
+
+ input_buf_cnt = portFmt.nBufferCountActual;
+ DEBUG_PRINT("Transition to Idle State succesful...\n");
+ /* Allocate buffer on decoder's i/p port */
+ error = Allocate_Buffer(dec_handle, &pInputBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountActual, portFmt.nBufferSize);
+ if (error != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Input buffer error\n");
+ return -1;
+ }
+ else {
+ DEBUG_PRINT("\nOMX_AllocateBuffer Input buffer success\n");
+ }
+
+ portFmt.nPortIndex = portParam.nStartPortNumber+1;
+ /* Port for which the Client needs to obtain info */
+
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt);
+ DEBUG_PRINT("nMin Buffer Count=%d", portFmt.nBufferCountMin);
+ DEBUG_PRINT("nBuffer Size=%d", portFmt.nBufferSize);
+ if(OMX_DirOutput != portFmt.eDir) {
+ DEBUG_PRINT_ERROR("Error - Expect Output Port\n");
+ return -1;
+ }
+
+ /* Allocate buffer on decoder's o/p port */
+ error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountActual, portFmt.nBufferSize);
+ if (error != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n");
+ return -1;
+ }
+ else
+ {
+ DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n");
+ }
+
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+
+ if (freeHandle_option == FREE_HANDLE_AT_IDLE)
+ {
+ OMX_STATETYPE state = OMX_StateInvalid;
+ OMX_GetState(dec_handle, &state);
+ if (state == OMX_StateIdle)
+ {
+ DEBUG_PRINT("Decoder is in OMX_StateIdle and trying to call OMX_FreeHandle \n");
+ do_freeHandle_and_clean_up(false);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state);
+ do_freeHandle_and_clean_up(true);
+ }
+ return -1;
+ }
+
+
+ DEBUG_PRINT("OMX_SendCommand Decoder -> Executing\n");
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0);
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) {
+ DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt);
+ pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1;
+ pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]);
+ if (OMX_ErrorNone != ret) {
+ DEBUG_PRINT_ERROR("Error - OMX_FillThisBuffer failed with result %d\n", ret);
+ }
+ else {
+ DEBUG_PRINT("OMX_FillThisBuffer success!\n");
+ }
+ }
+
+ used_ip_buf_cnt = input_buf_cnt;
+
+ rcv_v1 = 0;
+
+ //QPERF_START(client_decode);
+ if (codec_format_option == CODEC_FORMAT_VC1)
+ {
+ pInputBufHdrs[0]->nOffset = 0;
+ if(file_type_option == FILE_TYPE_RCV)
+ {
+ frameSize = Read_Buffer_From_RCV_File_Seq_Layer(pInputBufHdrs[0]);
+ pInputBufHdrs[0]->nFilledLen = frameSize;
+ DEBUG_PRINT("After Read_Buffer_From_RCV_File_Seq_Layer, "
+ "frameSize %d\n", frameSize);
+ }
+ else if(file_type_option == FILE_TYPE_VC1)
+ {
+ pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]);
+ DEBUG_PRINT_ERROR("After 1st Read_Buffer for VC1, "
+ "pInputBufHdrs[0]->nFilledLen %d\n", pInputBufHdrs[0]->nFilledLen);
+ }
+ else
+ {
+ pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]);
+ DEBUG_PRINT("After Read_Buffer pInputBufHdrs[0]->nFilledLen %d\n",
+ pInputBufHdrs[0]->nFilledLen);
+ }
+
+ pInputBufHdrs[0]->nInputPortIndex = 0;
+ pInputBufHdrs[0]->nOffset = 0;
+ pInputBufHdrs[0]->nFlags = 0;
+
+ ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[0]);
+ if (ret != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret);
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ else
+ {
+ etb_count++;
+ DEBUG_PRINT("OMX_EmptyThisBuffer success!\n");
+ if(cmd_data == etb_count)
+ {
+ sem_post(&seq_sem);
+ printf("\n Posted seq_sem");
+ }
+ }
+ i = 1;
+ }
+ else
+ {
+ i = 0;
+ }
+
+ for (i; i < used_ip_buf_cnt;i++) {
+ pInputBufHdrs[i]->nInputPortIndex = 0;
+ pInputBufHdrs[i]->nOffset = 0;
+ if((frameSize = Read_Buffer(pInputBufHdrs[i])) <= 0 ){
+ DEBUG_PRINT("NO FRAME READ\n");
+ pInputBufHdrs[i]->nFilledLen = frameSize;
+ pInputBufHdrs[i]->nInputPortIndex = 0;
+ pInputBufHdrs[i]->nFlags |= OMX_BUFFERFLAG_EOS;;
+ bInputEosReached = true;
+
+ OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]);
+ etb_count++;
+ if(cmd_data == etb_count)
+ {
+ sem_post(&seq_sem);
+ printf("\n Posted seq_sem");
+ }
+ DEBUG_PRINT("File is small::Either EOS or Some Error while reading file\n");
+ break;
+ }
+ pInputBufHdrs[i]->nFilledLen = frameSize;
+ pInputBufHdrs[i]->nInputPortIndex = 0;
+ pInputBufHdrs[i]->nFlags = 0;
+//pBufHdr[bufCnt]->pAppPrivate = this;
+ ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]);
+ if (OMX_ErrorNone != ret) {
+ DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret);
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ else {
+ DEBUG_PRINT("OMX_EmptyThisBuffer success!\n");
+ etb_count++;
+ if(cmd_data == etb_count)
+ {
+ sem_post(&seq_sem);
+ printf("\n Posted seq_sem");
+ }
+ }
+ }
+
+ if(0 != pthread_create(&ebd_thread_id, NULL, ebd_thread, NULL))
+ {
+ printf("\n Error in Creating fbd_thread \n");
+ free_queue(etb_queue);
+ free_queue(fbd_queue);
+ return -1;
+ }
+
+ // wait for event port settings changed event
+ wait_for_event();
+ DEBUG_PRINT("RECIEVED EVENT PORT TO DETERMINE IF DYN PORT RECONFIGURATION NEEDED, currentStatus %d\n",
+ currentStatus);
+ if (currentStatus == INVALID_STATE)
+ {
+ DEBUG_PRINT_ERROR("Error - INVALID_STATE\n");
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ else if (currentStatus == PORT_SETTING_CHANGE_STATE)
+ {
+ DEBUG_PRINT("PORT_SETTING_CHANGE_STATE\n");
+ // Send DISABLE command
+ sent_disabled = 1;
+ OMX_SendCommand(dec_handle, OMX_CommandPortDisable, 1, 0);
+
+ DEBUG_PRINT("FREEING BUFFERS\n");
+ // Free output Buffer
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) {
+ OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]);
+ }
+
+ // wait for Disable event to come back
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ DEBUG_PRINT("DISABLE EVENT RECD\n");
+ // GetParam and SetParam
+
+ // Send Enable command
+ OMX_SendCommand(dec_handle, OMX_CommandPortEnable, 1, 0);
+ // AllocateBuffers
+ /* Allocate buffer on decoder's o/p port */
+
+ portFmt.nPortIndex = 1;
+ /* Port for which the Client needs to obtain info */
+
+ OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt);
+ DEBUG_PRINT("Min Buffer Count=%d", portFmt.nBufferCountMin);
+ DEBUG_PRINT("Buffer Size=%d", portFmt.nBufferSize);
+ if(OMX_DirOutput != portFmt.eDir) {
+ DEBUG_PRINT_ERROR("Error - Expect Output Port\n");
+ return -1;
+ }
+ height = portFmt.format.video.nFrameHeight;
+ width = portFmt.format.video.nFrameWidth;
+ stride = portFmt.format.video.nStride;
+ sliceheight = portFmt.format.video.nSliceHeight;
+
+ error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex,
+ portFmt.nBufferCountActual, portFmt.nBufferSize);
+ if (error != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n");
+ return -1;
+ }
+ else
+ {
+ DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n");
+ }
+
+ // wait for enable event to come back
+ wait_for_event();
+ if (currentStatus == INVALID_STATE)
+ {
+ do_freeHandle_and_clean_up(true);
+ return -1;
+ }
+ DEBUG_PRINT("ENABLE EVENT HANDLER RECD\n");
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) {
+ DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt);
+ pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1;
+ pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]);
+ if (OMX_ErrorNone != ret) {
+ DEBUG_PRINT_ERROR("ERROR - OMX_FillThisBuffer failed with result %d\n", ret);
+ }
+ else {
+ DEBUG_PRINT("OMX_FillThisBuffer success!\n");
+ }
+ }
+
+ if(displayYuv)
+ {
+ overlay_set();
+ }
+ }
+
+ if (freeHandle_option == FREE_HANDLE_AT_EXECUTING)
+ {
+ OMX_STATETYPE state = OMX_StateInvalid;
+ OMX_GetState(dec_handle, &state);
+ if (state == OMX_StateExecuting)
+ {
+ DEBUG_PRINT("Decoder is in OMX_StateExecuting and trying to call OMX_FreeHandle \n");
+ do_freeHandle_and_clean_up(false);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state);
+ do_freeHandle_and_clean_up(true);
+ }
+ return -1;
+ }
+ else if (freeHandle_option == FREE_HANDLE_AT_PAUSE)
+ {
+ OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0);
+ wait_for_event();
+
+ OMX_STATETYPE state = OMX_StateInvalid;
+ OMX_GetState(dec_handle, &state);
+ if (state == OMX_StatePause)
+ {
+ DEBUG_PRINT("Decoder is in OMX_StatePause and trying to call OMX_FreeHandle \n");
+ do_freeHandle_and_clean_up(false);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state);
+ do_freeHandle_and_clean_up(true);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle,
+ OMX_BUFFERHEADERTYPE ***pBufHdrs,
+ OMX_U32 nPortIndex,
+ long bufCntMin, long bufSize)
+{
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+ OMX_ERRORTYPE error=OMX_ErrorNone;
+ long bufCnt=0;
+
+ DEBUG_PRINT("pBufHdrs = %x,bufCntMin = %d\n", pBufHdrs, bufCntMin);
+ *pBufHdrs= (OMX_BUFFERHEADERTYPE **)
+ malloc(sizeof(OMX_BUFFERHEADERTYPE)*bufCntMin);
+
+ for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) {
+ DEBUG_PRINT("OMX_AllocateBuffer No %d \n", bufCnt);
+ error = OMX_AllocateBuffer(dec_handle, &((*pBufHdrs)[bufCnt]),
+ nPortIndex, NULL, bufSize);
+ }
+
+ return error;
+}
+
+static void do_freeHandle_and_clean_up(bool isDueToError)
+{
+ int bufCnt = 0;
+
+ for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]);
+ }
+
+ for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt)
+ {
+ OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]);
+ }
+
+ DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n");
+ OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle);
+ if (result != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("[OMX Vdec Test] - OMX_FreeHandle error. Error code: %d\n", result);
+ }
+ dec_handle = NULL;
+
+ /* Deinit OpenMAX */
+ DEBUG_PRINT("[OMX Vdec Test] - De-initializing OMX \n");
+ OMX_Deinit();
+
+ DEBUG_PRINT("[OMX Vdec Test] - closing all files\n");
+ if(inputBufferFile)
+ {
+ fclose(inputBufferFile);
+ inputBufferFile = NULL;
+ }
+
+ DEBUG_PRINT("[OMX Vdec Test] - after free inputfile\n");
+
+ if (takeYuvLog && outputBufferFile) {
+ fclose(outputBufferFile);
+ outputBufferFile = NULL;
+ }
+ DEBUG_PRINT("[OMX Vdec Test] - after free outputfile\n");
+
+ if(etb_queue)
+ {
+ free_queue(etb_queue);
+ etb_queue = NULL;
+ }
+ DEBUG_PRINT("[OMX Vdec Test] - after free etb_queue \n");
+ if(fbd_queue)
+ {
+ free_queue(fbd_queue);
+ fbd_queue = NULL;
+ }
+ DEBUG_PRINT("[OMX Vdec Test] - after free iftb_queue\n");
+
+
+ printf("*****************************************\n");
+ if (isDueToError)
+ {
+ printf("************...TEST FAILED...************\n");
+ }
+ else
+ {
+ printf("**********...TEST SUCCESSFULL...*********\n");
+ }
+ printf("*****************************************\n");
+}
+
+static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ long frameSize=0;
+ char temp_buffer[10];
+ char temp_byte;
+ int bytes_read=0;
+ int i=0;
+ unsigned char *read_buffer=NULL;
+ char c = '1'; //initialize to anything except '\0'(0)
+ char inputFrameSize[10];
+ int count =0; char cnt =0;
+ memset(temp_buffer, 0, sizeof(temp_buffer));
+
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+
+ while (cnt < 10)
+ /* Check the input file format, may result in infinite loop */
+ {
+ DEBUG_PRINT("loop[%d] count[%d]\n",cnt,count);
+ count = fread(&inputFrameSize[cnt], 1, 1, inputBufferFile);
+ if(inputFrameSize[cnt] == '\0' )
+ break;
+ cnt++;
+ }
+ inputFrameSize[cnt]='\0';
+ frameSize = atoi(inputFrameSize);
+ pBufHdr->nFilledLen = 0;
+
+ /* get the frame length */
+ fseek(inputBufferFile, -1, SEEK_CUR);
+ bytes_read = fread(pBufHdr->pBuffer, 1, frameSize, inputBufferFile);
+
+ DEBUG_PRINT("Actual frame Size [%d] bytes_read using fread[%d]\n",
+ frameSize, bytes_read);
+
+ if(bytes_read == 0 || bytes_read < frameSize ) {
+ DEBUG_PRINT("Bytes read Zero After Read frame Size \n");
+ DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n",
+ video_playback_count);
+ return 0;
+ }
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ return bytes_read;
+}
+
+static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ char temp_buffer[10];
+ char temp_byte;
+ int bytes_read=0;
+ int i=0;
+ unsigned char *read_buffer=NULL;
+ char c = '1'; //initialize to anything except '\0'(0)
+ char inputFrameSize[10];
+ int count =0; char cnt =0;
+ memset(temp_buffer, 0, sizeof(temp_buffer));
+
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+
+ bytes_read = fread(pBufHdr->pBuffer, 1, NUMBER_OF_ARBITRARYBYTES_READ, inputBufferFile);
+
+ if(bytes_read == 0) {
+ DEBUG_PRINT("Bytes read Zero After Read frame Size \n");
+ DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n",
+ video_playback_count);
+ return 0;
+ }
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ return bytes_read;
+}
+
+static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int readOffset = 0;
+ int bytes_read = 0;
+ unsigned int code = 0;
+ pBufHdr->nFilledLen = 0;
+ static unsigned int header_code = 0;
+
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+
+ do
+ {
+ //Start codes are always byte aligned.
+ bytes_read = fread(&pBufHdr->pBuffer[readOffset],1, 1,inputBufferFile);
+ if(!bytes_read)
+ {
+ DEBUG_PRINT("Bytes read Zero \n");
+ break;
+ }
+ code <<= 8;
+ code |= (0x000000FF & pBufHdr->pBuffer[readOffset]);
+ //VOP start code comparision
+ if (readOffset>3)
+ {
+ if(!header_code ){
+ if( VOP_START_CODE == code)
+ {
+ header_code = VOP_START_CODE;
+ }
+ else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE )
+ {
+ header_code = SHORT_HEADER_START_CODE;
+ }
+ }
+ if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=3;
+ break;
+
+ }
+ else if (( header_code == SHORT_HEADER_START_CODE ) && ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00)))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=3;
+ break;
+ }
+ }
+ readOffset++;
+ }while (1);
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ return readOffset;
+}
+
+static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ // NAL unit stream processing
+ char temp_size[SIZE_NAL_FIELD_MAX];
+ int i = 0;
+ int j = 0;
+ unsigned int size = 0; // Need to make sure that uint32 has SIZE_NAL_FIELD_MAX (4) bytes
+ int bytes_read = 0;
+
+ // read the "size_nal_field"-byte size field
+ bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset, 1, nalSize, inputBufferFile);
+ if (bytes_read == 0)
+ {
+ DEBUG_PRINT("Failed to read frame or it might be EOF\n");
+ return 0;
+ }
+
+ for (i=0; i<SIZE_NAL_FIELD_MAX-nalSize; i++)
+ {
+ temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = 0;
+ }
+
+ /* Due to little endiannes, Reorder the size based on size_nal_field */
+ for (j=0; i<SIZE_NAL_FIELD_MAX; i++, j++)
+ {
+ temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = pBufHdr->pBuffer[pBufHdr->nOffset + j];
+ }
+ size = (unsigned int)(*((unsigned int *)(temp_size)));
+
+ // now read the data
+ bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset + nalSize, 1, size, inputBufferFile);
+ if (bytes_read != size)
+ {
+ DEBUG_PRINT_ERROR("Failed to read frame\n");
+ }
+
+ return bytes_read + nalSize;
+}
+
+static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int readOffset = 0, size_struct_C = 0;
+ unsigned int startcode = 0;
+ pBufHdr->nFilledLen = 0;
+ pBufHdr->nFlags = 0;
+
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+
+ fread(&startcode, 4, 1, inputBufferFile);
+
+ /* read size of struct C as it need not be 4 always*/
+ fread(&size_struct_C, 1, 4, inputBufferFile);
+
+ /* reseek to beginning of sequence header */
+ fseek(inputBufferFile, -8, SEEK_CUR);
+
+ if ((startcode & 0xFF000000) == 0xC5000000)
+ {
+
+ DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C);
+
+ readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC + size_struct_C, inputBufferFile);
+ }
+ else if((startcode & 0xFF000000) == 0x85000000)
+ {
+ // .RCV V1 file
+
+ rcv_v1 = 1;
+
+ DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C);
+
+ readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC + size_struct_C, inputBufferFile);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Error: Unknown VC1 clip format %x\n", startcode);
+ }
+
+#if 0
+ {
+ int i=0;
+ printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", readOffset, readOffset);
+ for (i=0; i<36; i++)
+ {
+ printf("0x%.2x ", pBufHdr->pBuffer[i]);
+ if (i%16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+ return readOffset;
+}
+
+static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int readOffset = 0;
+ unsigned int len = 0;
+ unsigned int key = 0;
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+
+ DEBUG_PRINT("Read_Buffer_From_RCV_File - nOffset %d\n", pBufHdr->nOffset);
+ if(rcv_v1)
+ {
+ /* for the case of RCV V1 format, the frame header is only of 4 bytes and has
+ only the frame size information */
+ readOffset = fread(&len, 1, 4, inputBufferFile);
+ DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len);
+
+ }
+ else
+ {
+ /* for a regular RCV file, 3 bytes comprise the frame size and 1 byte for key*/
+ readOffset = fread(&len, 1, 3, inputBufferFile);
+ DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len);
+
+ readOffset = fread(&key, 1, 1, inputBufferFile);
+ if ( (key & 0x80) == false)
+ {
+ DEBUG_PRINT("Read_Buffer_From_RCV_File - Non IDR frame key %x\n", key);
+ }
+
+ }
+
+ if(!rcv_v1)
+ {
+ /* There is timestamp field only for regular RCV format and not for RCV V1 format*/
+ readOffset = fread(&pBufHdr->nTimeStamp, 1, 4, inputBufferFile);
+ DEBUG_PRINT("Read_Buffer_From_RCV_File - timeStamp %d\n", pBufHdr->nTimeStamp);
+ pBufHdr->nTimeStamp *= 1000;
+ }
+ else
+ {
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+ }
+
+ if(len > pBufHdr->nAllocLen)
+ {
+ DEBUG_PRINT_ERROR("Error in sufficient buffer framesize %d, allocalen %d noffset %d\n",len,pBufHdr->nAllocLen, pBufHdr->nOffset);
+ readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, pBufHdr->nAllocLen - pBufHdr->nOffset , inputBufferFile);
+ fseek(inputBufferFile, len - readOffset,SEEK_CUR);
+ return readOffset;
+ }
+ else
+ readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, len, inputBufferFile);
+ if (readOffset != len)
+ {
+ DEBUG_PRINT("EOS reach or Reading error %d, %s \n", readOffset, strerror( errno ));
+ return 0;
+ }
+
+#if 0
+ {
+ int i=0;
+ printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", len, readOffset);
+ for (i=0; i<64; i++)
+ {
+ printf("0x%.2x ", pBufHdr->pBuffer[i]);
+ if (i%16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+
+ return readOffset;
+}
+
+static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ static int timeStampLfile = 0;
+ OMX_U8 *pBuffer = pBufHdr->pBuffer + pBufHdr->nOffset;
+ DEBUG_PRINT("Inside %s \n", __FUNCTION__);
+
+ unsigned int readOffset = 0;
+ int bytes_read = 0;
+ unsigned int code = 0;
+
+ do
+ {
+ //Start codes are always byte aligned.
+ bytes_read = fread(&pBuffer[readOffset],1, 1,inputBufferFile);
+ if(!bytes_read)
+ {
+ DEBUG_PRINT("\n Bytes read Zero \n");
+ break;
+ }
+ code <<= 8;
+ code |= (0x000000FF & pBufHdr->pBuffer[readOffset]);
+ //VOP start code comparision
+ if (readOffset>3)
+ {
+ if (VC1_FRAME_START_CODE == (code & 0xFFFFFFFF))
+ {
+ //Seek backwards by 4
+ fseek(inputBufferFile, -4, SEEK_CUR);
+ readOffset-=3;
+
+ while(pBufHdr->pBuffer[readOffset-1] == 0)
+ readOffset--;
+
+ break;
+ }
+ }
+ readOffset++;
+ }while (1);
+
+ pBufHdr->nTimeStamp = timeStampLfile;
+ timeStampLfile += timestampInterval;
+
+#if 0
+ {
+ int i=0;
+ printf("Read_Buffer_From_VC1_File, readOffset %d\n", readOffset);
+ for (i=0; i<64; i++)
+ {
+ printf("0x%.2x ", pBufHdr->pBuffer[i]);
+ if (i%16 == 15) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+#endif
+
+ return readOffset;
+}
+
+static int open_video_file ()
+{
+ int error_code = 0;
+ char outputfilename[512];
+ DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename);
+
+ inputBufferFile = fopen (in_filename, "rb");
+ if (inputBufferFile == NULL) {
+ DEBUG_PRINT_ERROR("Error - i/p file %s could NOT be opened\n",
+ in_filename);
+ error_code = -1;
+ }
+ else {
+ DEBUG_PRINT("I/p file %s is opened \n", in_filename);
+ }
+
+ if (takeYuvLog) {
+ strncpy(outputfilename, "yuvframes.yuv", 14);
+ outputBufferFile = fopen (outputfilename, "ab");
+ if (outputBufferFile == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR - o/p file %s could NOT be opened\n", outputfilename);
+ error_code = -1;
+ }
+ else
+ {
+ DEBUG_PRINT("O/p file %s is opened \n", outputfilename);
+ }
+ }
+ return error_code;
+}
+
+void swap_byte(char *pByte, int nbyte)
+{
+ int i=0;
+
+ for (i=0; i<nbyte/2; i++)
+ {
+ pByte[i] ^= pByte[nbyte-i-1];
+ pByte[nbyte-i-1] ^= pByte[i];
+ pByte[i] ^= pByte[nbyte-i-1];
+ }
+}
+
+int drawBG(void)
+{
+ int result;
+ int i;
+#ifdef FRAMEBUFFER_32
+ long * p;
+#else
+ short * p;
+#endif
+ void *fb_buf = mmap (NULL, finfo.smem_len,PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
+
+ if (fb_buf == MAP_FAILED)
+ {
+ printf("ERROR: Framebuffer MMAP failed!\n");
+ close(fb_fd);
+ return -1;
+ }
+
+ vinfo.yoffset = 0;
+ p = (long *)fb_buf;
+
+ for (i=0; i < vinfo.xres * vinfo.yres; i++)
+ {
+ #ifdef FRAMEBUFFER_32
+ *p++ = COLOR_BLACK_RGBA_8888;
+ #else
+ *p++ = CLR_KEY;
+ #endif
+ }
+
+ if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0)
+ {
+ printf("ERROR: FBIOPAN_DISPLAY failed! line=%d\n", __LINE__);
+ return -1;
+ }
+
+ DEBUG_PRINT("drawBG success!\n");
+ return 0;
+}
+
+void overlay_set()
+{
+ overlayp = &overlay;
+ overlayp->src.width = stride;
+ overlayp->src.height = sliceheight;
+ overlayp->src.format = MDP_Y_CRCB_H2V2;
+ overlayp->src_rect.x = 0;
+ overlayp->src_rect.y = 0;
+ overlayp->src_rect.w = width;
+ overlayp->src_rect.h = height;
+
+ if(width >= vinfo.xres)
+ {
+ overlayp->dst_rect.x = 0;
+ overlayp->dst_rect.w = vinfo.xres;
+ }
+ else
+ {
+ overlayp->dst_rect.x = (vinfo.xres - width)/2;
+ overlayp->dst_rect.w = width;
+ }
+
+ if(height >= vinfo.yres)
+ {
+ overlayp->dst_rect.y = 0;
+ overlayp->dst_rect.h = vinfo.yres;
+ }
+ else
+ {
+ overlayp->dst_rect.y = (vinfo.yres - height)/2;
+ overlayp->dst_rect.h = height;
+ }
+
+ overlayp->z_order = 0;
+ printf("overlayp->dst_rect.x = %u \n", overlayp->dst_rect.x);
+ printf("overlayp->dst_rect.y = %u \n", overlayp->dst_rect.y);
+ printf("overlayp->dst_rect.w = %u \n", overlayp->dst_rect.w);
+ printf("overlayp->dst_rect.h = %u \n", overlayp->dst_rect.h);
+
+ overlayp->alpha = 0x0;
+ overlayp->transp_mask = 0xFFFFFFFF;
+ overlayp->flags = 0;
+ overlayp->is_fg = 1;
+
+ overlayp->id = MSMFB_NEW_REQUEST;
+ vid_buf_front_id = ioctl(fb_fd, MSMFB_OVERLAY_SET, overlayp);
+ if (vid_buf_front_id < 0)
+ {
+ printf("ERROR: MSMFB_OVERLAY_SET failed! line=%d\n", __LINE__);
+ }
+ vid_buf_front_id = overlayp->id;
+ DEBUG_PRINT("\n vid_buf_front_id = %u", vid_buf_front_id);
+ drawBG();
+}
+
+int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
+ struct msmfb_overlay_data ov_front;
+ MemoryHeapBase *vheap = NULL;
+ ov_front.id = overlayp->id;
+ pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
+ pBufHdr->pPlatformPrivate)->entryList->entry;
+ vheap = (MemoryHeapBase*)pPMEMInfo->pmem_fd;
+
+#ifdef _ANDROID_
+ ov_front.data.memory_id = vheap->getHeapID();
+#else
+ ov_front.data.memory_id = pPMEMInfo->pmem_fd;
+#endif
+ ov_front.data.offset = pPMEMInfo->offset;
+
+ DEBUG_PRINT("\n ov_front.data.memory_id = %d", ov_front.data.memory_id);
+ DEBUG_PRINT("\n ov_front.data.offset = %u", ov_front.data.offset);
+
+ if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, (void*)&ov_front))
+ {
+ printf("\nERROR! MSMFB_OVERLAY_PLAY failed at frame (Line %d)\n",
+ __LINE__);
+ return -1;
+ }
+ DEBUG_PRINT("\nMSMFB_OVERLAY_PLAY successfull");
+ return 0;
+}
+
+void overlay_unset()
+{
+ if (ioctl(fb_fd, MSMFB_OVERLAY_UNSET, &vid_buf_front_id))
+ {
+ printf("\nERROR! MSMFB_OVERLAY_UNSET failed! (Line %d)\n", __LINE__);
+ }
+}
+
+void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr)
+{
+ unsigned int addr = 0;
+ OMX_OTHER_EXTRADATATYPE *pExtraData = 0;
+ OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
+ unsigned int destx, desty,destW, destH;
+#ifdef _ANDROID_
+ MemoryHeapBase *vheap = NULL;
+#endif
+
+ unsigned int end = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nAllocLen);
+
+ struct mdp_blit_req *e;
+ union {
+ char dummy[sizeof(struct mdp_blit_req_list) +
+ sizeof(struct mdp_blit_req) * 1];
+ struct mdp_blit_req_list list;
+ } img;
+
+ if (fb_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("Warning: /dev/fb0 is not opened!\n");
+ return;
+ }
+
+ img.list.count = 1;
+ e = &img.list.req[0];
+
+ addr = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nFilledLen);
+ // align to a 4 byte boundary
+ addr = (addr + 3) & (~3);
+
+ // read to the end of existing extra data sections
+ pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr;
+
+ while (addr < end && pExtraData->eType != OMX_ExtraDataFrameInfo)
+ {
+ addr += pExtraData->nSize;
+ pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr;
+ }
+
+ if (pExtraData->eType != OMX_ExtraDataFrameInfo)
+ {
+ DEBUG_PRINT_ERROR("pExtraData->eType %d pExtraData->nSize %d\n",pExtraData->eType,pExtraData->nSize);
+ }
+ pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtraData->data;
+
+ pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
+ pBufHdr->pPlatformPrivate)->entryList->entry;
+#ifdef _ANDROID_
+ vheap = (MemoryHeapBase *)pPMEMInfo->pmem_fd;
+#endif
+
+
+ DEBUG_PRINT_ERROR("DecWidth %d DecHeight %d\n",portFmt.format.video.nStride,portFmt.format.video.nSliceHeight);
+ DEBUG_PRINT_ERROR("DispWidth %d DispHeight %d\n",portFmt.format.video.nFrameWidth,portFmt.format.video.nFrameHeight);
+
+
+
+ e->src.width = portFmt.format.video.nStride;
+ e->src.height = portFmt.format.video.nSliceHeight;
+ e->src.format = MDP_Y_CBCR_H2V2;
+ e->src.offset = pPMEMInfo->offset;
+#ifdef _ANDROID_
+ e->src.memory_id = vheap->getHeapID();
+#else
+ e->src.memory_id = pPMEMInfo->pmem_fd;
+#endif
+
+ DEBUG_PRINT_ERROR("pmemOffset %d pmemID %d\n",e->src.offset,e->src.memory_id);
+
+ e->dst.width = vinfo.xres;
+ e->dst.height = vinfo.yres;
+ e->dst.format = MDP_RGB_565;
+ e->dst.offset = 0;
+ e->dst.memory_id = fb_fd;
+
+ e->transp_mask = 0xffffffff;
+ DEBUG_PRINT("Frame interlace type %d!\n", pExtraFrameInfo->interlaceType);
+ if(pExtraFrameInfo->interlaceType != OMX_QCOM_InterlaceFrameProgressive)
+ {
+ DEBUG_PRINT("Interlaced Frame!\n");
+ e->flags = MDP_DEINTERLACE;
+ }
+ else
+ e->flags = 0;
+ e->alpha = 0xff;
+
+ switch(displayWindow)
+ {
+ case 1: destx = 0;
+ desty = 0;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+ case 2: destx = vinfo.xres/2;
+ desty = 0;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+
+ case 3: destx = 0;
+ desty = vinfo.yres/2;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+ case 4: destx = vinfo.xres/2;
+ desty = vinfo.yres/2;
+ destW = vinfo.xres/2;
+ destH = vinfo.yres/2;
+ break;
+ case 0:
+ default:
+ destx = 0;
+ desty = 0;
+ destW = vinfo.xres;
+ destH = vinfo.yres;
+ }
+
+
+ if(portFmt.format.video.nFrameWidth < destW)
+ destW = portFmt.format.video.nFrameWidth ;
+
+
+ if(portFmt.format.video.nFrameHeight < destH)
+ destH = portFmt.format.video.nFrameHeight;
+
+ e->dst_rect.x = destx;
+ e->dst_rect.y = desty;
+ e->dst_rect.w = destW;
+ e->dst_rect.h = destH;
+
+ //e->dst_rect.w = 800;
+ //e->dst_rect.h = 480;
+
+ e->src_rect.x = 0;
+ e->src_rect.y = 0;
+ e->src_rect.w = portFmt.format.video.nFrameWidth;
+ e->src_rect.h = portFmt.format.video.nFrameHeight;
+
+ //e->src_rect.w = portFmt.format.video.nStride;
+ //e->src_rect.h = portFmt.format.video.nSliceHeight;
+
+ if (ioctl(fb_fd, MSMFB_BLIT, &img)) {
+ DEBUG_PRINT_ERROR("MSMFB_BLIT ioctl failed!\n");
+ return;
+ }
+
+ if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) {
+ DEBUG_PRINT_ERROR("FBIOPAN_DISPLAY failed! line=%d\n", __LINE__);
+ return;
+ }
+
+ DEBUG_PRINT("render_fb complete!\n");
+}
+
diff --git a/omx/mm-video/vidc/venc/Android.mk b/omx/mm-video/vidc/venc/Android.mk
new file mode 100644
index 0000000..3eb7464
--- /dev/null
+++ b/omx/mm-video/vidc/venc/Android.mk
@@ -0,0 +1,115 @@
+#--------------------------------------------------------------------------
+#Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#--------------------------------------------------------------------------
+
+ifneq ($(BUILD_TINY_ANDROID),true)
+
+ROOT_DIR := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PATH:= $(ROOT_DIR)
+
+# ---------------------------------------------------------------------------------
+# Common definitons
+# ---------------------------------------------------------------------------------
+
+libmm-venc-def := -g -O3 -Dlrintf=_ffix_r
+libmm-venc-def += -D__align=__alignx
+libmm-venc-def += -D__alignx\(x\)=__attribute__\(\(__aligned__\(x\)\)\)
+libmm-venc-def += -DT_ARM
+libmm-venc-def += -Dinline=__inline
+libmm-venc-def += -D_ANDROID_
+libmm-venc-def += -UENABLE_DEBUG_LOW
+libmm-venc-def += -DENABLE_DEBUG_HIGH
+libmm-venc-def += -DENABLE_DEBUG_ERROR
+
+# ---------------------------------------------------------------------------------
+# Make the Shared library (libOmxVenc)
+# ---------------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+libmm-venc-inc := $(LOCAL_PATH)/inc
+libmm-venc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore
+
+LOCAL_MODULE := libOmxVenc
+LOCAL_CFLAGS := $(libmm-venc-def)
+LOCAL_C_INCLUDES := $(libmm-venc-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := liblog libutils libbinder
+
+LOCAL_SRC_FILES := src/omx_video_base.cpp
+LOCAL_SRC_FILES += src/omx_video_encoder.cpp
+LOCAL_SRC_FILES += src/video_encoder_device.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
+# -----------------------------------------------------------------------------
+# # Make the apps-test (mm-venc-omx-test720p)
+# -----------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+mm-venc-test720p-inc := $(TARGET_OUT_HEADERS)/mm-core/omxcore
+mm-venc-test720p-inc += $(LOCAL_PATH)/inc
+
+LOCAL_MODULE := mm-venc-omx-test720p
+LOCAL_CFLAGS := $(libmm-venc-def)
+LOCAL_C_INCLUDES := $(mm-venc-test720p-inc)
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libmm-omxcore libOmxVenc libbinder
+
+LOCAL_SRC_FILES := test/venc_test.cpp
+LOCAL_SRC_FILES += test/camera_test.cpp
+LOCAL_SRC_FILES += test/venc_util.c
+LOCAL_SRC_FILES += test/fb_test.c
+
+include $(BUILD_EXECUTABLE)
+
+# -----------------------------------------------------------------------------
+# Make the apps-test (mm-video-driver-test)
+# -----------------------------------------------------------------------------
+
+include $(CLEAR_VARS)
+
+venc-test-inc += $(LOCAL_PATH)/inc
+
+LOCAL_MODULE := mm-video-encdrv-test
+LOCAL_C_INCLUDES := $(venc-test-inc)
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := test/video_encoder_test.c
+LOCAL_SRC_FILES += test/queue.c
+
+include $(BUILD_EXECUTABLE)
+
+endif #BUILD_TINY_ANDROID
+
+# ---------------------------------------------------------------------------------
+# END
+# ---------------------------------------------------------------------------------
+
diff --git a/omx/mm-video/vidc/venc/inc/camera_test.h b/omx/mm-video/vidc/venc/inc/camera_test.h
new file mode 100644
index 0000000..48a18c5
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/camera_test.h
@@ -0,0 +1,58 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _CAMERA_TEST_H
+#define _CAMERA_TEST_H
+
+#define EXTERN_C_START extern "C" {
+#define EXTERN_C_END }
+
+#ifdef __cplusplus
+EXTERN_C_START
+#endif
+
+typedef void (*CameraPreviewCallback)(int nFD,
+ int nOffset,
+ void* pPhys,
+ void* pVirt,
+ long long nTimeStamp);
+
+
+int CameraTest_Initialize(int nFrameRate,
+ int nFrameWidth,
+ int nFrameHeight,
+ CameraPreviewCallback pfnPreviewCallback);
+int CameraTest_Run();
+int CameraTest_ReleaseFrame(void* pPhys, void* pVirt);
+int CameraTest_Exit();
+
+
+#ifdef __cplusplus
+EXTERN_C_END
+#endif
+
+#endif
diff --git a/omx/mm-video/vidc/venc/inc/fb_test.h b/omx/mm-video/vidc/venc/inc/fb_test.h
new file mode 100644
index 0000000..b8894d0
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/fb_test.h
@@ -0,0 +1,48 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef _FB_TEST_H
+#define _FB_TEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int FBTest_Initialize(int nFrameWidth,
+ int nFrameHeight);
+int FBTest_DisplayImage(int nPmemFd, int nOffset);
+int FBTest_Exit();
+
+int FBTest_RunTest();
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // _FB_TEST_H
diff --git a/omx/mm-video/vidc/venc/inc/omx_video_base.h b/omx/mm-video/vidc/venc/inc/omx_video_base.h
new file mode 100644
index 0000000..1c14b22
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/omx_video_base.h
@@ -0,0 +1,496 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef __OMX_VIDEO_BASE_H__
+#define __OMX_VIDEO_BASE_H__
+/*============================================================================
+ O p e n M A X Component
+ Video Encoder
+
+*//** @file comx_video_base.h
+ This module contains the class definition for openMAX decoder component.
+
+*//*========================================================================*/
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include<stdlib.h>
+#include <stdio.h>
+#ifdef _ANDROID_
+ #include <binder/MemoryHeapBase.h>
+#endif // _ANDROID_
+#include <pthread.h>
+#include <semaphore.h>
+#include <linux/msm_vidc_enc.h>
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+#include "qc_omx_component.h"
+#include "omx_video_common.h"
+
+
+#ifdef _ANDROID_
+using namespace android;
+// local pmem heap object
+class VideoHeap : public MemoryHeapBase
+{
+public:
+ VideoHeap(int fd, size_t size, void* base);
+ virtual ~VideoHeap() {}
+};
+
+#include <utils/Log.h>
+#define LOG_TAG "OMX-VENC-720p"
+#ifdef ENABLE_DEBUG_LOW
+#define DEBUG_PRINT_LOW LOGE
+#else
+#define DEBUG_PRINT_LOW
+#endif
+#ifdef ENABLE_DEBUG_HIGH
+#define DEBUG_PRINT_HIGH LOGE
+#else
+#define DEBUG_PRINT_HIGH
+#endif
+#ifdef ENABLE_DEBUG_ERROR
+#define DEBUG_PRINT_ERROR LOGE
+#else
+#define DEBUG_PRINT_ERROR
+#endif
+#endif // _ANDROID_
+//////////////////////////////////////////////////////////////////////////////
+// Module specific globals
+//////////////////////////////////////////////////////////////////////////////
+
+#define OMX_SPEC_VERSION 0x00000101
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros
+//////////////////////////////////////////////////////////////////////////////
+#define PrintFrameHdr(bufHdr) DEBUG_PRINT("bufHdr %x buf %x size %d TS %d\n",\
+ (unsigned) bufHdr,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\
+ (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp)
+
+// BitMask Management logic
+#define BITS_PER_BYTE 32
+#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE)
+#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_BYTE)
+#define BITMASK_FLAG(mIndex) (1 << ((mIndex) % BITS_PER_BYTE))
+#define BITMASK_CLEAR(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \
+ &= ~(BITMASK_FLAG(mIndex))
+#define BITMASK_SET(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \
+ |= BITMASK_FLAG(mIndex)
+#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex))
+#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex)) == 0x0)
+#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex))
+#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \
+ & BITMASK_FLAG(mIndex)) == 0x0)
+
+void* message_thread(void *);
+// OMX video class
+class omx_video: public qc_omx_component
+{
+
+public:
+ omx_video(); // constructor
+ virtual ~omx_video(); // destructor
+
+ // virtual int async_message_process (void *context, void* message);
+ void process_event_cb(void *ctxt,unsigned char id);
+
+ OMX_ERRORTYPE allocate_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes
+ );
+
+
+ virtual OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp)= 0;
+
+ virtual OMX_ERRORTYPE component_init(OMX_STRING role)= 0;
+
+ virtual OMX_U32 dev_stop(void) = 0;
+ virtual OMX_U32 dev_pause(void) = 0;
+ virtual OMX_U32 dev_start(void) = 0;
+ virtual OMX_U32 dev_flush(unsigned) = 0;
+ virtual OMX_U32 dev_resume(void) = 0;
+ virtual bool dev_use_buf(void *,unsigned) = 0;
+ virtual bool dev_free_buf(void *,unsigned) = 0;
+ virtual bool dev_empty_buf(void *, void *) = 0;
+ virtual bool dev_fill_buf(void *buffer, void *) = 0;
+ virtual bool dev_get_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32) = 0;
+
+
+ OMX_ERRORTYPE component_role_enum(
+ OMX_HANDLETYPE hComp,
+ OMX_U8 *role,
+ OMX_U32 index
+ );
+
+ OMX_ERRORTYPE component_tunnel_request(
+ OMX_HANDLETYPE hComp,
+ OMX_U32 port,
+ OMX_HANDLETYPE peerComponent,
+ OMX_U32 peerPort,
+ OMX_TUNNELSETUPTYPE *tunnelSetup
+ );
+
+ OMX_ERRORTYPE empty_this_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+
+
+ OMX_ERRORTYPE fill_this_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+
+ OMX_ERRORTYPE free_buffer(
+ OMX_HANDLETYPE hComp,
+ OMX_U32 port,
+ OMX_BUFFERHEADERTYPE *buffer
+ );
+
+ OMX_ERRORTYPE get_component_version(
+ OMX_HANDLETYPE hComp,
+ OMX_STRING componentName,
+ OMX_VERSIONTYPE *componentVersion,
+ OMX_VERSIONTYPE *specVersion,
+ OMX_UUIDTYPE *componentUUID
+ );
+
+ OMX_ERRORTYPE get_config(
+ OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData
+ );
+
+ OMX_ERRORTYPE get_extension_index(
+ OMX_HANDLETYPE hComp,
+ OMX_STRING paramName,
+ OMX_INDEXTYPE *indexType
+ );
+
+ OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData);
+
+ OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp,
+ OMX_STATETYPE *state);
+
+
+
+ OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param1,
+ OMX_PTR cmdData);
+
+
+ OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp,
+ OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData);
+
+ virtual OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData) = 0;
+
+ virtual OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData) =0;
+
+ OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes,
+ OMX_U8 *buffer);
+
+
+ OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ void * eglImage);
+
+
+
+ int m_pipe_in;
+ int m_pipe_out;
+
+ pthread_t msg_thread_id;
+ pthread_t async_thread_id;
+
+ OMX_U8 m_nkind[128];
+
+
+ //int *input_pmem_fd;
+ //int *output_pmem_fd;
+ struct pmem *m_pInput_pmem;
+ struct pmem *m_pOutput_pmem;
+
+
+public:
+ // Bit Positions
+ enum flags_bit_positions
+ {
+ // Defer transition to IDLE
+ OMX_COMPONENT_IDLE_PENDING =0x1,
+ // Defer transition to LOADING
+ OMX_COMPONENT_LOADING_PENDING =0x2,
+ // First Buffer Pending
+ OMX_COMPONENT_FIRST_BUFFER_PENDING =0x3,
+ // Second Buffer Pending
+ OMX_COMPONENT_SECOND_BUFFER_PENDING =0x4,
+ // Defer transition to Enable
+ OMX_COMPONENT_INPUT_ENABLE_PENDING =0x5,
+ // Defer transition to Enable
+ OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x6,
+ // Defer transition to Disable
+ OMX_COMPONENT_INPUT_DISABLE_PENDING =0x7,
+ // Defer transition to Disable
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x8,
+ //defer flush notification
+ OMX_COMPONENT_OUTPUT_FLUSH_PENDING =0x9,
+ OMX_COMPONENT_INPUT_FLUSH_PENDING =0xA,
+ OMX_COMPONENT_PAUSE_PENDING =0xB,
+ OMX_COMPONENT_EXECUTE_PENDING =0xC
+
+ };
+
+ // Deferred callback identifiers
+ enum
+ {
+ //Event Callbacks from the venc component thread context
+ OMX_COMPONENT_GENERATE_EVENT = 0x1,
+ //Buffer Done callbacks from the venc component thread context
+ OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2,
+ //Frame Done callbacks from the venc component thread context
+ OMX_COMPONENT_GENERATE_FRAME_DONE = 0x3,
+ //Buffer Done callbacks from the venc component thread context
+ OMX_COMPONENT_GENERATE_FTB = 0x4,
+ //Frame Done callbacks from the venc component thread context
+ OMX_COMPONENT_GENERATE_ETB = 0x5,
+ //Command
+ OMX_COMPONENT_GENERATE_COMMAND = 0x6,
+ //Push-Pending Buffers
+ OMX_COMPONENT_PUSH_PENDING_BUFS = 0x7,
+ // Empty Buffer Done callbacks
+ OMX_COMPONENT_GENERATE_EBD = 0x8,
+ //Flush Event Callbacks from the venc component thread context
+ OMX_COMPONENT_GENERATE_EVENT_FLUSH = 0x9,
+ OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH = 0x0A,
+ OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH = 0x0B,
+ OMX_COMPONENT_GENERATE_FBD = 0xc,
+ OMX_COMPONENT_GENERATE_START_DONE = 0xD,
+ OMX_COMPONENT_GENERATE_PAUSE_DONE = 0xE,
+ OMX_COMPONENT_GENERATE_RESUME_DONE = 0xF,
+ OMX_COMPONENT_GENERATE_STOP_DONE = 0x10,
+ OMX_COMPONENT_GENERATE_HARDWARE_ERROR = 0x11
+ };
+
+ struct omx_event
+ {
+ unsigned param1;
+ unsigned param2;
+ unsigned id;
+ };
+
+ struct omx_cmd_queue
+ {
+ omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE];
+ unsigned m_read;
+ unsigned m_write;
+ unsigned m_size;
+
+ omx_cmd_queue();
+ ~omx_cmd_queue();
+ bool insert_entry(unsigned p1, unsigned p2, unsigned id);
+ bool pop_entry(unsigned *p1,unsigned *p2, unsigned *id);
+ // get msgtype of the first ele from the queue
+ unsigned get_q_msg_type();
+
+ };
+
+ bool allocate_done(void);
+ bool allocate_input_done(void);
+ bool allocate_output_done(void);
+
+ OMX_ERRORTYPE free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
+ OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
+
+ OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes);
+
+ OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,OMX_PTR appData,
+ OMX_U32 bytes);
+
+ OMX_ERRORTYPE use_input_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes,
+ OMX_U8 *buffer);
+
+ OMX_ERRORTYPE use_output_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes,
+ OMX_U8 *buffer);
+
+ bool execute_omx_flush(OMX_U32);
+ bool execute_output_flush(void);
+ bool execute_input_flush(void);
+ OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+
+ OMX_ERRORTYPE fill_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer);
+ OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer);
+ bool release_done();
+
+ bool release_output_done();
+ bool release_input_done();
+
+ OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param1,
+ OMX_PTR cmdData);
+ bool post_event( unsigned int p1,
+ unsigned int p2,
+ unsigned int id
+ );
+
+ inline void omx_report_error ()
+ {
+ m_state = OMX_StateInvalid;
+ if(m_pCallbacks.EventHandler)
+ {
+ m_pCallbacks.EventHandler(&m_cmp,m_app_data,
+ OMX_EventError,OMX_ErrorHardware,0,NULL);
+ m_pCallbacks.EventHandler(&m_cmp,m_app_data,
+ OMX_EventError, OMX_ErrorInvalidState,0, NULL);
+ }
+ }
+
+
+ //*************************************************************
+ //*******************MEMBER VARIABLES *************************
+ //*************************************************************
+
+ pthread_mutex_t m_lock;
+ sem_t m_cmd_lock;
+
+
+ //sem to handle the minimum procesing of commands
+
+
+ // compression format
+ //OMX_VIDEO_CODINGTYPE eCompressionFormat;
+ // OMX State
+ OMX_STATETYPE m_state;
+ // Application data
+ OMX_PTR m_app_data;
+ OMX_BOOL m_use_input_pmem;
+ OMX_BOOL m_use_output_pmem;
+ // Application callbacks
+ OMX_CALLBACKTYPE m_pCallbacks;
+ OMX_PORT_PARAM_TYPE m_sPortParam;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE m_sParamProfileLevel;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE m_sInPortFormat;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE m_sOutPortFormat;
+ OMX_PARAM_PORTDEFINITIONTYPE m_sInPortDef;
+ OMX_PARAM_PORTDEFINITIONTYPE m_sOutPortDef;
+ OMX_VIDEO_PARAM_MPEG4TYPE m_sParamMPEG4;
+ OMX_VIDEO_PARAM_H263TYPE m_sParamH263;
+ OMX_VIDEO_PARAM_AVCTYPE m_sParamAVC;
+ OMX_PORT_PARAM_TYPE m_sPortParam_img;
+ OMX_PORT_PARAM_TYPE m_sPortParam_audio;
+ OMX_VIDEO_CONFIG_BITRATETYPE m_sConfigBitrate;
+ OMX_CONFIG_FRAMERATETYPE m_sConfigFramerate;
+ OMX_VIDEO_PARAM_BITRATETYPE m_sParamBitrate;
+ OMX_PRIORITYMGMTTYPE m_sPriorityMgmt;
+ OMX_PARAM_BUFFERSUPPLIERTYPE m_sInBufSupplier;
+ OMX_PARAM_BUFFERSUPPLIERTYPE m_sOutBufSupplier;
+ OMX_CONFIG_ROTATIONTYPE m_sConfigFrameRotation;
+ OMX_CONFIG_INTRAREFRESHVOPTYPE m_sConfigIntraRefreshVOP;
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE m_sSessionQuantization;
+ OMX_VIDEO_PARAM_AVCSLICEFMO m_sAVCSliceFMO;
+
+ // fill this buffer queue
+ omx_cmd_queue m_ftb_q;
+ // Command Q for rest of the events
+ omx_cmd_queue m_cmd_q;
+ omx_cmd_queue m_etb_q;
+ // Input memory pointer
+ OMX_BUFFERHEADERTYPE *m_inp_mem_ptr;
+ // Output memory pointer
+ OMX_BUFFERHEADERTYPE *m_out_mem_ptr;
+
+ bool input_flush_progress;
+ bool output_flush_progress;
+ bool input_use_buffer;
+ bool output_use_buffer;
+ int pending_input_buffers;
+ int pending_output_buffers;
+
+ unsigned int m_out_bm_count;
+ unsigned int m_inp_bm_count;
+ unsigned int m_flags;
+ unsigned int m_etb_count;
+ unsigned int m_fbd_count;
+#ifdef _ANDROID_
+ // Heap pointer to frame buffers
+ sp<MemoryHeapBase> m_heap_ptr;
+#endif //_ANDROID_
+ // to know whether Event Port Settings change has been triggered or not.
+ bool m_event_port_settings_sent;
+ OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE];
+};
+
+#endif // __OMX_VIDEO_BASE_H__
diff --git a/omx/mm-video/vidc/venc/inc/omx_video_common.h b/omx/mm-video/vidc/venc/inc/omx_video_common.h
new file mode 100644
index 0000000..74803ab
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/omx_video_common.h
@@ -0,0 +1,75 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef __OMX_VIDEO_COMMON_H__
+#define __OMX_VIDEO_COMMON_H__
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include<stdlib.h>
+#include <stdio.h>
+
+#define OMX_VIDEO_DEC_NUM_INPUT_BUFFERS 2
+#define OMX_VIDEO_DEC_NUM_OUTPUT_BUFFERS 2
+
+#ifdef FEATURE_QTV_WVGA_ENABLE
+#define OMX_VIDEO_DEC_INPUT_BUFFER_SIZE (256*1024)
+#else
+#define OMX_VIDEO_DEC_INPUT_BUFFER_SIZE (128*1024)
+#endif
+
+#define OMX_CORE_CONTROL_CMDQ_SIZE 100
+#define OMX_CORE_QCIF_HEIGHT 144
+#define OMX_CORE_QCIF_WIDTH 176
+#define OMX_CORE_VGA_HEIGHT 480
+#define OMX_CORE_VGA_WIDTH 640
+#define OMX_CORE_WVGA_HEIGHT 480
+#define OMX_CORE_WVGA_WIDTH 800
+
+enum PortIndexType
+{
+ PORT_INDEX_IN = 0,
+ PORT_INDEX_OUT = 1,
+ PORT_INDEX_BOTH = -1,
+ PORT_INDEX_NONE = -2
+};
+
+struct pmem
+{
+ void *buffer;
+ int fd;
+ unsigned offset;
+ unsigned size;
+};
+
+#endif // __OMX_VIDEO_COMMON_H__
+
+
+
+
diff --git a/omx/mm-video/vidc/venc/inc/omx_video_encoder.h b/omx/mm-video/vidc/venc/inc/omx_video_encoder.h
new file mode 100644
index 0000000..df3e1fa
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/omx_video_encoder.h
@@ -0,0 +1,70 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef __OMX_VENC__H
+#define __OMX_VENC__H
+
+#include "omx_video_base.h"
+#include "video_encoder_device.h"
+
+extern "C" {
+ OMX_API void * get_omx_component_factory_fn(void);
+}
+
+class omx_venc: public omx_video
+{
+public:
+ omx_venc(); //constructor
+ ~omx_venc(); //des
+ static int async_message_process (void *context, void* message);
+ OMX_ERRORTYPE component_init(OMX_STRING role);
+ OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE paramIndex,
+ OMX_PTR paramData);
+ OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp,
+ OMX_INDEXTYPE configIndex,
+ OMX_PTR configData);
+ OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp);
+ //OMX strucutres
+ OMX_U32 m_nVenc_format;
+ class venc_dev *handle;
+
+private:
+ OMX_U32 dev_stop(void);
+ OMX_U32 dev_pause(void);
+ OMX_U32 dev_start(void);
+ OMX_U32 dev_flush(unsigned);
+ OMX_U32 dev_resume(void);
+ bool dev_use_buf( void *,unsigned);
+ bool dev_free_buf( void *,unsigned);
+ bool dev_empty_buf(void *, void *);
+ bool dev_fill_buf(void *, void *);
+ bool dev_get_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32);
+ bool dev_set_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32);
+};
+
+#endif //__OMX_VENC__H
diff --git a/omx/mm-video/vidc/venc/inc/queue.h b/omx/mm-video/vidc/venc/inc/queue.h
new file mode 100644
index 0000000..71ca479
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/queue.h
@@ -0,0 +1,80 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include<pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Message Queue structure */
+struct video_msgq
+{
+ /* Command to be executed */
+ unsigned int cmd;
+
+ unsigned int status;
+
+ /* Client-specific data */
+ void *clientdata;
+};
+
+
+/* Thread & Message Queue information */
+struct video_queue_context
+{
+ /* Message Queue related members */
+ pthread_mutex_t mutex;
+ sem_t sem_message;
+ int commandq_size;
+ int dataq_size;
+ struct video_msgq *ptr_dataq;
+ struct video_msgq *ptr_cmdq;
+ int write_dataq ;
+ int read_dataq;
+ int write_comq ;
+ int read_comq ;
+
+};
+
+int check_if_queue_empty ( unsigned int queuetocheck,void* queuecontext );
+
+struct video_msgq * queue_get_cmd ( void* queuecontext );
+
+
+
+int queue_post_cmdq ( void *queuecontext,
+ struct video_msgq *post_msg
+ );
+
+int queue_post_dataq ( void *queuecontext,
+ struct video_msgq *post_msg
+ );
+
+#endif /* QUEUE_H */
diff --git a/omx/mm-video/vidc/venc/inc/venc_util.h b/omx/mm-video/vidc/venc/inc/venc_util.h
new file mode 100644
index 0000000..20b4f56
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/venc_util.h
@@ -0,0 +1,53 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ V E N C _ U T I L. H
+
+DESCRIPTION
+
+
+REFERENCES
+
+
+============================================================================*/
+
+#ifndef _VENC_UTIL_H
+#define _VENC_UTIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+long long GetTimeStamp();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/omx/mm-video/vidc/venc/inc/video_encoder_device.h b/omx/mm-video/vidc/venc/inc/video_encoder_device.h
new file mode 100644
index 0000000..1728dff
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/video_encoder_device.h
@@ -0,0 +1,97 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#ifndef __OMX_VENC_DEV__
+#define __OMX_VENC_DEV__
+
+#include "OMX_Types.h"
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+#include "qc_omx_component.h"
+#include "omx_video_common.h"
+#include <linux/msm_vidc_enc.h>
+
+
+void* async_venc_message_thread (void *);
+
+class venc_dev
+{
+public:
+ venc_dev(); //constructor
+ ~venc_dev(); //des
+
+ bool venc_open(OMX_U32);
+ void venc_close();
+ unsigned venc_stop(void);
+ unsigned venc_pause(void);
+ unsigned venc_start(void);
+ unsigned venc_flush(unsigned);
+
+ unsigned venc_resume(void);
+ bool venc_use_buf(void*, unsigned);
+ bool venc_free_buf(void*, unsigned);
+ bool venc_empty_buf(void *, void *);
+ bool venc_fill_buf(void *, void *);
+
+ bool venc_get_buf_req(unsigned long *,unsigned long *,
+ unsigned long *,unsigned long);
+ bool venc_set_buf_req(unsigned long *,unsigned long *,
+ unsigned long *,unsigned long);
+ bool venc_set_param(void *,OMX_INDEXTYPE);
+ bool venc_set_config(void *configData, OMX_INDEXTYPE index);
+ bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel);
+ OMX_U32 m_nDriver_fd;
+ bool m_profile_set;
+ bool m_level_set;
+
+private:
+ struct venc_basecfg m_sVenc_cfg;
+ struct venc_ratectrlcfg rate_ctrl;
+ struct venc_targetbitrate bit_rate;
+ struct venc_intraperiod intra_period;
+ struct venc_profile codec_profile;
+ struct ven_profilelevel profile_level;
+ struct venc_switch set_param;
+ struct venc_voptimingcfg time_inc;
+ struct venc_allocatorproperty m_sInput_buff_property;
+ struct venc_allocatorproperty m_sOutput_buff_property;
+ struct venc_sessionqp session_qp;
+ struct venc_multiclicecfg multislice_cfg;
+
+ bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel);
+ bool venc_set_intra_period(OMX_U32 nPFrames);
+ bool venc_set_target_bitrate(OMX_U32 nTargetBitrate);
+ bool venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate);
+ bool venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp);
+ bool venc_set_encode_framerate(OMX_U32 encode_framerate);
+ bool venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh);
+ bool venc_set_color_format(OMX_COLOR_FORMATTYPE color_format);
+ bool venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel);
+ bool venc_set_multislice_cfg(OMX_VIDEO_AVCSLICEMODETYPE eSliceMode);
+};
+
+#endif
diff --git a/omx/mm-video/vidc/venc/inc/video_encoder_test.h b/omx/mm-video/vidc/venc/inc/video_encoder_test.h
new file mode 100644
index 0000000..6d0a50b
--- /dev/null
+++ b/omx/mm-video/vidc/venc/inc/video_encoder_test.h
@@ -0,0 +1,76 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include "queue.h"
+#include<fcntl.h>
+#include<sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/msm_vidc_enc.h>
+#include<pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+#define INPUT_BUFFER 0
+#define OUTPUT_BUFFER 1
+
+struct video_encoder_context
+{
+ unsigned long input_width;
+ unsigned long input_height;
+ unsigned long codectype;
+ unsigned long fps_num;
+ unsigned long fps_den;
+ unsigned long targetbitrate;
+ unsigned long inputformat;
+
+ struct venc_allocatorproperty input_buffer;
+ struct venc_allocatorproperty output_buffer;
+ struct venc_bufferpayload **ptr_inputbuffer;
+ struct venc_bufferpayload **ptr_outputbuffer;
+ struct video_queue_context queue_context;
+ int video_driver_fd;
+
+ FILE * inputBufferFile;
+ FILE * outputBufferFile;
+
+ pthread_t videothread_id;
+ pthread_t asyncthread_id;
+ sem_t sem_synchronize;
+};
+
+int init_encoder ( struct video_encoder_context *init_decode );
+int allocate_buffer ( unsigned int buffer_dir,
+ struct video_encoder_context *decode_context
+ );
+int free_buffer ( unsigned int buffer_dir,
+ struct video_encoder_context *decode_context
+ );
+int start_encoding (struct video_encoder_context *decode_context);
+int stop_encoding (struct video_encoder_context *decode_context);
+int deinit_encoder (struct video_encoder_context *init_decode);
diff --git a/omx/mm-video/vidc/venc/src/omx_video_base.cpp b/omx/mm-video/vidc/venc/src/omx_video_base.cpp
new file mode 100644
index 0000000..6c68262
--- /dev/null
+++ b/omx/mm-video/vidc/venc/src/omx_video_base.cpp
@@ -0,0 +1,3530 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ O p e n M A X w r a p p e r s
+ O p e n M A X C o r e
+
+*//** @file omx_video_base.cpp
+ This module contains the implementation of the OpenMAX core & component.
+
+*//*========================================================================*/
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#include <string.h>
+#include "omx_video_base.h"
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define H264_SUPPORTED_WIDTH (480)
+#define H264_SUPPORTED_HEIGHT (368)
+
+#define MPEG4_SUPPORTED_WIDTH (480)
+#define MPEG4_SUPPORTED_HEIGHT (368)
+
+#define VC1_SP_MP_START_CODE 0xC5000000
+#define VC1_SP_MP_START_CODE_MASK 0xFF000000
+#define VC1_AP_START_CODE 0x00000100
+#define VC1_AP_START_CODE_MASK 0xFFFFFF00
+#define VC1_STRUCT_C_PROFILE_MASK 0xF0
+#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
+#define VC1_SIMPLE_PROFILE 0
+#define VC1_MAIN_PROFILE 1
+#define VC1_ADVANCE_PROFILE 3
+#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
+#define VC1_SIMPLE_PROFILE_MED_LEVEL 2
+#define VC1_STRUCT_C_LEN 4
+#define VC1_STRUCT_C_POS 8
+#define VC1_STRUCT_A_POS 12
+#define VC1_STRUCT_B_POS 24
+#define VC1_SEQ_LAYER_SIZE 36
+
+typedef struct OMXComponentCapabilityFlagsType
+{
+ ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS
+ OMX_BOOL iIsOMXComponentMultiThreaded;
+ OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc;
+ OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc;
+ OMX_BOOL iOMXComponentSupportsMovableInputBuffers;
+ OMX_BOOL iOMXComponentSupportsPartialFrames;
+ OMX_BOOL iOMXComponentUsesNALStartCodes;
+ OMX_BOOL iOMXComponentCanHandleIncompleteFrames;
+ OMX_BOOL iOMXComponentUsesFullAVCFrames;
+
+} OMXComponentCapabilityFlagsType;
+#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347
+
+void* message_thread(void *input)
+{
+ omx_video* omx = reinterpret_cast<omx_video*>(input);
+ unsigned char id;
+ int n;
+
+ DEBUG_PRINT_LOW("omx_venc: message thread start\n");
+ while(1)
+ {
+ n = read(omx->m_pipe_in, &id, 1);
+ if(0 == n)
+ {
+ break;
+ }
+
+ if(1 == n)
+ {
+ omx->process_event_cb(omx, id);
+ }
+#ifdef QLE_BUILD
+ if(n < 0) break;
+#else
+ if((n < 0) && (errno != EINTR)) break;
+#endif
+ }
+ DEBUG_PRINT_LOW("omx_venc: message thread stop\n");
+ return 0;
+}
+
+void post_message(omx_video *omx, unsigned char id)
+{
+ DEBUG_PRINT_LOW("omx_venc: post_message %d\n", id);
+ write(omx->m_pipe_out, &id, 1);
+}
+
+// omx_cmd_queue destructor
+omx_video::omx_cmd_queue::~omx_cmd_queue()
+{
+ // Nothing to do
+}
+
+// omx cmd queue constructor
+omx_video::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
+{
+ memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
+}
+
+// omx cmd queue insert
+bool omx_video::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id)
+{
+ bool ret = true;
+ if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE)
+ {
+ m_q[m_write].id = id;
+ m_q[m_write].param1 = p1;
+ m_q[m_write].param2 = p2;
+ m_write++;
+ m_size ++;
+ if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE)
+ {
+ m_write = 0;
+ }
+ }
+ else
+ {
+ ret = false;
+ DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full\n");
+ }
+ return ret;
+}
+
+// omx cmd queue pop
+bool omx_video::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id)
+{
+ bool ret = true;
+ if(m_size > 0)
+ {
+ *id = m_q[m_read].id;
+ *p1 = m_q[m_read].param1;
+ *p2 = m_q[m_read].param2;
+ // Move the read pointer ahead
+ ++m_read;
+ --m_size;
+ if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE)
+ {
+ m_read = 0;
+ }
+ }
+ else
+ {
+ ret = false;
+ }
+ return ret;
+}
+
+// Retrieve the first mesg type in the queue
+unsigned omx_video::omx_cmd_queue::get_q_msg_type()
+{
+ return m_q[m_read].id;
+}
+
+
+
+#ifdef _ANDROID_
+VideoHeap::VideoHeap(int fd, size_t size, void* base)
+{
+ // dup file descriptor, map once, use pmem
+ init(dup(fd), base, size, 0 , "/dev/pmem_adsp");
+}
+#endif // _ANDROID_
+
+/* ======================================================================
+FUNCTION
+ omx_venc::omx_venc
+
+DESCRIPTION
+ Constructor
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None.
+========================================================================== */
+omx_video::omx_video(): m_state(OMX_StateInvalid),
+ m_app_data(NULL),
+ m_inp_mem_ptr(NULL),
+ m_out_mem_ptr(NULL),
+ pending_input_buffers(0),
+ pending_output_buffers(0),
+ m_out_bm_count(0),
+ m_inp_bm_count(0),
+ m_flags(0),
+ m_event_port_settings_sent(false),
+ output_flush_progress (false),
+ input_flush_progress (false),
+ input_use_buffer (false),
+ output_use_buffer (false),
+ m_use_input_pmem(OMX_FALSE),
+ m_use_output_pmem(OMX_FALSE),
+ m_etb_count(0),
+ m_fbd_count(0)
+{
+ DEBUG_PRINT_HIGH("\n omx_video(): Inside Constructor()");
+ memset(&m_cmp,0,sizeof(m_cmp));
+ memset(&m_pCallbacks,0,sizeof(m_pCallbacks));
+
+ pthread_mutex_init(&m_lock, NULL);
+ sem_init(&m_cmd_lock,0,0);
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::~omx_venc
+
+DESCRIPTION
+ Destructor
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ None.
+========================================================================== */
+omx_video::~omx_video()
+{
+ DEBUG_PRINT_HIGH("\n ~omx_video(): Inside Destructor()");
+ if(m_pipe_in) close(m_pipe_in);
+ if(m_pipe_out) close(m_pipe_out);
+ DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit\n");
+ pthread_join(msg_thread_id,NULL);
+ DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit\n");
+ pthread_join(async_thread_id,NULL);
+ pthread_mutex_destroy(&m_lock);
+ sem_destroy(&m_cmd_lock);
+ DEBUG_PRINT_HIGH("\n m_etb_count = %u, m_fbd_count = %u\n", m_etb_count,
+ m_fbd_count);
+ DEBUG_PRINT_HIGH("omx_video: Destructor exit\n");
+ DEBUG_PRINT_HIGH("Exiting 7x30 OMX Video Encoder ...\n");
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::OMXCntrlProcessMsgCb
+
+DESCRIPTION
+ IL Client callbacks are generated through this routine. The decoder
+ provides the thread context for this routine.
+
+PARAMETERS
+ ctxt -- Context information related to the self.
+ id -- Event identifier. This could be any of the following:
+ 1. Command completion event
+ 2. Buffer done callback event
+ 3. Frame done callback event
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+void omx_video::process_event_cb(void *ctxt, unsigned char id)
+{
+ unsigned p1; // Parameter - 1
+ unsigned p2; // Parameter - 2
+ unsigned ident;
+ unsigned qsize=0; // qsize
+ omx_video *pThis = (omx_video *) ctxt;
+
+ if(!pThis)
+ {
+ DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out\n");
+ return;
+ }
+
+ // Protect the shared queue data structure
+ do
+ {
+ /*Read the message id's from the queue*/
+
+ pthread_mutex_lock(&pThis->m_lock);
+ qsize = pThis->m_cmd_q.m_size;
+ if(qsize)
+ {
+ pThis->m_cmd_q.pop_entry(&p1,&p2,&ident);
+ }
+
+ if(qsize == 0)
+ {
+ qsize = pThis->m_ftb_q.m_size;
+ if(qsize)
+ {
+ pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
+ }
+ }
+
+ if(qsize == 0)
+ {
+ qsize = pThis->m_etb_q.m_size;
+ if(qsize)
+ {
+ pThis->m_etb_q.pop_entry(&p1,&p2,&ident);
+ }
+ }
+
+ pthread_mutex_unlock(&pThis->m_lock);
+
+ /*process message if we have one*/
+ if(qsize > 0)
+ {
+ id = ident;
+ switch(id)
+ {
+ case OMX_COMPONENT_GENERATE_EVENT:
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ switch(p1)
+ {
+ case OMX_CommandStateSet:
+ pThis->m_state = (OMX_STATETYPE) p2;
+ DEBUG_PRINT_LOW("Process -> state set to %d \n", pThis->m_state);
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete, p1, p2, NULL);
+ break;
+
+ case OMX_EventError:
+ DEBUG_PRINT_ERROR("\nERROR: OMX_EventError: p2 = %d\n", p2);
+ if(p2 == OMX_StateInvalid)
+ {
+ pThis->m_state = (OMX_STATETYPE) p2;
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
+ }
+ else if(p2 == OMX_ErrorHardware)
+ {
+ pThis->m_state = OMX_StateInvalid;
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError,OMX_ErrorHardware,0,NULL);
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
+
+ }
+ else
+ {
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError, p2, NULL, NULL );
+
+ }
+ break;
+
+ case OMX_CommandPortDisable:
+ DEBUG_PRINT_LOW("Process -> Port %d set to PORT_STATE_DISABLED" \
+ "state \n", p2);
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete, p1, p2, NULL );
+ break;
+ case OMX_CommandPortEnable:
+ DEBUG_PRINT_LOW("Process ->Port %d set PORT_STATE_ENABLED state\n" \
+ , p2);
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
+ OMX_EventCmdComplete, p1, p2, NULL );
+ break;
+
+ default:
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete, p1, p2, NULL );
+ break;
+
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks\n");
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_ETB:
+ if(pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
+ (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_FTB:
+ if( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
+ (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: FTBProxy() failed!\n");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_COMMAND:
+ pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
+ (OMX_U32)p2,(OMX_PTR)NULL);
+ break;
+
+ case OMX_COMPONENT_GENERATE_EBD:
+ if( pThis->empty_buffer_done(&pThis->m_cmp,
+ (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_FBD:
+ if( pThis->fill_buffer_done(&pThis->m_cmp,
+ (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone )
+ {
+ DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
+
+ pThis->input_flush_progress = false;
+ DEBUG_PRINT_HIGH("\nm_etb_count at i/p flush = %u", m_etb_count);
+ m_etb_count = 0;
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ /*Check if we need generate event for Flush done*/
+ if(BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_INPUT_FLUSH_PENDING))
+ {
+ BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandFlush,
+ PORT_INDEX_IN,NULL );
+ }
+ else if(BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_IDLE_PENDING))
+ {
+ if(!pThis->output_flush_progress)
+ {
+ printf("\n dev_stop called after input flush complete\n");
+ if(dev_stop() != 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in i/p flush!\n");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
+
+ pThis->output_flush_progress = false;
+ DEBUG_PRINT_HIGH("\nm_fbd_count at o/p flush = %u", m_fbd_count);
+ m_fbd_count = 0;
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ /*Check if we need generate event for Flush done*/
+ if(BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_OUTPUT_FLUSH_PENDING))
+ {
+ BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
+
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandFlush,
+ PORT_INDEX_OUT,NULL );
+ }
+ else if(BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING))
+ {
+ printf("\n dev_stop called after Output flush complete\n");
+ if(!pThis->input_flush_progress)
+ {
+ if(dev_stop() != 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in o/p flush!\n");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_START_DONE:
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE msg");
+
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success");
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
+ {
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Move to \
+ executing");
+ // Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
+ pThis->m_state = OMX_StateExecuting;
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StateExecuting, NULL);
+ }
+ else if(BITMASK_PRESENT(&pThis->m_flags,
+ OMX_COMPONENT_PAUSE_PENDING))
+ {
+ if(dev_pause())
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in Start Done!\n");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Event Handler callback is NULL");
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_PAUSE_DONE:
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE msg");
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING))
+ {
+ //Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
+ pThis->m_state = OMX_StatePause;
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StatePause, NULL);
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_RESUME_DONE:
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_RESUME_DONE msg");
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING))
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
+ pThis->m_state = OMX_StateExecuting;
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StateExecuting,NULL);
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_STOP_DONE:
+ DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE msg");
+ if(pThis->m_pCallbacks.EventHandler)
+ {
+ if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
+ pThis->m_state = OMX_StateIdle;
+ pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data,
+ OMX_EventCmdComplete,OMX_CommandStateSet,
+ OMX_StateIdle,NULL);
+ }
+ }
+
+ break;
+
+ case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
+ DEBUG_PRINT_ERROR("\nERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!\n");
+ pThis->omx_report_error ();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ pthread_mutex_lock(&pThis->m_lock);
+ qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\
+ pThis->m_etb_q.m_size;
+
+ pthread_mutex_unlock(&pThis->m_lock);
+
+ }
+ while(qsize>0);
+ printf("\n exited the while loop\n");
+
+}
+
+
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::GetComponentVersion
+
+DESCRIPTION
+ Returns the component version.
+
+PARAMETERS
+ TBD.
+
+RETURN VALUE
+ OMX_ErrorNone.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::get_component_version
+(
+OMX_IN OMX_HANDLETYPE hComp,
+OMX_OUT OMX_STRING componentName,
+OMX_OUT OMX_VERSIONTYPE* componentVersion,
+OMX_OUT OMX_VERSIONTYPE* specVersion,
+OMX_OUT OMX_UUIDTYPE* componentUUID
+)
+{
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ /* TBD -- Return the proper version */
+ return OMX_ErrorNone;
+}
+/* ======================================================================
+FUNCTION
+ omx_venc::SendCommand
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_COMMANDTYPE cmd,
+ OMX_IN OMX_U32 param1,
+ OMX_IN OMX_PTR cmdData
+ )
+{
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if(cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable)
+ {
+ if((param1 != PORT_INDEX_IN) && (param1 != PORT_INDEX_OUT) && (param1 != PORT_INDEX_BOTH))
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index\n");
+ return OMX_ErrorBadPortIndex;
+ }
+ }
+ if(cmd == OMX_CommandMarkBuffer)
+ {
+ if(param1 != PORT_INDEX_IN)
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index \n");
+ return OMX_ErrorBadPortIndex;
+ }
+ if(!cmdData)
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
+ sem_wait(&m_cmd_lock);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::SendCommand
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_COMMANDTYPE cmd,
+ OMX_IN OMX_U32 param1,
+ OMX_IN OMX_PTR cmdData
+ )
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_STATETYPE eState = (OMX_STATETYPE) param1;
+ int bFlag = 1;
+
+ if(cmd == OMX_CommandStateSet)
+ {
+ /***************************/
+ /* Current State is Loaded */
+ /***************************/
+ if(m_state == OMX_StateLoaded)
+ {
+ if(eState == OMX_StateIdle)
+ {
+ //if all buffers are allocated or all ports disabled
+ if(allocate_done() ||
+ ( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE))
+ {
+ DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle\n");
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Loaded to Loaded */
+ else if(eState == OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded\n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Loaded to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition */
+ DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources\n");
+ }
+ /* Requesting transition from Loaded to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Loaded to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Loaded to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid\n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid(%d Not Handled)\n",\
+ eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /***************************/
+ /* Current State is IDLE */
+ /***************************/
+ else if(m_state == OMX_StateIdle)
+ {
+ if(eState == OMX_StateLoaded)
+ {
+ if(release_done())
+ {
+ /*
+ Since error is None , we will post an event at the end
+ of this function definition
+ */
+ DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded\n");
+ if(dev_stop() != 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed at Idle --> Loaded");
+ eRet = OMX_ErrorHardware;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Idle to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ if( dev_start() )
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Exe\n");
+ omx_report_error ();
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
+ DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n");
+ bFlag = 0;
+ }
+
+ }
+ /* Requesting transition from Idle to Idle */
+ else if(eState == OMX_StateIdle)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle\n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Idle to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Idle to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ /*To pause the Video core we need to start the driver*/
+ if( dev_start() )
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Pause\n");
+ omx_report_error ();
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
+ DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n");
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Idle to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid\n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled\n",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /******************************/
+ /* Current State is Executing */
+ /******************************/
+ else if(m_state == OMX_StateExecuting)
+ {
+ /* Requesting transition from Executing to Idle */
+ if(eState == OMX_StateIdle)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition
+ */
+ DEBUG_PRINT_LOW("\n OMXCORE-SM: Executing --> Idle \n");
+ //here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle
+ BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
+ execute_omx_flush(OMX_ALL);
+ bFlag = 0;
+ }
+ /* Requesting transition from Executing to Paused */
+ else if(eState == OMX_StatePause)
+ {
+
+ if(dev_pause())
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in SCP on Exe --> Pause\n");
+ post_event(OMX_EventError,OMX_ErrorHardware,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
+ DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n");
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Executing to Loaded */
+ else if(eState == OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Loaded \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Executing to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> WaitForResources \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Executing to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Executing \n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Executing to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Invalid \n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled\n",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /***************************/
+ /* Current State is Pause */
+ /***************************/
+ else if(m_state == OMX_StatePause)
+ {
+ /* Requesting transition from Pause to Executing */
+ if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_LOW("\n Pause --> Executing \n");
+ if( dev_resume() )
+ {
+ post_event(OMX_EventError,OMX_ErrorHardware,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorHardware;
+ }
+ else
+ {
+ BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
+ DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n");
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Pause to Idle */
+ else if(eState == OMX_StateIdle)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition */
+ DEBUG_PRINT_LOW("\n Pause --> Idle \n");
+ BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
+ execute_omx_flush(OMX_ALL);
+ bFlag = 0;
+ }
+ /* Requesting transition from Pause to loaded */
+ else if(eState == OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Pause --> loaded \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Pause to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Pause --> WaitForResources \n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from Pause to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Pause --> Pause \n");
+ post_event(OMX_EventError,OMX_ErrorSameState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from Pause to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Pause --> Invalid \n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled\n",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /***************************/
+ /* Current State is WaitForResources */
+ /***************************/
+ else if(m_state == OMX_StateWaitForResources)
+ {
+ /* Requesting transition from WaitForResources to Loaded */
+ if(eState == OMX_StateLoaded)
+ {
+ /* Since error is None , we will post an event
+ at the end of this function definition */
+ DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded\n");
+ }
+ /* Requesting transition from WaitForResources to WaitForResources */
+ else if(eState == OMX_StateWaitForResources)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources\n");
+ post_event(OMX_EventError,OMX_ErrorSameState,
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorSameState;
+ }
+ /* Requesting transition from WaitForResources to Executing */
+ else if(eState == OMX_StateExecuting)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from WaitForResources to Pause */
+ else if(eState == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause\n");
+ post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorIncorrectStateTransition;
+ }
+ /* Requesting transition from WaitForResources to Invalid */
+ else if(eState == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid\n");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ /* Requesting transition from WaitForResources to Loaded -
+ is NOT tested by Khronos TS */
+
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)\n",m_state,eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ /********************************/
+ /* Current State is Invalid */
+ /*******************************/
+ else if(m_state == OMX_StateInvalid)
+ {
+ /* State Transition from Inavlid to any state */
+ if(eState == (OMX_StateLoaded || OMX_StateWaitForResources
+ || OMX_StateIdle || OMX_StateExecuting
+ || OMX_StatePause || OMX_StateInvalid))
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded\n");
+ post_event(OMX_EventError,OMX_ErrorInvalidState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ }
+ else if(cmd == OMX_CommandFlush)
+ {
+ if(0 == param1 || OMX_ALL == param1)
+ {
+ BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
+ }
+ if(1 == param1 || OMX_ALL == param1)
+ {
+ //generate output flush event only.
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
+ }
+
+ execute_omx_flush(param1);
+ bFlag = 0;
+ }
+ else if( cmd == OMX_CommandPortEnable)
+ {
+ if(param1 == PORT_INDEX_IN || param1 == OMX_ALL)
+ {
+ m_sInPortDef.bEnabled = OMX_TRUE;
+
+ if( (m_state == OMX_StateLoaded &&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ || allocate_input_done())
+ {
+ post_event(OMX_CommandPortEnable,PORT_INDEX_IN,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL)
+ {
+ m_sOutPortDef.bEnabled = OMX_TRUE;
+
+ if( (m_state == OMX_StateLoaded &&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ || (allocate_output_done()))
+ {
+ post_event(OMX_CommandPortEnable,PORT_INDEX_OUT,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ }
+ else if(cmd == OMX_CommandPortDisable)
+ {
+ if(param1 == PORT_INDEX_IN || param1 == OMX_ALL)
+ {
+ m_sInPortDef.bEnabled = OMX_FALSE;
+ if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
+ && release_input_done())
+ {
+ post_event(OMX_CommandPortDisable,PORT_INDEX_IN,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ else
+ {
+ BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
+ {
+ execute_omx_flush(PORT_INDEX_IN);
+ }
+
+ // Skip the event notification
+ bFlag = 0;
+ }
+ }
+ if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL)
+ {
+ m_sOutPortDef.bEnabled = OMX_FALSE;
+
+ if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
+ && release_output_done())
+ {
+ post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ else
+ {
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+ if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting)
+ {
+ execute_omx_flush(PORT_INDEX_OUT);
+ }
+ // Skip the event notification
+ bFlag = 0;
+
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)\n",cmd);
+ eRet = OMX_ErrorNotImplemented;
+ }
+ if(eRet == OMX_ErrorNone && bFlag)
+ {
+ post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
+ }
+ sem_post(&m_cmd_lock);
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::ExecuteOmxFlush
+
+DESCRIPTION
+ Executes the OMX flush.
+
+PARAMETERS
+ flushtype - input flush(1)/output flush(0)/ both.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_video::execute_omx_flush(OMX_U32 flushType)
+{
+ bool bRet = false;
+ DEBUG_PRINT_LOW("\n execute_omx_flush - %d\n", flushType);
+ if(flushType == 0 || flushType == OMX_ALL)
+ {
+ input_flush_progress = true;
+ //flush input only
+ bRet = execute_input_flush();
+ }
+ if(flushType == 1 || flushType == OMX_ALL)
+ {
+ //flush output only
+ output_flush_progress = true;
+ bRet = execute_output_flush();
+ }
+ return bRet;
+}
+/*=========================================================================
+FUNCTION : execute_output_flush
+
+DESCRIPTION
+ Executes the OMX flush at OUTPUT PORT.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+==========================================================================*/
+bool omx_video::execute_output_flush(void)
+{
+ unsigned p1 = 0; // Parameter - 1
+ unsigned p2 = 0; // Parameter - 2
+ unsigned ident = 0;
+ bool bRet = true;
+
+ /*Generate FBD for all Buffers in the FTBq*/
+ DEBUG_PRINT_LOW("\n execute_output_flush\n");
+ pthread_mutex_lock(&m_lock);
+ while(m_ftb_q.m_size)
+ {
+ m_ftb_q.pop_entry(&p1,&p2,&ident);
+
+ if(ident == OMX_COMPONENT_GENERATE_FTB )
+ {
+ pending_output_buffers++;
+ fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
+ }
+ else if(ident == OMX_COMPONENT_GENERATE_FBD)
+ {
+ fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
+ }
+ }
+
+ pthread_mutex_unlock(&m_lock);
+ /*Check if there are buffers with the Driver*/
+ if(dev_flush(PORT_INDEX_OUT))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: o/p dev_flush() Failed");
+ return false;
+ }
+
+ return bRet;
+}
+/*=========================================================================
+FUNCTION : execute_input_flush
+
+DESCRIPTION
+ Executes the OMX flush at INPUT PORT.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+==========================================================================*/
+bool omx_video::execute_input_flush(void)
+{
+ unsigned p1 = 0; // Parameter - 1
+ unsigned p2 = 0; // Parameter - 2
+ unsigned ident = 0;
+ bool bRet = true;
+
+ /*Generate EBD for all Buffers in the ETBq*/
+ DEBUG_PRINT_LOW("\n execute_input_flush\n");
+
+ pthread_mutex_lock(&m_lock);
+ while(m_etb_q.m_size)
+ {
+ m_etb_q.pop_entry(&p1,&p2,&ident);
+ if(ident == OMX_COMPONENT_GENERATE_ETB)
+ {
+ pending_input_buffers++;
+ empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
+ }
+ else if(ident == OMX_COMPONENT_GENERATE_EBD)
+ {
+ empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
+ }
+ }
+
+ pthread_mutex_unlock(&m_lock);
+ /*Check if there are buffers with the Driver*/
+ if(dev_flush(PORT_INDEX_IN))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: i/p dev_flush() Failed");
+ return false;
+ }
+
+ return bRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::SendCommandEvent
+
+DESCRIPTION
+ Send the event to decoder pipe. This is needed to generate the callbacks
+ in decoder thread context.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_video::post_event(unsigned int p1,
+ unsigned int p2,
+ unsigned int id)
+{
+ bool bRet = false;
+
+
+ pthread_mutex_lock(&m_lock);
+
+ if( id == OMX_COMPONENT_GENERATE_FTB || \
+ (id == OMX_COMPONENT_GENERATE_FRAME_DONE))
+ {
+ m_ftb_q.insert_entry(p1,p2,id);
+ }
+ else if((id == OMX_COMPONENT_GENERATE_ETB) \
+ || (id == OMX_COMPONENT_GENERATE_EBD))
+ {
+ m_etb_q.insert_entry(p1,p2,id);
+ }
+ else
+ {
+ m_cmd_q.insert_entry(p1,p2,id);
+ }
+
+ bRet = true;
+ DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this);
+ post_message(this, id);
+ pthread_mutex_unlock(&m_lock);
+
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::GetParameter
+
+DESCRIPTION
+ OMX Get Parameter method implementation
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_INOUT OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned int height=0,width = 0;
+
+ DEBUG_PRINT_LOW("get_parameter: \n");
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if(paramData == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n");
+ return OMX_ErrorBadParameter;
+ }
+ switch(paramIndex)
+ {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n");
+ if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ DEBUG_PRINT_LOW("\n i/p actual cnt = %d\n", m_sInPortDef.nBufferCountActual);
+ DEBUG_PRINT_LOW("\n i/p min cnt = %d\n", m_sInPortDef.nBufferCountMin);
+ memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef));
+ }
+ else if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ DEBUG_PRINT_LOW("\n o/p actual cnt = %d\n", m_sOutPortDef.nBufferCountActual);
+ DEBUG_PRINT_LOW("\n o/p min cnt = %d\n", m_sOutPortDef.nBufferCountMin);
+ memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef));
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexParamVideoInit:
+ {
+ OMX_PORT_PARAM_TYPE *portParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n");
+
+ memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam));
+ break;
+ }
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n");
+
+ if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat));
+ }
+ else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat));
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexParamVideoBitrate:
+ {
+ OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate\n");
+
+ if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate));
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4\n");
+ memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4));
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263\n");
+ memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263));
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc\n");
+ memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC));
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported\n");
+ //TODO include all the profiles and corresponding levels
+ if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4)
+ {
+ static const OMX_U32 MPEG4Profile[][2] =
+ { { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level0},
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level0b},
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level1},
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level2},
+ { (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple, (OMX_U32) OMX_VIDEO_MPEG4Level3}};
+
+ static const OMX_U32 nSupport = sizeof(MPEG4Profile) / (sizeof(OMX_U32) * 2);
+ if(pParam->nProfileIndex >= 0 && pParam->nProfileIndex < nSupport)
+ {
+ pParam->eProfile = (OMX_VIDEO_MPEG4PROFILETYPE) MPEG4Profile[pParam->nProfileIndex][0];
+ pParam->eLevel = (OMX_VIDEO_MPEG4LEVELTYPE) MPEG4Profile[pParam->nProfileIndex][1];
+ }
+ else
+ {
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263)
+ {
+ static const OMX_U32 H263Profile[][2] =
+ { { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level10},
+ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level20},
+ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level30},
+ { (OMX_U32) OMX_VIDEO_H263ProfileBaseline, (OMX_U32) OMX_VIDEO_H263Level45},
+ { (OMX_U32) OMX_VIDEO_H263ProfileISWV2, (OMX_U32) OMX_VIDEO_H263Level10},
+ { (OMX_U32) OMX_VIDEO_H263ProfileISWV2, (OMX_U32) OMX_VIDEO_H263Level45}};
+
+ static const OMX_U32 nSupport = sizeof(H263Profile) / (sizeof(OMX_U32) * 2);
+ if(pParam->nProfileIndex >= 0 && pParam->nProfileIndex < nSupport)
+ {
+ pParam->eProfile = (OMX_VIDEO_H263PROFILETYPE) H263Profile[pParam->nProfileIndex][0];
+ pParam->eLevel = (OMX_VIDEO_H263LEVELTYPE) H263Profile[pParam->nProfileIndex][1];
+ }
+ else
+ {
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC)
+ {
+ //TODO
+ }
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelCurrent:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent\n");
+ memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel));
+ break;
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamAudioInit:
+ {
+ OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n");
+ memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio));
+ break;
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamImageInit:
+ {
+ OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n");
+ memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img));
+ break;
+
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamOtherInit:
+ {
+ DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x\n", paramIndex);
+ eRet =OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
+ comp_role->nSize = sizeof(*comp_role);
+
+ DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",paramIndex);
+ if(NULL != comp_role->cRole)
+ {
+ strncpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",paramIndex);
+ eRet =OMX_ErrorBadParameter;
+ }
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamPriorityMgmt:
+ {
+
+ OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n");
+ memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt));
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n");
+ if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN)
+ {
+ memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier));
+ }
+ else if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT)
+ {
+ memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier));
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+
+ case OMX_IndexParamVideoQuantization:
+ {
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization\n");
+ memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization));
+ break;
+ }
+
+ case OMX_QcomIndexPortDefn:
+ //TODO
+ break;
+ case OMX_COMPONENT_CAPABILITY_TYPE_INDEX:
+ {
+ OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData);
+ DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX\n");
+ pParam->iIsOMXComponentMultiThreaded = OMX_TRUE;
+ pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE;
+ pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
+ pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
+ pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE;
+ pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE;
+ pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE;
+ pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE;
+ m_use_input_pmem = OMX_TRUE;
+ DEBUG_PRINT_LOW("Supporting capability index in encoder node");
+ break;
+ }
+ case OMX_IndexParamVideoSliceFMO:
+ {
+ OMX_VIDEO_PARAM_AVCSLICEFMO *avc_slice_fmo = (OMX_VIDEO_PARAM_AVCSLICEFMO*)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoSliceFMO\n");
+ if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ memcpy(avc_slice_fmo, &m_sAVCSliceFMO, sizeof(m_sAVCSliceFMO));
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: get_parameter: AVCSliceFMO queried non-AVC codec\n");
+ eRet = OMX_ErrorBadParameter;
+ }
+ break;
+ }
+ default:
+ {
+ DEBUG_PRINT_ERROR("ERROR: get_parameter: unknown param %08x\n", paramIndex);
+ eRet =OMX_ErrorUnsupportedIndex;
+ break;
+ }
+
+ }
+
+ return eRet;
+
+}
+/* ======================================================================
+FUNCTION
+ omx_video::GetConfig
+
+DESCRIPTION
+ OMX Get Config Method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_INOUT OMX_PTR configData)
+{
+ ////////////////////////////////////////////////////////////////
+ // Supported Config Index Type
+ // =============================================================
+ // OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE
+ // OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE
+ // OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE
+ ////////////////////////////////////////////////////////////////
+
+ if(configData == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR: param is null");
+ return OMX_ErrorBadParameter;
+ }
+
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: can't be in invalid state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ //@todo need to validate params
+ switch(configIndex)
+ {
+ case OMX_IndexConfigVideoBitrate:
+ {
+ OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData);
+ memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate));
+ break;
+ }
+ case OMX_IndexConfigVideoFramerate:
+ {
+ OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData);
+ if(m_state != OMX_StateLoaded)
+ {
+ // we only allow this at init time!
+ DEBUG_PRINT_ERROR("ERROR: frame rate can only be configured in loaded state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate));
+ break;
+ }
+ case OMX_IndexConfigCommonRotate:
+ {
+ OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
+ if(m_state != OMX_StateLoaded)
+ {
+ // we only allow this at init time!
+ DEBUG_PRINT_ERROR("ERROR: frame rate can only be configured in loaded state",0,0,0);
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation));
+ break;
+ }
+ default:
+ DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
+ return OMX_ErrorUnsupportedIndex;
+ }
+ return OMX_ErrorNone;
+
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::GetExtensionIndex
+
+DESCRIPTION
+ OMX GetExtensionIndex method implementaion. <TBD>
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_STRING paramName,
+ OMX_OUT OMX_INDEXTYPE* indexType)
+{
+ DEBUG_PRINT_ERROR("ERROR: get_extension_index: Error, Not implemented\n");
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::GetState
+
+DESCRIPTION
+ Returns the state information back to the caller.<TBD>
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Error None if everything is successful.
+========================================================================== */
+OMX_ERRORTYPE omx_video::get_state(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_STATETYPE* state)
+{
+ *state = m_state;
+ DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::ComponentTunnelRequest
+
+DESCRIPTION
+ OMX Component Tunnel Request method implementation. <TBD>
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_HANDLETYPE peerComponent,
+ OMX_IN OMX_U32 peerPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
+{
+ DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented\n");
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::UseInputBuffer
+
+DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::use_input_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ unsigned i = 0;
+ unsigned char *buf_addr = NULL;
+
+ DEBUG_PRINT_HIGH("use_input_buffer: port = %d appData = %p bytes = %d buffer = %p",port,appData,bytes,buffer);
+ if(bytes != m_sInPortDef.nBufferSize)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: use_input_buffer: Size Mismatch!! "
+ "bytes[%d] != Port.nBufferSize[%d]", bytes, m_sInPortDef.nBufferSize);
+ return OMX_ErrorBadParameter;
+ }
+
+ if(!m_inp_mem_ptr)
+ {
+ input_use_buffer = true;
+ m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
+ if(m_inp_mem_ptr == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
+ if(m_pInput_pmem == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem");
+ return OMX_ErrorInsufficientResources;
+ }
+ for(i=0; i< m_sInPortDef.nBufferCountActual; i++)
+ {
+ m_pInput_pmem[i].fd = -1;
+ }
+
+ }
+
+ for(i=0; i< m_sInPortDef.nBufferCountActual; i++)
+ {
+ if(BITMASK_ABSENT(&m_inp_bm_count,i))
+ {
+ break;
+ }
+ }
+
+ if(i < m_sInPortDef.nBufferCountActual)
+ {
+
+ *bufferHdr = (m_inp_mem_ptr + i);
+ BITMASK_SET(&m_inp_bm_count,i);
+
+ (*bufferHdr)->pBuffer = (OMX_U8 *)buffer;
+ (*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
+ (*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize;
+ (*bufferHdr)->pAppPrivate = appData;
+ (*bufferHdr)->nInputPortIndex = PORT_INDEX_IN;
+
+ if(!m_use_input_pmem)
+ {
+ m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+ if(m_pInput_pmem[i].fd == 0)
+ {
+ m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+ }
+
+ if(m_pInput_pmem[i] .fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
+ m_pInput_pmem[i].offset = 0;
+ m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,m_pInput_pmem[i].fd,0);
+
+ if(m_pInput_pmem[i].buffer == MAP_FAILED)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: mmap() Failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>((*bufferHdr)->pAppPrivate);
+ DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset);
+
+ if(pParam)
+ {
+ m_pInput_pmem[i].fd = pParam->pmem_fd;
+ m_pInput_pmem[i].offset = pParam->offset;
+ m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
+ m_pInput_pmem[i].buffer = (unsigned char *)buffer;
+ DEBUG_PRINT_LOW("\n DBG:: pParam->pmem_fd = %u, pParam->offset = %u",
+ pParam->pmem_fd, pParam->offset);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ DEBUG_PRINT_LOW("\n use_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p",
+ (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer);
+ if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_use_buf() Failed for i/p buf");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: All buffers are already used, invalid use_buf call for "
+ "index = %u", i);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ return eRet;
+}
+
+
+
+/* ======================================================================
+FUNCTION
+ omx_video::UseOutputBuffer
+
+DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::use_output_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
+ unsigned i= 0; // Temporary counter
+ unsigned char *buf_addr = NULL;
+
+ DEBUG_PRINT_HIGH("\n Inside use_output_buffer()");
+ if(bytes != m_sOutPortDef.nBufferSize)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: use_output_buffer: Size Mismatch!! "
+ "bytes[%d] != Port.nBufferSize[%d]", bytes, m_sOutPortDef.nBufferSize);
+ return OMX_ErrorBadParameter;
+ }
+
+ if(!m_out_mem_ptr)
+ {
+ output_use_buffer = true;
+ int nBufHdrSize = 0;
+
+ DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_sOutPortDef.nBufferCountActual);
+ nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);
+ /*
+ * Memory for output side involves the following:
+ * 1. Array of Buffer Headers
+ * 2. Bitmask array to hold the buffer allocation details
+ * In order to minimize the memory management entire allocation
+ * is done in one step.
+ */
+ //OMX Buffer header
+ m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
+ if(m_out_mem_ptr == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_out_mem_ptr");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual);
+ if(m_pOutput_pmem == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_pmem");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if(m_out_mem_ptr)
+ {
+ bufHdr = m_out_mem_ptr;
+ DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++)
+ {
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ bufHdr->nAllocLen = bytes;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex = PORT_INDEX_OUT;
+ bufHdr->pBuffer = NULL;
+ bufHdr++;
+ m_pOutput_pmem[i].fd = -1;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%x]\n",m_out_mem_ptr);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ for(i=0; i< m_sOutPortDef.nBufferCountActual; i++)
+ {
+ if(BITMASK_ABSENT(&m_out_bm_count,i))
+ {
+ break;
+ }
+ }
+
+ if(eRet == OMX_ErrorNone)
+ {
+ if(i < m_sOutPortDef.nBufferCountActual)
+ {
+ *bufferHdr = (m_out_mem_ptr + i );
+ (*bufferHdr)->pBuffer = (OMX_U8 *)buffer;
+ BITMASK_SET(&m_out_bm_count,i);
+
+ if(!m_use_output_pmem)
+ {
+ m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if(m_pOutput_pmem[i].fd == 0)
+ {
+ m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+ }
+
+ if(m_pOutput_pmem[i].fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
+ m_pOutput_pmem[i].offset = 0;
+ m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,m_pOutput_pmem[i].fd,0);
+ if(m_pOutput_pmem[i].buffer == MAP_FAILED)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: mmap() Failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*>((*bufferHdr)->pAppPrivate);
+ DEBUG_PRINT_LOW("Inside qcom_ext pParam:0x%x )", pParam);
+
+ if(pParam)
+ {
+ DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset);
+ m_pOutput_pmem[i].fd = pParam->pmem_fd;
+ m_pOutput_pmem[i].offset = pParam->offset;
+ m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
+ m_pOutput_pmem[i].buffer = (unsigned char *)buffer;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case");
+ return OMX_ErrorBadParameter;
+ }
+ buf_addr = (unsigned char *)buffer;
+ }
+
+ DEBUG_PRINT_LOW("\n use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p",
+ (*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer);
+ if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT) != true)
+ {
+ DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for "
+ "index = %u", i);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_video::UseBuffer
+
+DESCRIPTION
+ OMX Use Buffer method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None , if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::use_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if(port == PORT_INDEX_IN)
+ {
+ eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
+ }
+ else if(port == PORT_INDEX_OUT)
+ {
+ eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ if(eRet == OMX_ErrorNone)
+ {
+ if(allocate_done())
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet,OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ PORT_INDEX_IN,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ }
+ else if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ PORT_INDEX_OUT,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ return eRet;
+}
+
+OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
+{
+ unsigned int index = 0;
+ OMX_U8 *temp_buff ;
+
+ if(bufferHdr == NULL || m_inp_mem_ptr == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]",
+ bufferHdr, m_inp_mem_ptr);
+ return OMX_ErrorBadParameter;
+ }
+
+ index = bufferHdr - m_inp_mem_ptr;
+
+ if(index < m_sInPortDef.nBufferCountActual && m_pInput_pmem)
+ {
+ if(m_pInput_pmem[index].fd > 0 && input_use_buffer == false)
+ {
+ DEBUG_PRINT_LOW("\n FreeBuffer:: i/p AllocateBuffer case");
+ if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf");
+ }
+ munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
+ close (m_pInput_pmem[index].fd);
+ m_pInput_pmem[index].fd = -1;
+ }
+ else if(m_pInput_pmem[index].fd > 0 && (input_use_buffer == true &&
+ m_use_input_pmem == OMX_FALSE))
+ {
+ DEBUG_PRINT_LOW("\n FreeBuffer:: i/p Heap UseBuffer case");
+ if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf");
+ }
+ munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
+ close (m_pInput_pmem[index].fd);
+ m_pInput_pmem[index].fd = -1;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case");
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
+{
+ unsigned int index = 0;
+ OMX_U8 *temp_buff ;
+
+ if(bufferHdr == NULL || m_out_mem_ptr == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]",
+ bufferHdr, m_out_mem_ptr);
+ return OMX_ErrorBadParameter;
+ }
+ index = bufferHdr - m_out_mem_ptr;
+
+ if(index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem)
+ {
+ if(m_pOutput_pmem[index].fd > 0 && output_use_buffer == false )
+ {
+ DEBUG_PRINT_LOW("\n FreeBuffer:: o/p AllocateBuffer case");
+ if(dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true)
+ {
+ DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
+ }
+ munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size);
+ close (m_pOutput_pmem[index].fd);
+ m_pOutput_pmem[index].fd = -1;
+ }
+ else if( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true
+ && m_use_output_pmem == OMX_FALSE))
+ {
+ DEBUG_PRINT_LOW("\n FreeBuffer:: o/p Heap UseBuffer case");
+ if(dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true)
+ {
+ DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
+ }
+ munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size);
+ close (m_pOutput_pmem[index].fd);
+ m_pOutput_pmem[index].fd = -1;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case");
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::AllocateInputBuffer
+
+DESCRIPTION
+ Helper function for allocate buffer in the input pin
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::allocate_input_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned i = 0;
+
+ DEBUG_PRINT_HIGH("\n allocate_input_buffer()::");
+ if(bytes != m_sInPortDef.nBufferSize)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Buffer size mismatch error: bytes[%u] != nBufferSize[%u]\n",
+ bytes, m_sInPortDef.nBufferSize);
+ return OMX_ErrorBadParameter;
+ }
+
+ if(!m_inp_mem_ptr)
+ {
+ m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
+ if(m_inp_mem_ptr == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
+
+ if(m_pInput_pmem == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ for(i=0; i< m_sInPortDef.nBufferCountActual; i++)
+ {
+ m_pInput_pmem[i].fd = -1;
+ }
+ }
+
+ for(i=0; i< m_sInPortDef.nBufferCountActual; i++)
+ {
+ if(BITMASK_ABSENT(&m_inp_bm_count,i))
+ {
+ break;
+ }
+ }
+
+ if(i < m_sInPortDef.nBufferCountActual)
+ {
+
+ *bufferHdr = (m_inp_mem_ptr + i);
+ (*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
+ (*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize;
+ (*bufferHdr)->pAppPrivate = appData;
+ (*bufferHdr)->nInputPortIndex = PORT_INDEX_IN;
+
+ m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if(m_pInput_pmem[i].fd == 0)
+ {
+ m_pInput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+ }
+
+ if(m_pInput_pmem[i].fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed\n");
+ return OMX_ErrorInsufficientResources;
+ }
+ m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
+ m_pInput_pmem[i].offset = 0;
+
+ m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,m_pInput_pmem[i].fd,0);
+ if(m_pInput_pmem[i].buffer == MAP_FAILED)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: mmap FAILED\n");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ (*bufferHdr)->pBuffer = (OMX_U8 *)m_pInput_pmem[i].buffer;
+
+ BITMASK_SET(&m_inp_bm_count,i);
+ //here change the I/P param here from buf_adr to pmem
+ if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for i/p buf\n");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: All i/p buffers are allocated, invalid allocate buf call"
+ "for index [%d]\n", i);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::AllocateOutputBuffer
+
+DESCRIPTION
+ Helper fn for AllocateBuffer in the output pin
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything went well.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::allocate_output_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
+ unsigned i= 0; // Temporary counter
+ DEBUG_PRINT_HIGH("\n allocate_output_buffer()::");
+ if(!m_out_mem_ptr)
+ {
+ int nBufHdrSize = 0;
+ DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_sOutPortDef.nBufferCountActual);
+ nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);
+
+ /*
+ * Memory for output side involves the following:
+ * 1. Array of Buffer Headers
+ * 2. Bitmask array to hold the buffer allocation details
+ * In order to minimize the memory management entire allocation
+ * is done in one step.
+ */
+ m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
+
+ m_pOutput_pmem = (struct pmem *) calloc(sizeof(struct pmem), m_sOutPortDef.nBufferCountActual);
+
+ if(m_out_mem_ptr && m_pOutput_pmem)
+ {
+ bufHdr = m_out_mem_ptr;
+
+ for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++)
+ {
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = bytes;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex = PORT_INDEX_OUT;
+ bufHdr->pBuffer = NULL;
+ bufHdr++;
+ m_pOutput_pmem[i].fd = -1;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ DEBUG_PRINT_HIGH("\n actual cnt = %u", m_sOutPortDef.nBufferCountActual);
+ for(i=0; i< m_sOutPortDef.nBufferCountActual; i++)
+ {
+ if(BITMASK_ABSENT(&m_out_bm_count,i))
+ {
+ DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i);
+ break;
+ }
+ }
+
+ if(eRet == OMX_ErrorNone)
+ {
+ if(i < m_sOutPortDef.nBufferCountActual)
+ {
+ m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+ if(m_pOutput_pmem[i].fd == 0)
+ {
+ m_pOutput_pmem[i].fd = open ("/dev/pmem_adsp",O_RDWR);
+ }
+
+ if(m_pOutput_pmem[i].fd < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
+ m_pOutput_pmem[i].offset = 0;
+ m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
+ MAP_SHARED,m_pOutput_pmem[i].fd,0);
+ if(m_pOutput_pmem[i].buffer == MAP_FAILED)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: MMAP_FAILED in o/p alloc buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ *bufferHdr = (m_out_mem_ptr + i );
+ (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer;
+
+ BITMASK_SET(&m_out_bm_count,i);
+
+ if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for o/p buf");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: All o/p buffers are allocated, invalid allocate buf call"
+ "for index [%d]\n", i);
+ }
+ }
+
+ return eRet;
+}
+
+
+// AllocateBuffer -- API Call
+/* ======================================================================
+FUNCTION
+ omx_video::AllocateBuffer
+
+DESCRIPTION
+ Returns zero if all the buffers released..
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
+
+ DEBUG_PRINT_LOW("\n Allocate buffer on port %d \n", (int)port);
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ // What if the client calls again.
+ if(port == PORT_INDEX_IN)
+ {
+ eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
+ }
+ else if(port == PORT_INDEX_OUT)
+ {
+ eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
+ if(eRet == OMX_ErrorNone)
+ {
+ if(allocate_done())
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet,OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ PORT_INDEX_IN,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated)
+ {
+ if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING))
+ {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ PORT_INDEX_OUT,
+ OMX_COMPONENT_GENERATE_EVENT);
+ m_event_port_settings_sent = false;
+ }
+ }
+ }
+ DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet);
+ return eRet;
+}
+
+
+// Free Buffer - API call
+/* ======================================================================
+FUNCTION
+ omx_video::FreeBuffer
+
+DESCRIPTION
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned int nPortIndex;
+
+ DEBUG_PRINT_LOW("In for decoder free_buffer \n");
+
+ if(m_state == OMX_StateIdle &&
+ (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
+ {
+ DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n");
+ }
+ else if((m_sInPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_IN)||
+ (m_sOutPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_OUT))
+ {
+ DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port);
+ }
+ else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,ports need to be disabled\n");
+ post_event(OMX_EventError,
+ OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ return eRet;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,port lost Buffers\n");
+ post_event(OMX_EventError,
+ OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ if(port == PORT_INDEX_IN)
+ {
+ // check if the buffer is valid
+ nPortIndex = buffer - m_inp_mem_ptr;
+
+ DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d, actual cnt %d \n",
+ nPortIndex, m_sInPortDef.nBufferCountActual);
+ if(nPortIndex < m_sInPortDef.nBufferCountActual)
+ {
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
+ free_input_buffer (buffer);
+ m_sInPortDef.bPopulated = OMX_FALSE;
+
+ /*Free the Buffer Header*/
+ if(release_input_done())
+ {
+ input_use_buffer = false;
+ if(m_inp_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr\n");
+ free (m_inp_mem_ptr);
+ m_inp_mem_ptr = NULL;
+ }
+ if(m_pInput_pmem)
+ {
+ DEBUG_PRINT_LOW("Freeing m_pInput_pmem\n");
+ free(m_pInput_pmem);
+ m_pInput_pmem = NULL;
+ }
+
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
+ && release_input_done())
+ {
+ DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ post_event(OMX_CommandPortDisable,
+ PORT_INDEX_IN,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ else if(port == PORT_INDEX_OUT)
+ {
+ // check if the buffer is valid
+ nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
+
+ DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d, actual cnt %d \n",
+ nPortIndex, m_sOutPortDef.nBufferCountActual);
+ if(nPortIndex < m_sOutPortDef.nBufferCountActual)
+ {
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
+ m_sOutPortDef.bPopulated = OMX_FALSE;
+ free_output_buffer (buffer);
+
+ if(release_output_done())
+ {
+ output_use_buffer = false;
+ if(m_out_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("Freeing m_out_mem_ptr\n");
+ free (m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if(m_pOutput_pmem)
+ {
+ DEBUG_PRINT_LOW("Freeing m_pOutput_pmem\n");
+ free(m_pOutput_pmem);
+ m_pOutput_pmem = NULL;
+ }
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
+ && release_output_done() )
+ {
+ DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n");
+
+ DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n");
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+ post_event(OMX_CommandPortDisable,
+ PORT_INDEX_OUT,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ }
+ }
+ else
+ {
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if((eRet == OMX_ErrorNone) &&
+ (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING)))
+ {
+ if(release_done())
+ {
+ if(dev_stop() != 0)
+ {
+ DEBUG_PRINT_ERROR("ERROR: dev_stop() FAILED\n");
+ eRet = OMX_ErrorHardware;
+ }
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateLoaded,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_video::EmptyThisBuffer
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_ERRORTYPE ret1 = OMX_ErrorNone;
+ unsigned int nBufferIndex ;
+
+ DEBUG_PRINT_LOW("\n ETB: buffer = %p, buffer->pBuffer[%p]\n", buffer, buffer->pBuffer);
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> buffer is null or buffer size is invalid");
+ return OMX_ErrorBadParameter;
+ }
+
+ if(buffer->nVersion.nVersion != OMX_SPEC_VERSION)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> OMX Version Invalid");
+ return OMX_ErrorVersionMismatch;
+ }
+
+ if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Bad port index to call empty_this_buffer");
+ return OMX_ErrorBadPortIndex;
+ }
+ if(!m_sInPortDef.bEnabled)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Cannot call empty_this_buffer while I/P port is disabled");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ nBufferIndex = buffer - m_inp_mem_ptr;
+
+ if(nBufferIndex > m_sInPortDef.nBufferCountActual )
+ {
+ DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]\n", nBufferIndex);
+ return OMX_ErrorBadParameter;
+ }
+
+ m_etb_count++;
+ DEBUG_PRINT_LOW("\n DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp);
+ post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB);
+ return OMX_ErrorNone;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_video::empty_this_buffer_proxy
+
+DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything went successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_U8 *pmem_data_buf = NULL;
+ int push_cnt = 0;
+ unsigned nBufIndex = 0;
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+
+ DEBUG_PRINT_LOW("\n ETBProxy: buffer->pBuffer[%p]\n", buffer->pBuffer);
+
+ if(buffer == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid buffer[%p]\n", buffer);
+ return OMX_ErrorBadParameter;
+ }
+
+ nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
+
+ if(nBufIndex >= m_sInPortDef.nBufferCountActual)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid bufindex = %u\n", nBufIndex);
+ return OMX_ErrorBadParameter;
+ }
+
+ pending_input_buffers++;
+ if(input_flush_progress == true)
+ {
+ post_event ((unsigned int)buffer,0,
+ OMX_COMPONENT_GENERATE_EBD);
+ DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Input flush in progress");
+ return OMX_ErrorNone;
+ }
+
+ if(input_use_buffer && !m_use_input_pmem)
+ {
+ DEBUG_PRINT_LOW("\n Heap UseBuffer case, so memcpy the data");
+ pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer;
+
+ memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset),
+ buffer->nFilledLen);
+ DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf");
+ }
+
+ if(dev_empty_buf(buffer, pmem_data_buf) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ETBProxy: dev_empty_buf failed");
+ /*Generate an async error and move to invalid state*/
+ pending_input_buffers--;
+ return OMX_ErrorBadParameter;
+ }
+
+ return ret;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::FillThisBuffer
+
+DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ DEBUG_PRINT_LOW("\n FTB: buffer->pBuffer[%p]\n", buffer->pBuffer);
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)))
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size\n");
+ return OMX_ErrorBadParameter;
+ }
+
+ if(buffer->nVersion.nVersion != OMX_SPEC_VERSION)
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid\n");
+ return OMX_ErrorVersionMismatch;
+ }
+
+ if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT)
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index\n");
+ return OMX_ErrorBadPortIndex;
+ }
+
+ if(!m_sOutPortDef.bEnabled)
+ {
+ DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::fill_this_buffer_proxy
+
+DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::fill_this_buffer_proxy(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
+{
+ OMX_U8 *pmem_data_buf = NULL;
+ OMX_ERRORTYPE nRet = OMX_ErrorNone;
+
+ DEBUG_PRINT_LOW("\n FTBProxy: bufferAdd->pBuffer[%p]\n", bufferAdd->pBuffer);
+
+ if(bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= m_sOutPortDef.nBufferCountActual) )
+ {
+ DEBUG_PRINT_ERROR("\nERROR: FTBProxy: Invalid i/p params\n");
+ return OMX_ErrorBadParameter;
+ }
+
+ pending_output_buffers++;
+ /*Return back the output buffer to client*/
+ if( m_sOutPortDef.bEnabled != OMX_TRUE || output_flush_progress == true)
+ {
+ DEBUG_PRINT_LOW("\n o/p port is Disabled or Flush in Progress");
+ post_event ((unsigned int)bufferAdd,0,
+ OMX_COMPONENT_GENERATE_FBD);
+ return OMX_ErrorNone;
+ }
+
+ if(output_use_buffer && !m_use_output_pmem)
+ {
+ DEBUG_PRINT_LOW("\n Heap UseBuffer case");
+ pmem_data_buf = (OMX_U8 *)m_pOutput_pmem[bufferAdd - m_out_mem_ptr].buffer;
+ }
+
+ if(dev_fill_buf(bufferAdd, pmem_data_buf) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: dev_fill_buf() Failed");
+ pending_output_buffers--;
+ return OMX_ErrorBadParameter;
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::SetCallbacks
+
+DESCRIPTION
+ Set the callbacks.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_CALLBACKTYPE* callbacks,
+ OMX_IN OMX_PTR appData)
+{
+
+ m_pCallbacks = *callbacks;
+ DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_pCallbacks.EmptyBufferDone,\
+ m_pCallbacks.EventHandler,m_pCallbacks.FillBufferDone);
+ m_app_data = appData;
+ return OMX_ErrorNotImplemented;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::UseEGLImage
+
+DESCRIPTION
+ OMX Use EGL Image method implementation <TBD>.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ Not Implemented error.
+
+========================================================================== */
+OMX_ERRORTYPE omx_video::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN void* eglImage)
+{
+ DEBUG_PRINT_ERROR("ERROR: use_EGL_image: Not Implemented \n");
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::ComponentRoleEnum
+
+DESCRIPTION
+ OMX Component Role Enum method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything is successful.
+========================================================================== */
+OMX_ERRORTYPE omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_U8* role,
+ OMX_IN OMX_U32 index)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if((0 == index) && role)
+ {
+ strncpy((char *)role, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s\n",role);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: No more roles \n");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Querying Role on Unknown Component\n");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ return eRet;
+}
+
+
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::AllocateDone
+
+DESCRIPTION
+ Checks if entire buffer pool is allocated by IL Client or not.
+ Need this to move to IDLE state.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_video::allocate_done(void)
+{
+ bool bRet = false;
+ bool bRet_In = false;
+ bool bRet_Out = false;
+
+ bRet_In = allocate_input_done();
+ bRet_Out = allocate_output_done();
+
+ if(bRet_In && bRet_Out)
+ {
+ bRet = true;
+ }
+
+ return bRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_venc::AllocateInputDone
+
+DESCRIPTION
+ Checks if I/P buffer pool is allocated by IL Client or not.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_video::allocate_input_done(void)
+{
+ bool bRet = false;
+ unsigned i=0;
+
+ if(m_inp_mem_ptr == NULL)
+ {
+ return bRet;
+ }
+ if(m_inp_mem_ptr )
+ {
+ for(;i<m_sInPortDef.nBufferCountActual;i++)
+ {
+ if(BITMASK_ABSENT(&m_inp_bm_count,i))
+ {
+ break;
+ }
+ }
+ }
+ if(i==m_sInPortDef.nBufferCountActual)
+ {
+ bRet = true;
+ }
+ if(i==m_sInPortDef.nBufferCountActual && m_sInPortDef.bEnabled)
+ {
+ m_sInPortDef.bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_venc::AllocateOutputDone
+
+DESCRIPTION
+ Checks if entire O/P buffer pool is allocated by IL Client or not.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false.
+
+========================================================================== */
+bool omx_video::allocate_output_done(void)
+{
+ bool bRet = false;
+ unsigned j=0;
+
+ if(m_out_mem_ptr == NULL)
+ {
+ return bRet;
+ }
+
+ if(m_out_mem_ptr )
+ {
+ for(;j<m_sOutPortDef.nBufferCountActual;j++)
+ {
+ if(BITMASK_ABSENT(&m_out_bm_count,j))
+ {
+ break;
+ }
+ }
+ }
+
+ if(j==m_sOutPortDef.nBufferCountActual)
+ {
+ bRet = true;
+ }
+
+ if(j==m_sOutPortDef.nBufferCountActual && m_sOutPortDef.bEnabled)
+ {
+ m_sOutPortDef.bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::ReleaseDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_video::release_done(void)
+{
+ bool bRet = false;
+ DEBUG_PRINT_LOW("Inside release_done()\n");
+ if(release_input_done())
+ {
+ if(release_output_done())
+ {
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::ReleaseOutputDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_video::release_output_done(void)
+{
+ bool bRet = false;
+ unsigned i=0,j=0;
+
+ DEBUG_PRINT_LOW("Inside release_output_done()\n");
+ if(m_out_mem_ptr)
+ {
+ for(;j<m_sOutPortDef.nBufferCountActual;j++)
+ {
+ if(BITMASK_PRESENT(&m_out_bm_count,j))
+ {
+ break;
+ }
+ }
+ if(j==m_sOutPortDef.nBufferCountActual)
+ {
+ bRet = true;
+ }
+ }
+ else
+ {
+ bRet = true;
+ }
+ return bRet;
+}
+/* ======================================================================
+FUNCTION
+ omx_venc::ReleaseInputDone
+
+DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+PARAMETERS
+ None.
+
+RETURN VALUE
+ true/false
+
+========================================================================== */
+bool omx_video::release_input_done(void)
+{
+ bool bRet = false;
+ unsigned i=0,j=0;
+
+ DEBUG_PRINT_LOW("Inside release_input_done()\n");
+ if(m_inp_mem_ptr)
+ {
+ for(;j<m_sInPortDef.nBufferCountActual;j++)
+ {
+ if( BITMASK_PRESENT(&m_inp_bm_count,j))
+ {
+ break;
+ }
+ }
+ if(j==m_sInPortDef.nBufferCountActual)
+ {
+ bRet = true;
+ }
+ }
+ else
+ {
+ bRet = true;
+ }
+ return bRet;
+}
+
+OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer)
+{
+ DEBUG_PRINT_LOW("\nfill_buffer_done: buffer->pBuffer[%p]\n", buffer->pBuffer);
+ if(buffer == NULL || ((buffer - m_out_mem_ptr) > m_sOutPortDef.nBufferCountActual))
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ pending_output_buffers--;
+
+ /* For use buffer we need to copy the data */
+ if(m_pCallbacks.FillBufferDone)
+ {
+ if(buffer->nFilledLen > 0)
+ {
+ m_fbd_count++;
+ }
+ m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer);
+ }
+ else
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE* buffer)
+{
+ DEBUG_PRINT_LOW("\nempty_buffer_done: buffer->pBuffer[%p]\n", buffer->pBuffer);
+ if(buffer == NULL || ((buffer - m_inp_mem_ptr) > m_sInPortDef.nBufferCountActual))
+ {
+ return OMX_ErrorBadParameter;
+ }
+
+ pending_input_buffers--;
+ if(m_pCallbacks.EmptyBufferDone)
+ {
+ m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, buffer);
+ }
+ return OMX_ErrorNone;
+}
diff --git a/omx/mm-video/vidc/venc/src/omx_video_encoder.cpp b/omx/mm-video/vidc/venc/src/omx_video_encoder.cpp
new file mode 100644
index 0000000..a713fb4
--- /dev/null
+++ b/omx/mm-video/vidc/venc/src/omx_video_encoder.cpp
@@ -0,0 +1,1230 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "omx_video_encoder.h"
+#include <string.h>
+#include "video_encoder_device.h"
+#include <stdio.h>
+
+/*----------------------------------------------------------------------------
+* Preprocessor Definitions and Constants
+* -------------------------------------------------------------------------*/
+
+#define OMX_SPEC_VERSION 0x00000101
+#define OMX_INIT_STRUCT(_s_, _name_) \
+ memset((_s_), 0x0, sizeof(_name_)); \
+ (_s_)->nSize = sizeof(_name_); \
+ (_s_)->nVersion.nVersion = OMX_SPEC_VERSION
+
+extern int m_pipe;
+
+// factory function executed by the core to create instances
+void *get_omx_component_factory_fn(void)
+{
+ return(new omx_venc);
+}
+
+//constructor
+
+omx_venc::omx_venc()
+{
+ //nothing to do
+}
+
+omx_venc::~omx_venc()
+{
+ //nothing to do
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::ComponentInit
+
+DESCRIPTION
+ Initialize the component.
+
+PARAMETERS
+ ctxt -- Context information related to the self.
+ id -- Event identifier. This could be any of the following:
+ 1. Command completion event
+ 2. Buffer done callback event
+ 3. Frame done callback event
+
+RETURN VALUE
+ None.
+
+========================================================================== */
+OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role)
+{
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ int fds[2];
+ int r;
+
+ OMX_VIDEO_CODINGTYPE codec_type;
+
+ DEBUG_PRINT_HIGH("\n omx_venc(): Inside component_init()");
+ // Copy the role information which provides the decoder m_nkind
+ strncpy((char *)m_nkind,role,OMX_MAX_STRINGNAME_SIZE);
+
+ if(!strncmp((char *)m_nkind,"OMX.qcom.video.encoder.mpeg4",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_encoder.mpeg4",\
+ OMX_MAX_STRINGNAME_SIZE);
+ codec_type = OMX_VIDEO_CodingMPEG4;
+ }
+ else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.h263",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ codec_type = OMX_VIDEO_CodingH263;
+ }
+ else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char *)m_cRole, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ codec_type = OMX_VIDEO_CodingAVC;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Unknown Component\n");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+
+
+ if(eRet != OMX_ErrorNone)
+ {
+ return eRet;
+ }
+
+ handle = new venc_dev();
+
+ if(handle == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: handle is NULL");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if(handle->venc_open(codec_type) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_open failed");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ //Intialise the OMX layer variables
+ memset(&m_pCallbacks,0,sizeof(OMX_CALLBACKTYPE));
+
+ OMX_INIT_STRUCT(&m_sPortParam, OMX_PORT_PARAM_TYPE);
+ m_sPortParam.nPorts = 0x2;
+ m_sPortParam.nStartPortNumber = (OMX_U32) PORT_INDEX_IN;
+
+ OMX_INIT_STRUCT(&m_sPortParam_audio, OMX_PORT_PARAM_TYPE);
+ m_sPortParam_audio.nPorts = 0;
+ m_sPortParam_audio.nStartPortNumber = 0;
+
+ OMX_INIT_STRUCT(&m_sPortParam_img, OMX_PORT_PARAM_TYPE);
+ m_sPortParam_img.nPorts = 0;
+ m_sPortParam_img.nStartPortNumber = 0;
+
+ OMX_INIT_STRUCT(&m_sParamBitrate, OMX_VIDEO_PARAM_BITRATETYPE);
+ m_sParamBitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamBitrate.eControlRate = OMX_Video_ControlRateVariableSkipFrames;
+ m_sParamBitrate.nTargetBitrate = 64000;
+
+ OMX_INIT_STRUCT(&m_sConfigBitrate, OMX_VIDEO_CONFIG_BITRATETYPE);
+ m_sConfigBitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigBitrate.nEncodeBitrate = 64000;
+
+ OMX_INIT_STRUCT(&m_sConfigFramerate, OMX_CONFIG_FRAMERATETYPE);
+ m_sConfigFramerate.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigFramerate.xEncodeFramerate = 30 << 16;
+
+ OMX_INIT_STRUCT(&m_sConfigIntraRefreshVOP, OMX_CONFIG_INTRAREFRESHVOPTYPE);
+ m_sConfigIntraRefreshVOP.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigIntraRefreshVOP.IntraRefreshVOP = OMX_FALSE;
+
+ OMX_INIT_STRUCT(&m_sConfigFrameRotation, OMX_CONFIG_ROTATIONTYPE);
+ m_sConfigFrameRotation.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sConfigFrameRotation.nRotation = 0;
+
+ OMX_INIT_STRUCT(&m_sSessionQuantization, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
+ m_sSessionQuantization.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sSessionQuantization.nQpI = 9;
+ m_sSessionQuantization.nQpP = 6;
+ m_sSessionQuantization.nQpB = 2;
+
+ OMX_INIT_STRUCT(&m_sAVCSliceFMO, OMX_VIDEO_PARAM_AVCSLICEFMO);
+ m_sAVCSliceFMO.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sAVCSliceFMO.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault;
+ m_sAVCSliceFMO.nNumSliceGroups = 0;
+ m_sAVCSliceFMO.nSliceGroupMapType = 0;
+ OMX_INIT_STRUCT(&m_sParamProfileLevel, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
+ m_sParamProfileLevel.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+
+ if(codec_type == OMX_VIDEO_CodingMPEG4)
+ {
+ m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple;
+ m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_MPEG4Level0;
+ }
+ else if(codec_type == OMX_VIDEO_CodingH263)
+ {
+ m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_H263ProfileBaseline;
+ m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_H263Level10;
+ }
+ else if(codec_type == OMX_VIDEO_CodingAVC)
+ {
+ m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_AVCProfileBaseline;
+ m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_AVCLevel1;
+ }
+
+ // Initialize the video parameters for input port
+ OMX_INIT_STRUCT(&m_sInPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
+ m_sInPortDef.nPortIndex= (OMX_U32) PORT_INDEX_IN;
+ m_sInPortDef.bEnabled = OMX_TRUE;
+ m_sInPortDef.bPopulated = OMX_FALSE;
+ m_sInPortDef.eDomain = OMX_PortDomainVideo;
+ m_sInPortDef.eDir = OMX_DirInput;
+ m_sInPortDef.format.video.cMIMEType = "YUV420";
+ m_sInPortDef.format.video.nFrameWidth = OMX_CORE_QCIF_WIDTH;
+ m_sInPortDef.format.video.nFrameHeight = OMX_CORE_QCIF_HEIGHT;
+ m_sInPortDef.format.video.nBitrate = 64000;
+ m_sInPortDef.format.video.xFramerate = 15 << 16;
+ m_sInPortDef.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ m_sInPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+ if(dev_get_buf_req(&m_sInPortDef.nBufferCountMin,
+ &m_sInPortDef.nBufferCountActual,
+ &m_sInPortDef.nBufferSize,
+ m_sInPortDef.nPortIndex) != true)
+ {
+ eRet = OMX_ErrorUndefined;
+
+ }
+
+ // Initialize the video parameters for output port
+ OMX_INIT_STRUCT(&m_sOutPortDef, OMX_PARAM_PORTDEFINITIONTYPE);
+ m_sOutPortDef.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sOutPortDef.bEnabled = OMX_TRUE;
+ m_sOutPortDef.bPopulated = OMX_FALSE;
+ m_sOutPortDef.eDomain = OMX_PortDomainVideo;
+ m_sOutPortDef.eDir = OMX_DirOutput;
+ m_sOutPortDef.format.video.nFrameWidth = OMX_CORE_QCIF_WIDTH;
+ m_sOutPortDef.format.video.nFrameHeight = OMX_CORE_QCIF_HEIGHT;
+ m_sOutPortDef.format.video.nBitrate = 64000;
+ m_sOutPortDef.format.video.xFramerate = 15 << 16;
+ m_sOutPortDef.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ if(codec_type == OMX_VIDEO_CodingMPEG4)
+ {
+ m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ }
+ else if(codec_type == OMX_VIDEO_CodingH263)
+ {
+ m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
+ }
+ else
+ {
+ m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ }
+ if(dev_get_buf_req(&m_sOutPortDef.nBufferCountMin,
+ &m_sOutPortDef.nBufferCountActual,
+ &m_sOutPortDef.nBufferSize,
+ m_sOutPortDef.nPortIndex) != true)
+ {
+ eRet = OMX_ErrorUndefined;
+ }
+
+ // Initialize the video color format for input port
+ OMX_INIT_STRUCT(&m_sInPortFormat, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ m_sInPortFormat.nPortIndex = (OMX_U32) PORT_INDEX_IN;
+ m_sInPortFormat.nIndex = 0;
+ m_sInPortFormat.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ m_sInPortFormat.eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+
+ // Initialize the compression format for output port
+ OMX_INIT_STRUCT(&m_sOutPortFormat, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ m_sOutPortFormat.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sOutPortFormat.nIndex = 0;
+ m_sOutPortFormat.eColorFormat = OMX_COLOR_FormatUnused;
+ if(codec_type == OMX_VIDEO_CodingMPEG4)
+ {
+ m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ }
+ else if(codec_type == OMX_VIDEO_CodingH263)
+ {
+ m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingH263;
+ }
+ else
+ {
+ m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ }
+
+ // mandatory Indices for kronos test suite
+ OMX_INIT_STRUCT(&m_sPriorityMgmt, OMX_PRIORITYMGMTTYPE);
+
+ OMX_INIT_STRUCT(&m_sInBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE);
+ m_sInBufSupplier.nPortIndex = (OMX_U32) PORT_INDEX_IN;
+
+ OMX_INIT_STRUCT(&m_sOutBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE);
+ m_sOutBufSupplier.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+
+
+ // mp4 specific init
+ OMX_INIT_STRUCT(&m_sParamMPEG4, OMX_VIDEO_PARAM_MPEG4TYPE);
+ m_sParamMPEG4.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamMPEG4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level0;
+ m_sParamMPEG4.nSliceHeaderSpacing = 0;
+ m_sParamMPEG4.bSVH = OMX_FALSE;
+ m_sParamMPEG4.bGov = OMX_FALSE;
+ m_sParamMPEG4.nPFrames = 29; // 2 second intra period for default 15 fps
+ m_sParamMPEG4.bACPred = OMX_TRUE;
+ m_sParamMPEG4.nTimeIncRes = 30; // delta = 2 @ 15 fps
+ m_sParamMPEG4.nAllowedPictureTypes = 2; // pframe and iframe
+ m_sParamMPEG4.nHeaderExtension = 1; // number of video packet headers per vop
+ m_sParamMPEG4.bReversibleVLC = OMX_FALSE;
+
+ // h263 specific init
+ OMX_INIT_STRUCT(&m_sParamH263, OMX_VIDEO_PARAM_H263TYPE);
+ m_sParamH263.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamH263.nPFrames = 29;
+ m_sParamH263.nBFrames = 0;
+ m_sParamH263.eProfile = OMX_VIDEO_H263ProfileBaseline;
+ m_sParamH263.eLevel = OMX_VIDEO_H263Level10;
+ m_sParamH263.bPLUSPTYPEAllowed = OMX_FALSE;
+ m_sParamH263.nAllowedPictureTypes = 2;
+ m_sParamH263.bForceRoundingTypeToZero = OMX_TRUE; ///@todo determine what this should be
+ m_sParamH263.nPictureHeaderRepetition = 0; ///@todo determine what this should be
+ m_sParamH263.nGOBHeaderInterval = 0; ///@todo determine what this should be
+
+ // h264 specific init
+ OMX_INIT_STRUCT(&m_sParamH263, OMX_VIDEO_PARAM_AVCTYPE);
+ m_sParamAVC.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ m_sParamAVC.nSliceHeaderSpacing =
+ m_sParamAVC.nPFrames = 29;
+ m_sParamAVC.nBFrames = 0;
+ m_sParamAVC.bUseHadamard = OMX_FALSE;//todo: to decide the value
+ m_sParamAVC.nRefFrames = 0; //todo: to decide the value
+ m_sParamAVC.nRefIdx10ActiveMinus1 = 0; //todo: to decide the value
+ m_sParamAVC.nRefIdx11ActiveMinus1 = 0; //todo: to decide the value
+ m_sParamAVC.bEnableUEP = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.bEnableFMO = OMX_FALSE;//todo: to decide the value
+ m_sParamAVC.bEnableASO = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.bEnableRS = OMX_FALSE;//todo: to decide the value
+ m_sParamAVC.eProfile = OMX_VIDEO_AVCProfileBaseline;
+ m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel1;
+ m_sParamAVC.nAllowedPictureTypes = 2;
+ m_sParamAVC.bFrameMBsOnly = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.bMBAFF = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.bEntropyCodingCABAC = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.bWeightedPPrediction = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.nWeightedBipredicitonMode = 0;//todo: to decide the value
+ m_sParamAVC.bconstIpred = OMX_FALSE;//todo: to decide the value
+ m_sParamAVC.bDirect8x8Inference = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.bDirectSpatialTemporal = OMX_FALSE; //todo: to decide the value
+ m_sParamAVC.nCabacInitIdc = 0; //todo: to decide the value
+ //m_sParamAVC.eLoopFilterMode = 0; //todo: to decide the value
+
+ m_state = OMX_StateLoaded;
+
+ if(eRet == OMX_ErrorNone)
+ {
+ if(pipe(fds))
+ {
+ DEBUG_PRINT_ERROR("ERROR: pipe creation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ else
+ {
+ if(fds[0] == 0 || fds[1] == 0)
+ {
+ if(pipe(fds))
+ {
+ DEBUG_PRINT_ERROR("ERROR: pipe creation failed\n");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ if(eRet == OMX_ErrorNone)
+ {
+ m_pipe_in = fds[0];
+ m_pipe_out = fds[1];
+ }
+ }
+ r = pthread_create(&msg_thread_id,0,message_thread,this);
+
+ if(r < 0)
+ {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ else
+ {
+ r = pthread_create(&async_thread_id,0,async_venc_message_thread,this);
+ if(r < 0)
+ {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ }
+
+ DEBUG_PRINT_HIGH("\n Component_init return value = 0x%x", eRet);
+ return eRet;
+}
+
+
+/* ======================================================================
+FUNCTION
+ omx_venc::Setparameter
+
+DESCRIPTION
+ OMX Set Parameter method implementation.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_IN OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Set Param in Invalid State\n");
+ return OMX_ErrorInvalidState;
+ }
+ if(paramData == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n");
+ return OMX_ErrorBadParameter;
+ }
+
+ /*set_parameter can be called in loaded state
+ or disabled port */
+ if(m_state == OMX_StateLoaded
+ || m_sInPortDef.bEnabled == OMX_FALSE
+ || m_sOutPortDef.bEnabled == OMX_FALSE)
+ {
+ DEBUG_PRINT_LOW("Set Parameter called in valid state");
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ switch(paramIndex)
+ {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
+ (int)portDefn->format.video.nFrameHeight,
+ (int)portDefn->format.video.nFrameWidth);
+
+ if(PORT_INDEX_IN == portDefn->nPortIndex)
+ {
+ DEBUG_PRINT_LOW("\n i/p actual cnt requested = %d\n", portDefn->nBufferCountActual);
+ DEBUG_PRINT_LOW("\n i/p min cnt requested = %d\n", portDefn->nBufferCountMin);
+ DEBUG_PRINT_LOW("\n i/p buffersize requested = %d\n", portDefn->nBufferSize);
+ if(handle->venc_set_param(paramData,OMX_IndexParamPortDefinition) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_set_param input failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ DEBUG_PRINT_LOW("\n i/p previous actual cnt = %d\n", m_sInPortDef.nBufferCountActual);
+ DEBUG_PRINT_LOW("\n i/p previous min cnt = %d\n", m_sInPortDef.nBufferCountMin);
+ m_sInPortDef.format.video.nFrameWidth = portDefn->format.video.nFrameWidth;
+ m_sInPortDef.format.video.nFrameHeight = portDefn->format.video.nFrameHeight;
+ m_sInPortDef.format.video.xFramerate = portDefn->format.video.xFramerate;
+ m_sInPortDef.format.video.nBitrate = portDefn->format.video.nBitrate;
+ m_sInPortDef.format.video.eColorFormat = portDefn->format.video.eColorFormat;
+
+
+ /*Query Input Buffer Requirements*/
+ dev_get_buf_req (&m_sInPortDef.nBufferCountMin,
+ &m_sInPortDef.nBufferCountActual,
+ &m_sInPortDef.nBufferSize,
+ m_sInPortDef.nPortIndex);
+
+ /*Query ouput Buffer Requirements*/
+ dev_get_buf_req (&m_sOutPortDef.nBufferCountMin,
+ &m_sOutPortDef.nBufferCountActual,
+ &m_sOutPortDef.nBufferSize,
+ m_sOutPortDef.nPortIndex);
+ m_sInPortDef.nBufferCountActual = portDefn->nBufferCountActual;
+ }
+ else if(PORT_INDEX_OUT == portDefn->nPortIndex)
+ {
+ DEBUG_PRINT_LOW("\n o/p actual cnt requested = %d\n", portDefn->nBufferCountActual);
+ DEBUG_PRINT_LOW("\n o/p min cnt requested = %d\n", portDefn->nBufferCountMin);
+ DEBUG_PRINT_LOW("\n o/p buffersize requested = %d\n", portDefn->nBufferSize);
+ if(handle->venc_set_param(paramData,OMX_IndexParamPortDefinition) != true)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_set_param output failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ DEBUG_PRINT_LOW("\n o/p previous actual cnt = %d\n", m_sOutPortDef.nBufferCountActual);
+ DEBUG_PRINT_LOW("\n o/p previous min cnt = %d\n", m_sOutPortDef.nBufferCountMin);
+ m_sOutPortDef.nBufferCountActual = portDefn->nBufferCountActual;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Set_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ m_sConfigFramerate.xEncodeFramerate = portDefn->format.video.xFramerate;
+ m_sConfigBitrate.nEncodeBitrate = portDefn->format.video.nBitrate;
+ m_sParamBitrate.nTargetBitrate = portDefn->format.video.nBitrate;
+ }
+ break;
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
+ portFmt->eColorFormat);
+ //set the driver with the corresponding values
+ if(PORT_INDEX_IN == portFmt->nPortIndex)
+ {
+ if(handle->venc_set_param(paramData,OMX_IndexParamVideoPortFormat) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n",
+ portFmt->eColorFormat);
+
+ m_sInPortFormat.eColorFormat = portFmt->eColorFormat;
+ m_sInPortFormat.xFramerate = portFmt->xFramerate;
+ }
+ //TODO if no use case for O/P port,delet m_sOutPortFormat
+ }
+ break;
+ case OMX_IndexParamVideoInit:
+ { //TODO, do we need this index set param
+ OMX_PORT_PARAM_TYPE* pParam = (OMX_PORT_PARAM_TYPE*)(paramData);
+ DEBUG_PRINT_LOW("\n Set OMX_IndexParamVideoInit called");
+ break;
+ }
+
+ case OMX_IndexParamVideoBitrate:
+ {
+ OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoBitrate");
+ if(handle->venc_set_param(paramData,OMX_IndexParamVideoBitrate) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_sParamBitrate.nTargetBitrate = pParam->nTargetBitrate;
+ m_sParamBitrate.eControlRate = pParam->eControlRate;
+
+ m_sConfigBitrate.nEncodeBitrate = pParam->nTargetBitrate;
+ m_sInPortDef.format.video.nBitrate = pParam->nTargetBitrate;
+ m_sOutPortDef.format.video.nBitrate = pParam->nTargetBitrate;
+ DEBUG_PRINT_LOW("\nbitrate = %u", m_sOutPortDef.format.video.nBitrate);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4");
+ if(handle->venc_set_param(paramData,OMX_IndexParamVideoMpeg4) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ //.. more than one variable storing the npframes,profile,level details
+ m_sParamMPEG4.nPFrames = pParam->nPFrames;
+ m_sParamMPEG4.eProfile = pParam->eProfile;
+ m_sParamMPEG4.eLevel = pParam->eLevel;
+ m_sParamMPEG4.bACPred = pParam->bACPred;
+ m_sParamMPEG4.nTimeIncRes = pParam->nTimeIncRes;
+ m_sParamMPEG4.bReversibleVLC = pParam->bReversibleVLC;
+
+ m_sParamProfileLevel.eProfile = pParam->eProfile;
+ m_sParamProfileLevel.eLevel = pParam->eLevel;
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263");
+ if(handle->venc_set_param(paramData,OMX_IndexParamVideoH263) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ //.. more than one variable storing the npframes,profile,level details
+ m_sParamH263.nPFrames = pParam->nPFrames;
+ m_sParamH263.eProfile = pParam->eProfile;
+ m_sParamH263.eLevel = pParam->eLevel;
+
+ m_sParamProfileLevel.eProfile = pParam->eProfile;
+ m_sParamProfileLevel.eLevel = pParam->eLevel;
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc");
+ if(handle->venc_set_param(paramData,OMX_IndexParamVideoAvc) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ //.. more than one variable storing the npframes,profile,level details
+ m_sParamAVC.nPFrames = pParam->nPFrames;
+ m_sParamAVC.eProfile = pParam->eProfile;
+ m_sParamAVC.eLevel = pParam->eLevel;
+
+ m_sParamProfileLevel.eProfile = pParam->eProfile;
+ m_sParamProfileLevel.eLevel = pParam->eLevel;
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelCurrent:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoProfileLevelCurrent");
+ if(handle->venc_set_param(paramData,OMX_IndexParamVideoProfileLevelCurrent) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_sParamProfileLevel.eProfile = pParam->eProfile;
+ m_sParamProfileLevel.eLevel = pParam->eLevel;
+
+ if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.mpeg4",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ m_sParamMPEG4.eProfile = (OMX_VIDEO_MPEG4PROFILETYPE)m_sParamProfileLevel.eProfile;
+ m_sParamMPEG4.eLevel = (OMX_VIDEO_MPEG4LEVELTYPE)m_sParamProfileLevel.eLevel;
+ DEBUG_PRINT_LOW("\n MPEG4 profile = %d, level = %d", m_sParamMPEG4.eProfile,
+ m_sParamMPEG4.eLevel);
+ }
+ else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.h263",\
+ OMX_MAX_STRINGNAME_SIZE))
+ {
+ m_sParamH263.eProfile = (OMX_VIDEO_H263PROFILETYPE)m_sParamProfileLevel.eProfile;
+ m_sParamH263.eLevel = (OMX_VIDEO_H263LEVELTYPE)m_sParamProfileLevel.eLevel;
+ DEBUG_PRINT_LOW("\n H263 profile = %d, level = %d", m_sParamH263.eProfile,
+ m_sParamH263.eLevel);
+ }
+ else
+ {
+ m_sParamAVC.eProfile = (OMX_VIDEO_AVCPROFILETYPE)m_sParamProfileLevel.eProfile;
+ m_sParamAVC.eLevel = (OMX_VIDEO_AVCLEVELTYPE)m_sParamProfileLevel.eLevel;
+ DEBUG_PRINT_LOW("\n AVC profile = %d, level = %d", m_sParamAVC.eProfile,
+ m_sParamAVC.eLevel);
+ }
+ break;
+ }
+ case OMX_IndexParamStandardComponentRole:
+ {
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n",
+ comp_role->cRole);
+
+ if((m_state == OMX_StateLoaded)&&
+ !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
+ {
+ DEBUG_PRINT_LOW("Set Parameter called in valid state");
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((char*)comp_role->cRole,"video_encoder.avc",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_encoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((const char*)comp_role->cRole,"video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ if(!strncmp((const char*)comp_role->cRole,"video_encoder.h263",OMX_MAX_STRINGNAME_SIZE))
+ {
+ strncpy((char*)m_cRole,"video_encoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown param %s\n", m_nkind);
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ break;
+ }
+
+ case OMX_IndexParamPriorityMgmt:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt");
+ if(m_state != OMX_StateLoaded)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Set Parameter called in Invalid State\n");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n",
+ priorityMgmtype->nGroupID);
+
+ DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n",
+ priorityMgmtype->nGroupPriority);
+
+ m_sPriorityMgmt.nGroupID = priorityMgmtype->nGroupID;
+ m_sPriorityMgmt.nGroupPriority = priorityMgmtype->nGroupPriority;
+
+ break;
+ }
+
+ case OMX_IndexParamCompBufferSupplier:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier");
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
+ bufferSupplierType->eBufferSupplier);
+ if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
+ m_sInBufSupplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
+
+ else
+
+ eRet = OMX_ErrorBadPortIndex;
+
+ break;
+
+ }
+ case OMX_IndexParamVideoQuantization:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoQuantization\n");
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData;
+ if(session_qp->nPortIndex == PORT_INDEX_OUT)
+ {
+ if(handle->venc_set_param(paramData, OMX_IndexParamVideoQuantization) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_sSessionQuantization.nQpI = session_qp->nQpI;
+ m_sSessionQuantization.nQpP = session_qp->nQpP;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Unsupported port Index for Session QP setting\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+
+ case OMX_QcomIndexPortDefn:
+ {
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE* pParam =
+ (OMX_QCOM_PARAM_PORTDEFINITIONTYPE*)paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexPortDefn");
+ if(pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN)
+ {
+ if(pParam->nMemRegion > OMX_QCOM_MemRegionInvalid &&
+ pParam->nMemRegion < OMX_QCOM_MemRegionMax)
+ {
+ m_use_input_pmem = OMX_TRUE;
+ }
+ else
+ {
+ m_use_input_pmem = OMX_FALSE;
+ }
+ }
+ else if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_OUT)
+ {
+ if(pParam->nMemRegion > OMX_QCOM_MemRegionInvalid &&
+ pParam->nMemRegion < OMX_QCOM_MemRegionMax)
+ {
+ m_use_output_pmem = OMX_TRUE;
+ }
+ else
+ {
+ m_use_output_pmem = OMX_FALSE;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: SetParameter called on unsupported Port Index for QcomPortDefn");
+ return OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+//#endif //# QCOM_EXT
+ case OMX_IndexParamVideoSliceFMO:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoSliceFMO\n");
+ OMX_VIDEO_PARAM_AVCSLICEFMO *avc_slice_fmo = (OMX_VIDEO_PARAM_AVCSLICEFMO*)paramData;
+ if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\
+ OMX_MAX_STRINGNAME_SIZE) && avc_slice_fmo->nPortIndex == PORT_INDEX_OUT)
+ {
+ if(handle->venc_set_param(paramData, OMX_IndexParamVideoSliceFMO) != true)
+ {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_sAVCSliceFMO.eSliceMode = avc_slice_fmo->eSliceMode;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Unsupported codec type/port Index for AVCSliceFMO setting\n");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexParamVideoErrorCorrection:
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMX_IndexParamVideoErrorCorrection unsupported\n");
+ eRet = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ case OMX_IndexParamVideoIntraRefresh:
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMX_IndexParamVideoIntraRefresh unsupported\n");
+ eRet = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ default:
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown param %d\n", paramIndex);
+ eRet = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ }
+ return eRet;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_video::SetConfig
+
+DESCRIPTION
+ OMX Set Config method implementation
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if successful.
+========================================================================== */
+OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_IN OMX_PTR configData)
+{
+ if(configData == NULL)
+ {
+ DEBUG_PRINT_ERROR("ERROR: param is null");
+ return OMX_ErrorBadParameter;
+ }
+
+ if(m_state == OMX_StateInvalid)
+ {
+ DEBUG_PRINT_ERROR("ERROR: config called in Invalid state");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ // params will be validated prior to venc_init
+ switch(configIndex)
+ {
+ case OMX_IndexConfigVideoBitrate:
+ {
+ OMX_VIDEO_CONFIG_BITRATETYPE* pParam =
+ reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData);
+ DEBUG_PRINT_LOW("\n omx_venc:: set_config(): OMX_IndexConfigVideoBitrate");
+
+ if(pParam->nPortIndex == PORT_INDEX_OUT)
+ {
+ if(handle->venc_set_config(configData, OMX_IndexConfigVideoBitrate) != true)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigVideoBitrate failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ m_sConfigBitrate.nEncodeBitrate = pParam->nEncodeBitrate;
+ m_sParamBitrate.nTargetBitrate = pParam->nEncodeBitrate;
+ m_sOutPortDef.format.video.nBitrate = pParam->nEncodeBitrate;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex);
+ return OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_IndexConfigVideoFramerate:
+ {
+ OMX_CONFIG_FRAMERATETYPE* pParam =
+ reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData);
+ DEBUG_PRINT_LOW("\n omx_venc:: set_config(): OMX_IndexConfigVideoFramerate");
+
+ if(pParam->nPortIndex == PORT_INDEX_OUT)
+ {
+ if(handle->venc_set_config(configData, OMX_IndexConfigVideoFramerate) != true)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigVideoFramerate failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ m_sConfigFramerate.xEncodeFramerate = pParam->xEncodeFramerate;
+ m_sOutPortDef.format.video.xFramerate = pParam->xEncodeFramerate;
+ m_sOutPortFormat.xFramerate = pParam->xEncodeFramerate;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex);
+ return OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+ case OMX_IndexConfigVideoIntraVOPRefresh:
+ {
+ OMX_CONFIG_INTRAREFRESHVOPTYPE* pParam =
+ reinterpret_cast<OMX_CONFIG_INTRAREFRESHVOPTYPE*>(configData);
+
+ if(pParam->nPortIndex == PORT_INDEX_OUT)
+ {
+ if(handle->venc_set_config(configData,
+ OMX_IndexConfigVideoIntraVOPRefresh) != true)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigVideoIntraVOPRefresh failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ m_sConfigIntraRefreshVOP.IntraRefreshVOP = pParam->IntraRefreshVOP;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex);
+ return OMX_ErrorBadPortIndex;
+ }
+
+ break;
+ }
+ case OMX_IndexConfigCommonRotate:
+ {
+ DEBUG_PRINT_ERROR("ERROR: OMX_IndexConfigCommonRotate is currently unsupported");
+ break;
+ }
+ default:
+ DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
+ break;
+ }
+
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+FUNCTION
+ omx_venc::ComponentDeInit
+
+DESCRIPTION
+ Destroys the component and release memory allocated to the heap.
+
+PARAMETERS
+ <TBD>.
+
+RETURN VALUE
+ OMX Error None if everything successful.
+
+========================================================================== */
+OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
+{
+ OMX_U32 i = 0;
+ DEBUG_PRINT_HIGH("\n omx_venc(): Inside component_deinit()");
+ if(OMX_StateLoaded != m_state)
+ {
+ DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\
+ m_state);
+ }
+ if(m_out_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("Freeing the Output Memory\n");
+ for(i=0; i< m_sOutPortDef.nBufferCountActual; i++ )
+ {
+ free_output_buffer (&m_out_mem_ptr[i]);
+ }
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+
+ /*Check if the input buffers have to be cleaned up*/
+ if(m_inp_mem_ptr)
+ {
+ DEBUG_PRINT_LOW("Freeing the Input Memory\n");
+ for(i=0; i<m_sInPortDef.nBufferCountActual; i++ )
+ {
+ free_input_buffer (&m_inp_mem_ptr[i]);
+ }
+
+
+ free(m_inp_mem_ptr);
+ m_inp_mem_ptr = NULL;
+ }
+
+ // Reset counters in mesg queues
+ m_ftb_q.m_size=0;
+ m_cmd_q.m_size=0;
+ m_etb_q.m_size=0;
+ m_ftb_q.m_read = m_ftb_q.m_write =0;
+ m_cmd_q.m_read = m_cmd_q.m_write =0;
+ m_etb_q.m_read = m_etb_q.m_write =0;
+
+#ifdef _ANDROID_
+ // Clear the strong reference
+ DEBUG_PRINT_HIGH("Calling m_heap_ptr.clear()\n");
+ m_heap_ptr.clear();
+#endif // _ANDROID_
+ DEBUG_PRINT_HIGH("Calling venc_close()\n");
+ handle->venc_close();
+ DEBUG_PRINT_HIGH("Deleting HANDLE[%p]\n", handle);
+ delete (handle);
+ DEBUG_PRINT_HIGH("OMX_Venc:Component Deinit\n");
+ return OMX_ErrorNone;
+}
+
+
+OMX_U32 omx_venc::dev_stop( void)
+{
+ return handle->venc_stop();
+}
+
+
+OMX_U32 omx_venc::dev_pause(void)
+{
+ return handle->venc_pause();
+}
+
+OMX_U32 omx_venc::dev_start(void)
+{
+ return handle->venc_start();
+}
+
+OMX_U32 omx_venc::dev_flush(unsigned port)
+{
+ return handle->venc_flush(port);
+}
+OMX_U32 omx_venc::dev_resume(void)
+{
+ return handle->venc_resume();
+}
+
+bool omx_venc::dev_use_buf(void *buf_addr,unsigned port)
+{
+ return handle->venc_use_buf(buf_addr,port);
+}
+
+bool omx_venc::dev_free_buf(void *buf_addr,unsigned port)
+{
+ return handle->venc_free_buf(buf_addr,port);
+}
+
+bool omx_venc::dev_empty_buf(void *buffer, void *pmem_data_buf)
+{
+ return handle->venc_empty_buf(buffer, pmem_data_buf);
+}
+
+bool omx_venc::dev_fill_buf(void *buffer, void *pmem_data_buf)
+{
+ return handle->venc_fill_buf(buffer, pmem_data_buf);
+}
+
+
+bool omx_venc::dev_get_buf_req(OMX_U32 *min_buff_count,
+ OMX_U32 *actual_buff_count,
+ OMX_U32 *buff_size,
+ OMX_U32 port)
+{
+ return handle->venc_get_buf_req(min_buff_count,
+ actual_buff_count,
+ buff_size,
+ port);
+
+}
+
+bool omx_venc::dev_set_buf_req(OMX_U32 *min_buff_count,
+ OMX_U32 *actual_buff_count,
+ OMX_U32 *buff_size,
+ OMX_U32 port)
+{
+ return handle->venc_set_buf_req(min_buff_count,
+ actual_buff_count,
+ buff_size,
+ port);
+
+}
+
+int omx_venc::async_message_process (void *context, void* message)
+{
+ omx_video* omx = NULL;
+ struct venc_msg *m_sVenc_msg = NULL;
+ OMX_BUFFERHEADERTYPE* omxhdr = NULL;
+ struct venc_buffer *temp_buff = NULL;
+
+ if(context == NULL || message == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: omx_venc::async_message_process invalid i/p params");
+ return -1;
+ }
+ m_sVenc_msg = (struct venc_msg *)message;
+
+ omx = reinterpret_cast<omx_video*>(context);
+
+ if(m_sVenc_msg->statuscode != VEN_S_SUCCESS)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: async_msg_process() - Error statuscode = %d\n",
+ m_sVenc_msg->statuscode);
+ omx->omx_report_error();
+ }
+
+ DEBUG_PRINT_LOW("\n omx_venc::async_message_process- msgcode = %d\n",
+ m_sVenc_msg->msgcode);
+ switch(m_sVenc_msg->msgcode)
+ {
+
+ case VEN_MSG_START:
+ omx->post_event (NULL,m_sVenc_msg->statuscode,\
+ OMX_COMPONENT_GENERATE_START_DONE);
+ break;
+
+ case VEN_MSG_STOP:
+ omx->post_event (NULL,m_sVenc_msg->statuscode,\
+ OMX_COMPONENT_GENERATE_STOP_DONE);
+ break;
+
+ case VEN_MSG_RESUME:
+ omx->post_event (NULL,m_sVenc_msg->statuscode,\
+ OMX_COMPONENT_GENERATE_RESUME_DONE);
+ break;
+
+ case VEN_MSG_PAUSE:
+ omx->post_event (NULL,m_sVenc_msg->statuscode,\
+ OMX_COMPONENT_GENERATE_PAUSE_DONE);
+
+ break;
+
+ case VEN_MSG_FLUSH_INPUT_DONE:
+
+ omx->post_event (NULL,m_sVenc_msg->statuscode,\
+ OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
+ break;
+ case VEN_MSG_FLUSH_OUPUT_DONE:
+ omx->post_event (NULL,m_sVenc_msg->statuscode,\
+ OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
+ break;
+ case VEN_MSG_INPUT_BUFFER_DONE:
+ omxhdr = (OMX_BUFFERHEADERTYPE* )\
+ m_sVenc_msg->buf.clientdata;
+
+ if(omxhdr == NULL ||
+ ((OMX_U32)(omxhdr - omx->m_inp_mem_ptr) > omx->m_sInPortDef.nBufferCountActual) )
+ {
+ omxhdr = NULL;
+ m_sVenc_msg->statuscode = VEN_S_EFAIL;
+ }
+
+ omx->post_event ((unsigned int)omxhdr,m_sVenc_msg->statuscode,
+ OMX_COMPONENT_GENERATE_EBD);
+ break;
+ case VEN_MSG_OUTPUT_BUFFER_DONE:
+
+ omxhdr = (OMX_BUFFERHEADERTYPE*)m_sVenc_msg->buf.clientdata;
+
+ if( (omxhdr != NULL) &&
+ ((OMX_U32)(omxhdr - omx->m_out_mem_ptr) < omx->m_sOutPortDef.nBufferCountActual))
+ {
+ if(m_sVenc_msg->buf.len <= omxhdr->nAllocLen)
+ {
+ omxhdr->nFilledLen = m_sVenc_msg->buf.len;
+ omxhdr->nOffset = m_sVenc_msg->buf.offset;
+ omxhdr->nTimeStamp = m_sVenc_msg->buf.timestamp;
+ DEBUG_PRINT_LOW("\n o/p TS = %u", (OMX_U32)m_sVenc_msg->buf.timestamp);
+ omxhdr->nFlags = m_sVenc_msg->buf.flags;
+
+ /*Use buffer case*/
+ if(omx->output_use_buffer && !omx->m_use_output_pmem)
+ {
+ DEBUG_PRINT_LOW("\n memcpy() for o/p Heap UseBuffer");
+ memcpy(omxhdr->pBuffer,
+ (m_sVenc_msg->buf.ptrbuffer),
+ m_sVenc_msg->buf.len);
+ }
+ }
+ else
+ {
+ omxhdr->nFilledLen = 0;
+ }
+
+ }
+ else
+ {
+ omxhdr = NULL;
+ m_sVenc_msg->statuscode = VEN_S_EFAIL;
+ }
+
+ omx->post_event ((unsigned int)omxhdr,m_sVenc_msg->statuscode,
+ OMX_COMPONENT_GENERATE_FBD);
+ break;
+ case VEN_MSG_NEED_OUTPUT_BUFFER:
+ //TBD what action needs to be done here??
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
diff --git a/omx/mm-video/vidc/venc/src/video_encoder_device.cpp b/omx/mm-video/vidc/venc/src/video_encoder_device.cpp
new file mode 100644
index 0000000..74fa838
--- /dev/null
+++ b/omx/mm-video/vidc/venc/src/video_encoder_device.cpp
@@ -0,0 +1,1883 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include<string.h>
+#include <sys/ioctl.h>
+#include<unistd.h>
+#include <fcntl.h>
+#include "video_encoder_device.h"
+#include "omx_video_encoder.h"
+
+#define MPEG4_SP_START 0
+#define MPEG4_ASP_START (MPEG4_SP_START + 8)
+#define MPEG4_720P_LEVEL 6
+#define H263_BP_START 0
+#define H264_BP_START 0
+#define H264_HP_START (H264_BP_START + 11)
+#define H264_MP_START (H264_BP_START + 21)
+
+/* MPEG4 profile and level table*/
+static const unsigned int mpeg4_profile_level_table[][5]=
+{
+ /*max mb per frame, max mb per sec, max bitrate, level, profile*/
+ {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple},
+ {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple},
+ {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple},
+ {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple},
+ {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple},
+ {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
+ {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
+ {0,0,0,0,0},
+
+ {99,2970,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {99,2970,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {0,0,0,0,0}
+};
+
+/* H264 profile and level table*/
+static const unsigned int h264_profile_level_table[][5]=
+{
+ /*max mb per frame, max mb per sec, max bitrate, level, profile*/
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline},
+ {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline},
+ {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline},
+ {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline},
+ {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline},
+ {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline},
+ {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline},
+ {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline},
+ {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline},
+ {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline},
+ {0,0,0,0,0},
+
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh},
+ {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh},
+ {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh},
+ {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh},
+ {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh},
+ {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh},
+ {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh},
+ {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh},
+ {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh},
+ {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh},
+ {0,0,0,0,0},
+
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain},
+ {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain},
+ {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain},
+ {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain},
+ {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain},
+ {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain},
+ {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain},
+ {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain},
+ {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain},
+ {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain},
+ {0,0,0,0,0}
+};
+
+/* H263 profile and level table*/
+static const unsigned int h263_profile_level_table[][5]=
+{
+ /*max mb per frame, max mb per sec, max bitrate, level, profile*/
+ {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline},
+ {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline},
+ {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline},
+ {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline},
+ {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline},
+ {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline},
+ {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
+ {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
+ {0,0,0,0,0}
+};
+
+//constructor
+venc_dev::venc_dev()
+{
+//nothing to do
+
+}
+
+venc_dev::~venc_dev()
+{
+ //nothing to do
+}
+
+void* async_venc_message_thread (void *input)
+{
+ struct venc_ioctl_msg ioctl_msg ={NULL,NULL};
+ struct venc_timeout timeout;
+ struct venc_msg venc_msg;
+ omx_venc *omx = reinterpret_cast<omx_venc*>(input);
+
+ timeout.millisec = VEN_TIMEOUT_INFINITE;
+ while(1)
+ {
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&venc_msg;
+
+ /*Wait for a message from the video decoder driver*/
+ if(ioctl(omx->handle->m_nDriver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,(void *)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nioctl VEN_IOCTL_CMD_READ_NEXT_MSG failed/stopped");
+ break;
+ }
+ else
+ {
+ /*Call Instance specific process function*/
+ if(omx->async_message_process(input,&venc_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Wrong ioctl message");
+ break;
+ }
+ }
+ }
+ DEBUG_PRINT_HIGH("omx_venc: Async Thread exit\n");
+ return NULL;
+}
+
+bool venc_dev::venc_open(OMX_U32 codec)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ int r;
+ unsigned int alignment = 0,buffer_size = 0, temp =0;
+
+ m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK);
+ if(m_nDriver_fd == 0)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Got fd as 0 for msm_vidc_enc, Opening again\n");
+ m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK);
+ }
+
+ if((int)m_nDriver_fd < 0)
+ {
+ DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure\n");
+ return false;
+ }
+
+ DEBUG_PRINT_LOW("\nm_nDriver_fd = %d\n", m_nDriver_fd);
+ // set the basic configuration of the video encoder driver
+ m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH;
+ m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT;
+ m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH;
+ m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT;
+ m_sVenc_cfg.fps_num = 30;
+ m_sVenc_cfg.fps_den = 1;
+ m_sVenc_cfg.targetbitrate = 64000;
+ m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12;
+ if(codec == OMX_VIDEO_CodingMPEG4)
+ {
+ m_sVenc_cfg.codectype = VEN_CODEC_MPEG4;
+ codec_profile.profile = VEN_PROFILE_MPEG4_SP;
+ profile_level.level = VEN_LEVEL_MPEG4_2;
+ }
+ else if(codec == OMX_VIDEO_CodingH263)
+ {
+ m_sVenc_cfg.codectype = VEN_CODEC_H263;
+ codec_profile.profile = VEN_PROFILE_H263_BASELINE;
+ profile_level.level = VEN_LEVEL_H263_20;
+ }
+ if(codec == OMX_VIDEO_CodingAVC)
+ {
+ m_sVenc_cfg.codectype = VEN_CODEC_H264;
+ codec_profile.profile = VEN_PROFILE_H264_BASELINE;
+ profile_level.level = VEN_LEVEL_H264_1p1;
+ }
+ ioctl_msg.inputparam = (void*)&m_sVenc_cfg;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0 )
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting base configuration failed");
+ return false;
+ }
+
+ // Get the I/P and O/P buffer requirements
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&m_sInput_buff_property;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed");
+ return false;
+ }
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&m_sOutput_buff_property;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed");
+ return false;
+ }
+
+ m_profile_set = false;
+ m_level_set = false;
+ if(venc_set_profile_level(0, 0))
+ {
+ DEBUG_PRINT_HIGH("\n %s(): Init Profile/Level setting success",
+ __func__);
+ }
+
+ return true;
+}
+
+void venc_dev::venc_close()
+{
+ DEBUG_PRINT_LOW("\nvenc_close: fd = %d", m_nDriver_fd);
+ if((int)m_nDriver_fd >= 0)
+ {
+ DEBUG_PRINT_HIGH("\n venc_close(): Calling VEN_IOCTL_CMD_STOP_READ_MSG");
+ (void)ioctl(m_nDriver_fd, VEN_IOCTL_CMD_STOP_READ_MSG,
+ NULL);
+ DEBUG_PRINT_LOW("\nCalling close()\n");
+ close(m_nDriver_fd);
+ m_nDriver_fd = -1;
+ }
+}
+
+bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count,
+ unsigned long *actual_buff_count,
+ unsigned long *buff_size,
+ unsigned long port)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned long temp_count = 0;
+
+ if(port == 0)
+ {
+ if(*actual_buff_count > m_sInput_buff_property.mincount)
+ {
+ temp_count = m_sInput_buff_property.actualcount;
+ m_sInput_buff_property.actualcount = *actual_buff_count;
+ ioctl_msg.inputparam = (void*)&m_sInput_buff_property;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirement failed");
+ m_sInput_buff_property.actualcount = temp_count;
+ return false;
+ }
+ DEBUG_PRINT_LOW("\n I/P Count set to %lu\n", *actual_buff_count);
+ }
+ }
+ else
+ {
+ if(*actual_buff_count > m_sOutput_buff_property.mincount)
+ {
+ temp_count = m_sOutput_buff_property.actualcount;
+ m_sOutput_buff_property.actualcount = *actual_buff_count;
+ ioctl_msg.inputparam = (void*)&m_sOutput_buff_property;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p buffer requirement failed");
+ m_sOutput_buff_property.actualcount = temp_count;
+ return false;
+ }
+ DEBUG_PRINT_LOW("\n O/P Count set to %lu\n", *actual_buff_count);
+ }
+ }
+
+ return true;
+
+}
+
+bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count,
+ unsigned long *actual_buff_count,
+ unsigned long *buff_size,
+ unsigned long port)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+
+ if(port == 0)
+ {
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&m_sInput_buff_property;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed");
+ return false;
+ }
+ *min_buff_count = m_sInput_buff_property.mincount;
+ *actual_buff_count = m_sInput_buff_property.actualcount;
+ *buff_size = m_sInput_buff_property.datasize
+ + (m_sInput_buff_property.datasize % m_sInput_buff_property.alignment) ;
+ }
+ else
+ {
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&m_sOutput_buff_property;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed");
+ return false;
+ }
+ *min_buff_count = m_sOutput_buff_property.mincount;
+ *actual_buff_count = m_sOutput_buff_property.actualcount;
+ *buff_size = m_sOutput_buff_property.datasize
+ + (m_sOutput_buff_property.datasize % m_sOutput_buff_property.alignment) ;
+ }
+
+ return true;
+
+}
+
+bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
+{
+ venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ OMX_U32 temp_out_buf_count = 0;
+ DEBUG_PRINT_LOW("venc_set_param:: venc-720p\n");
+ switch(index)
+ {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+ DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition\n");
+ if(portDefn->nPortIndex == PORT_INDEX_IN)
+ {
+ if(!venc_set_color_format(portDefn->format.video.eColorFormat))
+ {
+ return false;
+ }
+ if(m_sVenc_cfg.input_height != portDefn->format.video.nFrameHeight ||
+ m_sVenc_cfg.input_width != portDefn->format.video.nFrameWidth)
+ {
+ DEBUG_PRINT_LOW("\n Basic parameter has changed");
+ m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight;
+ m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth;
+
+ temp_out_buf_count = m_sOutput_buff_property.actualcount;
+ ioctl_msg.inputparam = (void*)&m_sVenc_cfg;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting base config failed");
+ return false;
+ }
+
+ DEBUG_PRINT_LOW("\n Updating the buffer count/size for the new resolution");
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&m_sInput_buff_property;
+ if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p bufreq failed");
+ return false;
+ }
+ DEBUG_PRINT_LOW("\n Got updated m_sInput_buff_property values: "
+ "datasize = %u, maxcount = %u, actualcnt = %u, "
+ "mincount = %u", m_sInput_buff_property.datasize,
+ m_sInput_buff_property.maxcount, m_sInput_buff_property.actualcount,
+ m_sInput_buff_property.mincount);
+
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&m_sOutput_buff_property;
+ if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p bufreq failed");
+ return false;
+ }
+
+ DEBUG_PRINT_LOW("\n Got updated m_sOutput_buff_property values: "
+ "datasize = %u, maxcount = %u, actualcnt = %u, "
+ "mincount = %u", m_sOutput_buff_property.datasize,
+ m_sOutput_buff_property.maxcount, m_sOutput_buff_property.actualcount,
+ m_sOutput_buff_property.mincount);
+
+ if(temp_out_buf_count < 7)
+ temp_out_buf_count = 7;
+ m_sOutput_buff_property.actualcount = temp_out_buf_count;
+ ioctl_msg.inputparam = (void*)&m_sOutput_buff_property;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p bufreq failed");
+ return false;
+ }
+
+ if((portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) &&
+ (portDefn->nBufferCountActual <= m_sInput_buff_property.maxcount))
+ {
+ m_sInput_buff_property.actualcount = portDefn->nBufferCountActual;
+ ioctl_msg.inputparam = (void*)&m_sInput_buff_property;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl(m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirements failed");
+ return false;
+ }
+ }
+ if(m_sInput_buff_property.datasize != portDefn->nBufferSize)
+ {
+ DEBUG_PRINT_ERROR("\nWARNING: Requested i/p bufsize[%u],"
+ "Driver's updated i/p bufsize = %u", portDefn->nBufferSize,
+ m_sInput_buff_property.datasize);
+ }
+ m_level_set = false;
+ if(venc_set_profile_level(0, 0))
+ {
+ DEBUG_PRINT_HIGH("\n %s(): Dynamic Profile/Level setting success",
+ __func__);
+ }
+ }
+ else
+ {
+ if((portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) &&
+ (m_sInput_buff_property.actualcount <= portDefn->nBufferCountActual) &&
+ (m_sInput_buff_property.datasize == portDefn->nBufferSize))
+ {
+ m_sInput_buff_property.actualcount = portDefn->nBufferCountActual;
+ ioctl_msg.inputparam = (void*)&m_sInput_buff_property;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_SET_INPUT_BUFFER_REQ failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Input buffer requirements failed");
+ return false;
+ }
+ }
+ }
+ else if(portDefn->nPortIndex == PORT_INDEX_OUT)
+ {
+ if(!venc_set_encode_framerate(portDefn->format.video.xFramerate))
+ {
+ return false;
+ }
+
+ if(!venc_set_target_bitrate(portDefn->format.video.nBitrate))
+ {
+ return false;
+ }
+
+ if( (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount)
+ &&
+ (m_sOutput_buff_property.actualcount <= portDefn->nBufferCountActual)
+ &&
+ (m_sOutput_buff_property.datasize == portDefn->nBufferSize)
+ )
+ {
+ m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual;
+ ioctl_msg.inputparam = (void*)&m_sOutput_buff_property;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_SET_OUTPUT_BUFFER_REQ failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Output buffer requirements failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamPortDefinition");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt;
+ portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat\n");
+
+ if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN)
+ {
+ if(!venc_set_color_format(portFmt->eColorFormat))
+ {
+ return false;
+ }
+ }
+ else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(!venc_set_encode_framerate(portFmt->xFramerate))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoBitrate:
+ {
+ OMX_VIDEO_PARAM_BITRATETYPE* pParam;
+ pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
+ DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate\n");
+
+ if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(!venc_set_target_bitrate(pParam->nTargetBitrate))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Target Bit Rate setting failed");
+ return false;
+ }
+ if(!venc_set_ratectrl_cfg(pParam->eControlRate))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Rate Control setting failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoBitrate");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4:
+ {
+ OMX_VIDEO_PARAM_MPEG4TYPE* pParam;
+ pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
+ DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoMpeg4\n");
+ if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(!venc_set_intra_period (pParam->nPFrames))
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed");
+ return false;
+ }
+
+ m_profile_set = false;
+ m_level_set = false;
+ if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel))
+ {
+ DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoMpeg4");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoH263:
+ {
+ OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
+ DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoH263\n");
+ if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(venc_set_intra_period (pParam->nPFrames) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed");
+ return false;
+ }
+
+ m_profile_set = false;
+ m_level_set = false;
+ if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel))
+ {
+ DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoH263");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoAvc:
+ {
+ DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc\n");
+ OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
+ if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(venc_set_intra_period (pParam->nPFrames) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed");
+ return false;
+ }
+ DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d\n",
+ pParam->eProfile,pParam->eLevel);
+
+ m_profile_set = false;
+ m_level_set = false;
+ if(!venc_set_profile_level (pParam->eProfile,pParam->eLevel))
+ {
+ DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoAvc");
+ }
+ //TBD, lot of other variables to be updated, yet to decide
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelCurrent:
+ {
+ DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent\n");
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
+ if(profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ m_profile_set = false;
+ m_level_set = false;
+ if(!venc_set_profile_level (profile_level->eProfile,
+ profile_level->eLevel))
+ {
+ DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoQuantization:
+ {
+ DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization\n");
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp =
+ (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData;
+ if(session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(venc_set_session_qp (session_qp->nQpI,
+ session_qp->nQpP) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Session QP failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoQuantization");
+ }
+ break;
+ }
+ case OMX_IndexParamVideoSliceFMO:
+ {
+ DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoSliceFMO\n");
+ OMX_VIDEO_PARAM_AVCSLICEFMO *avc_slice_fmo =
+ (OMX_VIDEO_PARAM_AVCSLICEFMO*)paramData;
+ DEBUG_PRINT_LOW("\n portindex = %u", avc_slice_fmo->nPortIndex);
+ if(avc_slice_fmo->nPortIndex == (OMX_U32) PORT_INDEX_OUT)
+ {
+ if(venc_set_multislice_cfg(avc_slice_fmo->eSliceMode) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Multislice cfg failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for Multislice cfg");
+ }
+ break;
+ }
+ default:
+ DEBUG_PRINT_ERROR("\nERROR: Unsupported parameter in venc_set_param: %u",
+ index);
+ break;
+ //case
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
+{
+ venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ DEBUG_PRINT_LOW("\n Inside venc_set_config");
+
+ switch(index)
+ {
+ case OMX_IndexConfigVideoBitrate:
+ {
+ OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *)
+ configData;
+ DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoBitrate");
+ if(bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT)
+ {
+ if(venc_set_target_bitrate(bit_rate->nEncodeBitrate) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Target Bit rate failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate");
+ }
+ break;
+ }
+ case OMX_IndexConfigVideoFramerate:
+ {
+ OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *)
+ configData;
+ DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoFramerate");
+ if(frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT)
+ {
+ if(venc_set_encode_framerate(frame_rate->xEncodeFramerate) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
+ }
+ break;
+ }
+ case OMX_IndexConfigVideoIntraVOPRefresh:
+ {
+ OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)
+ configData;
+ DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh");
+ if(intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT)
+ {
+ if(venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
+ }
+ break;
+ }
+ default:
+ DEBUG_PRINT_ERROR("\n Unsupported config index = %u", index);
+ break;
+ }
+
+ return true;
+}
+
+unsigned venc_dev::venc_stop( void)
+{
+ return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_STOP,NULL);
+}
+
+unsigned venc_dev::venc_pause(void)
+{
+ return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_PAUSE,NULL);
+}
+
+unsigned venc_dev::venc_resume(void)
+{
+ return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_RESUME,NULL) ;
+}
+
+unsigned venc_dev::venc_start(void)
+{
+ DEBUG_PRINT_HIGH("\n %s(): Check Profile/Level set in driver before start",
+ __func__);
+ if (!venc_set_profile_level(0, 0))
+ {
+ DEBUG_PRINT_ERROR("\n ERROR: %s(): Driver Profile/Level is NOT SET",
+ __func__);
+ }
+ else
+ {
+ DEBUG_PRINT_HIGH("\n %s(): Driver Profile[%lu]/Level[%lu] successfully SET",
+ __func__, codec_profile.profile, profile_level.level);
+ }
+
+ return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL);
+}
+
+unsigned venc_dev::venc_flush( unsigned port)
+{
+ struct venc_ioctl_msg ioctl_msg;
+ struct venc_bufferflush buffer_index;
+
+ if(port == PORT_INDEX_IN)
+ {
+ buffer_index.flush_mode = VEN_FLUSH_INPUT;
+ ioctl_msg.inputparam = (void*)&buffer_index;
+ ioctl_msg.outputparam = NULL;
+
+ return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg);
+ }
+ else if(port == PORT_INDEX_OUT)
+ {
+ buffer_index.flush_mode = VEN_FLUSH_OUTPUT;
+ ioctl_msg.inputparam = (void*)&buffer_index;
+ ioctl_msg.outputparam = NULL;
+ return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg);
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+//allocating I/P memory from pmem and register with the device
+
+
+bool venc_dev::venc_use_buf(void *buf_addr, unsigned port)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct pmem *pmem_tmp;
+ struct venc_bufferpayload dev_buffer = {0};
+
+ pmem_tmp = (struct pmem *)buf_addr;
+
+ DEBUG_PRINT_LOW("\n venc_use_buf:: pmem_tmp = %p", pmem_tmp);
+
+ if(port == PORT_INDEX_IN)
+ {
+ dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
+ dev_buffer.fd = pmem_tmp->fd;
+ dev_buffer.maped_size = pmem_tmp->size;
+ dev_buffer.nsize = pmem_tmp->size;
+ dev_buffer.offset = pmem_tmp->offset;
+ ioctl_msg.inputparam = (void*)&dev_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("\n venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
+ dev_buffer.pbuffer, \
+ dev_buffer.fd, \
+ dev_buffer.offset, \
+ dev_buffer.maped_size);
+
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:set input buffer failed ");
+ return false;
+ }
+ }
+ else if(port == PORT_INDEX_OUT)
+ {
+ dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
+ dev_buffer.fd = pmem_tmp->fd;
+ dev_buffer.nsize = pmem_tmp->size;
+ dev_buffer.maped_size = pmem_tmp->size;
+ dev_buffer.offset = pmem_tmp->offset;
+ ioctl_msg.inputparam = (void*)&dev_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("\n venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
+ dev_buffer.pbuffer, \
+ dev_buffer.fd, \
+ dev_buffer.offset, \
+ dev_buffer.maped_size);
+
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:set output buffer failed ");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:Invalid Port Index ");
+ return false;
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_free_buf(void *buf_addr, unsigned port)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct pmem *pmem_tmp;
+ struct venc_bufferpayload dev_buffer = {0};
+
+ pmem_tmp = (struct pmem *)buf_addr;
+
+ DEBUG_PRINT_LOW("\n venc_use_buf:: pmem_tmp = %p", pmem_tmp);
+
+ if(port == PORT_INDEX_IN)
+ {
+ dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
+ dev_buffer.fd = pmem_tmp->fd;
+ dev_buffer.maped_size = pmem_tmp->size;
+ dev_buffer.nsize = pmem_tmp->size;
+ dev_buffer.offset = pmem_tmp->offset;
+ ioctl_msg.inputparam = (void*)&dev_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
+ dev_buffer.pbuffer, \
+ dev_buffer.fd, \
+ dev_buffer.offset, \
+ dev_buffer.maped_size);
+
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_INPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_free_buf: free input buffer failed ");
+ return false;
+ }
+ }
+ else if(port == PORT_INDEX_OUT)
+ {
+ dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
+ dev_buffer.fd = pmem_tmp->fd;
+ dev_buffer.nsize = pmem_tmp->size;
+ dev_buffer.maped_size = pmem_tmp->size;
+ dev_buffer.offset = pmem_tmp->offset;
+ ioctl_msg.inputparam = (void*)&dev_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
+ dev_buffer.pbuffer, \
+ dev_buffer.fd, \
+ dev_buffer.offset, \
+ dev_buffer.maped_size);
+
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_free_buf: free output buffer failed ");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_free_buf:Invalid Port Index ");
+ return false;
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf)
+{
+ struct venc_buffer frameinfo;
+ struct pmem *temp_buffer;
+ struct venc_ioctl_msg ioctl_msg;
+ struct OMX_BUFFERHEADERTYPE *bufhdr;
+
+ if(buffer == NULL)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: venc_etb: buffer is NULL");
+ return false;
+ }
+ bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
+
+ DEBUG_PRINT_LOW("\n Input buffer length %d",bufhdr->nFilledLen);
+
+ if(pmem_data_buf)
+ {
+ DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
+ frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
+ frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer;
+ }
+
+ frameinfo.clientdata = (void *) buffer;
+ frameinfo.size = bufhdr->nFilledLen;
+ frameinfo.len = bufhdr->nFilledLen;
+ frameinfo.flags = bufhdr->nFlags;
+ frameinfo.offset = bufhdr->nOffset;
+ frameinfo.timestamp = bufhdr->nTimeStamp;
+ DEBUG_PRINT_LOW("\n i/p TS = %u", (OMX_U32)frameinfo.timestamp);
+ ioctl_msg.inputparam = &frameinfo;
+ ioctl_msg.outputparam = NULL;
+
+ DEBUG_PRINT_LOW("DBG: i/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u",
+ bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len);
+ if(ioctl(m_nDriver_fd,VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0)
+ {
+ /*Generate an async error and move to invalid state*/
+ return false;
+ }
+
+ return true;
+}
+bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct pmem *temp_buffer = NULL;
+ struct venc_buffer frameinfo;
+ struct OMX_BUFFERHEADERTYPE *bufhdr;
+
+ if(buffer == NULL)
+ {
+ return false;
+ }
+ bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
+
+ if(pmem_data_buf)
+ {
+ DEBUG_PRINT_LOW("\n Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf);
+ frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
+ frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer;
+ }
+
+ frameinfo.clientdata = buffer;
+ frameinfo.size = bufhdr->nAllocLen;
+ frameinfo.flags = bufhdr->nFlags;
+ frameinfo.offset = bufhdr->nOffset;
+
+ ioctl_msg.inputparam = &frameinfo;
+ ioctl_msg.outputparam = NULL;
+ DEBUG_PRINT_LOW("DBG: o/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u",
+ bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len);
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed");
+ return false;
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp)
+{
+ venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_sessionqp qp = {0, 0};
+ DEBUG_PRINT_LOW("venc_set_session_qp:: i_frame_qp = %d, p_frame_qp = %d", i_frame_qp,
+ p_frame_qp);
+
+ qp.iframeqp = i_frame_qp;
+ qp.pframqp = p_frame_qp;
+
+ ioctl_msg.inputparam = (void*)&qp;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_SESSION_QP,(void*)&ioctl_msg)< 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting session qp failed");
+ return false;
+ }
+
+ session_qp.iframeqp = i_frame_qp;
+ session_qp.pframqp = p_frame_qp;
+
+ return true;
+}
+
+bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel)
+{
+ venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_profile requested_profile;
+ struct ven_profilelevel requested_level;
+ unsigned const int *profile_tbl = NULL;
+ unsigned long mb_per_frame = 0, mb_per_sec = 0;
+ DEBUG_PRINT_LOW("venc_set_profile_level:: eProfile = %d, Level = %d",
+ eProfile, eLevel);
+
+ if((eProfile == 0) && (eLevel == 0) && m_profile_set && m_level_set)
+ {
+ DEBUG_PRINT_LOW("\n Profile/Level setting complete before venc_start");
+ return true;
+ }
+
+ DEBUG_PRINT_LOW("\n Validating Profile/Level from table");
+ if(!venc_validate_profile_level(&eProfile, &eLevel))
+ {
+ DEBUG_PRINT_LOW("\nERROR: Profile/Level validation failed");
+ return false;
+ }
+
+ if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4)
+ {
+ DEBUG_PRINT_LOW("eProfile = %d, OMX_VIDEO_MPEG4ProfileSimple = %d and "
+ "OMX_VIDEO_MPEG4ProfileAdvancedSimple = %d", eProfile,
+ OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4ProfileAdvancedSimple);
+ if(eProfile == OMX_VIDEO_MPEG4ProfileSimple)
+ {
+ requested_profile.profile = VEN_PROFILE_MPEG4_SP;
+ profile_tbl = (unsigned int const *)
+ (&mpeg4_profile_level_table[MPEG4_SP_START]);
+ profile_tbl += MPEG4_720P_LEVEL*5;
+ }
+ else if(eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple)
+ {
+ requested_profile.profile = VEN_PROFILE_MPEG4_ASP;
+ profile_tbl = (unsigned int const *)
+ (&mpeg4_profile_level_table[MPEG4_ASP_START]);
+ profile_tbl += MPEG4_720P_LEVEL*5;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\nERROR: Unsupported MPEG4 profile = %u",
+ eProfile);
+ return false;
+ }
+
+ DEBUG_PRINT_LOW("eLevel = %d, OMX_VIDEO_MPEG4Level0 = %d, OMX_VIDEO_MPEG4Level1 = %d,"
+ "OMX_VIDEO_MPEG4Level2 = %d, OMX_VIDEO_MPEG4Level3 = %d, OMX_VIDEO_MPEG4Level4 = %d,"
+ "OMX_VIDEO_MPEG4Level5 = %d", eLevel, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_MPEG4Level1,
+ OMX_VIDEO_MPEG4Level2, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_MPEG4Level5);
+
+ switch(eLevel)
+ {
+ case OMX_VIDEO_MPEG4Level0:
+ requested_level.level = VEN_LEVEL_MPEG4_0;
+ break;
+ case OMX_VIDEO_MPEG4Level1:
+ requested_level.level = VEN_LEVEL_MPEG4_1;
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ requested_level.level = VEN_LEVEL_MPEG4_2;
+ break;
+ case OMX_VIDEO_MPEG4Level3:
+ requested_level.level = VEN_LEVEL_MPEG4_3;
+ break;
+ case OMX_VIDEO_MPEG4Level4a:
+ requested_level.level = VEN_LEVEL_MPEG4_4;
+ break;
+ case OMX_VIDEO_MPEG4Level5:
+ mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)*
+ ((m_sVenc_cfg.input_width + 15) >> 4);
+ mb_per_sec = mb_per_frame * (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den);
+
+ if((mb_per_frame >= profile_tbl[0]) &&
+ (mb_per_sec >= profile_tbl[1]))
+ {
+ DEBUG_PRINT_LOW("\nMPEG4 Level 6 is set for 720p resolution");
+ requested_level.level = VEN_LEVEL_MPEG4_6;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\nMPEG4 Level 5 is set for non-720p resolution");
+ requested_level.level = VEN_LEVEL_MPEG4_5;
+ }
+ break;
+ default:
+ return false;
+ // TODO update corresponding levels for MPEG4_LEVEL_3b,MPEG4_LEVEL_6
+ break;
+ }
+ }
+ else if(m_sVenc_cfg.codectype == VEN_CODEC_H263)
+ {
+ if(eProfile == OMX_VIDEO_H263ProfileBaseline)
+ {
+ requested_profile.profile = VEN_PROFILE_H263_BASELINE;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\nERROR: Unsupported H.263 profile = %u",
+ requested_profile.profile);
+ return false;
+ }
+ //profile level
+ switch(eLevel)
+ {
+ case OMX_VIDEO_H263Level10:
+ requested_level.level = VEN_LEVEL_H263_10;
+ break;
+ case OMX_VIDEO_H263Level20:
+ requested_level.level = VEN_LEVEL_H263_20;
+ break;
+ case OMX_VIDEO_H263Level30:
+ requested_level.level = VEN_LEVEL_H263_30;
+ break;
+ case OMX_VIDEO_H263Level40:
+ requested_level.level = VEN_LEVEL_H263_40;
+ break;
+ case OMX_VIDEO_H263Level45:
+ requested_level.level = VEN_LEVEL_H263_45;
+ break;
+ case OMX_VIDEO_H263Level50:
+ requested_level.level = VEN_LEVEL_H263_50;
+ break;
+ case OMX_VIDEO_H263Level60:
+ requested_level.level = VEN_LEVEL_H263_60;
+ break;
+ case OMX_VIDEO_H263Level70:
+ requested_level.level = VEN_LEVEL_H263_70;
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+ else if(m_sVenc_cfg.codectype == VEN_CODEC_H264)
+ {
+ if(eProfile == OMX_VIDEO_AVCProfileBaseline)
+ {
+ requested_profile.profile = VEN_PROFILE_H264_BASELINE;
+ }
+ else if(eProfile == OMX_VIDEO_AVCProfileMain)
+ {
+ requested_profile.profile = VEN_PROFILE_H264_MAIN;
+ }
+ else if(eProfile == OMX_VIDEO_AVCProfileHigh)
+ {
+ requested_profile.profile = VEN_PROFILE_H264_HIGH;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\nERROR: Unsupported H.264 profile = %u",
+ requested_profile.profile);
+ return false;
+ }
+ //profile level
+ switch(eLevel)
+ {
+ case OMX_VIDEO_AVCLevel1:
+ requested_level.level = VEN_LEVEL_H264_1;
+ break;
+ case OMX_VIDEO_AVCLevel1b:
+ requested_level.level = VEN_LEVEL_H264_1b;
+ break;
+ case OMX_VIDEO_AVCLevel11:
+ requested_level.level = VEN_LEVEL_H264_1p1;
+ break;
+ case OMX_VIDEO_AVCLevel12:
+ requested_level.level = VEN_LEVEL_H264_1p2;
+ break;
+ case OMX_VIDEO_AVCLevel13:
+ requested_level.level = VEN_LEVEL_H264_1p3;
+ break;
+ case OMX_VIDEO_AVCLevel2:
+ requested_level.level = VEN_LEVEL_H264_2;
+ break;
+ case OMX_VIDEO_AVCLevel21:
+ requested_level.level = VEN_LEVEL_H264_2p1;
+ break;
+ case OMX_VIDEO_AVCLevel22:
+ requested_level.level = VEN_LEVEL_H264_2p2;
+ break;
+ case OMX_VIDEO_AVCLevel3:
+ requested_level.level = VEN_LEVEL_H264_3;
+ break;
+ case OMX_VIDEO_AVCLevel31:
+ requested_level.level = VEN_LEVEL_H264_3p1;
+ break;
+ default :
+ return false;
+ break;
+ }
+ }
+
+ if(!m_profile_set)
+ {
+ ioctl_msg.inputparam = (void*)&requested_profile;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_CODEC_PROFILE,(void*)&ioctl_msg)< 0)
+ {
+ DEBUG_PRINT_LOW("\nERROR: Request for setting profile failed");
+ return false;
+ }
+ codec_profile.profile = requested_profile.profile;
+ m_profile_set = true;
+ }
+
+ if(!m_level_set)
+ {
+ ioctl_msg.inputparam = (void*)&requested_level;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,(void*)&ioctl_msg)< 0)
+ {
+ DEBUG_PRINT_LOW("\nERROR: Request for setting profile level failed");
+ return false;
+ }
+ profile_level.level = requested_level.level;
+ m_level_set = true;
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames)
+{
+ venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_intraperiod intra_period;
+
+ DEBUG_PRINT_LOW("\n venc_set_intra_period: nPFrames = %u",
+ nPFrames);
+ intra_period.num_pframes = nPFrames;
+ ioctl_msg.inputparam = (void*)&intra_period;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_PERIOD,(void*)&ioctl_msg)< 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed");
+ return false;
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate)
+{
+ venc_ioctl_msg ioctl_msg = {NULL, NULL};
+ struct venc_targetbitrate bit_rate;
+
+ DEBUG_PRINT_LOW("\n venc_set_target_bitrate: bitrate = %u",
+ nTargetBitrate);
+ bit_rate.target_bitrate = nTargetBitrate ;
+ ioctl_msg.inputparam = (void*)&bit_rate;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_TARGET_BITRATE,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting bit rate failed");
+ return false;
+ }
+ m_sVenc_cfg.targetbitrate = nTargetBitrate;
+ m_level_set = false;
+ if(venc_set_profile_level(0, 0))
+ {
+ DEBUG_PRINT_HIGH("\n %s(): Dynamic Profile/Level setting success",
+ __func__);
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate)
+{
+ venc_ioctl_msg ioctl_msg = {NULL, NULL};
+ struct venc_framerate frame_rate;
+
+ DEBUG_PRINT_LOW("\n venc_set_encode_framerate: framerate(Q16) = %u",
+ encode_framerate);
+ frame_rate.fps_numerator = 30;
+ if((encode_framerate >> 16)== 30)
+ {
+ frame_rate.fps_denominator = 1;
+ }
+ else if((encode_framerate >>16) == 15)
+ {
+ frame_rate.fps_denominator = 2;
+ }
+ else if((encode_framerate >> 16)== 7.5)
+ {
+ frame_rate.fps_denominator = 4;
+ }
+ else
+ {
+ frame_rate.fps_denominator = 1;
+ }
+
+ ioctl_msg.inputparam = (void*)&frame_rate;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl(m_nDriver_fd, VEN_IOCTL_SET_FRAME_RATE,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting framerate failed");
+ return false;
+ }
+
+ m_sVenc_cfg.fps_den = frame_rate.fps_denominator;
+ m_sVenc_cfg.fps_num = frame_rate.fps_numerator;
+ m_level_set = false;
+ if(venc_set_profile_level(0, 0))
+ {
+ DEBUG_PRINT_HIGH("\n %s(): Dynamic Profile/Level setting success",
+ __func__);
+ }
+
+ return true;
+}
+
+bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)
+{
+ venc_ioctl_msg ioctl_msg = {NULL, NULL};
+ DEBUG_PRINT_LOW("\n venc_set_color_format: color_format = %u ", color_format);
+
+ if(color_format == OMX_COLOR_FormatYUV420SemiPlanar)
+ {
+ m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12;
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nWARNING: Unsupported Color format [%d]", color_format);
+ m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12;
+ DEBUG_PRINT_HIGH("\n Default color format YUV420SemiPlanar is set");
+ }
+ ioctl_msg.inputparam = (void*)&m_sVenc_cfg;
+ ioctl_msg.outputparam = NULL;
+ if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_BASE_CFG, (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting color format failed");
+ return false;
+ }
+ return true;
+}
+
+bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)
+{
+ DEBUG_PRINT_LOW("\n venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh);
+ if(intra_vop_refresh == OMX_TRUE)
+ {
+ if(ioctl(m_nDriver_fd, VEN_IOCTL_CMD_REQUEST_IFRAME, NULL) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting Intra VOP Refresh failed");
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_ERROR("\nERROR: VOP Refresh is False, no effect");
+ }
+ return true;
+}
+
+bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
+{
+ venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ bool status = true;
+
+ //rate control
+ switch(eControlRate)
+ {
+ case OMX_Video_ControlRateDisable:
+ rate_ctrl.rcmode = VEN_RC_OFF;
+ break;
+ case OMX_Video_ControlRateVariableSkipFrames:
+ rate_ctrl.rcmode = VEN_RC_VBR_VFR;
+ break;
+ case OMX_Video_ControlRateVariable:
+ rate_ctrl.rcmode = VEN_RC_VBR_CFR;
+ break;
+ case OMX_Video_ControlRateConstantSkipFrames:
+ rate_ctrl.rcmode = VEN_RC_CBR_VFR;
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ if(status)
+ {
+ ioctl_msg.inputparam = (void*)&rate_ctrl;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting rate control failed");
+ status = false;
+ }
+ }
+ return status;
+}
+
+bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
+{
+ bool status = true;
+ if(eProfile == NULL || eLevel == NULL)
+ {
+ return false;
+ }
+
+ if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4)
+ {
+ switch(codec_profile.profile)
+ {
+ case VEN_PROFILE_MPEG4_SP:
+ *eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ break;
+ case VEN_PROFILE_MPEG4_ASP:
+ *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ break;
+ default:
+ *eProfile = OMX_VIDEO_MPEG4ProfileMax;
+ status = false;
+ break;
+ }
+
+ if(!status)
+ {
+ return status;
+ }
+
+ //profile level
+ switch(profile_level.level)
+ {
+ case VEN_LEVEL_MPEG4_0:
+ *eLevel = OMX_VIDEO_MPEG4Level0;
+ break;
+ case VEN_LEVEL_MPEG4_1:
+ *eLevel = OMX_VIDEO_MPEG4Level1;
+ break;
+ case VEN_LEVEL_MPEG4_2:
+ *eLevel = OMX_VIDEO_MPEG4Level2;
+ break;
+ case VEN_LEVEL_MPEG4_3:
+ *eLevel = OMX_VIDEO_MPEG4Level3;
+ break;
+ case VEN_LEVEL_MPEG4_4:
+ *eLevel = OMX_VIDEO_MPEG4Level4a;
+ break;
+ case VEN_LEVEL_MPEG4_5:
+ case VEN_LEVEL_MPEG4_6:
+ *eLevel = OMX_VIDEO_MPEG4Level5;
+ break;
+ default:
+ *eLevel = OMX_VIDEO_MPEG4LevelMax;
+ status = false;
+ break;
+ }
+ }
+ else if(m_sVenc_cfg.codectype == VEN_CODEC_H263)
+ {
+ if(codec_profile.profile == VEN_PROFILE_H263_BASELINE)
+ {
+ *eProfile = OMX_VIDEO_H263ProfileBaseline;
+ }
+ else
+ {
+ *eProfile = OMX_VIDEO_H263ProfileMax;
+ return false;
+ }
+ switch(profile_level.level)
+ {
+ case VEN_LEVEL_H263_10:
+ *eLevel = OMX_VIDEO_H263Level10;
+ break;
+ case VEN_LEVEL_H263_20:
+ *eLevel = OMX_VIDEO_H263Level20;
+ break;
+ case VEN_LEVEL_H263_30:
+ *eLevel = OMX_VIDEO_H263Level30;
+ break;
+ case VEN_LEVEL_H263_40:
+ *eLevel = OMX_VIDEO_H263Level40;
+ break;
+ case VEN_LEVEL_H263_45:
+ *eLevel = OMX_VIDEO_H263Level45;
+ break;
+ case VEN_LEVEL_H263_50:
+ *eLevel = OMX_VIDEO_H263Level50;
+ break;
+ case VEN_LEVEL_H263_60:
+ *eLevel = OMX_VIDEO_H263Level60;
+ break;
+ case VEN_LEVEL_H263_70:
+ *eLevel = OMX_VIDEO_H263Level70;
+ break;
+ default:
+ *eLevel = OMX_VIDEO_H263LevelMax;
+ status = false;
+ break;
+ }
+ }
+ else if(m_sVenc_cfg.codectype == VEN_CODEC_H264)
+ {
+ switch(codec_profile.profile)
+ {
+ case VEN_PROFILE_H264_BASELINE:
+ *eProfile = OMX_VIDEO_AVCProfileBaseline;
+ break;
+ case VEN_PROFILE_H264_MAIN:
+ *eProfile = OMX_VIDEO_AVCProfileMain;
+ break;
+ case VEN_PROFILE_H264_HIGH:
+ *eProfile = OMX_VIDEO_AVCProfileHigh;
+ break;
+ default:
+ *eProfile = OMX_VIDEO_AVCProfileMax;
+ status = false;
+ break;
+ }
+
+ if(!status)
+ {
+ return status;
+ }
+
+ switch(profile_level.level)
+ {
+ case VEN_LEVEL_H264_1:
+ *eLevel = OMX_VIDEO_AVCLevel1;
+ break;
+ case VEN_LEVEL_H264_1b:
+ *eLevel = OMX_VIDEO_AVCLevel1b;
+ break;
+ case VEN_LEVEL_H264_1p1:
+ *eLevel = OMX_VIDEO_AVCLevel11;
+ break;
+ case VEN_LEVEL_H264_1p2:
+ *eLevel = OMX_VIDEO_AVCLevel12;
+ break;
+ case VEN_LEVEL_H264_1p3:
+ *eLevel = OMX_VIDEO_AVCLevel13;
+ break;
+ case VEN_LEVEL_H264_2:
+ *eLevel = OMX_VIDEO_AVCLevel2;
+ break;
+ case VEN_LEVEL_H264_2p1:
+ *eLevel = OMX_VIDEO_AVCLevel21;
+ break;
+ case VEN_LEVEL_H264_2p2:
+ *eLevel = OMX_VIDEO_AVCLevel22;
+ break;
+ case VEN_LEVEL_H264_3:
+ *eLevel = OMX_VIDEO_AVCLevel3;
+ break;
+ case VEN_LEVEL_H264_3p1:
+ *eLevel = OMX_VIDEO_AVCLevel31;
+ break;
+ default :
+ *eLevel = OMX_VIDEO_AVCLevelMax;
+ status = false;
+ break;
+ }
+ }
+ return status;
+}
+
+bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel)
+{
+ OMX_U32 new_profile = 0, new_level = 0;
+ unsigned const int *profile_tbl = NULL;
+ OMX_U32 mb_per_frame, mb_per_sec;
+ bool profile_level_found = false;
+
+ DEBUG_PRINT_LOW("\n Init profile table for respective codec");
+ //validate the ht,width,fps,bitrate and set the appropriate profile and level
+ if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4)
+ {
+ if(*eProfile == 0)
+ {
+ if(!m_profile_set)
+ {
+ *eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ }
+ else
+ {
+ switch(codec_profile.profile)
+ {
+ case VEN_PROFILE_MPEG4_ASP:
+ *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ break;
+ case VEN_PROFILE_MPEG4_SP:
+ *eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ break;
+ default:
+ DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__);
+ return false;
+ }
+ }
+ }
+
+ if(*eLevel == 0 && !m_level_set)
+ {
+ *eLevel = OMX_VIDEO_MPEG4LevelMax;
+ }
+
+ if(*eProfile == OMX_VIDEO_MPEG4ProfileSimple)
+ {
+ profile_tbl = (unsigned int const *)mpeg4_profile_level_table;
+ }
+ else if(*eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple)
+ {
+ profile_tbl = (unsigned int const *)
+ (&mpeg4_profile_level_table[MPEG4_ASP_START]);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Unsupported MPEG4 profile type %lu", *eProfile);
+ return false;
+ }
+ }
+ else if(m_sVenc_cfg.codectype == VEN_CODEC_H264)
+ {
+ if(*eProfile == 0)
+ {
+ if(!m_profile_set)
+ {
+ *eProfile = OMX_VIDEO_AVCProfileBaseline;
+ }
+ else
+ {
+ switch(codec_profile.profile)
+ {
+ case VEN_PROFILE_H264_BASELINE:
+ *eProfile = OMX_VIDEO_AVCProfileBaseline;
+ break;
+ case VEN_PROFILE_H264_MAIN:
+ *eProfile = OMX_VIDEO_AVCProfileMain;
+ break;
+ case VEN_PROFILE_H264_HIGH:
+ *eProfile = OMX_VIDEO_AVCProfileHigh;
+ break;
+ default:
+ DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__);
+ return false;
+ }
+ }
+ }
+
+ if(*eLevel == 0 && !m_level_set)
+ {
+ *eLevel = OMX_VIDEO_AVCLevelMax;
+ }
+
+ if(*eProfile == OMX_VIDEO_AVCProfileBaseline)
+ {
+ profile_tbl = (unsigned int const *)h264_profile_level_table;
+ }
+ else if(*eProfile == OMX_VIDEO_AVCProfileHigh)
+ {
+ profile_tbl = (unsigned int const *)
+ (&h264_profile_level_table[H264_HP_START]);
+ }
+ else if(*eProfile == OMX_VIDEO_AVCProfileMain)
+ {
+ profile_tbl = (unsigned int const *)
+ (&h264_profile_level_table[H264_MP_START]);
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Unsupported AVC profile type %lu", *eProfile);
+ return false;
+ }
+ }
+ else if(m_sVenc_cfg.codectype == VEN_CODEC_H263)
+ {
+ if(*eProfile == 0)
+ {
+ if(!m_profile_set)
+ {
+ *eProfile = OMX_VIDEO_H263ProfileBaseline;
+ }
+ else
+ {
+ switch(codec_profile.profile)
+ {
+ case VEN_PROFILE_H263_BASELINE:
+ *eProfile = OMX_VIDEO_H263ProfileBaseline;
+ break;
+ default:
+ DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__);
+ return false;
+ }
+ }
+ }
+
+ if(*eLevel == 0 && !m_level_set)
+ {
+ *eLevel = OMX_VIDEO_H263LevelMax;
+ }
+
+ if(*eProfile == OMX_VIDEO_H263ProfileBaseline)
+ {
+ profile_tbl = (unsigned int const *)h263_profile_level_table;
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Unsupported H.263 profile type %lu", *eProfile);
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT_LOW("\n Invalid codec type");
+ return false;
+ }
+
+ mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)*
+ ((m_sVenc_cfg.input_width + 15)>> 4);
+
+ mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den;
+
+ do{
+ if(mb_per_frame <= (int)profile_tbl[0])
+ {
+ if(mb_per_sec <= (int)profile_tbl[1])
+ {
+ if(m_sVenc_cfg.targetbitrate <= (int)profile_tbl[2])
+ {
+ DEBUG_PRINT_LOW("\n Appropriate profile/level found \n");
+ new_level = (int)profile_tbl[3];
+ new_profile = (int)profile_tbl[4];
+ profile_level_found = true;
+ break;
+ }
+ }
+ }
+ profile_tbl = profile_tbl + 5;
+ }while(profile_tbl[0] != 0);
+
+ if ((profile_level_found != true) || (new_profile != *eProfile)
+ || (new_level > *eLevel))
+ {
+ DEBUG_PRINT_LOW("\n ERROR: Unsupported profile/level\n");
+ return false;
+ }
+
+ if((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax)
+ || (*eLevel == OMX_VIDEO_H263LevelMax))
+ {
+ *eLevel = new_level;
+ }
+ DEBUG_PRINT_HIGH("%s: Returning with eProfile = %lu"
+ "Level = %lu", __func__, *eProfile, *eLevel);
+
+ return true;
+}
+bool venc_dev::venc_set_multislice_cfg(OMX_VIDEO_AVCSLICEMODETYPE eSliceMode)
+{
+ venc_ioctl_msg ioctl_msg = {NULL, NULL};
+ bool status = true;
+ DEBUG_PRINT_LOW("\n %s(): eSliceMode = %u", __func__, eSliceMode);
+ switch(eSliceMode)
+ {
+ case OMX_VIDEO_SLICEMODE_AVCDefault:
+ DEBUG_PRINT_LOW("\n %s(): OMX_VIDEO_SLICEMODE_AVCDefault", __func__);
+ multislice_cfg.mslice_mode = VEN_MSLICE_OFF;
+ multislice_cfg.mslice_size = 0;
+ break;
+ case OMX_VIDEO_SLICEMODE_AVCMBSlice:
+ DEBUG_PRINT_LOW("\n %s(): OMX_VIDEO_SLICEMODE_AVCMBSlice", __func__);
+ multislice_cfg.mslice_mode = VEN_MSLICE_CNT_MB;
+ multislice_cfg.mslice_size = ((m_sVenc_cfg.input_width/16) *
+ (m_sVenc_cfg.input_height/16))/2;
+ break;
+ case OMX_VIDEO_SLICEMODE_AVCByteSlice:
+ DEBUG_PRINT_LOW("\n %s(): OMX_VIDEO_SLICEMODE_AVCByteSlice", __func__);
+ multislice_cfg.mslice_mode = VEN_MSLICE_CNT_BYTE;
+ multislice_cfg.mslice_size = 1920;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("\n %s(): Unsupported SliceMode = %u",__func__, eSliceMode);
+ status = false;
+ break;
+ }
+ DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode,
+ multislice_cfg.mslice_size);
+
+ if(status)
+ {
+ ioctl_msg.inputparam = (void*)&multislice_cfg;
+ ioctl_msg.outputparam = NULL;
+ if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed");
+ status = false;
+ }
+ }
+ return status;
+}
diff --git a/omx/mm-video/vidc/venc/test/camera_test.cpp b/omx/mm-video/vidc/venc/test/camera_test.cpp
new file mode 100644
index 0000000..8de4337
--- /dev/null
+++ b/omx/mm-video/vidc/venc/test/camera_test.cpp
@@ -0,0 +1,93 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "camera_test.h"
+// #include "camera_class.h"
+
+EXTERN_C_START
+
+// static android::Camera* pCamera = NULL;
+
+int CameraTest_Initialize(int nFrameRate,
+ int nFrameWidth,
+ int nFrameHeight,
+ CameraPreviewCallback pfnPreviewCallback)
+{
+ int result = 0;
+
+// pCamera = new android::Camera;
+// if (!pCamera)
+// return 1;
+
+// pCamera->init_camera(nFrameWidth,
+// nFrameHeight,
+// nFrameRate,
+// pfnPreviewCallback);
+
+ return result;
+}
+
+int CameraTest_Run()
+{
+ int result = 0;
+
+// if (pCamera)
+// pCamera->startPreview();
+// else
+// return 1;
+
+ return result;
+}
+
+int CameraTest_ReleaseFrame(void* pPhys, void* pVirt)
+{
+ int result = 0;
+
+// if (pCamera)
+// pCamera->releaseFrame(pPhys, pVirt);
+// else
+// return 1;
+
+ return result;
+}
+
+int CameraTest_Exit()
+{
+ int result = 0;
+
+// if (pCamera)
+// {
+// pCamera->stopPreview();
+// delete pCamera;
+// }
+// pCamera = NULL;
+
+ return result;
+}
+
+
+EXTERN_C_END
diff --git a/omx/mm-video/vidc/venc/test/fb_test.c b/omx/mm-video/vidc/venc/test/fb_test.c
new file mode 100644
index 0000000..c637989
--- /dev/null
+++ b/omx/mm-video/vidc/venc/test/fb_test.c
@@ -0,0 +1,48 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "fb_test.h"
+
+int FBTest_Initialize(int nFrameWidth,
+ int nFrameHeight)
+{
+ return 0;
+}
+int FBTest_DisplayImage(int nPmemFd, int nOffset)
+{
+ return 0;
+}
+
+int FBTest_Exit()
+{
+ return 0;
+}
+
+int FBTest_RunTest()
+{
+ return 0;
+}
diff --git a/omx/mm-video/vidc/venc/test/queue.c b/omx/mm-video/vidc/venc/test/queue.c
new file mode 100644
index 0000000..c04db64
--- /dev/null
+++ b/omx/mm-video/vidc/venc/test/queue.c
@@ -0,0 +1,174 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "queue.h"
+
+int check_if_queue_empty ( unsigned int queuetocheck, void* queuecontext )
+{
+ struct video_queue_context *ptr_q = NULL;
+ /*
+ * queuetocheck - 0 command queue
+ * queuetocheck - 1 data queue
+ */
+ if ( queuecontext == NULL || (queuetocheck > 1 ) )
+ {
+ return 1;
+ }
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ if (queuetocheck == 0)
+ {
+ if (ptr_q->read_comq == ptr_q->write_comq)
+ {
+ return 1;
+ }
+ }
+ else if (queuetocheck == 1)
+ {
+ if (ptr_q->write_dataq == ptr_q->read_dataq)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+
+struct video_msgq * queue_get_cmd (void* queuecontext )
+{
+ struct video_queue_context *ptr_q = NULL;
+ struct video_msgq *pitem = NULL;
+
+ if( NULL == queuecontext )
+ {
+ printf("\n queue_get_cmd: Invalid Input parameter\n");
+ return NULL;
+ }
+
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ /* Wait on the semaphore till it is released */
+ sem_wait(&ptr_q->sem_message);
+
+ /* Lock the mutex to protect the critical section */
+ pthread_mutex_lock(&ptr_q->mutex);
+
+ if (ptr_q->read_comq != ptr_q->write_comq)
+ {
+ pitem = &ptr_q->ptr_cmdq [ptr_q->read_comq];
+ ptr_q->read_comq = (ptr_q->read_comq + 1) % \
+ ptr_q->commandq_size;
+ }
+ else if (ptr_q->write_dataq != ptr_q->read_dataq)
+ {
+ pitem = &ptr_q->ptr_dataq [ptr_q->read_dataq];
+ ptr_q->read_dataq = (ptr_q->read_dataq + 1) % \
+ ptr_q->dataq_size;
+ }
+
+ /* Unlock the mutex to release the critical section */
+ pthread_mutex_unlock(&ptr_q->mutex);
+
+ return pitem;
+}
+
+
+int queue_post_cmdq ( void* queuecontext,
+ struct video_msgq *pitem
+ )
+{
+ struct video_queue_context *ptr_q = NULL;
+
+ if (pitem == NULL || queuecontext == NULL)
+ {
+ return -1;
+ }
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ /* Lock the mutex to protect the critical section */
+ pthread_mutex_lock(&ptr_q->mutex);
+
+ if ((ptr_q->write_comq + 1) % ptr_q->commandq_size == ptr_q->read_comq)
+ {
+ printf("\n QUEUE is FULL");
+ return 0;
+ }
+ else
+ {
+ /* Store the command in the Message Queue & increment write offset */
+ memcpy ( &ptr_q->ptr_cmdq [ptr_q->write_comq],pitem, \
+ sizeof (struct video_msgq));
+ ptr_q->write_comq = (ptr_q->write_comq + 1) % ptr_q->commandq_size;
+ }
+
+ /* Unlock the mutex to release the critical section */
+ pthread_mutex_unlock(&ptr_q->mutex);
+
+ /* Post the semaphore */
+ sem_post(&ptr_q->sem_message);
+ return 1;
+}
+
+
+int queue_post_dataq ( void *queuecontext,
+ struct video_msgq *pitem
+ )
+{
+ struct video_queue_context *ptr_q = NULL;
+
+ if (pitem == NULL || queuecontext == NULL)
+ {
+ return -1;
+ }
+ ptr_q = (struct video_queue_context *)queuecontext;
+
+ /* Lock the mutex to protect the critical section */
+ pthread_mutex_lock(&ptr_q->mutex);
+
+ if ((ptr_q->write_dataq + 1) % ptr_q->dataq_size == ptr_q->read_dataq)
+ {
+ printf("\n QUEUE is FULL");
+ return 0;
+ }
+ else
+ {
+ /* Store the command in the Message Queue & increment write offset */
+ memcpy ( &ptr_q->ptr_dataq [ptr_q->write_dataq],pitem, \
+ sizeof (struct video_msgq));
+ ptr_q->write_dataq = (ptr_q->write_dataq + 1) % ptr_q->dataq_size;
+ }
+
+ /* Unlock the mutex to release the critical section */
+ pthread_mutex_unlock(&ptr_q->mutex);
+
+ /* Post the semaphore */
+ sem_post(&ptr_q->sem_message);
+ return 1;
+
+}
diff --git a/omx/mm-video/vidc/venc/test/venc_test.cpp b/omx/mm-video/vidc/venc/test/venc_test.cpp
new file mode 100644
index 0000000..12cff8d
--- /dev/null
+++ b/omx/mm-video/vidc/venc/test/venc_test.cpp
@@ -0,0 +1,1635 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ V E N C _ T E S T. C P P
+
+DESCRIPTION
+
+ This is the OMX test app .
+
+REFERENCES
+
+============================================================================*/
+
+//usage
+// FILE QVGA MP4 24 384000 100 enc_qvga.yuv QVGA_24.m4v
+// FILE QCIF MP4 15 96000 0 foreman.qcif.yuv output_qcif.m4v
+// FILE VGA MP4 24 1200000 218 enc_vga.yuv vga_output.m4v
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+//#include <sys/time.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <string.h>
+//#include <sys/stat.h>
+#include "OMX_QCOMExtns.h"
+#include "OMX_Core.h"
+
+
+#define QCOM_EXT 1
+
+#include "OMX_Core.h"
+#include "OMX_Video.h"
+#include "OMX_Component.h"
+#include "camera_test.h"
+#include "fb_test.h"
+#include "venc_util.h"
+
+//////////////////////////
+// MACROS
+//////////////////////////
+
+#define CHK(result) if (result != OMX_ErrorNone) { E("*************** error *************"); exit(0); }
+#define TEST_LOG
+#ifdef VENC_SYSLOG
+#include "cutils/log.h"
+/// Debug message macro
+#define D(fmt, ...) LOGE("venc_test Debug %s::%d "fmt"\n", \
+ __FUNCTION__, __LINE__, \
+ ## __VA_ARGS__)
+
+/// Error message macro
+#define E(fmt, ...) LOGE("venc_test Error %s::%d "fmt"\n", \
+ __FUNCTION__, __LINE__, \
+ ## __VA_ARGS__)
+
+#else
+ #ifdef TEST_LOG
+ #define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d "fmt"\n", \
+ __FUNCTION__, __LINE__, \
+ ## __VA_ARGS__)
+
+ /// Error message macro
+ #define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d "fmt"\n", \
+ __FUNCTION__, __LINE__, \
+ ## __VA_ARGS__)
+ #else
+ #define D(fmt, ...)
+ #define E(fmt, ...)
+ #endif
+
+#endif
+
+//////////////////////////
+// CONSTANTS
+//////////////////////////
+static const int MAX_MSG = 100;
+//#warning do not hardcode these use port definition
+static const int PORT_INDEX_IN = 0;
+static const int PORT_INDEX_OUT = 1;
+
+static const int NUM_IN_BUFFERS = 10;
+static const int NUM_OUT_BUFFERS = 10;
+
+unsigned int num_in_buffers = 0;
+unsigned int num_out_buffers = 0;
+
+//////////////////////////
+/* MPEG4 profile and level table*/
+static const unsigned int mpeg4_profile_level_table[][5]=
+{
+ /*max mb per frame, max mb per sec, max bitrate, level, profile*/
+ {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple},
+ {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple},
+ {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple},
+ {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple},
+ {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple},
+ {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
+ {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
+
+ {99,2970,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {99,2970,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
+ {0 ,0 ,0 ,0 ,0 }
+};
+
+/* H264 profile and level table*/
+static const unsigned int h264_profile_level_table[][5]=
+{
+ /*max mb per frame, max mb per sec, max bitrate, level, profile*/
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline},
+ {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline},
+ {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline},
+ {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline},
+ {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline},
+ {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline},
+ {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline},
+ {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline},
+ {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline},
+ {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline},
+
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh},
+ {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh},
+ {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh},
+ {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh},
+ {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh},
+ {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh},
+ {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh},
+ {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh},
+ {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh},
+ {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh},
+ {0 ,0 ,0 ,0 }
+};
+
+/* H263 profile and level table*/
+static const unsigned int h263_profile_level_table[][5]=
+{
+ /*max mb per frame, max mb per sec, max bitrate, level, profile*/
+ {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline},
+ {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline},
+ {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline},
+ {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline},
+ {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline},
+ {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline},
+ {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
+ {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
+ {0 , 0 , 0 , 0 }
+};
+
+//////////////////////////
+// TYPES
+//////////////////////////
+struct ProfileType
+{
+ OMX_VIDEO_CODINGTYPE eCodec;
+ OMX_VIDEO_MPEG4LEVELTYPE eLevel;
+ OMX_VIDEO_CONTROLRATETYPE eControlRate;
+ OMX_VIDEO_AVCSLICEMODETYPE eSliceMode;
+ OMX_U32 nFrameWidth;
+ OMX_U32 nFrameHeight;
+ OMX_U32 nFrameBytes;
+ OMX_U32 nBitrate;
+ OMX_U32 nFramerate;
+ char* cInFileName;
+ char* cOutFileName;
+};
+
+enum MsgId
+{
+ MSG_ID_OUTPUT_FRAME_DONE,
+ MSG_ID_INPUT_FRAME_DONE,
+ MSG_ID_MAX
+};
+union MsgData
+{
+ struct
+ {
+ OMX_BUFFERHEADERTYPE* pBuffer;
+ } sBitstreamData;
+};
+struct Msg
+{
+ MsgId id;
+ MsgData data;
+};
+struct MsgQ
+{
+ Msg q[MAX_MSG];
+ int head;
+ int size;
+};
+
+enum Mode
+{
+ MODE_PREVIEW,
+ MODE_DISPLAY,
+ MODE_PROFILE,
+ MODE_FILE_ENCODE,
+ MODE_LIVE_ENCODE
+};
+
+//////////////////////////
+// MODULE VARS
+//////////////////////////
+static pthread_mutex_t m_mutex;
+static pthread_cond_t m_signal;
+static MsgQ m_sMsgQ;
+
+//#warning determine how many buffers we really have
+OMX_STATETYPE m_eState = OMX_StateInvalid;
+OMX_COMPONENTTYPE m_sComponent;
+OMX_HANDLETYPE m_hHandle = NULL;
+OMX_BUFFERHEADERTYPE* m_pOutBuffers[NUM_OUT_BUFFERS] = {NULL};
+OMX_BUFFERHEADERTYPE* m_pInBuffers[NUM_IN_BUFFERS] = {NULL};
+OMX_BOOL m_bInFrameFree[NUM_IN_BUFFERS];
+
+ProfileType m_sProfile;
+
+static int m_nFramePlay = 0;
+static int m_eMode = MODE_PREVIEW;
+static int m_nInFd = -1;
+static int m_nOutFd = -1;
+static int m_nTimeStamp = 0;
+static int m_nFrameIn = 0; // frames pushed to encoder
+static int m_nFrameOut = 0; // frames returned by encoder
+static int m_nAVCSliceMode = 0;
+
+static bool m_bWatchDogKicked = false;
+
+/* Statistics Logging */
+static long long tot_bufsize = 0;
+int ebd_cnt=0, fbd_cnt=0;
+
+//////////////////////////
+// MODULE FUNCTIONS
+//////////////////////////
+
+void* PmemMalloc(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, int nSize)
+{
+ void *pvirt = NULL;
+
+ if (!pMem)
+ return NULL;
+
+ pMem->pmem_fd = open("/dev/pmem_adsp", O_RDWR);
+ if ((int)(pMem->pmem_fd) < 0)
+ return NULL;
+ nSize = (nSize + 4095) & (~4095);
+ pMem->offset = 0;
+ pvirt = mmap(NULL, nSize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, pMem->pmem_fd, pMem->offset);
+ if (pvirt == (void*) MAP_FAILED)
+ {
+ close(pMem->pmem_fd);
+ pMem->pmem_fd = -1;
+ return NULL;
+ }
+ D("allocated pMem->fd = %d pvirt=0x%x, pMem->phys=0x%x, size = %d", pMem->pmem_fd,
+ pvirt, pMem->offset, nSize);
+ return pvirt;
+}
+
+int PmemFree(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, void* pvirt, int nSize)
+{
+ if (!pMem || !pvirt)
+ return -1;
+
+ nSize = (nSize + 4095) & (~4095);
+ munmap(pvirt, nSize);
+ close(pMem->pmem_fd);
+ pMem->pmem_fd = -1;
+ return 0;
+}
+
+void SetState(OMX_STATETYPE eState)
+{
+#define GOTO_STATE(eState) \
+ case eState: \
+ { \
+ D("Going to state " # eState"..."); \
+ OMX_SendCommand(m_hHandle, \
+ OMX_CommandStateSet, \
+ (OMX_U32) eState, \
+ NULL); \
+ while (m_eState != eState) \
+ { \
+ sleep(1); \
+ } \
+ D("Now in state " # eState); \
+ break; \
+ }
+
+ switch (eState)
+ {
+ GOTO_STATE(OMX_StateLoaded);
+ GOTO_STATE(OMX_StateIdle);
+ GOTO_STATE(OMX_StateExecuting);
+ GOTO_STATE(OMX_StateInvalid);
+ GOTO_STATE(OMX_StateWaitForResources);
+ GOTO_STATE(OMX_StatePause);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE ConfigureEncoder()
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ unsigned const int *profile_tbl = NULL;
+ OMX_U32 mb_per_sec, mb_per_frame;
+ bool profile_level_found = false;
+ OMX_U32 eProfile,eLevel;
+
+ OMX_PARAM_PORTDEFINITIONTYPE portdef; // OMX_IndexParamPortDefinition
+#ifdef QCOM_EXT
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE qPortDefnType;
+#endif
+
+ portdef.nPortIndex = (OMX_U32) 0; // input
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamPortDefinition,
+ &portdef);
+ E("\n OMX_IndexParamPortDefinition Get Paramter on input port");
+ CHK(result);
+ portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth;
+ portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight;
+
+ E ("\n Height %d width %d bit rate %d",portdef.format.video.nFrameHeight
+ ,portdef.format.video.nFrameWidth,portdef.format.video.nBitrate);
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamPortDefinition,
+ &portdef);
+ E("\n OMX_IndexParamPortDefinition Set Paramter on input port");
+ CHK(result);
+ portdef.nPortIndex = (OMX_U32) 1; // output
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamPortDefinition,
+ &portdef);
+ E("\n OMX_IndexParamPortDefinition Get Paramter on output port");
+ CHK(result);
+ portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth;
+ portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight;
+ portdef.format.video.nBitrate = m_sProfile.nBitrate;
+ portdef.format.video.xFramerate = m_sProfile.nFramerate << 16;
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamPortDefinition,
+ &portdef);
+ E("\n OMX_IndexParamPortDefinition Set Paramter on output port");
+ CHK(result);
+
+#ifdef QCOM_EXT
+
+qPortDefnType.nPortIndex = PORT_INDEX_IN;
+qPortDefnType.nMemRegion = OMX_QCOM_MemRegionEBI1;
+qPortDefnType.nSize = sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
+
+result = OMX_SetParameter(m_hHandle,
+ (OMX_INDEXTYPE)OMX_QcomIndexPortDefn,
+ &qPortDefnType);
+
+#endif
+ //validate the ht,width,fps,bitrate and set the appropriate profile and level
+ if(m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ profile_tbl = (unsigned int const *)mpeg4_profile_level_table;
+ }
+ else if(m_sProfile.eCodec == OMX_VIDEO_CodingAVC)
+ {
+ profile_tbl = (unsigned int const *)h264_profile_level_table;
+ }
+ else if(m_sProfile.eCodec == OMX_VIDEO_CodingH263)
+ {
+ profile_tbl = (unsigned int const *)h263_profile_level_table;
+ }
+
+ mb_per_frame = ((m_sProfile.nFrameHeight+15)>>4)*
+ ((m_sProfile.nFrameWidth+15)>>4);
+
+ mb_per_sec = mb_per_frame*(m_sProfile.nFramerate);
+
+ do{
+ if(mb_per_frame <= (int)profile_tbl[0])
+ {
+ if(mb_per_sec <= (int)profile_tbl[1])
+ {
+ if(m_sProfile.nBitrate <= (int)profile_tbl[2])
+ {
+ eLevel = (int)profile_tbl[3];
+ eProfile = (int)profile_tbl[4];
+ E("\n profile and level found \n");
+ profile_level_found = true;
+ break;
+ }
+ }
+ }
+ profile_tbl = profile_tbl + 5;
+ }while(profile_tbl[0] != 0);
+
+ if ( profile_level_found != true )
+ {
+ E("\n Error: Unsupported profile/level\n");
+ return OMX_ErrorNone;
+ }
+
+ if (m_sProfile.eCodec == OMX_VIDEO_CodingH263)
+ {
+ D("Configuring H263...");
+
+ OMX_VIDEO_PARAM_H263TYPE h263;
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamVideoH263,
+ &h263);
+ CHK(result);
+ h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+ h263.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period
+ h263.nBFrames = 0;
+ h263.eProfile = (OMX_VIDEO_H263PROFILETYPE)eProfile;
+ h263.eLevel = (OMX_VIDEO_H263LEVELTYPE)eLevel;
+ h263.bPLUSPTYPEAllowed = OMX_FALSE;
+ h263.nAllowedPictureTypes = 2;
+ h263.bForceRoundingTypeToZero = OMX_TRUE; ///@todo determine what this should be
+ h263.nPictureHeaderRepetition = 0; ///@todo determine what this should be
+ h263.nGOBHeaderInterval = 0; ///@todo determine what this should be
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamVideoH263,
+ &h263);
+ }
+ else
+ {
+ D("Configuring MP4/H264...");
+
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE profileLevel; // OMX_IndexParamVideoProfileLevelCurrent
+ profileLevel.eProfile = eProfile;
+ profileLevel.eLevel = eLevel;
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamVideoProfileLevelCurrent,
+ &profileLevel);
+ E("\n OMX_IndexParamVideoProfileLevelCurrent Set Paramter port");
+ CHK(result);
+ //profileLevel.eLevel = (OMX_U32) m_sProfile.eLevel;
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamVideoProfileLevelCurrent,
+ &profileLevel);
+ E("\n OMX_IndexParamVideoProfileLevelCurrent Get Paramter port");
+ D ("\n Profile = %d level = %d",profileLevel.eProfile,profileLevel.eLevel);
+ CHK(result);
+
+ /*OMX_VIDEO_PARAM_MPEG4TYPE mp4;
+
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamVideoMpeg4,
+ &mp4);
+ E("\n OMX_IndexParamVideoMpeg4 Set Paramter port");
+ CHK(result);
+
+ mp4.nTimeIncRes = m_sProfile.nFramerate * 2;
+ mp4.nPFrames = mp4.nTimeIncRes - 1; // intra period
+
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamVideoMpeg4,
+ &mp4);
+ CHK(result);*/
+
+// OMX_VIDEO_PARAM_MPEG4TYPE mp4; // OMX_IndexParamVideoMpeg4
+// result = OMX_GetParameter(m_hHandle,
+// OMX_IndexParamVideoMpeg4,
+// &mp4);
+// CHK(result);
+// mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+// mp4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+// mp4.eLevel = m_sProfile.eLevel;
+// mp4.nSliceHeaderSpacing = 0;
+// mp4.bSVH = OMX_FALSE;
+// mp4.bGov = OMX_FALSE;
+// mp4.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period
+// mp4.bACPred = OMX_TRUE;
+// mp4.nTimeIncRes = m_sProfile.nFramerate * 2; // delta = 2 @ 15 fps
+// mp4.nAllowedPictureTypes = 2; // pframe and iframe
+// result = OMX_SetParameter(m_hHandle,
+// OMX_IndexParamVideoMpeg4,
+// &mp4);
+// CHK(result);
+ }
+
+ if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC)
+ {
+ OMX_VIDEO_PARAM_AVCSLICEFMO avcslicefmo;
+ avcslicefmo.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamVideoSliceFMO,
+ &avcslicefmo);
+ E("\n OMX_IndexParamVideoSliceFMO Get Paramter port");
+ CHK(result);
+
+ avcslicefmo.eSliceMode = m_sProfile.eSliceMode;
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamVideoSliceFMO,
+ &avcslicefmo);
+ E("\n OMX_IndexParamVideoSliceFMO Set Paramter port");
+ CHK(result);
+ }
+
+ OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate
+ bitrate.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamVideoBitrate,
+ &bitrate);
+ E("\n OMX_IndexParamVideoBitrate Get Paramter port");
+ CHK(result);
+ bitrate.eControlRate = m_sProfile.eControlRate;
+ bitrate.nTargetBitrate = m_sProfile.nBitrate;
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamVideoBitrate,
+ &bitrate);
+ E("\n OMX_IndexParamVideoBitrate Set Paramter port");
+ CHK(result);
+
+ OMX_VIDEO_PARAM_PORTFORMATTYPE framerate; // OMX_IndexParamVidePortFormat
+ framerate.nPortIndex = 0;
+ result = OMX_GetParameter(m_hHandle,
+ OMX_IndexParamVideoPortFormat,
+ &framerate);
+ E("\n OMX_IndexParamVideoPortFormat Get Paramter port");
+ CHK(result);
+ framerate.xFramerate = m_sProfile.nFramerate << 16;
+ result = OMX_SetParameter(m_hHandle,
+ OMX_IndexParamVideoPortFormat,
+ &framerate);
+ E("\n OMX_IndexParamVideoPortFormat Set Paramter port");
+ CHK(result);
+
+#if 1
+ OMX_CONFIG_FRAMERATETYPE enc_framerate; // OMX_IndexConfigVideoFramerate
+ enc_framerate.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
+ result = OMX_GetConfig(m_hHandle,
+ OMX_IndexConfigVideoFramerate,
+ &enc_framerate);
+ E("\n OMX_IndexConfigVideoFramerate Get config port");
+ CHK(result);
+ enc_framerate.xEncodeFramerate = m_sProfile.nFramerate << 16;
+ result = OMX_SetConfig(m_hHandle,
+ OMX_IndexConfigVideoFramerate,
+ &enc_framerate);
+ E("\n OMX_IndexConfigVideoFramerate Set config port");
+ CHK(result);
+#endif
+ return OMX_ErrorNone;
+}
+////////////////////////////////////////////////////////////////////////////////
+void SendMessage(MsgId id, MsgData* data)
+{
+ pthread_mutex_lock(&m_mutex);
+ if (m_sMsgQ.size >= MAX_MSG)
+ {
+ E("main msg m_sMsgQ is full");
+ return;
+ }
+ m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].id = id;
+ if (data)
+ m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].data = *data;
+ ++m_sMsgQ.size;
+ pthread_cond_signal(&m_signal);
+ pthread_mutex_unlock(&m_mutex);
+}
+////////////////////////////////////////////////////////////////////////////////
+void PopMessage(Msg* msg)
+{
+ pthread_mutex_lock(&m_mutex);
+ while (m_sMsgQ.size == 0)
+ {
+ pthread_cond_wait(&m_signal, &m_mutex);
+ }
+ *msg = m_sMsgQ.q[m_sMsgQ.head];
+ --m_sMsgQ.size;
+ m_sMsgQ.head = (m_sMsgQ.head + 1) % MAX_MSG;
+ pthread_mutex_unlock(&m_mutex);
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE EVT_CB(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+#define SET_STATE(eState) \
+ case eState: \
+ { \
+ D("" # eState " complete"); \
+ m_eState = eState; \
+ break; \
+ }
+
+ if (eEvent == OMX_EventCmdComplete)
+ {
+ if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet)
+ {
+ switch ((OMX_STATETYPE) nData2)
+ {
+ SET_STATE(OMX_StateLoaded);
+ SET_STATE(OMX_StateIdle);
+ SET_STATE(OMX_StateExecuting);
+ SET_STATE(OMX_StateInvalid);
+ SET_STATE(OMX_StateWaitForResources);
+ SET_STATE(OMX_StatePause);
+ default:
+ E("invalid state %d", (int) nData2);
+ }
+ }
+ }
+
+ else if (eEvent == OMX_EventError)
+ {
+ E("OMX_EventError");
+ }
+
+ else
+ {
+ E("unexpected event %d", (int) eEvent);
+ }
+ return OMX_ErrorNone;
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE EBD_CB(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ D("Got EBD callback ts=%lld", pBuffer->nTimeStamp);
+
+ for (int i = 0; i < num_in_buffers; i++)
+ {
+ // mark this buffer ready for use again
+ if (m_pInBuffers[i] == pBuffer)
+ {
+
+ D("Marked input buffer idx %d as free, buf %p", i, pBuffer->pBuffer);
+ m_bInFrameFree[i] = OMX_TRUE;
+ break;
+ }
+ }
+
+ if (m_eMode == MODE_LIVE_ENCODE)
+ {
+ CameraTest_ReleaseFrame(pBuffer->pBuffer,
+ ((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)pBuffer->pAppPrivate));
+ }
+ else
+ {
+ // wake up main thread and tell it to send next frame
+ MsgData data;
+ data.sBitstreamData.pBuffer = pBuffer;
+ SendMessage(MSG_ID_INPUT_FRAME_DONE,
+ &data);
+
+ }
+ return OMX_ErrorNone;
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE FBD_CB(OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ D("Got FBD callback ts=%lld", pBuffer->nTimeStamp);
+
+ static long long prevTime = 0;
+ long long currTime = GetTimeStamp();
+
+ m_bWatchDogKicked = true;
+
+ /* Empty Buffers should not be counted */
+ if(pBuffer->nFilledLen !=0)
+ {
+ /* Counting Buffers supplied from OpneMax Encoder */
+ fbd_cnt++;
+ tot_bufsize += pBuffer->nFilledLen;
+ }
+ if (prevTime != 0)
+ {
+ long long currTime = GetTimeStamp();
+ D("FBD_DELTA = %lld\n", currTime - prevTime);
+ }
+ prevTime = currTime;
+
+ if (m_eMode == MODE_PROFILE)
+ {
+ // if we are profiling we are not doing file I/O
+ // so just give back to encoder
+ if (OMX_FillThisBuffer(m_hHandle, pBuffer) != OMX_ErrorNone)
+ {
+ E("empty buffer failed for profiling");
+ }
+ }
+ else
+ {
+ // wake up main thread and tell it to write to file
+ MsgData data;
+ data.sBitstreamData.pBuffer = pBuffer;
+ SendMessage(MSG_ID_OUTPUT_FRAME_DONE,
+ &data);
+ }
+ return OMX_ErrorNone;
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE VencTest_Initialize()
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ static OMX_CALLBACKTYPE sCallbacks = {EVT_CB, EBD_CB, FBD_CB};
+ int i;
+
+ for (i = 0; i < num_in_buffers; i++)
+ {
+ m_pInBuffers[i] = NULL;
+ }
+
+ result = OMX_Init();
+ CHK(result);
+
+ if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4)
+ {
+ result = OMX_GetHandle(&m_hHandle,
+ "OMX.qcom.video.encoder.mpeg4",
+ NULL,
+ &sCallbacks);
+ // CHK(result);
+ }
+ else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263)
+ {
+ result = OMX_GetHandle(&m_hHandle,
+ "OMX.qcom.video.encoder.h263",
+ NULL,
+ &sCallbacks);
+ CHK(result);
+ }
+ else
+ {
+ result = OMX_GetHandle(&m_hHandle,
+ "OMX.qcom.video.encoder.avc",
+ NULL,
+ &sCallbacks);
+ CHK(result);
+ }
+
+
+ result = ConfigureEncoder();
+ CHK(result);
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE VencTest_RegisterYUVBuffer(OMX_BUFFERHEADERTYPE** ppBufferHeader,
+ OMX_U8 *pBuffer,
+ OMX_PTR pAppPrivate)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+#if 0
+ D("register buffer");
+ if ((result = OMX_AllocateBuffer(m_hHandle,
+ ppBufferHeader,
+ (OMX_U32) PORT_INDEX_IN,
+ pAppPrivate,
+ m_sProfile.nFrameBytes
+ )) != OMX_ErrorNone)
+ {
+ E("use buffer failed");
+ }
+ else
+ {
+ E("Allocate Buffer Success %x", (*ppBufferHeader)->pBuffer);
+ }
+ #endif
+ D("register buffer");
+ D("Calling UseBuffer for Input port");
+ if ((result = OMX_UseBuffer(m_hHandle,
+ ppBufferHeader,
+ (OMX_U32) PORT_INDEX_IN,
+ pAppPrivate,
+ m_sProfile.nFrameBytes,
+ pBuffer)) != OMX_ErrorNone)
+ {
+ E("use buffer failed");
+ }
+
+ return result;
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE VencTest_EncodeFrame(void* pYUVBuff,
+ long long nTimeStamp)
+{
+ OMX_ERRORTYPE result = OMX_ErrorUndefined;
+ D("calling OMX empty this buffer");
+ for (int i = 0; i < num_in_buffers; i++)
+ {
+ if (pYUVBuff == m_pInBuffers[i]->pBuffer)
+ {
+ m_pInBuffers[i]->nTimeStamp = nTimeStamp;
+ D("Sending Buffer - %x", m_pInBuffers[i]->pBuffer);
+ result = OMX_EmptyThisBuffer(m_hHandle,
+ m_pInBuffers[i]);
+ /* Counting Buffers supplied to OpenMax Encoder */
+ if(OMX_ErrorNone == result)
+ ebd_cnt++;
+ CHK(result);
+ break;
+ }
+ }
+ return result;
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE VencTest_Exit(void)
+{
+ int i;
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+ D("trying to exit venc");
+
+ D("going to idle state");
+ SetState(OMX_StateIdle);
+
+
+ D("going to loaded state");
+ //SetState(OMX_StateLoaded);
+ OMX_SendCommand(m_hHandle,
+ OMX_CommandStateSet,
+ (OMX_U32) OMX_StateLoaded,
+ NULL);
+
+ for (i = 0; i < num_in_buffers; i++)
+ {
+ D("free buffer");
+ if (m_pInBuffers[i]->pBuffer)
+ {
+ // free(m_pInBuffers[i]->pBuffer);
+ result = OMX_FreeBuffer(m_hHandle,
+ PORT_INDEX_IN,
+ m_pInBuffers[i]);
+ CHK(result);
+ }
+ else
+ {
+ E("buffer %d is null", i);
+ result = OMX_ErrorUndefined;
+ CHK(result);
+ }
+ }
+ for (i = 0; i < num_out_buffers; i++)
+ {
+ D("free buffer");
+ if (m_pOutBuffers[i]->pBuffer)
+ {
+ free(m_pOutBuffers[i]->pBuffer);
+ result = OMX_FreeBuffer(m_hHandle,
+ PORT_INDEX_OUT,
+ m_pOutBuffers[i]);
+ CHK(result);
+
+ }
+ else
+ {
+ E("buffer %d is null", i);
+ result = OMX_ErrorUndefined;
+ CHK(result);
+ }
+ }
+
+ while (m_eState != OMX_StateLoaded)
+ {
+ sleep(1);
+ }
+ D("component_deinit...");
+ result = OMX_Deinit();
+ CHK(result);
+
+ D("venc is exiting...");
+ return result;
+}
+////////////////////////////////////////////////////////////////////////////////
+OMX_ERRORTYPE VencTest_ReadAndEmpty(OMX_BUFFERHEADERTYPE* pYUVBuffer)
+{
+ OMX_ERRORTYPE result = OMX_ErrorNone;
+#ifdef T_ARM
+ if (read(m_nInFd,
+ pYUVBuffer->pBuffer,
+ m_sProfile.nFrameBytes) != m_sProfile.nFrameBytes)
+ {
+ return OMX_ErrorUndefined;
+ }
+#else
+ {
+ char * pInputbuf = (char *)(pYUVBuffer->pBuffer) ;
+ read(m_nInFd,pInputbuf,m_sProfile.nFrameBytes) ;
+
+ }
+#endif
+ D("about to call VencTest_EncodeFrame...");
+ pthread_mutex_lock(&m_mutex);
+ ++m_nFrameIn;
+ pYUVBuffer->nFilledLen = m_sProfile.nFrameBytes;
+ D("Called Buffer with Data filled length %d",pYUVBuffer->nFilledLen);
+
+ result = VencTest_EncodeFrame(pYUVBuffer->pBuffer,
+ m_nTimeStamp);
+
+ m_nTimeStamp += (1000000) / m_sProfile.nFramerate;
+ CHK(result);
+ pthread_mutex_unlock(&m_mutex);
+ return result;
+}
+////////////////////////////////////////////////////////////////////////////////
+void PreviewCallback(int nFD,
+ int nOffset,
+ void* pPhys,
+ void* pVirt,
+ long long nTimeStamp)
+{
+
+ D("================= preview frame %d, phys=0x%x, nTimeStamp(millis)=%lld",
+ m_nFrameIn+1, pPhys, (nTimeStamp / 1000));
+
+ if (m_nFrameIn == m_nFramePlay &&
+ m_nFramePlay != 0)
+ {
+ // we will stop camera after last frame is encoded.
+ // for now just ignore input frames
+
+ CameraTest_ReleaseFrame(pPhys, pVirt);
+ return;
+ }
+
+ // see if we should stop
+ pthread_mutex_lock(&m_mutex);
+ ++m_nFrameIn;
+ pthread_mutex_unlock(&m_mutex);
+
+
+ if (m_eMode == MODE_LIVE_ENCODE)
+ {
+
+ OMX_ERRORTYPE result;
+
+ // register new camera buffers with encoder
+ int i;
+ for (i = 0; i < num_in_buffers; i++)
+ {
+ if (m_pInBuffers[i] != NULL &&
+ m_pInBuffers[i]->pBuffer == pPhys)
+ {
+ break;
+ }
+ else if (m_pInBuffers[i] == NULL)
+ {
+ D("registering buffer...");
+ result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i],
+ (OMX_U8*) pPhys,
+ (OMX_PTR) pVirt); // store virt in app private field
+ D("register done");
+ CHK(result);
+ break;
+ }
+ }
+
+ if (i == num_in_buffers)
+ {
+ E("There are more camera buffers than we thought");
+ CHK(1);
+ }
+
+ // encode the yuv frame
+
+ D("StartEncodeTime=%lld", GetTimeStamp());
+ result = VencTest_EncodeFrame(pPhys,
+ nTimeStamp);
+ CHK(result);
+ // FBTest_DisplayImage(nFD, nOffset);
+ }
+ else
+ {
+ // FBTest_DisplayImage(nFD, nOffset);
+ CameraTest_ReleaseFrame(pPhys, pVirt);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void usage(char* filename)
+{
+ char* fname = strrchr(filename, (int) '/');
+ fname = (fname == NULL) ? filename : fname;
+
+ fprintf(stderr, "usage: %s LIVE <QCIF|QVGA> <MP4|H263> <FPS> <BITRATE> <NFRAMES> <OUTFILE>\n", fname);
+ fprintf(stderr, "usage: %s FILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE> <OUTFILE> ", fname);
+ fprintf(stderr, "<Rate Control - optional> <AVC Slice Mode - optional\n", fname);
+ fprintf(stderr, "usage: %s PROFILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE>\n", fname);
+ fprintf(stderr, "usage: %s PREVIEW <QCIF|QVGA> <FPS> <NFRAMES>\n", fname);
+ fprintf(stderr, "usage: %s DISPLAY <QCIF|QVGA> <FPS> <NFRAMES> <INFILE>\n", fname);
+ fprintf(stderr, "\n BITRATE - bitrate in kbps\n");
+ fprintf(stderr, " FPS - frames per second\n");
+ fprintf(stderr, " NFRAMES - number of frames to play, 0 for infinite\n");
+ fprintf(stderr, " RateControl (Values 0 - 4 for RC_OFF, RC_CBR_CFR, RC_CBR_VFR, RC_VBR_CFR, RC_VBR_VFR\n");
+ exit(1);
+}
+////////////////////////////////////////////////////////////////////////////////
+void parseArgs(int argc, char** argv)
+{
+
+ if (argc == 1)
+ {
+ usage(argv[0]);
+ }
+ else if (strcmp("PREVIEW", argv[1]) == 0 ||
+ strcmp("preview", argv[1]) == 0)
+ {
+ m_eMode = MODE_PREVIEW;
+ if (argc != 5)
+ {
+ usage(argv[0]);
+ }
+ }
+ else if (strcmp("DISPLAY", argv[1]) == 0 ||
+ strcmp("display", argv[1]) == 0)
+ {
+ m_eMode = MODE_DISPLAY;
+ if (argc != 6)
+ {
+ usage(argv[0]);
+ }
+ m_sProfile.cInFileName = argv[5];
+ m_sProfile.cOutFileName = NULL;
+ }
+ else if (strcmp("LIVE", argv[1]) == 0 ||
+ strcmp("live", argv[1]) == 0)
+ {//263
+ m_eMode = MODE_LIVE_ENCODE;
+ if (argc != 8)
+ {
+ usage(argv[0]);
+ }
+ m_sProfile.cInFileName = NULL;
+ m_sProfile.cOutFileName = argv[7];
+ }
+ else if (strcmp("FILE", argv[1]) == 0 ||
+ strcmp("file", argv[1]) == 0)
+ {//263
+ m_eMode = MODE_FILE_ENCODE;
+
+ if(argc < 9 || argc > 11)
+ {
+ usage(argv[0]);
+ }
+ else
+ {
+ if ((argc == 10))
+ {
+ m_sProfile.eControlRate = OMX_Video_ControlRateVariable;
+ int RC = atoi(argv[9]);
+
+ switch (RC)
+ {
+ case 0:
+ m_sProfile.eControlRate = OMX_Video_ControlRateDisable ;//VENC_RC_NONE
+ break;
+ case 1:
+ m_sProfile.eControlRate = OMX_Video_ControlRateConstant;//VENC_RC_CBR_CFR
+ break;
+
+ case 2:
+ m_sProfile.eControlRate = OMX_Video_ControlRateConstantSkipFrames;//VENC_RC_CBR_VFR
+ break;
+
+ case 3:
+ m_sProfile.eControlRate =OMX_Video_ControlRateVariable ;//VENC_RC_VBR_CFR
+ break;
+
+ case 4:
+ m_sProfile.eControlRate = OMX_Video_ControlRateVariableSkipFrames;//VENC_RC_VBR_VFR
+ break;
+
+ default:
+ E("invalid rate control selection");
+ m_sProfile.eControlRate = OMX_Video_ControlRateVariable; //VENC_RC_VBR_CFR
+ break;
+ }
+ }
+
+ if (argc == 11)
+ {
+ if(!strcmp(argv[3], "H264") || !strcmp(argv[3], "h264"))
+ {
+ E("\nSetting AVCSliceMode ... ");
+ int AVCSliceMode = atoi(argv[10]);
+ switch(AVCSliceMode)
+ {
+ case 0:
+ m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault;
+ break;
+
+ case 1:
+ m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice;
+ break;
+
+ case 2:
+ m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCByteSlice;
+ break;
+
+ default:
+ E("invalid Slice Mode");
+ m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault;
+ break;
+ }
+ }
+ else
+ {
+ E("SliceMode support only for H.264 codec");
+ usage(argv[0]);
+ }
+ }
+ }
+ m_sProfile.cInFileName = argv[7];
+ m_sProfile.cOutFileName = argv[8];
+ }
+ else if (strcmp("PROFILE", argv[1]) == 0 ||
+ strcmp("profile", argv[1]) == 0)
+ {//263
+ m_eMode = MODE_PROFILE;
+ if (argc != 8)
+ {
+ usage(argv[0]);
+ }
+ m_sProfile.cInFileName = argv[7];
+ m_sProfile.cOutFileName = NULL;
+ }
+ else
+ {
+ usage(argv[0]);
+ }
+
+
+ if (strcmp("QCIF", argv[2]) == 0 ||
+ strcmp("qcif", argv[2]) == 0)
+ {
+ m_sProfile.nFrameWidth = 176;
+ m_sProfile.nFrameHeight = 144;
+ m_sProfile.nFrameBytes = 176*144*3/2;
+ m_sProfile.eLevel = OMX_VIDEO_MPEG4Level0;
+ }
+ else if (strcmp("QVGA", argv[2]) == 0 ||
+ strcmp("qvga", argv[2]) == 0)
+ {
+ m_sProfile.nFrameWidth = 320;
+ m_sProfile.nFrameHeight = 240;
+ m_sProfile.nFrameBytes = 320*240*3/2;
+ m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
+ }
+
+
+ else if (strcmp("VGA", argv[2]) == 0 ||
+ strcmp("vga", argv[2]) == 0)
+ {
+ m_sProfile.nFrameWidth = 640;
+ m_sProfile.nFrameHeight = 480;
+ m_sProfile.nFrameBytes = 640*480*3/2;
+ m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
+ }
+
+ else if (strcmp("WVGA", argv[2]) == 0 ||
+ strcmp("wvga", argv[2]) == 0)
+ {
+ m_sProfile.nFrameWidth = 800;
+ m_sProfile.nFrameHeight = 480;
+ m_sProfile.nFrameBytes = 800*480*3/2;
+ m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
+ }
+ else if (strcmp("CIF", argv[2]) == 0 ||
+ strcmp("CIF", argv[2]) == 0)
+ {
+ m_sProfile.nFrameWidth = 352;
+ m_sProfile.nFrameHeight = 288;
+ m_sProfile.nFrameBytes = 352*288*3/2;
+ m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
+ }
+ else if (strcmp("720", argv[2]) == 0 ||
+ strcmp("720", argv[2]) == 0)
+ {
+ m_sProfile.nFrameWidth = 1280;
+ m_sProfile.nFrameHeight = 720;
+ m_sProfile.nFrameBytes = 720*1280*3/2;
+ m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
+ }
+ else
+ {
+ usage(argv[0]);
+ }
+
+ if (m_eMode == MODE_DISPLAY ||
+ m_eMode == MODE_PREVIEW)
+ {
+ m_sProfile.nFramerate = atoi(argv[3]);
+ m_nFramePlay = atoi(argv[4]);
+
+ }
+ else if (m_eMode == MODE_LIVE_ENCODE ||
+ m_eMode == MODE_FILE_ENCODE ||
+ m_eMode == MODE_PROFILE)
+ {//263
+ if ((!strcmp(argv[3], "MP4")) || (!strcmp(argv[3], "mp4")))
+ {
+ m_sProfile.eCodec = OMX_VIDEO_CodingMPEG4;
+ }
+ else if ((!strcmp(argv[3], "H263")) || (!strcmp(argv[3], "h263")))
+ {
+ m_sProfile.eCodec = OMX_VIDEO_CodingH263;
+ }
+ else if ((!strcmp(argv[3], "H264")) || (!strcmp(argv[3], "h264")))
+ {
+ m_sProfile.eCodec = OMX_VIDEO_CodingAVC;
+ }
+ else
+ {
+ usage(argv[0]);
+ }
+
+ m_sProfile.nFramerate = atoi(argv[4]);
+ m_sProfile.nBitrate = atoi(argv[5]);
+// m_sProfile.eControlRate = OMX_Video_ControlRateVariable;
+ m_nFramePlay = atoi(argv[6]);
+ }
+}
+
+
+void* Watchdog(void* data)
+{
+ while (1)
+ {
+ sleep(1000);
+ if (m_bWatchDogKicked == true)
+ m_bWatchDogKicked = false;
+ else
+ E("watchdog has not been kicked. we may have a deadlock");
+ }
+ return NULL;
+}
+
+int main(int argc, char** argv)
+{
+ OMX_U8* pvirt = NULL;
+ int result;
+ float enc_time_sec=0.0,enc_time_usec=0.0;
+
+ m_nInFd = -1;
+ m_nOutFd = -1;
+ m_nTimeStamp = 0;
+ m_nFrameIn = 0;
+ m_nFrameOut = 0;
+
+ memset(&m_sMsgQ, 0, sizeof(MsgQ));
+ parseArgs(argc, argv);
+
+ D("fps=%d, bitrate=%d, width=%d, height=%d",
+ m_sProfile.nFramerate,
+ m_sProfile.nBitrate,
+ m_sProfile.nFrameWidth,
+ m_sProfile.nFrameHeight);
+
+
+ //if (m_eMode != MODE_PREVIEW && m_eMode != MODE_DISPLAY)
+ //{
+ // pthread_t wd;
+ // pthread_create(&wd, NULL, Watchdog, NULL);
+ //}
+
+ for (int x = 0; x < num_in_buffers; x++)
+ {
+ // mark all buffers as ready to use
+ m_bInFrameFree[x] = OMX_TRUE;
+ }
+
+
+ if (m_eMode != MODE_PROFILE)
+ {
+ #if T_ARM
+ m_nOutFd = open(m_sProfile.cOutFileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
+ #else
+ m_nOutFd = open(m_sProfile.cOutFileName,0);
+ #endif
+ if (m_nOutFd < 0)
+ {
+ E("could not open output file %s", m_sProfile.cOutFileName);
+ CHK(1);
+ }
+ }
+
+ pthread_mutex_init(&m_mutex, NULL);
+ pthread_cond_init(&m_signal, NULL);
+
+ if (m_eMode != MODE_PREVIEW)
+ {
+ VencTest_Initialize();
+ }
+
+ ////////////////////////////////////////
+ // Camera + Encode
+ ////////////////////////////////////////
+ if (m_eMode == MODE_LIVE_ENCODE)
+ {
+ CameraTest_Initialize(m_sProfile.nFramerate,
+ m_sProfile.nFrameWidth,
+ m_sProfile.nFrameHeight,
+ PreviewCallback);
+ CameraTest_Run();
+ }
+
+ if (m_eMode == MODE_FILE_ENCODE ||
+ m_eMode == MODE_PROFILE)
+ {
+ int i;
+ #if T_ARM
+ m_nInFd = open(m_sProfile.cInFileName, O_RDONLY);
+ #else
+ m_nInFd = open(m_sProfile.cInFileName,1);
+ #endif
+ if (m_nInFd < 0)
+ {
+ E("could not open input file");
+ CHK(1);
+ }
+ D("going to idle state");
+ //SetState(OMX_StateIdle);
+ OMX_SendCommand(m_hHandle,
+ OMX_CommandStateSet,
+ (OMX_U32) OMX_StateIdle,
+ NULL);
+
+ OMX_PARAM_PORTDEFINITIONTYPE portDef;
+
+ portDef.nPortIndex = 0;
+ result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef);
+ CHK(result);
+
+ D("allocating output buffers");
+
+ D("allocating Input buffers");
+ num_in_buffers = portDef.nBufferCountActual;
+ for (i = 0; i < portDef.nBufferCountActual; i++)
+ {
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO;
+ pvirt = (OMX_U8*)PmemMalloc(pMem, m_sProfile.nFrameBytes);
+
+ if(pvirt == NULL)
+ {
+ CHK(1);
+ }
+ result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i],
+ (OMX_U8*) pvirt,
+ (OMX_PTR) pMem);
+ CHK(result);
+ }
+ }
+ else if (m_eMode == MODE_LIVE_ENCODE)
+ {
+ D("going to idle state");
+ //SetState(OMX_StateIdle);
+ OMX_SendCommand(m_hHandle,
+ OMX_CommandStateSet,
+ (OMX_U32) OMX_StateIdle,
+ NULL);
+ }
+
+ int i;
+ OMX_PARAM_PORTDEFINITIONTYPE portDef;
+
+ portDef.nPortIndex = 1;
+ result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef);
+ CHK(result);
+
+ D("allocating output buffers");
+ D("Calling UseBuffer for Output port");
+ num_out_buffers = portDef.nBufferCountActual;
+ for (i = 0; i < portDef.nBufferCountActual; i++)
+ {
+ void* pBuff;
+
+ pBuff = malloc(portDef.nBufferSize);
+ D("portDef.nBufferSize = %d ",portDef.nBufferSize);
+ result = OMX_UseBuffer(m_hHandle,
+ &m_pOutBuffers[i],
+ (OMX_U32) PORT_INDEX_OUT,
+ NULL,
+ portDef.nBufferSize,
+ (OMX_U8*) pBuff);
+ CHK(result);
+ }
+ D("allocate done");
+
+ // D("Going to state " # eState"...");
+
+ while (m_eState != OMX_StateIdle)
+ {
+ sleep(1);
+ }
+ //D("Now in state " # eState);
+
+
+ D("going to executing state");
+ SetState(OMX_StateExecuting);
+
+ for (i = 0; i < num_out_buffers; i++)
+ {
+ D("filling buffer %d", i);
+ result = OMX_FillThisBuffer(m_hHandle, m_pOutBuffers[i]);
+ //sleep(1000);
+ CHK(result);
+ }
+
+ if (m_eMode == MODE_FILE_ENCODE)
+ {
+ // encode the first frame to kick off the whole process
+ VencTest_ReadAndEmpty(m_pInBuffers[0]);
+ // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[0]->pAppPrivate)->fd,0);
+ }
+
+ if (m_eMode == MODE_PROFILE)
+ {
+ int i;
+
+ // read several frames into memory
+ D("reading frames into memory");
+ for (i = 0; i < num_in_buffers; i++)
+ {
+ D("[%d] address 0x%x",i, m_pInBuffers[i]->pBuffer);
+ read(m_nInFd,
+ m_pInBuffers[i]->pBuffer,
+ m_sProfile.nFrameBytes);
+
+ }
+
+ // FBTest_Initialize(m_sProfile.nFrameWidth, m_sProfile.nFrameHeight);
+
+ // loop over the mem-resident frames and encode them
+ D("beging playing mem-resident frames...");
+ for (i = 0; m_nFramePlay == 0 || i < m_nFramePlay; i++)
+ {
+ int idx = i % num_in_buffers;
+ if (m_bInFrameFree[idx] == OMX_FALSE)
+ {
+ int j;
+ E("the expected buffer is not free, but lets find another");
+
+ idx = -1;
+
+ // lets see if we can find another free buffer
+ for (j = 0; j < num_in_buffers; j++)
+ {
+ if(m_bInFrameFree[j])
+ {
+ idx = j;
+ break;
+ }
+ }
+ }
+
+ // if we have a free buffer let's encode it
+ if (idx >= 0)
+ {
+ D("encode frame %d...m_pInBuffers[idx]->pBuffer=0x%x", i,m_pInBuffers[idx]->pBuffer);
+ m_bInFrameFree[idx] = OMX_FALSE;
+ VencTest_EncodeFrame(m_pInBuffers[idx]->pBuffer,
+ m_nTimeStamp);
+ D("display frame %d...", i);
+ // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[idx]->pAppPrivate)->fd,0);
+ m_nTimeStamp += 1000000 / m_sProfile.nFramerate;
+ }
+ else
+ {
+ E("wow, no buffers are free, performance "
+ "is not so good. lets just sleep some more");
+
+ }
+ D("sleep for %d microsec", 1000000/m_sProfile.nFramerate);
+ sleep (1000000 / m_sProfile.nFramerate);
+ }
+ // FBTest_Exit();
+ }
+
+ Msg msg;
+ bool bQuit = false;
+ while ((m_eMode == MODE_FILE_ENCODE || m_eMode == MODE_LIVE_ENCODE) &&
+ !bQuit)
+ {
+ PopMessage(&msg);
+ switch (msg.id)
+ {
+ //////////////////////////////////
+ // FRAME IS ENCODED
+ //////////////////////////////////
+ case MSG_ID_INPUT_FRAME_DONE:
+ /*pthread_mutex_lock(&m_mutex);
+ ++m_nFrameOut;
+ if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0)
+ {
+ bQuit = true;
+ }
+ pthread_mutex_unlock(&m_mutex);*/
+
+ if (!bQuit && m_eMode == MODE_FILE_ENCODE)
+ {
+ D("pushing another frame down to encoder");
+ if (VencTest_ReadAndEmpty(msg.data.sBitstreamData.pBuffer))
+ {
+ // we have read the last frame
+ D("main is exiting...");
+ bQuit = true;
+ }
+ }
+ break;
+ case MSG_ID_OUTPUT_FRAME_DONE:
+ D("================ writing frame %d = %d bytes to output file",
+ m_nFrameOut+1,
+ msg.data.sBitstreamData.pBuffer->nFilledLen);
+ D("StopEncodeTime=%lld", GetTimeStamp());
+
+
+ write(m_nOutFd,
+ msg.data.sBitstreamData.pBuffer->pBuffer,
+ msg.data.sBitstreamData.pBuffer->nFilledLen);
+
+
+ result = OMX_FillThisBuffer(m_hHandle,
+ msg.data.sBitstreamData.pBuffer);
+
+ if (result != OMX_ErrorNone)
+ {
+ CHK(result);
+ }
+
+ pthread_mutex_lock(&m_mutex);
+ ++m_nFrameOut;
+ if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0)
+ {
+ bQuit = true;
+ }
+ pthread_mutex_unlock(&m_mutex);
+ break;
+
+ default:
+ E("invalid msg id %d", (int) msg.id);
+ } // end switch (msg.id)
+ } // end while (!bQuit)
+
+
+ if (m_eMode == MODE_LIVE_ENCODE)
+ {
+ CameraTest_Exit();
+ close(m_nOutFd);
+ }
+ else if (m_eMode == MODE_FILE_ENCODE ||
+ m_eMode == MODE_PROFILE)
+ {
+ // deallocate pmem buffers
+ for (int i = 0; i < num_in_buffers; i++)
+ {
+ PmemFree((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)m_pInBuffers[i]->pAppPrivate,
+ m_pInBuffers[i]->pBuffer,
+ m_sProfile.nFrameBytes);
+ delete (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*) m_pInBuffers[i]->pAppPrivate;
+ }
+ close(m_nInFd);
+
+ if (m_eMode == MODE_FILE_ENCODE)
+ {
+ close(m_nOutFd);
+ }
+ }
+
+ if (m_eMode != MODE_PREVIEW)
+ {
+ D("exit encoder test");
+ VencTest_Exit();
+ }
+
+ pthread_mutex_destroy(&m_mutex);
+ pthread_cond_destroy(&m_signal);
+
+ /* Time Statistics Logging */
+ if(0 != m_sProfile.nFramerate)
+ {
+ enc_time_usec = m_nTimeStamp - (1000000 / m_sProfile.nFramerate);
+ enc_time_sec =enc_time_usec/1000000;
+ if(0 != enc_time_sec)
+ {
+ printf("Total Frame Rate: %f",ebd_cnt/enc_time_sec);
+ printf("\nEncoder Bitrate :%lf Kbps",(tot_bufsize*8)/(enc_time_sec*1000));
+ }
+ }
+ else
+ {
+ printf("\n\n Encode Time is zero");
+ }
+ printf("\nTotal Number of Frames :%d",ebd_cnt);
+ printf("\nNumber of dropped frames during encoding:%d\n",ebd_cnt-fbd_cnt);
+ /* End of Time Statistics Logging */
+
+ D("main has exited");
+ return 0;
+}
diff --git a/omx/mm-video/vidc/venc/test/venc_util.c b/omx/mm-video/vidc/venc/test/venc_util.c
new file mode 100644
index 0000000..e4d3217
--- /dev/null
+++ b/omx/mm-video/vidc/venc/test/venc_util.c
@@ -0,0 +1,51 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+/*============================================================================
+ V E N C _ U T I L. C
+
+DESCRIPTION
+
+
+REFERENCES
+
+============================================================================*/
+
+#include "venc_util.h"
+#include <time.h>
+#include <sys/time.h>
+
+long long GetTimeStamp()
+{
+ struct timeval tv;
+ long long microsec;
+ gettimeofday(&tv, NULL);
+ microsec = (tv.tv_sec * 1000000) + (tv.tv_usec);
+ return microsec;
+
+}
+
diff --git a/omx/mm-video/vidc/venc/test/video_encoder_test.c b/omx/mm-video/vidc/venc/test/video_encoder_test.c
new file mode 100644
index 0000000..dd28728
--- /dev/null
+++ b/omx/mm-video/vidc/venc/test/video_encoder_test.c
@@ -0,0 +1,1065 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "video_encoder_test.h"
+
+#define DEBUG_PRINT printf
+/************************************************************************/
+/* #DEFINES */
+/************************************************************************/
+
+#define VOP_START_CODE 0x000001B6
+#define SHORT_HEADER_START_CODE 0x00008000
+#define H264_START_CODE 0x00000001
+
+/************************************************************************/
+/* STATIC VARIABLES */
+/************************************************************************/
+
+static int Code_type;
+static int total_frames = 0;
+static unsigned int header_code = 0;
+static pthread_mutex_t read_lock;
+
+static unsigned int read_frame ( unsigned char *dataptr,unsigned int length,
+ FILE * inputBufferFile
+ );
+static unsigned clp2(unsigned x)
+{
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >>16);
+ return x + 1;
+}
+
+
+static void* video_thread (void *);
+static void* async_thread (void *);
+
+
+
+int main (int argc, char **argv)
+{
+ struct video_encoder_context *encoder_context = NULL;
+ char *file_name = NULL;
+ FILE *file_ptr = NULL;
+ int temp1 =0,temp2 =0;
+ int error = 1;
+ unsigned int i = 0;
+
+ file_name = argv [1];
+ file_ptr = fopen (file_name,"rb");
+
+ if (file_ptr == NULL)
+ {
+ DEBUG_PRINT("\n File is not located ");
+ return -1;
+ }
+
+
+ encoder_context = (struct video_encoder_context *) \
+ calloc (sizeof (struct video_encoder_context),1);
+
+ encoder_context->outputBufferFile = NULL;
+ encoder_context->inputBufferFile = NULL;
+ encoder_context->video_driver_fd = -1;
+
+ if (encoder_context == NULL)
+ {
+ return -1;
+ }
+
+ encoder_context->inputBufferFile = file_ptr;
+ encoder_context->input_width = 176;
+ encoder_context->input_height = 144;
+ encoder_context->codectype = VEN_CODEC_MPEG4;
+ encoder_context->fps_num = 60;
+ encoder_context->fps_den = 2;
+ encoder_context->inputformat = VEN_INPUTFMT_NV12;
+ encoder_context->targetbitrate = 128000;
+
+ file_ptr = fopen ("/data/output.m4v","wb");
+ if (file_ptr == NULL)
+ {
+ DEBUG_PRINT("\n File can't be created");
+ return -1;
+ }
+ encoder_context->outputBufferFile = file_ptr;
+
+ switch (atoi(argv[2]))
+ {
+ case 0:
+ DEBUG_PRINT("\n MPEG4 codec selected");
+ encoder_context->codectype = VEN_CODEC_MPEG4;
+ Code_type = 0;
+ break;
+ case 1:
+ DEBUG_PRINT("\n H.263");
+ encoder_context->codectype = VEN_CODEC_H263;
+ Code_type = 0;
+ break;
+ case 2:
+ DEBUG_PRINT("\n H.264");
+ encoder_context->codectype = VEN_CODEC_H264;
+ Code_type = 1;
+ break;
+ default:
+ DEBUG_PRINT("\n Wrong codec type");
+ error = -1;
+ break;
+ }
+
+ if (error != -1)
+ {
+ temp1 = atoi(argv[3]);
+ temp2 = atoi(argv[4]);
+
+ if (((temp1%16) != 0) || ((temp2%16) != 0))
+ {
+ error = -1;
+ }
+ else
+ {
+ encoder_context->input_width = temp1;
+ encoder_context->input_height = temp2;
+ }
+ }
+
+ switch (atoi(argv[5]))
+ {
+ case 0:
+ DEBUG_PRINT("\n No Sink");
+ encoder_context->outputBufferFile = NULL;
+ break;
+ }
+
+ if (error != -1)
+ {
+ encoder_context->targetbitrate = atoi (argv[6]);
+ }
+
+ if ( error != -1 && (init_encoder (encoder_context) == -1 ))
+ {
+ DEBUG_PRINT("\n Init decoder fails ");
+ error = -1;
+ }
+ DEBUG_PRINT("\n Decoder open successfull");
+
+
+ /*Allocate input and output buffers*/
+ if (error != -1 && (allocate_buffer (0,encoder_context)== -1))
+ {
+ DEBUG_PRINT("\n Error in input Buffer allocation");
+ error = -1;
+ }
+
+ if (error != -1 && (allocate_buffer (1,encoder_context)== -1))
+ {
+ DEBUG_PRINT("\n Error in output Buffer allocation");
+ error = -1;
+ }
+
+
+ if (error != -1 && (start_encoding (encoder_context) == -1))
+ {
+ DEBUG_PRINT("\n Error in start decoding call");
+ error = -1;
+ }
+
+ if (error != -1 && (stop_encoding (encoder_context) == -1))
+ {
+ DEBUG_PRINT("\n Error in stop decoding call");
+ error = -1;
+ }
+
+ DEBUG_PRINT("\n De-init the decoder");
+ if ((deinit_encoder (encoder_context) == -1))
+ {
+ error = -1;
+ }
+
+
+ (void)free_buffer (INPUT_BUFFER,encoder_context);
+ (void)free_buffer (OUTPUT_BUFFER,encoder_context);
+
+ if (encoder_context->inputBufferFile != NULL)
+ {
+ fclose (encoder_context->inputBufferFile);
+ }
+ if (encoder_context->outputBufferFile != NULL)
+ {
+ fclose (encoder_context->outputBufferFile);
+ }
+ DEBUG_PRINT ("\n Total Number of frames decoded %d",total_frames);
+ DEBUG_PRINT("\n closing the driver");
+ free (encoder_context);
+
+ return error;
+}
+
+int init_encoder ( struct video_encoder_context *init_decode )
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_basecfg basecfg;
+ struct video_queue_context *queue_ptr = NULL;
+ struct venc_ratectrlcfg ratecrl;
+ pthread_mutexattr_t init_values;
+ struct venc_profile profile;
+ struct ven_profilelevel profilelevel;
+
+ DEBUG_PRINT("\n Before calling the open");
+
+ init_decode->video_driver_fd = open ("/dev/msm_vidc_enc", \
+ O_RDWR | O_NONBLOCK);
+
+
+
+ if (init_decode->video_driver_fd < 0)
+ {
+ DEBUG_PRINT("\n Open failed");
+ return -1;
+ }
+
+ basecfg.codectype = init_decode->codectype;
+ basecfg.dvs_height = 0;
+ basecfg.dvs_width = 0;
+ basecfg.fps_den = init_decode->fps_den;
+ basecfg.fps_num = init_decode->fps_num;
+ basecfg.input_height = init_decode->input_height;
+ basecfg.input_width = init_decode->input_width;
+ basecfg.inputformat = init_decode->inputformat;
+ basecfg.targetbitrate = init_decode->targetbitrate;
+
+ /*Initialize Decoder with codec type and resolution*/
+ ioctl_msg.inputparam = &basecfg;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_BASE_CFG,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set base config type failed");
+ return -1;
+ }
+
+ /*Initialize Decoder with codec type and resolution*/
+ DEBUG_PRINT ("\n Switch off rate control");
+ ioctl_msg.inputparam = &ratecrl;
+ ioctl_msg.outputparam = NULL;
+ ratecrl.rcmode = VEN_RC_OFF;
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set rate control failed");
+ return -1;
+ }
+
+ if (basecfg.codectype == VEN_CODEC_H264)
+ {
+ DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High");
+ ioctl_msg.inputparam = &profile;
+ ioctl_msg.outputparam = NULL;
+ profile.profile = VEN_PROFILE_H264_BASELINE;
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_CODEC_PROFILE,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed");
+ return -1;
+ }
+
+ DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High");
+ ioctl_msg.inputparam = &profilelevel;
+ ioctl_msg.outputparam = NULL;
+ profilelevel.level = VEN_LEVEL_H264_1p1;
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed");
+ return -1;
+ }
+
+ if (basecfg.input_width > 720)
+ {
+ DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High");
+ ioctl_msg.inputparam = &profile;
+ ioctl_msg.outputparam = NULL;
+ profile.profile = VEN_PROFILE_H264_HIGH;
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_CODEC_PROFILE,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed");
+ return -1;
+ }
+
+ DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High");
+ ioctl_msg.inputparam = &profilelevel;
+ ioctl_msg.outputparam = NULL;
+ profilelevel.level = VEN_LEVEL_H264_3p1;
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed");
+ return -1;
+ }
+ }
+ }
+
+ DEBUG_PRINT("\n Query Input bufffer requirements");
+ /*Get the Buffer requirements for input and output ports*/
+
+
+
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &init_decode->input_buffer;
+
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Requesting for input buffer requirements failed");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n input Size=%d min count =%d actual count = %d", \
+ (int)init_decode->input_buffer.datasize,\
+ (int)init_decode->input_buffer.mincount,\
+ (int)init_decode->input_buffer.actualcount);
+
+
+ ioctl_msg.inputparam = &init_decode->input_buffer;
+ ioctl_msg.outputparam = NULL;
+ init_decode->input_buffer.actualcount = init_decode->input_buffer.mincount + 2;
+
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Set Buffer Requirements Failed");
+ return -1;
+ }
+
+
+ DEBUG_PRINT("\n Query output bufffer requirements");
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = &init_decode->output_buffer;
+
+ if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Requesting for output buffer requirements failed");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n output Size=%d min count =%d actual count = %d", \
+ (int)init_decode->output_buffer.datasize,\
+ (int)init_decode->output_buffer.mincount,\
+ (int)init_decode->output_buffer.actualcount);
+
+ /*Create Queue related data structures*/
+ queue_ptr = &init_decode->queue_context;
+ queue_ptr->commandq_size = 50;
+ queue_ptr->dataq_size = 50;
+
+ sem_init(&queue_ptr->sem_message,0, 0);
+ sem_init(&init_decode->sem_synchronize,0, 0);
+
+ pthread_mutexattr_init (&init_values);
+ pthread_mutex_init (&queue_ptr->mutex,&init_values);
+ pthread_mutex_init (&read_lock,&init_values);
+ DEBUG_PRINT("\n create Queues");
+ queue_ptr->ptr_cmdq = (struct video_msgq*) \
+ calloc (sizeof (struct video_msgq),
+ queue_ptr->commandq_size);
+ queue_ptr->ptr_dataq = (struct video_msgq*) \
+ calloc (sizeof (struct video_msgq),
+ queue_ptr->dataq_size
+ );
+
+ if ( queue_ptr->ptr_cmdq == NULL ||
+ queue_ptr->ptr_dataq == NULL
+ )
+ {
+ return -1;
+ }
+ DEBUG_PRINT("\n create Threads");
+ /*Create two threads*/
+ if ( (pthread_create (&init_decode->videothread_id,NULL,video_thread,
+ init_decode) < 0) ||
+ (pthread_create (&init_decode->asyncthread_id,NULL,async_thread,
+ init_decode) < 0)
+ )
+ {
+ return -1;
+ }
+
+ return 1;
+}
+
+
+
+int free_buffer ( unsigned int buffer_dir,
+ struct video_encoder_context *encoder_context
+ )
+{
+ unsigned int buffercount = 0,i=0;
+ struct venc_bufferpayload **ptemp = NULL;
+
+ if (encoder_context == NULL)
+ {
+ return -1;
+ }
+
+ if (buffer_dir == INPUT_BUFFER && encoder_context->ptr_inputbuffer)
+ {
+ buffercount = encoder_context->input_buffer.actualcount;
+ ptemp = encoder_context->ptr_inputbuffer;
+
+ for (i=0;i<buffercount;i++)
+ {
+ if (ptemp [i])
+ {
+ if (ptemp [i]->fd != -1)
+ {
+ munmap ( ptemp [i]->pbuffer,ptemp [i]->maped_size);
+ ptemp [i]->pbuffer = NULL;
+ close (ptemp [i]->fd);
+ }
+ free (ptemp [i]);
+ ptemp [i] = NULL;
+ }
+ }
+ free (encoder_context->ptr_inputbuffer);
+ encoder_context->ptr_inputbuffer = NULL;
+ }
+ else if ( buffer_dir == OUTPUT_BUFFER && encoder_context->ptr_outputbuffer )
+ {
+ buffercount = encoder_context->output_buffer.actualcount;
+ ptemp = encoder_context->ptr_outputbuffer;
+
+ if (ptemp)
+ {
+ for (i=0;i<buffercount;i++)
+ {
+ if (ptemp [i])
+ {
+ if (ptemp [i]->fd != -1)
+ {
+ munmap ( ptemp [i]->pbuffer,ptemp [i]->maped_size);
+ ptemp [i]->pbuffer = NULL;
+ close (ptemp [i]->fd);
+ }
+ free (ptemp [i]);
+ ptemp [i] = NULL;
+ }
+ }
+ free (ptemp);
+ encoder_context->ptr_outputbuffer = NULL;
+ }
+ }
+
+ return 1;
+}
+
+int allocate_buffer ( unsigned int buffer_dir,
+ struct video_encoder_context *encoder_context
+ )
+{
+ struct venc_bufferpayload **ptemp = NULL;
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ unsigned int buffercount = 0,i=0,alignedsize=0;
+ unsigned int buffersize = 0;
+
+ if ( encoder_context == NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: context is NULL");
+ return -1;
+ }
+
+ if ( buffer_dir == INPUT_BUFFER )
+ {
+ /*Check if buffers are allocated*/
+ if (encoder_context->ptr_inputbuffer != NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: encoder_context->ptr_inputbuffer is set");
+ return -1;
+ }
+
+ buffercount = encoder_context->input_buffer.actualcount;
+ alignedsize = encoder_context->input_buffer.alignment;
+ buffersize = encoder_context->input_buffer.datasize;
+ buffersize = (buffersize + alignedsize) & (~alignedsize);
+ }
+ else if (buffer_dir == OUTPUT_BUFFER)
+ {
+ /*Check if buffers are allocated*/
+ if (encoder_context->ptr_outputbuffer != NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Double allcoate output");
+ return -1;
+ }
+
+ buffercount = encoder_context->output_buffer.actualcount;
+ alignedsize = encoder_context->output_buffer.alignment;
+ buffersize = encoder_context->output_buffer.datasize;
+ buffersize = (buffersize + alignedsize) & (~alignedsize);
+
+ }
+ else
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Wrong buffer directions");
+ return -1;
+ }
+
+ ptemp = (struct venc_bufferpayload **)\
+ calloc (sizeof (struct venc_bufferpayload *),buffercount);
+
+ if (ptemp == NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: venc_bufferpayload failure");
+ return -1;
+ }
+
+
+ if (buffer_dir == OUTPUT_BUFFER)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: OUT");
+ encoder_context->ptr_outputbuffer = ptemp;
+ }
+ else
+ {
+ DEBUG_PRINT ("\nallocate_buffer: IN");
+ encoder_context->ptr_inputbuffer = ptemp;
+ }
+
+ /*Allocate buffer headers*/
+ for (i=0; i< buffercount; i++)
+ {
+ ptemp [i] = (struct venc_bufferpayload*)\
+ calloc (sizeof (struct venc_bufferpayload),1);
+
+ if (ptemp [i] == NULL)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: ptemp [i] calloc failure");
+ return -1;
+ }
+ ptemp [i]->fd = -1;
+ }
+
+ for (i=0; i< buffercount; i++)
+ {
+ ptemp [i]->fd = open ("/dev/pmem_adsp",O_RDWR);
+
+ if (ptemp [i]->fd < 0)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: open pmem_adsp failed");
+ return -1;
+ }
+
+ ptemp [i]->pbuffer = mmap(NULL,clp2(buffersize),PROT_READ|PROT_WRITE,
+ MAP_SHARED,ptemp [i]->fd,0);
+ DEBUG_PRINT ("\n pmem fd = %d virt addr = %p",ptemp [i]->fd,\
+ ptemp [i]->pbuffer);
+ if (ptemp [i]->pbuffer == MAP_FAILED)
+ {
+ ptemp [i]->pbuffer = NULL;
+ DEBUG_PRINT ("\nallocate_buffer: MMAP failed");
+ return -1;
+ }
+ ptemp [i]->nsize = buffersize;
+ ptemp [i]->maped_size = clp2 (buffersize);
+
+ ioctl_msg.inputparam = ptemp [i];
+ ioctl_msg.outputparam = NULL;
+
+ if (buffer_dir == OUTPUT_BUFFER)
+ {
+ if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Set Output Buffer IOCTL failed");
+ return -1;
+ }
+ }
+ else
+ {
+ if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_SET_INPUT_BUFFER,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT ("\nallocate_buffer: Set input Buffer IOCTL failed");
+ return -1;
+ }
+ }
+
+ }
+ DEBUG_PRINT ("\nallocate_buffer: Success");
+ return 1;
+}
+
+
+
+int start_encoding (struct video_encoder_context *encoder_context)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_buffer enc_buffer;
+ unsigned int i = 0;
+ unsigned int data_len =0;
+
+
+ if (encoder_context == NULL)
+ {
+ return -1;
+ }
+
+ if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_CMD_START,
+ NULL) < 0)
+ {
+ DEBUG_PRINT("\n Start failed");
+ return -1;
+ }
+
+ DEBUG_PRINT("\n Start Issued successfully waiting for Start Done");
+ /*Wait for Start command response*/
+ sem_wait (&encoder_context->sem_synchronize);
+
+ /*Push output Buffers*/
+ i = 0;
+ while (i < encoder_context->output_buffer.actualcount)
+ {
+ enc_buffer.clientdata = (void *)encoder_context->ptr_outputbuffer [i];
+ enc_buffer.flags = 0;
+ enc_buffer.size = encoder_context->ptr_outputbuffer [i]->nsize;
+ enc_buffer.len = 0;
+ enc_buffer.ptrbuffer = encoder_context->ptr_outputbuffer [i]->pbuffer;
+ enc_buffer.offset = 0;
+ enc_buffer.timestamp = 0;
+
+ DEBUG_PRINT ("\n Client Data on output = %p",(void *)enc_buffer.clientdata);
+ ioctl_msg.inputparam = &enc_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (encoder_context->video_driver_fd,
+ VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n fill output frame failed");
+ return -1;
+ }
+ i++;
+ }
+
+
+ /*push input buffers*/
+ i = 0;
+ while (i < encoder_context->input_buffer.actualcount)
+ {
+ DEBUG_PRINT("\n Read Frame from File");
+
+ enc_buffer.clientdata = (void *)encoder_context->ptr_inputbuffer [i];
+ enc_buffer.flags = 0;
+ enc_buffer.size = encoder_context->ptr_inputbuffer [i]->nsize;
+ enc_buffer.len = 0;
+ enc_buffer.ptrbuffer = encoder_context->ptr_inputbuffer [i]->pbuffer;
+ enc_buffer.offset = 0;
+ enc_buffer.timestamp = total_frames *
+ ((encoder_context->fps_den * 1000000)/encoder_context->fps_num);
+ enc_buffer.len = (encoder_context->input_height *
+ encoder_context->input_width *3)/2;
+ data_len = read_frame ( enc_buffer.ptrbuffer,
+ enc_buffer.len,
+ encoder_context->inputBufferFile);
+ if (data_len == 0)
+ {
+ DEBUG_PRINT("\n Length is zero error");
+ return -1;
+ }
+ enc_buffer.len = data_len;
+ DEBUG_PRINT("\n Read Frame from File szie = %d",(int)data_len);
+
+ DEBUG_PRINT ("\n Client Data on output = %p",(void *)enc_buffer.clientdata);
+ ioctl_msg.inputparam = &enc_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (encoder_context->video_driver_fd,
+ VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Encode input frame failed");
+ return -1;
+ }
+ total_frames++;
+ i++;
+ }
+ DEBUG_PRINT ("\n Wait for EOS");
+ /*Wait for EOS or Error condition*/
+ sem_wait (&encoder_context->sem_synchronize);
+ DEBUG_PRINT ("\n Reached EOS");
+
+ return 1;
+}
+
+int stop_encoding (struct video_encoder_context *encoder_context)
+{
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_bufferflush buffer_flush;
+
+ if (encoder_context == NULL)
+ {
+ return -1;
+ }
+ buffer_flush.flush_mode = VEN_FLUSH_INPUT;
+ ioctl_msg.inputparam = &buffer_flush;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_FLUSH,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Flush input failed");
+ }
+ else
+ {
+ sem_wait (&encoder_context->sem_synchronize);
+ }
+
+ buffer_flush.flush_mode = VEN_FLUSH_OUTPUT;
+ ioctl_msg.inputparam = &buffer_flush;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_FLUSH,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Flush output failed");
+ }
+ else
+ {
+ sem_wait (&encoder_context->sem_synchronize);
+ }
+
+ DEBUG_PRINT("\n Stop VEN_IOCTL_CMD_STOP");
+ if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_STOP,NULL) < 0)
+ {
+ DEBUG_PRINT("\n Stop failed");
+ }
+ else
+ {
+ sem_wait (&encoder_context->sem_synchronize);
+ }
+ return 1;
+}
+
+int deinit_encoder (struct video_encoder_context *init_decode)
+{
+ if (init_decode == NULL)
+ {
+ return -1;
+ }
+
+ /*Close the driver*/
+ if (init_decode->video_driver_fd != -1)
+ {
+ close (init_decode->video_driver_fd);
+ }
+
+ if (init_decode->queue_context.ptr_cmdq)
+ {
+ free (init_decode->queue_context.ptr_cmdq);
+ init_decode->queue_context.ptr_cmdq = NULL;
+ }
+
+ if (init_decode->queue_context.ptr_dataq)
+ {
+ free (init_decode->queue_context.ptr_dataq);
+ init_decode->queue_context.ptr_dataq = NULL;
+ }
+
+ sem_destroy (&init_decode->queue_context.sem_message);
+ sem_destroy (&init_decode->sem_synchronize);
+
+ pthread_mutex_destroy(&init_decode->queue_context.mutex);
+ pthread_mutex_destroy (&read_lock);
+
+ return 1;
+}
+
+static void* video_thread (void *context)
+{
+ struct video_encoder_context *encoder_context = NULL;
+ struct video_msgq *queueitem = NULL;
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ struct venc_bufferpayload *tempbuffer = NULL;
+ struct venc_buffer enc_buffer;
+ unsigned int data_len =0;
+
+
+ if (context == NULL)
+ {
+ DEBUG_PRINT("\n video thread recieved NULL context");
+ return NULL;
+ }
+ encoder_context = (struct video_encoder_context *) context;
+
+ /* Thread function which will accept commands from async thread
+ * or main thread
+ */
+ while (1)
+ {
+ queueitem = queue_get_cmd (&encoder_context ->queue_context);
+ if (queueitem != NULL)
+ {
+ switch (queueitem->cmd)
+ {
+ case VEN_MSG_START:
+ DEBUG_PRINT("\n recived start done command");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+
+ case VEN_MSG_STOP:
+ DEBUG_PRINT("\n recieved stop done");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+
+ case VEN_MSG_INPUT_BUFFER_DONE:
+
+ tempbuffer = (struct venc_bufferpayload *)queueitem->clientdata;
+ if (tempbuffer == NULL)
+ {
+ DEBUG_PRINT("\n FATAL ERROR input buffer address is bad");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+ }
+ tempbuffer->filled_len = (encoder_context->input_height *
+ encoder_context->input_width *3)/2;
+
+ data_len = read_frame ( tempbuffer->pbuffer,
+ tempbuffer->filled_len,
+ encoder_context->inputBufferFile);
+
+ if (data_len == 0)
+ {
+ DEBUG_PRINT ("\n End of stream reached");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+ }
+ enc_buffer.clientdata = (void *)tempbuffer;
+ enc_buffer.flags = 0;
+ enc_buffer.ptrbuffer = tempbuffer->pbuffer;
+ enc_buffer.size = tempbuffer->nsize;
+ enc_buffer.len = tempbuffer->filled_len;
+ enc_buffer.offset = 0;
+ enc_buffer.timestamp = total_frames *
+ ((encoder_context->fps_den * 1000000)/encoder_context->fps_num);
+
+ /*TODO: Time stamp needs to be updated*/
+ ioctl_msg.inputparam = &enc_buffer;
+ ioctl_msg.outputparam = NULL;
+ total_frames++;
+ if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_ENCODE_FRAME,
+ &ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Decoder frame failed");
+ sem_post (&encoder_context->sem_synchronize);
+ }
+ DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\
+ total_frames);
+ break;
+
+ case VEN_MSG_OUTPUT_BUFFER_DONE:
+
+ tempbuffer = (struct venc_bufferpayload *)queueitem->clientdata;
+ if (tempbuffer == NULL)
+ {
+ DEBUG_PRINT("\n FATAL ERROR input buffer address is bad");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+ }
+
+ if (encoder_context->outputBufferFile != NULL)
+ {
+ fwrite (tempbuffer->pbuffer,1,tempbuffer->filled_len,
+ encoder_context->outputBufferFile);
+ }
+
+
+ DEBUG_PRINT("\n recieved output buffer consume outbuffer");
+ DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\
+ tempbuffer->pbuffer);
+ enc_buffer.clientdata = (void *)tempbuffer;
+ enc_buffer.flags = 0;
+ enc_buffer.size = tempbuffer->nsize;
+ enc_buffer.len = 0;
+ enc_buffer.ptrbuffer = tempbuffer->pbuffer;
+ enc_buffer.offset = 0;
+ enc_buffer.timestamp = 0;
+
+ ioctl_msg.inputparam = &enc_buffer;
+ ioctl_msg.outputparam = NULL;
+
+ if (ioctl (encoder_context->video_driver_fd,
+ VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Decoder frame failed");
+ return NULL;
+ }
+
+ break;
+
+ case VEN_MSG_FLUSH_INPUT_DONE:
+ DEBUG_PRINT("\n Flush input complete");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+
+ case VEN_MSG_FLUSH_OUPUT_DONE:
+ DEBUG_PRINT("\n Flush output complete");
+ sem_post (&encoder_context->sem_synchronize);
+ break;
+ }
+ }
+ else
+ {
+ DEBUG_PRINT("\n Error condition recieved NULL from Queue");
+ }
+
+ if (queueitem->cmd == VEN_MSG_STOP)
+ {
+ DEBUG_PRINT("\n Playback has ended thread will exit");
+ return NULL;
+ }
+ }
+}
+
+static void* async_thread (void *context)
+{
+ struct video_encoder_context *encoder_context = NULL;
+ struct video_msgq queueitem ;
+ struct venc_msg venc_msg;
+ struct venc_bufferpayload *tempbuffer = NULL;
+ struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
+ int result = -1;
+
+ if (context == NULL)
+ {
+ DEBUG_PRINT("\n aynsc thread recieved NULL context");
+ return NULL;
+ }
+ encoder_context = (struct video_encoder_context *) context;
+ DEBUG_PRINT("\n Entering the async thread");
+
+ while (1)
+ {
+ ioctl_msg.inputparam = NULL;
+ ioctl_msg.outputparam = (void*)&venc_msg;
+ DEBUG_PRINT ("\n Sizeof venc_msginfo = %d ",sizeof (venc_msg));
+ DEBUG_PRINT("\n Address of Venc msg in async thread %p",\
+ ioctl_msg.outputparam);
+ if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,\
+ (void*)&ioctl_msg) < 0)
+ {
+ DEBUG_PRINT("\n Error in ioctl read next msg");
+ }
+ else
+ {
+ switch (venc_msg.msgcode)
+ {
+ case VEN_MSG_START:
+ case VEN_MSG_STOP:
+ case VEN_MSG_INDICATION:
+ DEBUG_PRINT("\nSTOP/START Indiacation");
+ queueitem.cmd = venc_msg.msgcode;
+ queueitem.status = venc_msg.statuscode;
+ queueitem.clientdata = NULL;
+ break;
+
+ case VEN_MSG_INPUT_BUFFER_DONE:
+ DEBUG_PRINT("\nINPUT buffer done Indiacation");
+ queueitem.cmd = venc_msg.msgcode;
+ queueitem.status = venc_msg.statuscode;
+ queueitem.clientdata = (void *)venc_msg.buf.clientdata;
+ DEBUG_PRINT("\nInput Client data pointer is %p",queueitem.clientdata);
+ tempbuffer = (struct venc_bufferpayload *) queueitem.clientdata;
+ DEBUG_PRINT ("\n Input Address of tempbuffer %p",tempbuffer);
+ tempbuffer->filled_len = venc_msg.buf.len;
+ DEBUG_PRINT ("\n Input value of tempbuffer tempbuffer->filled_len %d",(int)tempbuffer->filled_len);
+ break;
+ case VEN_MSG_OUTPUT_BUFFER_DONE:
+ DEBUG_PRINT("\nOUPUT buffer done Indiacation");
+ queueitem.cmd = venc_msg.msgcode;
+ queueitem.status = venc_msg.statuscode;
+ queueitem.clientdata = (void *)venc_msg.buf.clientdata;
+ DEBUG_PRINT("\nOutput Client data pointer is %p",queueitem.clientdata);
+ tempbuffer = (struct venc_bufferpayload *) queueitem.clientdata;
+ DEBUG_PRINT ("\n Output Address of tempbuffer %p",tempbuffer);
+ tempbuffer->filled_len = venc_msg.buf.len;
+ DEBUG_PRINT ("\n Output value of tempbuffer tempbuffer->filled_len %d",(int)tempbuffer->filled_len);
+ break;
+
+ default:
+ DEBUG_PRINT("\nIn Default of get next message %d",(int)venc_msg.msgcode);
+ queueitem.cmd = venc_msg.msgcode;
+ queueitem.status = venc_msg.statuscode;
+ queueitem.clientdata = NULL;
+ break;
+ }
+ result = queue_post_cmdq (&encoder_context->queue_context,&queueitem);
+ while (result == 0)
+ {
+ result = queue_post_cmdq (&encoder_context->queue_context,&queueitem);
+ }
+
+ if (result == -1)
+ {
+ DEBUG_PRINT("\n FATAL ERROR WITH Queue");
+ }
+ }
+ if (venc_msg.msgcode == VEN_MSG_STOP)
+ {
+ /*Thread can exit at this point*/
+ return NULL;
+ }
+ }
+}
+
+
+static unsigned int read_frame (unsigned char *dataptr, unsigned int length,
+ FILE * inputBufferFile)
+{
+
+ unsigned int readOffset = 0;
+ int bytes_read = 0;
+ unsigned int code = 0;
+ int found = 0;
+
+ DEBUG_PRINT ("\n Inside the readframe");
+
+ if (dataptr == NULL && length == 0)
+ {
+ DEBUG_PRINT ("\n dataptr = %p length = %d",dataptr,(int)length);
+ return 0;
+ }
+
+ pthread_mutex_lock(&read_lock);
+ bytes_read = fread(&dataptr[readOffset],1,length,inputBufferFile);
+ pthread_mutex_unlock(&read_lock);
+
+ return bytes_read;
+}