diff options
author | Timo Teräs <timo.teras@iki.fi> | 2016-02-11 13:06:21 +0000 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2016-02-11 13:06:21 +0000 |
commit | f8ef363cfbe8bf49f841131fc0ea361dc71e85e5 (patch) | |
tree | 1a0ae952128948c06040b1a3bd9c4a53ad950853 /main/omxplayer | |
parent | e51dc3ec2de764ad64fda854fd78f519b9a83524 (diff) | |
download | aports-f8ef363cfbe8bf49f841131fc0ea361dc71e85e5.tar.bz2 aports-f8ef363cfbe8bf49f841131fc0ea361dc71e85e5.tar.xz |
main/omxplayer: upgrade to snapshot of 2016-02-06 + alsa rewrite
alsa support is rewritten properly. the new code is smaller,
faster and more correct. seeking and pause works correct now too.
Diffstat (limited to 'main/omxplayer')
-rw-r--r-- | main/omxplayer/APKBUILD | 20 | ||||
-rw-r--r-- | main/omxplayer/fix-dbus-dispatch.patch | 13 | ||||
-rw-r--r-- | main/omxplayer/omxplayer-alsa.patch | 7664 |
3 files changed, 1313 insertions, 6384 deletions
diff --git a/main/omxplayer/APKBUILD b/main/omxplayer/APKBUILD index 5a0f988009..38428b7677 100644 --- a/main/omxplayer/APKBUILD +++ b/main/omxplayer/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Timo Teräs <timo.teras@iki.fi> pkgname=omxplayer -pkgver=0.20160126 -_commitid=32b732e787e2dda2b045ec6e3156dfe3d85513e3 +pkgver=0.20160206 +_commitid=19efb03b881da0bcc70632eaf7f7292edcf33eeb pkgrel=0 pkgdesc="Commandline OMX player for Raspberry Pi" url="https://github.com/popcornmix/omxplayer" @@ -16,7 +16,6 @@ source="omxplayer-$pkgver.tar.gz::https://github.com/popcornmix/omxplayer/archiv issue-260.patch issue-297.patch fix-makefile.patch - fix-dbus-dispatch.patch default-font.patch omxplayer-alsa.patch @@ -59,30 +58,27 @@ package() { "$pkgdir"/etc/conf.d/$pkgname || return 1 } -md5sums="b0758b93fb5c793d66533368e9e7dc8f omxplayer-0.20160126.tar.gz +md5sums="d4fa33de6e46c49ef6bde16848d849b0 omxplayer-0.20160206.tar.gz a900cdded87b7df503c6599ac43bd8de issue-260.patch c858882036b9fb03859edf7ce4a1d942 issue-297.patch d8f335e1dff4b34faf36c25ad2c2b881 fix-makefile.patch -f56949213d53b8fbd6c0b0e393b9cab0 fix-dbus-dispatch.patch 9ebd96155288809fe0a657cf491e433f default-font.patch -628a9bc0b26f75547299e92542e65d47 omxplayer-alsa.patch +24bc3d0db0fcbd547bec6df454937940 omxplayer-alsa.patch b4054a311d76aef91aa10bacd68bc9c4 omxplayer.initd 80e37e7ac04402808015084e26e6072d omxplayer.confd" -sha256sums="250da0fe32ea400ddf37c50722b09ae6447b04fdfb2976f78539445afa56e61c omxplayer-0.20160126.tar.gz +sha256sums="bfdcd411e759f7791ceace6c700b5ee6f5a6e8b34abbc261f01c32b8e71d559e omxplayer-0.20160206.tar.gz 5eb797de354c63a23847a574b103a28d451a4329320f3335f82dc000adbc5c63 issue-260.patch 389c97df4919a3fe4d115f092cb256246e33374150102f0e2cb9ce11456cadb1 issue-297.patch 799b0aba6aef8c665a685777cd912268315309d0d74ce76be5fdfd0dcffbb422 fix-makefile.patch -2de5b9b51146508ecff219d2c02a7df1c4ba4814b978254b2610d06eb4f6a0a8 fix-dbus-dispatch.patch 2bab3d05b12d730737220b8c0052498a34bbebc12b7beb8afb3c054beb0fb3bb default-font.patch -87dc80b61ce6c69a52637dffb64f526e7fa213e4c2b0c97177457c95851ec594 omxplayer-alsa.patch +dd547f952cdc6d96f565694993817075803a05d4d16c6b51e982244f8980445c omxplayer-alsa.patch e2db0f7ffbe2488dd69ee0bfad006bd863f418554f078ca3432f643de7589d2f omxplayer.initd 530eb9aa50e72fb4828af410b965e0ec7653d1bed87aa86bf04fc340ff3232bd omxplayer.confd" -sha512sums="599cd0179da3ec56d8ed733696ecbb969645dc237c2f50933adad880b9e090c5e850ffd1c56b17d266e3721d6c0694aae1bca4fb8b889403ec11de506e96b09f omxplayer-0.20160126.tar.gz +sha512sums="be14f94876a47b107aea13a23379c0be1df245f064f03b7de7e8cd18fd42a3f5c3a6f2b95a1aa791290c8ea6c202dd9885a76a61d1a56a9a0f6d20dc84e2fa7a omxplayer-0.20160206.tar.gz c349eea5f7c513a07d82a6cf6467c4d21bcb29c053bc5e39d8f675b1212db9beef0abf5248d50ac5a2f14fda73055786f94f421377ffcf5f6bcf8daa2f1b56e8 issue-260.patch 2a8a6def1e09f726cba58c0b9109fa6c4fbd4a3b4f1d27d200488f262a0e0978579d83db7fe24f1d3e03beef318c3674ed79cbd2f1994c4551a59c9fe0f63489 issue-297.patch 3210242f9b834ffec9d3077d5a25caf8be84aa7f4f13c73eb7f61c0a406ec787e4055951fc5a6236f1da7897c95db94a5e11e25d1b3e859a6ea67f31fc6eb517 fix-makefile.patch -fe7d3ff020513a1688333918665468fffefd5b1e94bbc7cac82823e625e64c7894c438a30361deedf7b5545a38bcac2aced7d8ce0ab6bc5ef4d79eba5fa5fa40 fix-dbus-dispatch.patch 8aa58aaa07453186302dc68d92f28c1b50bf0f8fccd50359640a7fc8339b233b32a0c8c02284a9974599e56d69cc557acc25e76e6438c6d64d15afd9c1788a8e default-font.patch -bc11327631453026784a7b80efb259f6f86a670a12dfc3ba8b92b841611db73408ffab89b9c131bc7ff59695a5eef6f3e94af19136ffcfcbac9a9a7362a93f5f omxplayer-alsa.patch +7f12f253321ef25e9645514451b0d57f1d6ec1cada372884d3aa2a1d1529f385490fe0f656f00af7e3bb567c56ba60d4cc310007658841d6e17c92c55ba8184a omxplayer-alsa.patch 3ddd32235d87a46478d0237ee9b253edeb75729e377b09a33069ecdca2ee230d2851f308897ee75ff69a9f3bdd2876f490bc1667a572dce1c186f80fddcf6df3 omxplayer.initd 4f906ada035869a0e515e7615056b18b0f6906ce4b3a2d34081c0efa79bb9455380f729e7c5270180f5ace89c53a7ac7c93f609e6761825f639f44aa22346bb2 omxplayer.confd" diff --git a/main/omxplayer/fix-dbus-dispatch.patch b/main/omxplayer/fix-dbus-dispatch.patch deleted file mode 100644 index ef732c5094..0000000000 --- a/main/omxplayer/fix-dbus-dispatch.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/OMXControl.cpp b/OMXControl.cpp -index 0ef8e5f..834461f 100644 ---- a/OMXControl.cpp -+++ b/OMXControl.cpp -@@ -88,7 +88,7 @@ int OMXControl::init(OMXClock *m_av_clock, OMXPlayerAudio *m_player_audio, OMXPl - void OMXControl::dispatch() - { - if (bus) -- dbus_connection_read_write_dispatch(bus, 0); -+ dbus_connection_read_write(bus, 0); - } - - int OMXControl::dbus_connect(std::string& dbus_name) diff --git a/main/omxplayer/omxplayer-alsa.patch b/main/omxplayer/omxplayer-alsa.patch index 0886b896a3..e1b25f6ed9 100644 --- a/main/omxplayer/omxplayer-alsa.patch +++ b/main/omxplayer/omxplayer-alsa.patch @@ -1,6508 +1,1454 @@ +From 5ff66870da7d3376cba3a927bcb173b87bff9fb5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Tue, 9 Feb 2016 15:25:41 +0200 +Subject: [PATCH] preliminary alsa support + +--- + Makefile | 5 +- + OMXAudio.cpp | 5 +- + OMXAudio.h | 1 + + OMXCore.cpp | 11 + + README.md | 1 + + linux/OMXAlsa.cpp | 1275 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + linux/OMXAlsa.h | 11 + + omxplayer.cpp | 6 +- + 8 files changed, 1310 insertions(+), 5 deletions(-) + create mode 100644 linux/OMXAlsa.cpp + create mode 100644 linux/OMXAlsa.h + diff --git a/Makefile b/Makefile -index 9fc45de..921b449 100644 +index 9fc45de..5337ee7 100644 --- a/Makefile +++ b/Makefile -@@ -8,7 +8,21 @@ INCLUDES+=-I./ -Ilinux -Iffmpeg_compiled/usr/local/include/ -I /usr/include/dbus +@@ -2,13 +2,14 @@ include Makefile.include + + CFLAGS+=-std=c++0x -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -DTARGET_POSIX -DTARGET_LINUX -fPIC -DPIC -D_REENTRANT -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CMAKE_CONFIG -D__VIDEOCORE4__ -U_FORTIFY_SOURCE -Wall -DHAVE_OMXLIB -DUSE_EXTERNAL_FFMPEG -DHAVE_LIBAVCODEC_AVCODEC_H -DHAVE_LIBAVUTIL_OPT_H -DHAVE_LIBAVUTIL_MEM_H -DHAVE_LIBAVUTIL_AVUTIL_H -DHAVE_LIBAVFORMAT_AVFORMAT_H -DHAVE_LIBAVFILTER_AVFILTER_H -DHAVE_LIBSWRESAMPLE_SWRESAMPLE_H -DOMX -DOMX_SKIP64BIT -ftree-vectorize -DUSE_EXTERNAL_OMX -DTARGET_RASPBERRY_PI -DUSE_EXTERNAL_LIBBCM_HOST + +-LDFLAGS+=-L./ -Lffmpeg_compiled/usr/local/lib/ -lc -lWFC -lGLESv2 -lEGL -lbcm_host -lopenmaxil -lfreetype -lz ++LDFLAGS+=-L./ -Lffmpeg_compiled/usr/local/lib/ -lc -lWFC -lGLESv2 -lEGL -lbcm_host -lopenmaxil -lfreetype -lz -lasound + + INCLUDES+=-I./ -Ilinux -Iffmpeg_compiled/usr/local/include/ -I /usr/include/dbus-1.0 -I /usr/lib/arm-linux-gnueabihf/dbus-1.0/include DIST ?= omxplayer-dist -SRC=linux/XMemUtils.cpp \ -+INCLUDES+=-Ialsa -+LDFLAGS+=-lasound -+SRC += \ -+ alsa/omx_semaphore.cpp \ -+ alsa/omx_alsasink_component.cpp \ -+ alsa/omx_base_audio_port.cpp \ -+ alsa/omx_base_clock_port.cpp \ -+ alsa/omx_base_component.cpp \ -+ alsa/omx_base_port.cpp \ -+ alsa/omx_base_sink.cpp \ -+ alsa/omx_queue.cpp \ -+ alsa/omx_loader_XBMC.cpp -+ -+SRC += \ -+ linux/XMemUtils.cpp \ ++SRC= linux/XMemUtils.cpp \ ++ linux/OMXAlsa.cpp \ utils/log.cpp \ DynamicDll.cpp \ utils/PCMRemap.cpp \ -@@ -34,8 +48,9 @@ SRC=linux/XMemUtils.cpp \ - Srt.cpp \ - KeyConfig.cpp \ - OMXControl.cpp \ -- Keyboard.cpp \ -- omxplayer.cpp \ -+ Keyboard.cpp -+ -+SRC += omxplayer.cpp - - OBJS+=$(filter %.o,$(SRC:.cpp=.o)) - -diff --git a/Makefile.include b/Makefile.include -index 58e9560..3b99d3b 100644 ---- a/Makefile.include -+++ b/Makefile.include -@@ -1,40 +1,5 @@ --USE_BUILDROOT=0 --FLOAT=hard -- --ifeq ($(USE_BUILDROOT), 1) --BUILDROOT :=/opt/xbmc-bcm/buildroot --SDKSTAGE :=$(BUILDROOT)/output/staging --TARGETFS :=$(BUILDROOT)/output/target --TOOLCHAIN :=$(BUILDROOT)/output/host/usr/ --HOST :=arm-unknown-linux-gnueabi --SYSROOT :=$(BUILDROOT)/output/host/usr/arm-unknown-linux-gnueabi/sysroot --else --BUILDROOT :=/opt/bcm-rootfs --SDKSTAGE :=/opt/bcm-rootfs --TARGETFS :=/opt/bcm-rootfs --TOOLCHAIN :=/home/dc4/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/ --HOST :=arm-linux-gnueabihf --#SYSROOT :=$(TOOLCHAIN)/arm-bcm2708hardfp-linux-gnueabi/sysroot --SYSROOT :=/opt/bcm-rootfs --endif -- --JOBS=7 -- --CFLAGS := -isystem$(PREFIX)/include --CXXFLAGS := $(CFLAGS) --CPPFLAGS := $(CFLAGS) --LDFLAGS := -L$(BUILDROOT)/lib --LD := $(TOOLCHAIN)/bin/$(HOST)-ld --sysroot=$(SYSROOT) --CC := $(TOOLCHAIN)/bin/$(HOST)-gcc --sysroot=$(SYSROOT) --CXX := $(TOOLCHAIN)/bin/$(HOST)-g++ --sysroot=$(SYSROOT) --OBJDUMP := $(TOOLCHAIN)/bin/$(HOST)-objdump --RANLIB := $(TOOLCHAIN)/bin/$(HOST)-ranlib --STRIP := $(TOOLCHAIN)/bin/$(HOST)-strip --AR := $(TOOLCHAIN)/bin/$(HOST)-ar --CXXCP := $(CXX) -E --PATH := $(PREFIX)/bin:$(BUILDROOT)/output/host/usr/bin:$(PATH) -- --CFLAGS += -pipe -mfloat-abi=$(FLOAT) -mcpu=arm1176jzf-s -fomit-frame-pointer -mabi=aapcs-linux -mtune=arm1176jzf-s -mfpu=vfp -Wno-psabi -mno-apcs-stack-check -g -mstructure-size-boundary=32 -mno-sched-prolog --LDFLAGS += -L$(SDKSTAGE)/lib -L$(SDKSTAGE)/usr/lib -L$(SDKSTAGE)/opt/vc/lib/ -Lpcre/build --#INCLUDES += -isystem$(SDKSTAGE)/usr/include -isystem$(SDKSTAGE)/opt/vc/include -isystem$(SYSROOT)/usr/include -isystem$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -isystem$(SDKSTAGE)/usr/include/freetype2 --INCLUDES += -isystem$(SDKSTAGE)/opt/vc/include -isystem$(SYSROOT)/usr/include -isystem$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -Ipcre/build -Iboost-trunk -Ifreetype2/include -+INCLUDES:=-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux -+INCLUDES+=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -+LDFLAGS:=-L/opt/vc/lib -Wl,-rpath,/opt/vc/lib -+LDFLAGS+=-lfreetype -ldbus-1 -+STRIP:=echo diff --git a/OMXAudio.cpp b/OMXAudio.cpp -index 41f282d..e1e82c4 100644 +index 6da019f..434ced7 100644 --- a/OMXAudio.cpp +++ b/OMXAudio.cpp -@@ -112,6 +112,11 @@ bool COMXAudio::PortSettingsChanged() - if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) +@@ -104,7 +104,8 @@ bool COMXAudio::PortSettingsChanged() + } + if (m_config.device == "omx:both" || m_config.device == "omx:local") + { +- if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) ++ const char *component = m_config.alsa_device.empty() ? "OMX.broadcom.audio_render" : "OMX.alsa.audio_render"; ++ if(!m_omx_render_analog.Initialize(component, OMX_IndexParamAudioInit)) return false; } -+ if (m_config.device == "omx:alsa") -+ { -+ if(!m_omx_render_analog.Initialize("OMX.XBMC.alsa.alsasink", OMX_IndexParamAudioInit)) -+ return false; -+ } - - UpdateAttenuation(); + if (m_config.device == "omx:both" || m_config.device == "omx:hdmi") +@@ -235,7 +236,7 @@ bool COMXAudio::PortSettingsChanged() + OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest; + OMX_INIT_STRUCTURE(audioDest); +- strncpy((char *)audioDest.sName, "local", strlen("local")); ++ strcpy((char *)audioDest.sName, m_config.alsa_device.empty() ? "local" : m_config.alsa_device.c_str()); + omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest); + if (omx_err != OMX_ErrorNone) + { +diff --git a/OMXAudio.h b/OMXAudio.h +index 5b56e97..09d593d 100644 +--- a/OMXAudio.h ++++ b/OMXAudio.h +@@ -46,6 +46,7 @@ public: + COMXStreamInfo hints; + bool use_thread; + CStdString device; ++ CStdString alsa_device; + enum PCMLayout layout; + bool boostOnDownmix; + bool passthrough; diff --git a/OMXCore.cpp b/OMXCore.cpp -index 9d5fe61..389c41e 100644 +index 9d5fe61..548ed2f 100644 --- a/OMXCore.cpp +++ b/OMXCore.cpp @@ -35,6 +35,7 @@ #ifdef TARGET_LINUX #include "XMemUtils.h" -+#include "alsa/omx_loader_XBMC.h" ++#include "OMXAlsa.h" #endif //#define OMX_DEBUG_EVENTS -@@ -1430,6 +1431,12 @@ bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEX +@@ -1429,6 +1430,11 @@ bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEX + // Get video component handle setting up callbacks, component is in loaded state on return. if(!m_handle) { - omx_err = m_DllOMX->OMX_GetHandle(&m_handle, (char*)component_name.c_str(), this, &m_callbacks); +#ifdef TARGET_LINUX -+ if (strncmp("OMX.XBMC.", component_name.c_str(), 9) == 0) -+ omx_err = OMX_GetHandle_XBMC(&m_handle, (char*) component_name.c_str(), this, &m_callbacks); ++ if (strncmp("OMX.alsa.", component_name.c_str(), 9) == 0) ++ omx_err = OMXALSA_GetHandle(&m_handle, (char*) component_name.c_str(), this, &m_callbacks); + else +#endif -+ omx_err = m_DllOMX->OMX_GetHandle(&m_handle, (char*)component_name.c_str(), this, &m_callbacks); + omx_err = m_DllOMX->OMX_GetHandle(&m_handle, (char*)component_name.c_str(), this, &m_callbacks); if (!m_handle || omx_err != OMX_ErrorNone) { - CLog::Log(LOGERROR, "COMXCoreComponent::Initialize - could not get component handle for %s omx_err(0x%08x)\n", -@@ -1505,6 +1512,11 @@ bool COMXCoreComponent::Deinitialize() +@@ -1505,6 +1511,11 @@ bool COMXCoreComponent::Deinitialize() CLog::Log(LOGDEBUG, "COMXCoreComponent::Deinitialize : %s handle %p\n", m_componentName.c_str(), m_handle); +#ifdef TARGET_LINUX -+ if (strncmp("OMX.XBMC.", m_componentName.c_str(), 9) == 0) -+ omx_err = OMX_FreeHandle_XBMC(m_handle); ++ if (strncmp("OMX.alsa.", m_componentName.c_str(), 9) == 0) ++ omx_err = OMXALSA_FreeHandle(m_handle); + else +#endif omx_err = m_DllOMX->OMX_FreeHandle(m_handle); if (omx_err != OMX_ErrorNone) { diff --git a/README.md b/README.md -index 2eb78f3..f70d73c 100644 +index 726127c..cc718b1 100644 --- a/README.md +++ b/README.md -@@ -55,7 +55,7 @@ Usage: omxplayer [OPTIONS] [FILE] - -v --version Print version info +@@ -56,6 +56,7 @@ Usage: omxplayer [OPTIONS] [FILE] -k --keys Print key bindings -n --aidx index Audio stream index : e.g. 1 -- -o --adev device Audio out device : e.g. hdmi/local/both -+ -o --adev device Audio out device : e.g. hdmi/local/both/alsa + -o --adev device Audio out device : e.g. hdmi/local/both ++ -A --alsa device Use alsa device instead of BCM analog output -i --info Dump stream format and exit -I --with-info dump stream format before playback -s --stats Pts and buffer stats -diff --git a/alsa/omx_alsasink_component.cpp b/alsa/omx_alsasink_component.cpp -new file mode 100644 -index 0000000..9803e63 ---- /dev/null -+++ b/alsa/omx_alsasink_component.cpp -@@ -0,0 +1,1035 @@ -+/** -+ @file src/components/alsa/omx_alsasink_component.c -+ -+ OpenMAX ALSA sink component. This component is an audio sink that uses ALSA library. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-08-08 06:56:06 +0200 (Fri, 08 Aug 2008) $ -+ Revision $Rev: 581 $ -+ Author $Author: pankaj_sen $ -+ -+*/ -+ -+#undef OMX_SKIP64BIT -+#include <omx_base_component.h> -+#include <omx_base_audio_port.h> -+#include <omx_base_clock_port.h> -+#include <omx_alsasink_component.h> -+ -+/** Maximum Number of AlsaSink Instance*/ -+#define MAX_COMPONENT_ALSASINK 1 -+ -+/** Number of AlsaSink Instance*/ -+static OMX_U32 noAlsasinkInstance=0; -+ -+#ifdef AV_SYNC_LOG /* for checking AV sync */ //TODO : give seg fault if enabled -+static FILE *fd = NULL; -+#endif -+ -+/** The Constructor -+ */ -+OMX_ERRORTYPE omx_alsasink_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) { -+ int err; -+ int omxErr; -+ omx_base_audio_PortType *pPort; -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private; -+ -+ if (!openmaxStandComp->pComponentPrivate) { -+ openmaxStandComp->pComponentPrivate = calloc(1, sizeof(omx_alsasink_component_PrivateType)); -+ if(openmaxStandComp->pComponentPrivate==NULL) { -+ return OMX_ErrorInsufficientResources; -+ } -+ } -+ -+ omx_alsasink_component_Private = (omx_alsasink_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ omx_alsasink_component_Private->ports = NULL; -+ -+ omxErr = omx_base_sink_Constructor(openmaxStandComp,cComponentName); -+ if (omxErr != OMX_ErrorNone) { -+ return OMX_ErrorInsufficientResources; -+ } -+ -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nStartPortNumber = 0; -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts = 1; -+ -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nStartPortNumber = 1; -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts = 1; -+ -+ /** Allocate Ports and call port constructor. */ -+ if ((omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) -+ && !omx_alsasink_component_Private->ports) { -+ omx_alsasink_component_Private->ports = (omx_base_PortType**)calloc((omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts), sizeof(omx_base_PortType *)); -+ if (!omx_alsasink_component_Private->ports) { -+ return OMX_ErrorInsufficientResources; -+ } -+ omx_alsasink_component_Private->ports[0] = (omx_base_PortType*)calloc(1, sizeof(omx_base_audio_PortType)); -+ if (!omx_alsasink_component_Private->ports[0]) { -+ return OMX_ErrorInsufficientResources; -+ } -+ base_audio_port_Constructor(openmaxStandComp, &omx_alsasink_component_Private->ports[0], 0, OMX_TRUE); -+ -+ omx_alsasink_component_Private->ports[1] = (omx_base_PortType*)calloc(1, sizeof(omx_base_clock_PortType)); -+ if (!omx_alsasink_component_Private->ports[1]) { -+ return OMX_ErrorInsufficientResources; -+ } -+ base_clock_port_Constructor(openmaxStandComp, &omx_alsasink_component_Private->ports[1], 1, OMX_TRUE); -+ omx_alsasink_component_Private->ports[1]->sPortParam.bEnabled = OMX_FALSE; -+ } -+ -+ pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; -+ -+ // set the pPort params, now that the ports exist -+ /** Domain specific section for the ports. */ -+ pPort->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM; -+ /*Input pPort buffer size is equal to the size of the output buffer of the previous component*/ -+ pPort->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE; -+ -+ /* Initializing the function pointers */ -+ omx_alsasink_component_Private->BufferMgmtCallback = omx_alsasink_component_BufferMgmtCallback; -+ omx_alsasink_component_Private->destructor = omx_alsasink_component_Destructor; -+ pPort->Port_SendBufferFunction = omx_alsasink_component_port_SendBufferFunction; -+ pPort->FlushProcessingBuffers = omx_alsasink_component_port_FlushProcessingBuffers; -+ -+ setHeader(&pPort->sAudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); -+ pPort->sAudioParam.nPortIndex = 0; -+ pPort->sAudioParam.nIndex = 0; -+ pPort->sAudioParam.eEncoding = OMX_AUDIO_CodingPCM; -+ -+ /* OMX_AUDIO_PARAM_PCMMODETYPE */ -+ setHeader(&omx_alsasink_component_Private->sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ omx_alsasink_component_Private->sPCMModeParam.nPortIndex = 0; -+ omx_alsasink_component_Private->sPCMModeParam.nChannels = 2; -+ omx_alsasink_component_Private->sPCMModeParam.eNumData = OMX_NumericalDataSigned; -+ omx_alsasink_component_Private->sPCMModeParam.eEndian = OMX_EndianLittle; -+ omx_alsasink_component_Private->sPCMModeParam.bInterleaved = OMX_TRUE; -+ omx_alsasink_component_Private->sPCMModeParam.nBitPerSample = 16; -+ omx_alsasink_component_Private->sPCMModeParam.nSamplingRate = 44100; -+ omx_alsasink_component_Private->sPCMModeParam.ePCMMode = OMX_AUDIO_PCMModeLinear; -+ omx_alsasink_component_Private->sPCMModeParam.eChannelMapping[0] = OMX_AUDIO_ChannelNone; -+ -+/* testing the A/V sync */ -+#ifdef AV_SYNC_LOG -+ fd = fopen("audio_timestamps.out","w"); -+ if(!fd) { -+ DEBUG(DEB_LEV_ERR, "Couldn't open audio timestamp log err=%d\n",errno); -+ } -+#endif -+ -+ noAlsasinkInstance++; -+ if(noAlsasinkInstance > MAX_COMPONENT_ALSASINK) { -+ return OMX_ErrorInsufficientResources; -+ } -+ -+ /* Allocate the playback handle and the hardware parameter structure */ -+ char* name = "default"; -+ if ((err = snd_pcm_open (&omx_alsasink_component_Private->playback_handle, name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot open audio device %s (%s)\n", name, snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ else -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Got playback handle at %p %p in %i\n", omx_alsasink_component_Private->playback_handle, &omx_alsasink_component_Private->playback_handle, getpid()); -+ -+ if (snd_pcm_status_malloc(&omx_alsasink_component_Private->pcm_status) < 0 ) { -+ DEBUG(DEB_LEV_ERR, "%s: failed allocating pcm_status\n", __func__); -+ return OMX_ErrorHardware; -+ } -+ -+ openmaxStandComp->SetParameter = omx_alsasink_component_SetParameter; -+ openmaxStandComp->GetParameter = omx_alsasink_component_GetParameter; -+ openmaxStandComp->GetConfig = omx_alsasink_component_GetConfig; -+ -+ /* Write in the default parameters */ -+ omx_alsasink_component_Private->AudioPCMConfigured = 0; -+ omx_alsasink_component_Private->eState = OMX_TIME_ClockStateStopped; -+ omx_alsasink_component_Private->xScale = 1<<16; -+ -+ if (!omx_alsasink_component_Private->AudioPCMConfigured) { -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring the PCM interface in the Init function\n"); -+ omxErr = omx_alsasink_component_SetParameter(openmaxStandComp, OMX_IndexParamAudioPcm, &omx_alsasink_component_Private->sPCMModeParam); -+ if(omxErr != OMX_ErrorNone){ -+ DEBUG(DEB_LEV_ERR, "In %s Error %08x\n",__func__,omxErr); -+ } -+ } -+ -+ return OMX_ErrorNone; -+} -+ -+/** The Destructor -+ */ -+OMX_ERRORTYPE omx_alsasink_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) { -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private = (omx_alsasink_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ OMX_U32 i; -+ -+ if(omx_alsasink_component_Private->pcm_status) { -+ snd_pcm_status_free(omx_alsasink_component_Private->pcm_status); -+ } -+ if(omx_alsasink_component_Private->playback_handle) { -+ snd_pcm_close(omx_alsasink_component_Private->playback_handle); -+ } -+ -+ /* frees port/s */ -+ if (omx_alsasink_component_Private->ports) { -+ for (i=0; i < (omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts); i++) { -+ if(omx_alsasink_component_Private->ports[i]) -+ omx_alsasink_component_Private->ports[i]->PortDestructor(omx_alsasink_component_Private->ports[i]); -+ } -+ free(omx_alsasink_component_Private->ports); -+ omx_alsasink_component_Private->ports=NULL; -+ } -+ -+#ifdef AV_SYNC_LOG -+ fclose(fd); -+#endif -+ -+ noAlsasinkInstance--; -+ -+ return omx_base_sink_Destructor(openmaxStandComp); -+ -+} -+ -+/** @brief the entry point for sending buffers to the alsa sink port -+ * -+ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on -+ * the nature of the port, that can be an input or output port. -+ */ -+OMX_ERRORTYPE omx_alsasink_component_port_SendBufferFunction(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer) { -+ -+ OMX_ERRORTYPE err; -+ OMX_U32 portIndex; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ OMX_BOOL SendFrame; -+ omx_base_clock_PortType* pClockPort; -+#if NO_GST_OMX_PATCH -+ unsigned int i; -+#endif -+ -+ portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, (unsigned long)portIndex); -+ -+ if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", -+ __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if(omx_base_component_Private->state == OMX_StateInvalid) { -+ DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); -+ return OMX_ErrorInvalidState; -+ } -+ -+ if(omx_base_component_Private->state != OMX_StateExecuting && -+ omx_base_component_Private->state != OMX_StatePause && -+ omx_base_component_Private->state != OMX_StateIdle) { -+ DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || -+ (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && -+ (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { -+ DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ -+ /* Temporarily disable this check for gst-openmax */ -+#if NO_GST_OMX_PATCH -+ { -+ OMX_BOOL foundBuffer = OMX_FALSE; -+ if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { -+ foundBuffer = OMX_TRUE; -+ break; -+ } -+ } -+ } -+ if (!foundBuffer) { -+ return OMX_ErrorBadParameter; -+ } -+ } -+#endif -+ -+ if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); -+ return err; -+ } -+ -+ /* And notify the buffer management thread we have a fresh new buffer to manage */ -+ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ -+ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ //DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", -+ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); -+ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ } -+ else { // If port being flushed and not tunneled then return error -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ return OMX_ErrorNone; -+} -+ -+OMX_ERRORTYPE omx_alsasink_component_GetConfig( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nIndex, -+ OMX_INOUT OMX_PTR pComponentConfigStructure) { -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ if (nIndex == OMX_IndexConfigAudioRenderingLatency) { -+ OMX_PARAM_U32TYPE* param = (OMX_PARAM_U32TYPE*)pComponentConfigStructure; -+ -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private = (omx_alsasink_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ -+ if (param->nPortIndex == OMX_BASE_SINK_INPUTPORT_INDEX ) { -+ // As this is used only as bool, we can return 'just something' here. -+ // TODO: Add appropriate processing when needed -+ param->nU32 = omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]->pBufferQueue->nelem; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s OMX_IndexConfigAudioRenderingLatency return %d\n", __func__, param->nU32); -+ return OMX_ErrorNone; -+ } -+ } -+ -+ return OMX_ErrorNotImplemented; -+} -+ -+ -+OMX_BOOL omx_alsasink_component_ClockPortHandleFunction(omx_alsasink_component_PrivateType* omx_alsasink_component_Private, OMX_BUFFERHEADERTYPE* inputbuffer){ -+ omx_base_clock_PortType* pClockPort; -+ OMX_BUFFERHEADERTYPE* clockBuffer; -+ OMX_TIME_MEDIATIMETYPE* pMediaTime; -+ OMX_HANDLETYPE hclkComponent; -+ OMX_TIME_CONFIG_TIMESTAMPTYPE sClientTimeStamp; -+ OMX_ERRORTYPE err; -+ OMX_BOOL SendFrame=OMX_TRUE; -+ omx_base_audio_PortType *pAudioPort; -+ -+ int static count=0; //frame counter -+ -+ pClockPort = (omx_base_clock_PortType*)omx_alsasink_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; -+ pAudioPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; -+ hclkComponent = pClockPort->hTunneledComponent; -+ setHeader(&pClockPort->sMediaTimeRequest, sizeof(OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE)); -+ -+ /* check for any scale change information from the clock component */ -+ if(pClockPort->pBufferSem->semval>0){ -+ omx_tsem_down(pClockPort->pBufferSem); -+ if(pClockPort->pBufferQueue->nelem > 0) { -+ clockBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(pClockPort->pBufferQueue); -+ pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; -+ if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { -+ //if((pMediaTime->xScale>>16)==1){ /* check with Q16 format only */ -+ // /* rebase the clock time base when turning to normal play mode*/ -+ // hclkComponent = pClockPort->hTunneledComponent; -+ // setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); -+ // sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; -+ // sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; -+ // err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentAudioReference, &sClientTimeStamp); -+ // if(err!=OMX_ErrorNone) { -+ // DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s line=%d\n",err,__func__, __LINE__); -+ // } -+ //} -+ omx_alsasink_component_Private->eState = pMediaTime->eState; -+ omx_alsasink_component_Private->xScale = pMediaTime->xScale; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s OMX_TIME_UpdateScaleChanged Line=%d new eState=%d xScale=%d\n", -+ __func__, __LINE__, pMediaTime->eState, pMediaTime->xScale); -+ /// AND -+ } else if(pMediaTime->eUpdateType==OMX_TIME_UpdateClockStateChanged) { -+ omx_alsasink_component_Private->eState = pMediaTime->eState; -+ omx_alsasink_component_Private->xScale = pMediaTime->xScale; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s OMX_TIME_UpdateClockStateChanged Line=%d new eState=%d xScale=%d\n", -+ __func__, __LINE__, pMediaTime->eState, pMediaTime->xScale); -+ } -+ /// AND -+ pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); -+ } -+ } -+ -+ /* if first time stamp is received then notify the clock component */ -+ if(inputbuffer->nFlags == OMX_BUFFERFLAG_STARTTIME) { -+ DEBUG(DEB_LEV_FULL_SEQ,"In %s first time stamp = %llx \n", __func__,(long long)inputbuffer->nTimeStamp); -+ inputbuffer->nFlags = 0; -+ hclkComponent = pClockPort->hTunneledComponent; -+ setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); -+ sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; -+ sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; -+ err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeClientStartTime, &sClientTimeStamp); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); -+ } -+ -+ if(!PORT_IS_BEING_FLUSHED(pAudioPort) && !PORT_IS_BEING_FLUSHED(pClockPort)) { -+ omx_tsem_down(pClockPort->pBufferSem); /* wait for state change notification from clock src*/ -+ -+ /* update the clock state and clock scale info into the alsa sink private data */ -+ if(pClockPort->pBufferQueue->nelem > 0) { -+ clockBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(pClockPort->pBufferQueue); -+ pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; -+ omx_alsasink_component_Private->eState = pMediaTime->eState; -+ omx_alsasink_component_Private->xScale = pMediaTime->xScale; -+ pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); -+ } -+ } -+ } -+ -+ /* do not send the data to alsa and return back, if the clock is not running or the scale is anything but 1*/ -+ /*if(!(omx_alsasink_component_Private->eState==OMX_TIME_ClockStateRunning && omx_alsasink_component_Private->xScale==(1<<16))){ -+ // TODO: 0 means PAUSED. is correct to keep that frame? -+ if ((omx_alsasink_component_Private->xScale!=0) && (omx_alsasink_component_Private->xScale!=(1<<16))){ -+ inputbuffer->nFilledLen=0; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Dropping frame !!!!! eState=%d xScale=%d\n", __func__, omx_alsasink_component_Private->eState, omx_alsasink_component_Private->xScale); -+ } -+ //return; -+ SendFrame = OMX_FALSE; -+ return SendFrame; -+ }*/ -+ -+ count++; -+ if(count==15) { //send request for every 15th frame -+ count=0; -+ -+ OMX_TIME_CONFIG_TIMESTAMPTYPE ts; -+ setHeader(&ts, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); -+ ts.nPortIndex = pClockPort->nTunneledPort; -+ -+ snd_pcm_sframes_t avail = 0; -+ int diff = 0; -+ snd_pcm_sframes_t delay = 0; -+ -+ OMX_AUDIO_PARAM_PCMMODETYPE* sPCMModeParam = &omx_alsasink_component_Private->sPCMModeParam; -+ -+ //snd_pcm_delay(omx_alsasink_component_Private->playback_handle, &delay); -+ // snd_pcm_avail() & snd_pcm_avail_update() are broken on raspberry pi!!!! -+ //avail = snd_pcm_avail(omx_alsasink_component_Private->playback_handle); -+ -+ if (snd_pcm_status(omx_alsasink_component_Private->playback_handle, omx_alsasink_component_Private->pcm_status) < 0) { -+ DEBUG(DEB_LEV_ERR,"In %s unable to obtain pcm_status.\n",__func__); -+ } -+ -+ delay = snd_pcm_status_get_delay(omx_alsasink_component_Private->pcm_status); -+ avail = (snd_pcm_sframes_t) snd_pcm_status_get_avail(omx_alsasink_component_Private->pcm_status); -+ -+ diff = ((double)(delay - avail) / sPCMModeParam->nSamplingRate) * 1000 * 1000; // in microseconds !!! -+ -+ //DEBUG(DEB_LEV_FULL_SEQ,"In %s delay=%d avail=%d diff=%d inputbuffer->nTimeStamp=%lld corected nTimeStamp=%lld\n", -+ // __func__, delay, avail, diff, inputbuffer->nTimeStamp, inputbuffer->nTimeStamp - (OMX_TICKS)diff); -+ -+ ts.nTimestamp = inputbuffer->nTimeStamp - (OMX_TICKS)diff; -+ -+ if (OMX_ErrorNone != OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentAudioReference,&ts)) { -+ DEBUG(DEB_LEV_ERR,"In %s unable to update reference clock.\n",__func__); -+ } -+ -+#if 0 -+ /* requesting for the timestamp for the data delivery */ -+ if(!PORT_IS_BEING_FLUSHED(pAudioPort) && !PORT_IS_BEING_FLUSHED(pClockPort)&& -+ omx_alsasink_component_Private->transientState != OMX_TransStateExecutingToIdle) { -+ pClockPort->sMediaTimeRequest.nOffset = 100; /*set the requested offset */ -+ pClockPort->sMediaTimeRequest.nPortIndex = pClockPort->nTunneledPort; -+ pClockPort->sMediaTimeRequest.pClientPrivate = NULL; /* fill the appropriate value */ -+ pClockPort->sMediaTimeRequest.nMediaTimestamp = inputbuffer->nTimeStamp; -+ err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeMediaTimeRequest, &pClockPort->sMediaTimeRequest); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s \n",err,__func__); -+ } -+ if(!PORT_IS_BEING_FLUSHED(pAudioPort) && !PORT_IS_BEING_FLUSHED(pClockPort) && -+ omx_alsasink_component_Private->transientState != OMX_TransStateExecutingToIdle) { -+ omx_tsem_down(pClockPort->pBufferSem); /* wait for the request fullfillment */ -+ if(pClockPort->pBufferQueue->nelem > 0) { -+ clockBuffer = omx_dequeue(pClockPort->pBufferQueue); -+ pMediaTime = (OMX_TIME_MEDIATIMETYPE*)clockBuffer->pBuffer; -+ if(pMediaTime->eUpdateType==OMX_TIME_UpdateScaleChanged) { -+ /// AND -+ //if((pMediaTime->xScale>>16)==1){ /* check with Q16 format only */ -+ // /* rebase the clock time base when turning to normal play mode*/ -+ // hclkComponent = pClockPort->hTunneledComponent; -+ // setHeader(&sClientTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); -+ // sClientTimeStamp.nPortIndex = pClockPort->nTunneledPort; -+ // sClientTimeStamp.nTimestamp = inputbuffer->nTimeStamp; -+ // err = OMX_SetConfig(hclkComponent, OMX_IndexConfigTimeCurrentAudioReference, &sClientTimeStamp); -+ // if(err!=OMX_ErrorNone) { -+ // DEBUG(DEB_LEV_ERR,"Error %08x In OMX_SetConfig in func=%s line=%d\n",err,__func__, __LINE__); -+ // } -+ //} -+ /// AND -+ omx_alsasink_component_Private->eState = pMediaTime->eState; -+ omx_alsasink_component_Private->xScale = pMediaTime->xScale; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s OMX_TIME_UpdateScaleChanged Line=%d new eState=%d xScale=%d\n", -+ __func__, __LINE__, pMediaTime->eState, pMediaTime->xScale); -+ /// AND -+ } else if(pMediaTime->eUpdateType==OMX_TIME_UpdateClockStateChanged) { -+ omx_alsasink_component_Private->eState = pMediaTime->eState; -+ omx_alsasink_component_Private->xScale = pMediaTime->xScale; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s OMX_TIME_UpdateClockStateChanged Line=%d new eState=%d xScale=%d\n", -+ __func__, __LINE__, pMediaTime->eState, pMediaTime->xScale); -+ } -+ /// AND -+ if(pMediaTime->eUpdateType==OMX_TIME_UpdateRequestFulfillment) { -+ if((pMediaTime->nOffset)>0) { -+#ifdef AV_SYNC_LOG -+ fprintf(fd,"%lld %lld\n",inputbuffer->nTimeStamp,pMediaTime->nWallTimeAtMediaTime); -+#endif -+ SendFrame = OMX_TRUE; /* as offset is >0 send the data to the device */ -+ } -+ else { -+ SendFrame = OMX_FALSE; /* as offset is <0 do not send the data to the device */ -+ //DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s Dropping frame !!!!! nOffset>0 !!! nOffset=%ll\n", __func__, pMediaTime->nOffset); -+ } -+ } -+ pClockPort->ReturnBufferFunction((omx_base_PortType*)pClockPort,clockBuffer); -+ } -+ } -+ } -+#endif -+ } -+ -+ return(SendFrame); -+} -+ -+/** @brief Releases buffers under processing. -+ * This function must be implemented in the derived classes, for the -+ * specific processing -+ */ -+OMX_ERRORTYPE omx_alsasink_component_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort) { -+ omx_base_component_PrivateType* omx_base_component_Private; -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private; -+ OMX_BUFFERHEADERTYPE* pBuffer; -+ omx_base_clock_PortType *pClockPort; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; -+ omx_alsasink_component_Private = ( omx_alsasink_component_PrivateType*) omx_base_component_Private; -+ -+ pClockPort = (omx_base_clock_PortType*) omx_alsasink_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; -+ -+ if (!PORT_IS_ENABLED(openmaxStandPort) || PORT_IS_BEING_DISABLED(openmaxStandPort)) { -+ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s ---------- waiting for buffers. qelem=%d\n",__func__,openmaxStandPort->pBufferQueue->nelem); -+ int nRetry = 0; -+ while((openmaxStandPort->pBufferQueue->nelem != openmaxStandPort->nNumAssignedBuffers) && -+ (nRetry < TUNNEL_USE_BUFFER_RETRY)){ -+ usleep(TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME); -+ nRetry++; -+ } -+ if (nRetry == TUNNEL_USE_BUFFER_RETRY){ -+ // In some rare cases we can't collect all buffers back -+ DEBUG(DEB_LEV_ERR, "In %s Failed to get buffers back. Got a buffer qelem=%d\n",__func__,openmaxStandPort->pBufferQueue->nelem); -+ } -+ else{ -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s All buffers returned in %d iterations.\n",__func__, nRetry); -+ } -+ -+ omx_tsem_reset(openmaxStandPort->pBufferSem); -+ } -+ return OMX_ErrorNone; -+ } -+ -+ if(openmaxStandPort->sPortParam.eDomain!=OMX_PortDomainOther) { /* clock buffers not used in the clients buffer managment function */ -+ pthread_mutex_lock(&omx_base_component_Private->flush_mutex); -+ openmaxStandPort->bIsPortFlushed=OMX_TRUE; -+ /*Signal the buffer management thread of port flush,if it is waiting for buffers*/ -+ if(omx_base_component_Private->bMgmtSem->semval==0) { -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ -+ if(omx_base_component_Private->state==OMX_StatePause ) { -+ /*Waiting at paused state*/ -+ omx_tsem_signal(omx_base_component_Private->bStateSem); -+ } -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s waiting for flush all condition port index =%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); -+ /* Wait until flush is completed */ -+ pthread_mutex_unlock(&omx_base_component_Private->flush_mutex); -+ -+ /*Dummy signal to clock port*/ -+ if(pClockPort->pBufferSem->semval == 0) { -+ omx_tsem_up(pClockPort->pBufferSem); -+ } -+ omx_tsem_down(omx_base_component_Private->flush_all_condition); -+ if(pClockPort->pBufferSem->semval > 0) { -+ omx_tsem_down(pClockPort->pBufferSem); -+ } -+ } -+ -+ omx_tsem_reset(omx_base_component_Private->bMgmtSem); -+ -+ /* Flush all the buffers not under processing */ -+ while (openmaxStandPort->pBufferSem->semval > 0) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s TFlag=%x Flusing Port=%d,Semval=%d Qelem=%d\n", -+ __func__,(int)openmaxStandPort->nTunnelFlags,(int)openmaxStandPort->sPortParam.nPortIndex, -+ (int)openmaxStandPort->pBufferSem->semval,(int)openmaxStandPort->pBufferQueue->nelem); -+ -+ omx_tsem_down(openmaxStandPort->pBufferSem); -+ pBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(openmaxStandPort->pBufferQueue); -+ if (PORT_IS_TUNNELED(openmaxStandPort)) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s is returning io:%d buffer\n", -+ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); -+ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ } else { -+ ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ } -+ } else { -+ (*(openmaxStandPort->BufferProcessedCallback))( -+ openmaxStandPort->standCompContainer, -+ omx_base_component_Private->callbackData, -+ pBuffer); -+ } -+ } -+ -+ pthread_mutex_lock(&omx_base_component_Private->flush_mutex); -+ openmaxStandPort->bIsPortFlushed=OMX_FALSE; -+ pthread_mutex_unlock(&omx_base_component_Private->flush_mutex); -+ -+ omx_tsem_up(omx_base_component_Private->flush_condition); -+ -+ DEBUG(DEB_LEV_FULL_SEQ, "Out %s Port Index=%d bIsPortFlushed=%d Component %s\n", __func__, -+ (int)openmaxStandPort->sPortParam.nPortIndex,(int)openmaxStandPort->bIsPortFlushed,omx_base_component_Private->name); -+ -+ DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__, -+ (int)openmaxStandPort->nTunnelFlags, -+ (int)openmaxStandPort->pBufferQueue->nelem, -+ (int)openmaxStandPort->pBufferSem->semval, -+ (int)omx_base_component_Private->bMgmtSem->semval, -+ omx_base_component_Private->name); -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); -+ -+ return OMX_ErrorNone; -+} -+ -+/** -+ * This function plays the input buffer. When fully consumed it returns. -+ */ -+void omx_alsasink_component_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* inputbuffer) { -+ OMX_U32 frameSize; -+ OMX_S32 written; -+ OMX_S32 totalBuffer; -+ OMX_S32 offsetBuffer; -+ OMX_BOOL allDataSent; -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private = (omx_alsasink_component_PrivateType*) openmaxStandComp->pComponentPrivate; -+ -+ frameSize = (omx_alsasink_component_Private->sPCMModeParam.nChannels * omx_alsasink_component_Private->sPCMModeParam.nBitPerSample) >> 3; -+ //DEBUG(DEB_LEV_FULL_SEQ, "Framesize is %u chl=%d bufSize=%d\n", -+ //(int)frameSize, (int)omx_alsasink_component_Private->sPCMModeParam.nChannels, (int)inputbuffer->nFilledLen); -+ -+ if(inputbuffer->nFilledLen < frameSize){ -+ DEBUG(DEB_LEV_ERR, "Ouch!! In %s input buffer filled len(%d) less than frame size(%d)\n",__func__, (int)inputbuffer->nFilledLen, (int)frameSize); -+ return; -+ } -+ -+ allDataSent = OMX_FALSE; -+ -+ totalBuffer = inputbuffer->nFilledLen/frameSize; -+ -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omx_alsasink_component_Private; -+ omx_base_clock_PortType*pClockPort = (omx_base_clock_PortType*)omx_base_component_Private->ports[OMX_BASE_SINK_CLOCKPORT_INDEX]; -+ omx_base_PortType *openmaxStandPort = omx_base_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; -+ if(PORT_IS_TUNNELED(pClockPort) && !PORT_IS_BEING_FLUSHED(openmaxStandPort) && -+ (omx_base_component_Private->transientState != OMX_TransStateExecutingToIdle) && -+ (inputbuffer->nFlags != OMX_BUFFERFLAG_EOS)){ -+ omx_alsasink_component_ClockPortHandleFunction(omx_alsasink_component_Private, inputbuffer); -+ if(inputbuffer->nFilledLen == 0) -+ { -+ // Dropped frame by clock -+ return; -+ } -+ } -+ -+ /* Feed it to ALSA */ -+ -+ offsetBuffer = 0; -+ while (!allDataSent) { -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Writing to the device ..\n"); -+ written = snd_pcm_writei(omx_alsasink_component_Private->playback_handle, inputbuffer->pBuffer + (offsetBuffer * frameSize), totalBuffer); -+ if (written < 0) { -+ if(written == -EPIPE){ -+ DEBUG(DEB_LEV_ERR, "ALSA Underrun..\n"); -+ snd_pcm_prepare(omx_alsasink_component_Private->playback_handle); -+ written = 0; -+ } else { -+ DEBUG(DEB_LEV_ERR, "Cannot send any data to the audio device %s (%s)\n", "default", snd_strerror (written)); -+ DEBUG(DEB_LEV_ERR, "IB FilledLen=%d,totalBuffer=%d,frame size=%d,offset=%d\n", -+ (int)inputbuffer->nFilledLen, (int)totalBuffer, (int)frameSize, (int)offsetBuffer); -+ break; -+ return; -+ } -+ } -+ -+ if(written != totalBuffer){ -+ totalBuffer = totalBuffer - written; -+ offsetBuffer = written; -+ } else { -+ DEBUG(DEB_LEV_FULL_SEQ, "Buffer successfully sent to ALSA. Length was %i\n", (int)inputbuffer->nFilledLen); -+ allDataSent = OMX_TRUE; -+ } -+ } -+ -+ inputbuffer->nFilledLen=0; -+} -+ -+OMX_ERRORTYPE omx_alsasink_component_SetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_IN OMX_PTR ComponentParameterStructure) -+{ -+ int err; -+ OMX_ERRORTYPE omxErr = OMX_ErrorNone; -+ OMX_AUDIO_PARAM_PORTFORMATTYPE *pAudioPortFormat; -+ OMX_OTHER_PARAM_PORTFORMATTYPE *pOtherPortFormat; -+ OMX_AUDIO_PARAM_MP3TYPE * pAudioMp3; -+ OMX_U32 portIndex; -+ -+ /* Check which structure we are being fed and make control its header */ -+ OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent; -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private = (omx_alsasink_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ omx_base_audio_PortType* pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; -+ omx_base_clock_PortType *pClockPort; -+ snd_pcm_t* playback_handle = omx_alsasink_component_Private->playback_handle; -+ -+ if (ComponentParameterStructure == NULL) { -+ return OMX_ErrorBadParameter; -+ } -+ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, " Setting parameter %i\n", nParamIndex); -+ -+ switch(nParamIndex) { -+ case OMX_IndexParamAudioPortFormat: -+ pAudioPortFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure; -+ portIndex = pAudioPortFormat->nPortIndex; -+ /*Check Structure Header and verify component state*/ -+ omxErr = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pAudioPortFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); -+ if(omxErr!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, omxErr); -+ break; -+ } -+ if (portIndex < 1) { -+ memcpy(&pPort->sAudioParam,pAudioPortFormat,sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); -+ } else { -+ return OMX_ErrorBadPortIndex; -+ } -+ break; -+ case OMX_IndexParamOtherPortFormat: -+ pOtherPortFormat = (OMX_OTHER_PARAM_PORTFORMATTYPE*)ComponentParameterStructure; -+ portIndex = pOtherPortFormat->nPortIndex; -+ err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pOtherPortFormat, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE)); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err); -+ break; -+ } -+ if(portIndex != 1) { -+ return OMX_ErrorBadPortIndex; -+ } -+ pClockPort = (omx_base_clock_PortType *) omx_alsasink_component_Private->ports[portIndex]; -+ -+ pClockPort->sOtherParam.eFormat = pOtherPortFormat->eFormat; -+ break; -+ case OMX_IndexParamAudioPcm: -+ { -+ unsigned int rate; -+ OMX_AUDIO_PARAM_PCMMODETYPE* sPCMModeParam = (OMX_AUDIO_PARAM_PCMMODETYPE*)ComponentParameterStructure; -+ snd_pcm_hw_params_t *hw_params; -+ snd_pcm_hw_params_alloca(&hw_params); -+ -+ /** Each time we are (re)configuring the hw_params thing -+ * we need to reinitialize it, otherwise previous changes will not take effect. -+ * e.g.: changing a previously configured sampling rate does not have -+ * any effect if we are not calling this each time. -+ */ -+ snd_pcm_hw_params_any(omx_alsasink_component_Private->playback_handle, hw_params); -+ -+ portIndex = sPCMModeParam->nPortIndex; -+ /*Check Structure Header and verify component state*/ -+ omxErr = omx_base_component_ParameterSanityCheck(hComponent, portIndex, sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ if(omxErr!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, omxErr); -+ break; -+ } -+ -+ omx_alsasink_component_Private->AudioPCMConfigured = 1; -+ if(sPCMModeParam->nPortIndex != omx_alsasink_component_Private->sPCMModeParam.nPortIndex){ -+ DEBUG(DEB_LEV_ERR, "Error setting input pPort index\n"); -+ omxErr = OMX_ErrorBadParameter; -+ break; -+ } -+ -+ if(snd_pcm_hw_params_set_channels(playback_handle, hw_params, sPCMModeParam->nChannels)){ -+ DEBUG(DEB_LEV_ERR, "Error setting number of channels\n"); -+ return OMX_ErrorBadParameter; -+ } -+ -+ if(sPCMModeParam->bInterleaved == OMX_TRUE){ -+ if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set access type intrleaved (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ } -+ else{ -+ if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set access type non interleaved (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ } -+ rate = sPCMModeParam->nSamplingRate; -+ if ((err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set sample rate (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ else{ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Set correctly sampling rate from %lu to %lu\n", (unsigned long)sPCMModeParam->nSamplingRate, (unsigned long)rate); -+ sPCMModeParam->nSamplingRate = rate; -+ } -+ -+ if(sPCMModeParam->ePCMMode == OMX_AUDIO_PCMModeLinear){ -+ snd_pcm_format_t snd_pcm_format = SND_PCM_FORMAT_UNKNOWN; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Bit per sample %i, signed=%i, little endian=%i\n", -+ (int)sPCMModeParam->nBitPerSample, -+ (int)sPCMModeParam->eNumData == OMX_NumericalDataSigned, -+ (int)sPCMModeParam->eEndian == OMX_EndianLittle); -+ -+ switch(sPCMModeParam->nBitPerSample){ -+ case 8: -+ if(sPCMModeParam->eNumData == OMX_NumericalDataSigned) { -+ snd_pcm_format = SND_PCM_FORMAT_S8; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_U8; -+ } -+ break; -+ case 16: -+ if(sPCMModeParam->eNumData == OMX_NumericalDataSigned){ -+ if(sPCMModeParam->eEndian == OMX_EndianLittle) { -+ snd_pcm_format = SND_PCM_FORMAT_S16_LE; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_S16_BE; -+ } -+ } -+ if(sPCMModeParam->eNumData == OMX_NumericalDataUnsigned){ -+ if(sPCMModeParam->eEndian == OMX_EndianLittle){ -+ snd_pcm_format = SND_PCM_FORMAT_U16_LE; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_U16_BE; -+ } -+ } -+ break; -+ case 24: -+ if(sPCMModeParam->eNumData == OMX_NumericalDataSigned){ -+ if(sPCMModeParam->eEndian == OMX_EndianLittle) { -+ snd_pcm_format = SND_PCM_FORMAT_S24_LE; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_S24_BE; -+ } -+ } -+ if(sPCMModeParam->eNumData == OMX_NumericalDataUnsigned){ -+ if(sPCMModeParam->eEndian == OMX_EndianLittle) { -+ snd_pcm_format = SND_PCM_FORMAT_U24_LE; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_U24_BE; -+ } -+ } -+ break; -+ -+ case 32: -+ if(sPCMModeParam->eNumData == OMX_NumericalDataSigned){ -+ if(sPCMModeParam->eEndian == OMX_EndianLittle) { -+ snd_pcm_format = SND_PCM_FORMAT_S32_LE; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_S32_BE; -+ } -+ } -+ if(sPCMModeParam->eNumData == OMX_NumericalDataUnsigned){ -+ if(sPCMModeParam->eEndian == OMX_EndianLittle) { -+ snd_pcm_format = SND_PCM_FORMAT_U32_LE; -+ } else { -+ snd_pcm_format = SND_PCM_FORMAT_U32_BE; -+ } -+ } -+ break; -+ default: -+ omxErr = OMX_ErrorBadParameter; -+ break; -+ } -+ -+ if(snd_pcm_format != SND_PCM_FORMAT_UNKNOWN){ -+ if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, snd_pcm_format)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set sample format (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ } else{ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "ALSA OMX_IndexParamAudioPcm configured\n"); -+ memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ } -+ } -+ else if(sPCMModeParam->ePCMMode == OMX_AUDIO_PCMModeALaw){ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring ALAW format\n\n"); -+ if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_A_LAW)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set sample format (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ } -+ else if(sPCMModeParam->ePCMMode == OMX_AUDIO_PCMModeMULaw){ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring ALAW format\n\n"); -+ if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_MU_LAW)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set sample format (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ memcpy(&omx_alsasink_component_Private->sPCMModeParam, ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ } -+ -+ snd_pcm_uframes_t periodSize, bufferSize; -+ bufferSize = sPCMModeParam->nSamplingRate / 5; -+ periodSize = bufferSize / 4; //sPCMModeParam->nSamplingRate / 20; -+ -+ snd_pcm_uframes_t periodSizeMax = bufferSize / 3; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "trying snd_pcm_hw_params_set_period_size_max (%d)\n", (int)periodSizeMax); -+ if ((err = snd_pcm_hw_params_set_period_size_max(omx_alsasink_component_Private->playback_handle, hw_params, &periodSizeMax, NULL)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot snd_pcm_hw_params_set_period_size_max (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "trying snd_pcm_hw_params_set_buffer_size_near (%d)\n", (int)bufferSize); -+ if ((err = snd_pcm_hw_params_set_buffer_size_near(omx_alsasink_component_Private->playback_handle, hw_params, &bufferSize)) < 0) { -+ //if (err = snd_pcm_hw_params_set_buffer_size(omx_alsasink_component_Private->playback_handle, hw_params, bufferSize) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot snd_pcm_hw_params_set_buffer_size_near (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "snd_pcm_hw_params_set_buffer_size_near returned (%d)\n", (int)bufferSize); -+ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "trying snd_pcm_hw_params_set_period_size_near (%d)\n", (int)periodSize); -+ if ((err = snd_pcm_hw_params_set_period_size_near(omx_alsasink_component_Private->playback_handle, hw_params, &periodSize, NULL)) < 0) { -+ //if (err = snd_pcm_hw_params_set_period_size(omx_alsasink_component_Private->playback_handle, hw_params, periodSize, 0) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot snd_pcm_hw_params_set_period_size_near (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "snd_pcm_hw_params_set_period_size_near returned (%d)\n", (int)periodSize); -+ /* -+ unsigned int val = 200000; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "trying snd_pcm_hw_params_set_buffer_time_near (%d)\n", val); -+ if (err = snd_pcm_hw_params_set_buffer_time_near(omx_alsasink_component_Private->playback_handle, hw_params, &val, NULL) < 0 ) { -+ DEBUG(DEB_LEV_ERR, "cannot snd_pcm_hw_params_set_buffer_time (%s)\n", snd_strerror (err)); -+ return; -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "snd_pcm_hw_params_set_buffer_time_near returned (%d)\n", val); -+ */ -+ -+ /** Configure and prepare the ALSA handle */ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Configuring the PCM interface\n"); -+ if ((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot set parameters (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ -+ if ((err = snd_pcm_prepare (playback_handle)) < 0) { -+ DEBUG(DEB_LEV_ERR, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); -+ return OMX_ErrorHardware; -+ } -+ } -+ break; -+ case OMX_IndexParamAudioMp3: -+ pAudioMp3 = (OMX_AUDIO_PARAM_MP3TYPE*)ComponentParameterStructure; -+ /*Check Structure Header and verify component state*/ -+ omxErr = omx_base_component_ParameterSanityCheck(hComponent, pAudioMp3->nPortIndex, pAudioMp3, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); -+ if(omxErr != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, omxErr); -+ break; -+ } -+ break; -+ default: /*Call the base component function*/ -+ return omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure); -+ } -+ return omxErr; -+} -+ -+OMX_ERRORTYPE omx_alsasink_component_GetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_INOUT OMX_PTR ComponentParameterStructure) -+{ -+ OMX_AUDIO_PARAM_PORTFORMATTYPE *pAudioPortFormat; -+ OMX_OTHER_PARAM_PORTFORMATTYPE *pOtherPortFormat; -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent; -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private = (omx_alsasink_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ omx_base_audio_PortType *pPort = (omx_base_audio_PortType *) omx_alsasink_component_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; -+ omx_base_clock_PortType *pClockPort = (omx_base_clock_PortType *) omx_alsasink_component_Private->ports[1]; -+ if (ComponentParameterStructure == NULL) { -+ return OMX_ErrorBadParameter; -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ, " Getting parameter %i\n", nParamIndex); -+ /* Check which structure we are being fed and fill its header */ -+ switch(nParamIndex) { -+ case OMX_IndexParamAudioInit: -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ memcpy(ComponentParameterStructure, &omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainAudio], sizeof(OMX_PORT_PARAM_TYPE)); -+ break; -+ case OMX_IndexParamOtherInit: -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ memcpy(ComponentParameterStructure, &omx_alsasink_component_Private->sPortTypesParam[OMX_PortDomainOther], sizeof(OMX_PORT_PARAM_TYPE)); -+ break; -+ case OMX_IndexParamAudioPortFormat: -+ pAudioPortFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE*)ComponentParameterStructure; -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ if (pAudioPortFormat->nPortIndex < 1) { -+ memcpy(pAudioPortFormat, &pPort->sAudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); -+ } else { -+ return OMX_ErrorBadPortIndex; -+ } -+ break; -+ case OMX_IndexParamAudioPcm: -+ if(((OMX_AUDIO_PARAM_PCMMODETYPE*)ComponentParameterStructure)->nPortIndex != -+ omx_alsasink_component_Private->sPCMModeParam.nPortIndex) { -+ return OMX_ErrorBadParameter; -+ } -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ memcpy(ComponentParameterStructure, &omx_alsasink_component_Private->sPCMModeParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); -+ break; -+ case OMX_IndexParamOtherPortFormat: -+ -+ pOtherPortFormat = (OMX_OTHER_PARAM_PORTFORMATTYPE*)ComponentParameterStructure; -+ -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ if (pOtherPortFormat->nPortIndex == 1) { -+ memcpy(pOtherPortFormat, &pClockPort->sOtherParam, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE)); -+ } else { -+ return OMX_ErrorBadPortIndex; -+ } -+ break; -+ default: /*Call the base component function*/ -+ return omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); -+ } -+ return err; -+} -diff --git a/alsa/omx_alsasink_component.h b/alsa/omx_alsasink_component.h -new file mode 100644 -index 0000000..a6f2e7d ---- /dev/null -+++ b/alsa/omx_alsasink_component.h -@@ -0,0 +1,94 @@ -+/** -+ @file src/components/alsa/omx_alsasink_component.h -+ -+ OpenMAX ALSA sink component. This component is an audio sink that uses ALSA library. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-08-08 06:56:06 +0200 (Fri, 08 Aug 2008) $ -+ Revision $Rev: 581 $ -+ Author $Author: pankaj_sen $ -+ -+*/ -+ -+#ifndef _OMX_ALSASINK_COMPONENT_H_ -+#define _OMX_ALSASINK_COMPONENT_H_ -+ -+//#include <OMX_Types.h> -+//#include <IL/OMX_Component.h> -+//#include <IL/OMX_Core.h> -+//#include <IL/OMX_Audio.h> -+#include <pthread.h> -+#include <omx_base_sink.h> -+#include <alsa/asoundlib.h> -+ -+/** Alsasinkport component private structure. -+ * see the define above -+ * @param sPCMModeParam Audio PCM specific OpenMAX parameter -+ * @param AudioPCMConfigured boolean flag to check if the audio has been configured -+ * @param playback_handle ALSA specif handle for audio player -+ * @param xScale the scale of the media clock -+ * @param eState the state of the media clock -+ * @param hw_params ALSA specif hardware parameters -+ */ -+DERIVEDCLASS(omx_alsasink_component_PrivateType, omx_base_sink_PrivateType) -+#define omx_alsasink_component_PrivateType_FIELDS omx_base_sink_PrivateType_FIELDS \ -+ OMX_AUDIO_PARAM_PCMMODETYPE sPCMModeParam; \ -+ char AudioPCMConfigured; \ -+ snd_pcm_t* playback_handle; \ -+ snd_pcm_status_t* pcm_status; \ -+ OMX_S32 xScale; \ -+ OMX_TIME_CLOCKSTATE eState; -+ENDCLASS(omx_alsasink_component_PrivateType) -+ -+/* Component private entry points declaration */ -+OMX_ERRORTYPE omx_alsasink_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName); -+OMX_ERRORTYPE omx_alsasink_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp); -+ -+void omx_alsasink_component_BufferMgmtCallback( -+ OMX_COMPONENTTYPE *openmaxStandComp, -+ OMX_BUFFERHEADERTYPE* inputbuffer); -+ -+OMX_ERRORTYPE omx_alsasink_component_port_SendBufferFunction( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE* pBuffer); -+ -+/* to handle the communication at the clock port */ -+OMX_BOOL omx_alsasink_component_ClockPortHandleFunction( -+ omx_alsasink_component_PrivateType* omx_alsasink_component_Private, -+ OMX_BUFFERHEADERTYPE* inputbuffer); -+ -+OMX_ERRORTYPE omx_alsasink_component_GetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_INOUT OMX_PTR ComponentParameterStructure); -+ -+OMX_ERRORTYPE omx_alsasink_component_SetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_IN OMX_PTR ComponentParameterStructure); -+ -+OMX_ERRORTYPE omx_alsasink_component_GetConfig( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nIndex, -+ OMX_INOUT OMX_PTR pComponentConfigStructure); -+ -+OMX_ERRORTYPE omx_alsasink_component_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort); -+ -+#endif -diff --git a/alsa/omx_base_audio_port.cpp b/alsa/omx_base_audio_port.cpp -new file mode 100644 -index 0000000..fb611d7 ---- /dev/null -+++ b/alsa/omx_base_audio_port.cpp -@@ -0,0 +1,111 @@ -+/** -+ @file src/base/omx_base_audio_port.c -+ -+ Base Audio Port class for OpenMAX ports to be used in derived components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-08-07 12:42:40 +0200 (Thu, 07 Aug 2008) $ -+ Revision $Rev: 580 $ -+ Author $Author: pankaj_sen $ -+*/ -+ -+#include <stdlib.h> -+#include <string.h> -+#include <unistd.h> -+//#include <IL/OMX_Core.h> -+//#include <IL/OMX_Component.h> -+ -+#include "omx_base_component.h" -+#include "omx_base_audio_port.h" -+ -+/** -+ * @brief The base contructor for the generic OpenMAX ST Audio port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of constructing the instance of the port and -+ * every object needed by the base port. -+ * -+ * @param openmaxStandComp pointer to the Handle of the component -+ * @param openmaxStandPort the ST port to be initialized -+ * @param nPortIndex Index of the port to be constructed -+ * @param isInput specifices if the port is an input or an output -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+ -+OMX_ERRORTYPE base_audio_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput) { -+ -+ omx_base_audio_PortType *omx_base_audio_Port; -+ -+ if (!(*openmaxStandPort)) { -+ *openmaxStandPort = (omx_base_PortType *) calloc(1,sizeof (omx_base_audio_PortType)); -+ } -+ -+ if (!(*openmaxStandPort)) { -+ return OMX_ErrorInsufficientResources; -+ } -+ -+ base_port_Constructor(openmaxStandComp,openmaxStandPort,nPortIndex, isInput); -+ -+ omx_base_audio_Port = (omx_base_audio_PortType *)*openmaxStandPort; -+ -+ setHeader(&omx_base_audio_Port->sAudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); -+ omx_base_audio_Port->sAudioParam.nPortIndex = nPortIndex; -+ omx_base_audio_Port->sAudioParam.nIndex = 0; -+ omx_base_audio_Port->sAudioParam.eEncoding = OMX_AUDIO_CodingUnused; -+ -+ omx_base_audio_Port->sPortParam.eDomain = OMX_PortDomainAudio; -+ omx_base_audio_Port->sPortParam.format.audio.cMIMEType = (OMX_STRING) malloc(DEFAULT_MIME_STRING_LENGTH); -+ strcpy(omx_base_audio_Port->sPortParam.format.audio.cMIMEType, "raw/audio"); -+ omx_base_audio_Port->sPortParam.format.audio.pNativeRender = 0; -+ omx_base_audio_Port->sPortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; -+ omx_base_audio_Port->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingUnused; -+ -+ omx_base_audio_Port->sPortParam.nBufferSize = (isInput == OMX_TRUE)?DEFAULT_IN_BUFFER_SIZE:DEFAULT_OUT_BUFFER_SIZE ; -+ -+ omx_base_audio_Port->PortDestructor = &base_audio_port_Destructor; -+ -+ return OMX_ErrorNone; -+} -+ -+/** -+ * @brief The base audio port destructor for the generic OpenMAX ST Audio port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the port. -+ * It takes care of destructing the instance of the port -+ * -+ * @param openmaxStandPort the ST port to be destructed -+ * -+ * @return OMX_ErrorNone -+ */ -+ -+OMX_ERRORTYPE base_audio_port_Destructor(omx_base_PortType *openmaxStandPort){ -+ -+ if(openmaxStandPort->sPortParam.format.audio.cMIMEType) { -+ free(openmaxStandPort->sPortParam.format.audio.cMIMEType); -+ openmaxStandPort->sPortParam.format.audio.cMIMEType = NULL; -+ } -+ -+ base_port_Destructor(openmaxStandPort); -+ -+ return OMX_ErrorNone; -+} -diff --git a/alsa/omx_base_audio_port.h b/alsa/omx_base_audio_port.h -new file mode 100644 -index 0000000..d03a83c ---- /dev/null -+++ b/alsa/omx_base_audio_port.h -@@ -0,0 +1,88 @@ -+/** -+ @file src/base/omx_base_audio_port.h -+ -+ Base Audio Port class for OpenMAX ports to be used in derived components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-07-07 14:30:38 +0200 (Mon, 07 Jul 2008) $ -+ Revision $Rev: 562 $ -+ Author $Author: gsent $ -+ -+*/ -+ -+#include "omx_classmagic.h" -+#include "omx_base_port.h" -+ -+#ifndef __OMX_BASE_AUDIO_PORT_H__ -+#define __OMX_BASE_AUDIO_PORT_H__ -+ -+/** -+ * @brief the base audio domain structure that describes each port. -+ * -+ * The data structure is derived from base port class and contain audio -+ * domain specific parameters. -+ * Other elements can be added in the derived components structures. -+ */ -+ -+DERIVEDCLASS(omx_base_audio_PortType, omx_base_PortType) -+#define omx_base_audio_PortType_FIELDS omx_base_PortType_FIELDS \ -+ /** @param sAudioParam Domain specific (audio) OpenMAX port parameter */ \ -+ OMX_AUDIO_PARAM_PORTFORMATTYPE sAudioParam; -+ENDCLASS(omx_base_audio_PortType) -+ -+/** -+ * @brief the base contructor for the generic OpenMAX ST Audio port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of constructing the instance of the port and -+ * every object needed by the base port. -+ * -+ * @param openmaxStandComp pointer to the Handle of the component -+ * @param openmaxStandPort the ST port to be initialized -+ * @param nPortIndex Index of the port to be constructed -+ * @param isInput specifices if the port is an input or an output -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+ -+OMX_ERRORTYPE base_audio_port_Constructor( -+ OMX_COMPONENTTYPE *openmaxStandComp, -+ omx_base_PortType **openmaxStandPort, -+ OMX_U32 nPortIndex, -+ OMX_BOOL isInput); -+ -+/** -+ * @brief the base audio port destructor for the generic OpenMAX ST Audio port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the port. -+ * It takes care of destructing the instance of the port -+ * -+ * @param openmaxStandPort the ST port to be destructed -+ * -+ * @return OMX_ErrorNone -+ */ -+ -+ -+OMX_ERRORTYPE base_audio_port_Destructor( -+ omx_base_PortType *openmaxStandPort); -+ -+#endif -diff --git a/alsa/omx_base_clock_port.cpp b/alsa/omx_base_clock_port.cpp -new file mode 100644 -index 0000000..cf27b71 ---- /dev/null -+++ b/alsa/omx_base_clock_port.cpp -@@ -0,0 +1,209 @@ -+/** -+ @file src/base/omx_base_clock_port.c -+ -+ Base Clock Port class for OpenMAX clock ports to be used in derived components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-07-04 11:48:31 +0200 (Fri, 04 Jul 2008) $ -+ Revision $Rev: 560 $ -+ Author $Author: gsent $ -+*/ -+ -+#undef OMX_SKIP64BIT -+#include <stdlib.h> -+#include <string.h> -+#include <unistd.h> -+//#include <IL/OMX_Core.h> -+//#include <IL/OMX_Component.h> -+#include "omx_base_component.h" -+#include "omx_base_clock_port.h" -+ -+/** -+ * @brief the base contructor for the generic openmax ST Clock port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of constructing the instance of the port and -+ * every object needed by the base port. -+ * -+ * @param openmaxStandComp pointer to the Handle of the component -+ * @param openmaxStandPort the ST port to be initialized -+ * @param nPortIndex Index of the port to be constructed -+ * @param isInput specifices if the port is an input or an output -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+ -+OMX_ERRORTYPE base_clock_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput) { -+ -+ omx_base_clock_PortType *omx_base_clock_Port; -+ -+ if (!(*openmaxStandPort)) { -+ *openmaxStandPort = (omx_base_PortType*)calloc(1,sizeof (omx_base_clock_PortType)); -+ } -+ -+ if (!(*openmaxStandPort)) { -+ return OMX_ErrorInsufficientResources; -+ } -+ -+ base_port_Constructor(openmaxStandComp,openmaxStandPort,nPortIndex, isInput); -+ -+ omx_base_clock_Port = (omx_base_clock_PortType *)*openmaxStandPort; -+ -+ setHeader(&omx_base_clock_Port->sOtherParam, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE)); -+ omx_base_clock_Port->sOtherParam.nPortIndex = nPortIndex; -+ omx_base_clock_Port->sOtherParam.nIndex = 0; -+ omx_base_clock_Port->sOtherParam.eFormat = OMX_OTHER_FormatTime; -+ -+ omx_base_clock_Port->sPortParam.eDomain = OMX_PortDomainOther; -+ omx_base_clock_Port->sPortParam.format.other.eFormat = OMX_OTHER_FormatTime; -+ omx_base_clock_Port->sPortParam.nBufferSize = sizeof(OMX_TIME_MEDIATIMETYPE) ; -+ omx_base_clock_Port->sPortParam.nBufferCountActual = 1; -+ omx_base_clock_Port->sPortParam.nBufferCountMin = 1; -+ omx_base_clock_Port->sPortParam.format.other.eFormat = OMX_OTHER_FormatTime; -+ -+ setHeader(&omx_base_clock_Port->sTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); -+ omx_base_clock_Port->sTimeStamp.nPortIndex = nPortIndex; -+ omx_base_clock_Port->sTimeStamp.nTimestamp = 0x00; -+ -+ -+ setHeader(&omx_base_clock_Port->sMediaTime, sizeof(OMX_TIME_MEDIATIMETYPE)); -+ omx_base_clock_Port->sMediaTime.nClientPrivate = 0; -+ omx_base_clock_Port->sMediaTime.nOffset = 0x0; -+ omx_base_clock_Port->sMediaTime.xScale = 1; -+ -+ setHeader(&omx_base_clock_Port->sMediaTimeRequest, sizeof(OMX_TIME_MEDIATIMETYPE)); -+ omx_base_clock_Port->sMediaTimeRequest.nPortIndex = nPortIndex; -+ omx_base_clock_Port->sMediaTimeRequest.pClientPrivate = NULL; -+ omx_base_clock_Port->sMediaTimeRequest.nOffset = 0x0; -+ -+ omx_base_clock_Port->Port_SendBufferFunction = &base_clock_port_SendBufferFunction; -+ omx_base_clock_Port->PortDestructor = &base_clock_port_Destructor; -+ -+ return OMX_ErrorNone; -+} -+ -+/** -+ * @brief the base clock port destructor for the generic openmax ST clock port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the port. -+ * It takes care of destructing the instance of the port -+ * -+ * @param openmaxStandPort the ST port to be destructed -+ * -+ * @return OMX_ErrorNone -+ */ -+ -+OMX_ERRORTYPE base_clock_port_Destructor(omx_base_PortType *openmaxStandPort){ -+ -+ base_port_Destructor(openmaxStandPort); -+ -+ return OMX_ErrorNone; -+} -+ -+/** @brief the entry point for sending buffers to the port -+ * -+ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on -+ * the nature of the port, that can be an input or output port. -+ */ -+OMX_ERRORTYPE base_clock_port_SendBufferFunction( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE* pBuffer) { -+ -+ OMX_ERRORTYPE err; -+ OMX_U32 portIndex; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+#if NO_GST_OMX_PATCH -+ unsigned int i; -+#endif -+ portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, (unsigned long)portIndex); -+ -+ if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if(omx_base_component_Private->state == OMX_StateInvalid) { -+ DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); -+ return OMX_ErrorInvalidState; -+ } -+ -+ if(omx_base_component_Private->state != OMX_StateExecuting && -+ omx_base_component_Private->state != OMX_StatePause && -+ omx_base_component_Private->state != OMX_StateIdle) { -+ DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || -+ (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && -+ (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { -+ DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ -+ /* Temporarily disable this check for gst-openmax */ -+#if NO_GST_OMX_PATCH -+ { -+ OMX_BOOL foundBuffer = OMX_FALSE; -+ if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { -+ foundBuffer = OMX_TRUE; -+ break; -+ } -+ } -+ } -+ if (!foundBuffer) { -+ return OMX_ErrorBadParameter; -+ } -+ } -+#endif -+ -+ if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); -+ return err; -+ } -+ /*If port is not tunneled then simply return the buffer except paused state*/ -+ if (!PORT_IS_TUNNELED(openmaxStandPort) && (omx_base_component_Private->state != OMX_StatePause)) { -+ openmaxStandPort->ReturnBufferFunction(openmaxStandPort,pBuffer); -+ return OMX_ErrorNone; -+ } -+ -+ /* And notify the buffer management thread we have a fresh new buffer to manage */ -+ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ -+ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", -+ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); -+ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ } -+ else { // If port being flushed and not tunneled then return error -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ return OMX_ErrorNone; -+} -diff --git a/alsa/omx_base_clock_port.h b/alsa/omx_base_clock_port.h +diff --git a/linux/OMXAlsa.cpp b/linux/OMXAlsa.cpp new file mode 100644 -index 0000000..97f543e +index 0000000..b19ef31 --- /dev/null -+++ b/alsa/omx_base_clock_port.h -@@ -0,0 +1,95 @@ -+/** -+ @file src/base/omx_base_clock_port.h -+ -+ Base Clock Port class for OpenMAX clock ports to be used in derived components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-07-04 11:48:31 +0200 (Fri, 04 Jul 2008) $ -+ Revision $Rev: 560 $ -+ Author $Author: gsent $ -+ -+*/ -+ -+#include "omx_classmagic.h" -+#include "omx_base_port.h" -+ -+#ifndef __OMX_BASE_CLOCK_PORT_H__ -+#define __OMX_BASE_CLOCK_PORT_H__ -+ -+/** -+ * @brief the base clock domain structure that describes each port. ++++ b/linux/OMXAlsa.cpp +@@ -0,0 +1,1275 @@ ++/* ++ * OMX IL Alsa Sink component ++ * Copyright (c) 2016 Timo Teräs + * -+ * The data structure is derived from base port class and contain clock -+ * domain specific parameters. -+ * Other elements can be added in the derived components structures. ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. + * -+ * @param sOtherParam Domain specific (other) OpenMAX port parameter ++ * TODO: ++ * - rate changing, test --live for speed control handling ++ * - timeouts for state transition failures + */ + -+DERIVEDCLASS(omx_base_clock_PortType, omx_base_PortType) -+#define omx_base_clock_PortType_FIELDS omx_base_PortType_FIELDS \ -+ OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp; /**< General OpenMAX configuration time stamp parameter */ \ -+ OMX_TIME_MEDIATIMETYPE sMediaTime; \ -+ OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE sMediaTimeRequest; \ -+ OMX_OTHER_PARAM_PORTFORMATTYPE sOtherParam; /**< Domain specific (other) OpenMAX port parameter */ -+ENDCLASS(omx_base_clock_PortType) -+ -+/** -+ * @brief the base contructor for the generic openmax ST clock port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of constructing the instance of the port and -+ * every object needed by the base port. -+ * -+ * @param openmaxStandComp pointer to the Handle of the component -+ * @param openmaxStandPort the ST port to be initialized -+ * @param nPortIndex Index of the port to be constructed -+ * @param isInput specifices if the port is an input or an output -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+ -+OMX_ERRORTYPE base_clock_port_Constructor( -+ OMX_COMPONENTTYPE *openmaxStandComp, -+ omx_base_PortType **openmaxStandPort, -+ OMX_U32 nPortIndex, -+ OMX_BOOL isInput); -+ -+/** -+ * @brief the base clock port destructor for the generic openmax ST clock port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the port. -+ * It takes care of destructing the instance of the port -+ * -+ * @param openmaxStandPort the ST port to be destructed -+ * -+ * @return OMX_ErrorNone -+ */ -+ -+OMX_ERRORTYPE base_clock_port_Destructor( -+ omx_base_PortType *openmaxStandPort); -+ -+OMX_ERRORTYPE base_clock_port_SendBufferFunction( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE* pBuffer); -+ -+#endif -diff --git a/alsa/omx_base_component.cpp b/alsa/omx_base_component.cpp -new file mode 100644 -index 0000000..8396979 ---- /dev/null -+++ b/alsa/omx_base_component.cpp -@@ -0,0 +1,1755 @@ -+/** -+ @file src/base/omx_base_component.c -+ -+ OpenMAX base_component component. This component does not perform any multimedia -+ processing. It is used as a base_component for new components development. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-09-16 15:59:45 +0200 (Tue, 16 Sep 2008) $ -+ Revision $Rev: 621 $ -+ Author $Author: gsent $ -+ -+*/ -+ -+#include <stdlib.h> +#include <stdio.h> ++#include <stdint.h> ++#include <stddef.h> +#include <string.h> -+#include <unistd.h> -+#include <errno.h> -+ -+//#include <IL/OMX_Core.h> -+//#include <IL/OMX_Component.h> -+ -+#include "omx_semaphore.h" -+#include "omx_base_component.h" -+ -+/** -+ * @brief The base contructor for the OpenMAX st components -+ * -+ * This function is executed by the ST static component loader. -+ * It takes care of constructing the instance of the component. -+ * For the base_component component, the following is done: -+ * -+ * 1) Fills the basic OpenMAX structure. The fields can be overwritten -+ * by derived components. -+ * 2) Allocates (if needed) the omx_base_component_PrivateType private structure -+ * -+ * @param openmaxStandComp the ST component to be initialized -+ * @param cComponentName the OpenMAX string that describes the component -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+OMX_ERRORTYPE omx_base_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) { -+ omx_base_component_PrivateType* omx_base_component_Private; -+ OMX_U32 i; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ if (openmaxStandComp->pComponentPrivate) { -+ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ } else { -+ omx_base_component_Private = (omx_base_component_PrivateType*)calloc(1,sizeof(omx_base_component_PrivateType)); -+ if (!omx_base_component_Private) { -+ return OMX_ErrorInsufficientResources; -+ } -+ } -+ -+ if(!omx_base_component_Private->messageQueue) { -+ omx_base_component_Private->messageQueue = (omx_queue_t*)calloc(1,sizeof(omx_queue_t)); -+ omx_queue_init(omx_base_component_Private->messageQueue); -+ } -+ -+ if(!omx_base_component_Private->messageSem) { -+ omx_base_component_Private->messageSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ omx_tsem_init(omx_base_component_Private->messageSem, 0); -+ } -+ if(!omx_base_component_Private->bMgmtSem) { -+ omx_base_component_Private->bMgmtSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ omx_tsem_init(omx_base_component_Private->bMgmtSem, 0); -+ } -+ -+ if(!omx_base_component_Private->bStateSem) { -+ omx_base_component_Private->bStateSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ omx_tsem_init(omx_base_component_Private->bStateSem, 0); -+ } -+ -+ openmaxStandComp->nSize = sizeof(OMX_COMPONENTTYPE); -+ openmaxStandComp->pApplicationPrivate = NULL; -+ openmaxStandComp->GetComponentVersion = omx_base_component_GetComponentVersion; -+ openmaxStandComp->SendCommand = omx_base_component_SendCommand; -+ openmaxStandComp->GetParameter = omx_base_component_GetParameter; -+ openmaxStandComp->SetParameter = omx_base_component_SetParameter; -+ openmaxStandComp->GetConfig = omx_base_component_GetConfig; -+ openmaxStandComp->SetConfig = omx_base_component_SetConfig; -+ openmaxStandComp->GetExtensionIndex = omx_base_component_GetExtensionIndex; -+ openmaxStandComp->GetState = omx_base_component_GetState; -+ openmaxStandComp->SetCallbacks = omx_base_component_SetCallbacks; -+ openmaxStandComp->ComponentDeInit = omx_base_component_ComponentDeInit; -+ openmaxStandComp->ComponentRoleEnum = omx_base_component_ComponentRoleEnum; -+ openmaxStandComp->ComponentTunnelRequest =omx_base_component_ComponentTunnelRequest; -+ -+ /*Will make Specific port Allocate buffer call*/ -+ openmaxStandComp->AllocateBuffer = omx_base_component_AllocateBuffer; -+ openmaxStandComp->UseBuffer = omx_base_component_UseBuffer; -+ openmaxStandComp->UseEGLImage = omx_base_component_UseEGLImage; -+ openmaxStandComp->FreeBuffer = omx_base_component_FreeBuffer; -+ openmaxStandComp->EmptyThisBuffer = omx_base_component_EmptyThisBuffer; -+ openmaxStandComp->FillThisBuffer = omx_base_component_FillThisBuffer; -+ -+ openmaxStandComp->nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; -+ openmaxStandComp->nVersion.s.nVersionMinor = OMX_VERSION_MINOR; -+ openmaxStandComp->nVersion.s.nRevision = OMX_VERSION_REVISION; -+ openmaxStandComp->nVersion.s.nStep = OMX_VERSION_STEP; -+ -+ omx_base_component_Private->name = (char*)calloc(1,OMX_MAX_STRINGNAME_SIZE); -+ if (!omx_base_component_Private->name) { -+ return OMX_ErrorInsufficientResources; -+ } -+ strcpy(omx_base_component_Private->name,cComponentName); -+ omx_base_component_Private->state = OMX_StateLoaded; -+ omx_base_component_Private->transientState = OMX_TransStateMax; -+ omx_base_component_Private->callbacks = NULL; -+ omx_base_component_Private->callbackData = NULL; -+ omx_base_component_Private->nGroupPriority = 0; -+ omx_base_component_Private->nGroupID = 0; -+ omx_base_component_Private->pMark.hMarkTargetComponent = NULL; -+ omx_base_component_Private->pMark.pMarkData = NULL; -+ omx_base_component_Private->openmaxStandComp=openmaxStandComp; -+ omx_base_component_Private->DoStateSet = &omx_base_component_DoStateSet; -+ omx_base_component_Private->messageHandler = omx_base_component_MessageHandler; -+ omx_base_component_Private->destructor = omx_base_component_Destructor; -+ omx_base_component_Private->bufferMgmtThreadID = -1; -+ -+ pthread_mutex_init(&omx_base_component_Private->flush_mutex, NULL); -+ -+ if(!omx_base_component_Private->flush_all_condition) { -+ omx_base_component_Private->flush_all_condition = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ omx_tsem_init(omx_base_component_Private->flush_all_condition, 0); -+ } -+ -+ if(!omx_base_component_Private->flush_condition) { -+ omx_base_component_Private->flush_condition = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ omx_tsem_init(omx_base_component_Private->flush_condition, 0); -+ } -+ -+ for(i=0;i<NUM_DOMAINS;i++) { -+ memset(&omx_base_component_Private->sPortTypesParam[i], 0, sizeof(OMX_PORT_PARAM_TYPE)); -+ setHeader(&omx_base_component_Private->sPortTypesParam[i], sizeof(OMX_PORT_PARAM_TYPE)); -+ } -+ -+ omx_base_component_Private->messageHandlerThreadID = pthread_create(&omx_base_component_Private->messageHandlerThread, -+ NULL, -+ compMessageHandlerFunction, -+ openmaxStandComp); -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME,"Out of %s\n",__func__); -+ return OMX_ErrorNone; -+} -+ -+/** @brief The base destructor for ST OpenMAX components -+ * -+ * This function is called by the standard function ComponentDeInit() -+ * that is called by the IL core during the execution of the FreeHandle() -+ * -+ * @param openmaxStandComp the ST OpenMAX component to be disposed -+ */ -+OMX_ERRORTYPE omx_base_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ int err; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ omx_base_component_Private->state = OMX_StateInvalid; -+ -+ /*Send Dummy signal to Component Message handler to exit*/ -+ omx_tsem_up(omx_base_component_Private->messageSem); -+ DEBUG(DEB_LEV_FUNCTION_NAME,"In %s messageSem signaled. messageSem->semval=%d\n", __func__, omx_base_component_Private->messageSem->semval); -+ -+ err = pthread_join(omx_base_component_Private->messageHandlerThread,NULL); -+ if(err!=0) { -+ DEBUG(DEB_LEV_FUNCTION_NAME,"In %s pthread_join returned err=%d\n", __func__, err); -+ } -+ DEBUG(DEB_LEV_FUNCTION_NAME,"In %s past pthread_join\n", __func__); -+ -+ omx_base_component_Private->callbacks=NULL; -+ -+ /*Deinitialize and free message queue*/ -+ if(omx_base_component_Private->messageQueue) { -+ omx_queue_deinit(omx_base_component_Private->messageQueue); -+ free(omx_base_component_Private->messageQueue); -+ omx_base_component_Private->messageQueue=NULL; -+ } -+ -+ /*Deinitialize and free buffer management semaphore*/ -+ if(omx_base_component_Private->bMgmtSem){ -+ omx_tsem_deinit(omx_base_component_Private->bMgmtSem); -+ free(omx_base_component_Private->bMgmtSem); -+ omx_base_component_Private->bMgmtSem=NULL; -+ } -+ -+ /*Deinitialize and free message semaphore*/ -+ if(omx_base_component_Private->messageSem) { -+ omx_tsem_deinit(omx_base_component_Private->messageSem); -+ free(omx_base_component_Private->messageSem); -+ omx_base_component_Private->messageSem=NULL; -+ } -+ -+ if(omx_base_component_Private->bStateSem){ -+ omx_tsem_deinit(omx_base_component_Private->bStateSem); -+ free(omx_base_component_Private->bStateSem); -+ omx_base_component_Private->bStateSem=NULL; -+ } -+ -+ if(omx_base_component_Private->name){ -+ free(omx_base_component_Private->name); -+ omx_base_component_Private->name=NULL; -+ } -+ -+ pthread_mutex_destroy(&omx_base_component_Private->flush_mutex); -+ -+ if(omx_base_component_Private->flush_all_condition){ -+ omx_tsem_deinit(omx_base_component_Private->flush_all_condition); -+ free(omx_base_component_Private->flush_all_condition); -+ omx_base_component_Private->flush_all_condition=NULL; -+ } -+ -+ if(omx_base_component_Private->flush_condition){ -+ omx_tsem_deinit(omx_base_component_Private->flush_condition); -+ free(omx_base_component_Private->flush_condition); -+ omx_base_component_Private->flush_condition=NULL; -+ } -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME,"Out of %s\n",__func__); -+ return OMX_ErrorNone; -+} -+ -+/** @brief This standard functionality is called when the component is -+ * destroyed in the FreeHandle standard call. -+ * -+ * In this way the implementation of the FreeHandle is standard, -+ * and it does not need a support by a specific component loader. -+ * The implementaiton of the ComponentDeInit contains the -+ * implementation specific part of the destroying phase. -+ */ -+OMX_ERRORTYPE omx_base_component_ComponentDeInit( -+ OMX_IN OMX_HANDLETYPE hComponent) { -+ OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE *)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s pComponentPrivate =%x \n", __func__,(int)openmaxStandComp->pComponentPrivate); -+ omx_base_component_Private->destructor(openmaxStandComp); -+ -+ free(openmaxStandComp->pComponentPrivate); -+ openmaxStandComp->pComponentPrivate=NULL; -+ return OMX_ErrorNone; -+} -+ -+/** Changes the state of a component taking proper actions depending on -+ * the transiotion requested. This base function cover only the state -+ * changes that do not involve any port -+ * -+ * @param openmaxStandComp the OpenMAX component which state is to be changed -+ * @param destinationState the requested target state -+ * -+ * @return OMX_ErrorNotImplemented if the state change is noty handled in this base class, but needs -+ * a specific handling -+ */ -+OMX_ERRORTYPE omx_base_component_DoStateSet(OMX_COMPONENTTYPE *openmaxStandComp, OMX_U32 destinationState) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ omx_base_PortType *pPort; -+ OMX_U32 i,j,k; -+ OMX_ERRORTYPE err=OMX_ErrorNone; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ DEBUG(DEB_LEV_PARAMS, "Changing state from %i to %i\n", omx_base_component_Private->state, (int)destinationState); -+ -+ if(destinationState == OMX_StateLoaded){ -+ switch(omx_base_component_Private->state){ -+ case OMX_StateInvalid: -+ err = OMX_ErrorInvalidState; -+ break; -+ case OMX_StateWaitForResources: -+ /* return back from wait for resources */ -+ omx_base_component_Private->state = OMX_StateLoaded; -+ break; -+ case OMX_StateLoaded: -+ err = OMX_ErrorSameState; -+ break; -+ case OMX_StateIdle: -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ -+ pPort = omx_base_component_Private->ports[i]; -+ if (PORT_IS_TUNNELED(pPort) && PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ while(pPort->pBufferQueue->nelem > 0) { -+ DEBUG(DEB_LEV_PARAMS, "In %s Buffer %d remained in the port %d queue of comp%s\n", -+ __func__,(int)pPort->pBufferQueue->nelem,(int)i,omx_base_component_Private->name); -+ omx_dequeue(pPort->pBufferQueue); -+ } -+ /* Freeing here the buffers allocated for the tunneling:*/ -+ err = pPort->Port_FreeTunnelBuffer(pPort,i); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Freeing Tunnel Buffer Error=%x\n",__func__,err); -+ return err; -+ } -+ } else { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s nPortIndex=%d pAllocSem Semval=%x\n", __func__,(int)i,(int)pPort->pAllocSem->semval); -+ -+ /*If ports are enabled then wait till all buffers are freed*/ -+ if(PORT_IS_ENABLED(pPort)) { -+ omx_tsem_down(pPort->pAllocSem); -+ } -+ } -+ pPort->sPortParam.bPopulated = OMX_FALSE; -+ -+ if(pPort->bTunnelTearDown == OMX_TRUE){ -+ DEBUG(DEB_LEV_PARAMS, "In %s TearDown tunnel\n", __func__); -+ pPort->hTunneledComponent = 0; -+ pPort->nTunneledPort = 0; -+ pPort->nTunnelFlags = 0; -+ pPort->eBufferSupplier=OMX_BufferSupplyUnspecified; -+ pPort->bTunnelTearDown = OMX_FALSE; -+ } -+ -+ if(pPort->pInternalBufferStorage != NULL) { -+ free(pPort->pInternalBufferStorage); -+ pPort->pInternalBufferStorage=NULL; -+ } -+ -+ if(pPort->bBufferStateAllocated != NULL) { -+ free(pPort->bBufferStateAllocated); -+ pPort->bBufferStateAllocated=NULL; -+ } -+ } -+ } -+ omx_base_component_Private->state = OMX_StateLoaded; -+ -+ if(omx_base_component_Private->bufferMgmtThreadID == 0 ){ -+ /*Signal Buffer Management thread to exit*/ -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ pthread_join(omx_base_component_Private->bufferMgmtThread,NULL); -+ omx_base_component_Private->bufferMgmtThreadID = -1; -+ if(err != 0) { -+ DEBUG(DEB_LEV_FUNCTION_NAME,"In %s pthread_join returned err=%d\n",__func__,err); -+ } -+ } -+ -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s: state transition not allowed\n", __func__); -+ err = OMX_ErrorIncorrectStateTransition; -+ break; -+ } -+ return err; -+ } -+ -+ if(destinationState == OMX_StateWaitForResources){ -+ switch(omx_base_component_Private->state){ -+ case OMX_StateInvalid: -+ err = OMX_ErrorInvalidState; -+ break; -+ case OMX_StateLoaded: -+ omx_base_component_Private->state = OMX_StateWaitForResources; -+ break; -+ case OMX_StateWaitForResources: -+ err = OMX_ErrorSameState; -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s: state transition not allowed\n", __func__); -+ err = OMX_ErrorIncorrectStateTransition; -+ break; -+ } -+ return err; -+ } -+ -+ if(destinationState == OMX_StateIdle){ -+ switch(omx_base_component_Private->state){ -+ case OMX_StateInvalid: -+ err = OMX_ErrorInvalidState; -+ break; -+ case OMX_StateWaitForResources: -+ omx_base_component_Private->state = OMX_StateIdle; -+ break; -+ case OMX_StateLoaded: -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort = omx_base_component_Private->ports[i]; -+ if (PORT_IS_TUNNELED(pPort) && PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ if(PORT_IS_ENABLED(pPort)) { -+ /** Allocate here the buffers needed for the tunneling */ -+ err= pPort->Port_AllocateTunnelBuffer(pPort, i, omx_base_component_Private->ports[i]->sPortParam.nBufferSize); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Allocating Tunnel Buffer Port=%d, Error=%x\n",__func__,i,err); -+ return err; -+ } -+ } -+ } else { -+ if(PORT_IS_ENABLED(pPort)) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: wait for buffers. port enabled %i, port populated %i\n", -+ __func__, pPort->sPortParam.bEnabled,pPort->sPortParam.bPopulated); -+ omx_tsem_down(pPort->pAllocSem); -+ pPort->sPortParam.bPopulated = OMX_TRUE; -+ } -+ else -+ DEBUG(DEB_LEV_ERR, "In %s: Port %i Disabled So no wait\n",__func__,(int)i); -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "---> Tunnel status : port %d flags 0x%x\n",(int)i, (int)pPort->nTunnelFlags); -+ } -+ } -+ omx_base_component_Private->state = OMX_StateIdle; -+ /** starting buffer management thread */ -+ omx_base_component_Private->bufferMgmtThreadID = pthread_create(&omx_base_component_Private->bufferMgmtThread, -+ NULL, -+ omx_base_component_Private->BufferMgmtFunction, -+ openmaxStandComp); -+ if(omx_base_component_Private->bufferMgmtThreadID < 0){ -+ DEBUG(DEB_LEV_ERR, "Starting buffer management thread failed\n"); -+ return OMX_ErrorUndefined; -+ } -+ break; -+ case OMX_StateIdle: -+ err = OMX_ErrorSameState; -+ break; -+ case OMX_StateExecuting: -+ /*Flush Ports*/ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ DEBUG(DEB_LEV_FULL_SEQ, "Flushing Port %i\n",(int)i); -+ pPort = omx_base_component_Private->ports[i]; -+ if(PORT_IS_ENABLED(pPort)) { -+ pPort->FlushProcessingBuffers(pPort); -+ } -+ } -+ } -+ omx_base_component_Private->state = OMX_StateIdle; -+ break; -+ case OMX_StatePause: -+ omx_base_component_Private->state = OMX_StateIdle; -+ /*Signal buffer management thread if waiting at paused state*/ -+ omx_tsem_signal(omx_base_component_Private->bStateSem); -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s: state transition not allowed\n", __func__); -+ err = OMX_ErrorIncorrectStateTransition; -+ break; -+ } -+ return err; -+ } -+ -+ if(destinationState == OMX_StatePause) { -+ switch(omx_base_component_Private->state) { -+ case OMX_StateInvalid: -+ err = OMX_ErrorInvalidState; -+ break; -+ case OMX_StatePause: -+ err = OMX_ErrorSameState; -+ break; -+ case OMX_StateExecuting: -+ case OMX_StateIdle: -+ omx_base_component_Private->state = OMX_StatePause; -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s: state transition not allowed\n", __func__); -+ err = OMX_ErrorIncorrectStateTransition; -+ break; -+ } -+ return err; -+ } -+ -+ if(destinationState == OMX_StateExecuting) { -+ switch(omx_base_component_Private->state) { -+ case OMX_StateInvalid: -+ err = OMX_ErrorInvalidState; -+ break; -+ case OMX_StateIdle: -+ omx_base_component_Private->state=OMX_StateExecuting; -+ /*Send Tunneled Buffer to the Neighbouring Components*/ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort = omx_base_component_Private->ports[i]; -+ if (PORT_IS_TUNNELED(pPort) && PORT_IS_BUFFER_SUPPLIER(pPort) && PORT_IS_ENABLED(pPort)) { -+ for(k=0;k<pPort->nNumTunnelBuffer;k++) { -+ omx_tsem_up(pPort->pBufferSem); -+ /*signal buffer management thread availability of buffers*/ -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ } -+ } -+ omx_base_component_Private->transientState = OMX_TransStateMax; -+ err = OMX_ErrorNone; -+ break; -+ case OMX_StatePause: -+ omx_base_component_Private->state=OMX_StateExecuting; -+ -+ /* Tunneled Supplier Ports were enabled in paused state. So signal buffer managment thread*/ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ -+ pPort=omx_base_component_Private->ports[i]; -+ DEBUG(DEB_LEV_PARAMS, "In %s: state transition Paused 2 Executing, nelem=%d,semval=%d,Buf Count Actual=%d\n", __func__, -+ pPort->pBufferQueue->nelem,pPort->pBufferSem->semval,(int)pPort->sPortParam.nBufferCountActual); -+ -+ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(pPort) && -+ (pPort->pBufferQueue->nelem == (pPort->pBufferSem->semval + pPort->sPortParam.nBufferCountActual))) { -+ for(k=0; k < pPort->sPortParam.nBufferCountActual;k++) { -+ omx_tsem_up(pPort->pBufferSem); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ } -+ } -+ /*Signal buffer management thread if waiting at paused state*/ -+ omx_tsem_signal(omx_base_component_Private->bStateSem); -+ break; -+ case OMX_StateExecuting: -+ err = OMX_ErrorSameState; -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s: state transition not allowed\n", __func__); -+ err = OMX_ErrorIncorrectStateTransition; -+ break; -+ } -+ return err; -+ } -+ -+ if(destinationState == OMX_StateInvalid) { -+ switch(omx_base_component_Private->state) { -+ case OMX_StateInvalid: -+ err = OMX_ErrorInvalidState; -+ break; -+ default: -+ omx_base_component_Private->state = OMX_StateInvalid; -+ -+ if(omx_base_component_Private->bufferMgmtThreadID == 0 ){ -+ /*Signal Buffer Management Thread to Exit*/ -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ pthread_join(omx_base_component_Private->bufferMgmtThread,NULL); -+ omx_base_component_Private->bufferMgmtThreadID = -1; -+ if(err!=0) { -+ DEBUG(DEB_LEV_FUNCTION_NAME,"In %s pthread_join returned err=%d\n",__func__,err); -+ } -+ } -+ err = OMX_ErrorInvalidState; -+ break; -+ } -+ return err; -+ } -+ return OMX_ErrorNone; -+} -+ -+/** @brief Checks the header of a structure for consistency -+ * with size and spec version -+ * -+ * @param header Pointer to the structure to be checked -+ * @param size Size of the structure. it is in general obtained -+ * with a sizeof call applied to the structure -+ * -+ * @return OMX error code. If the header has failed the check, -+ * OMX_ErrorVersionMismatch is returned. -+ * If the header fails the size check OMX_ErrorBadParameter is returned -+ */ -+OMX_ERRORTYPE checkHeader(OMX_PTR header, OMX_U32 size) { -+ OMX_VERSIONTYPE* ver; -+ if (header == NULL) { -+ DEBUG(DEB_LEV_ERR, "In %s the header is null\n",__func__); -+ return OMX_ErrorBadParameter; -+ } -+ ver = (OMX_VERSIONTYPE*)((char*)header + sizeof(OMX_U32)); -+ if(*((OMX_U32*)header) != size) { -+ DEBUG(DEB_LEV_ERR, "In %s the header has a wrong size %i should be %i\n",__func__,(int)*((OMX_U32*)header),(int)size); -+ return OMX_ErrorBadParameter; -+ } -+ if(ver->s.nVersionMajor != OMX_VERSION_MAJOR || -+ ver->s.nVersionMinor != OMX_VERSION_MINOR) { -+ DEBUG(DEB_LEV_ERR, "The version does not match\n"); -+ return OMX_ErrorVersionMismatch; -+ } -+ return OMX_ErrorNone; -+} -+ -+/** @brief Simply fills the first two fields in any OMX structure -+ * with the size and the version -+ * -+ * @param header pointer to the structure to be filled -+ * @param size size of the structure. It can be obtained with -+ * a call to sizeof of the structure type -+ */ -+void setHeader(OMX_PTR header, OMX_U32 size) { -+ OMX_VERSIONTYPE* ver = (OMX_VERSIONTYPE*)((char*)header + sizeof(OMX_U32)); -+ *((OMX_U32*)header) = size; -+ -+ ver->s.nVersionMajor = OMX_VERSION_MAJOR; -+ ver->s.nVersionMinor = OMX_VERSION_MINOR; -+ ver->s.nRevision = OMX_VERSION_REVISION; -+ ver->s.nStep = OMX_VERSION_STEP; -+} -+ -+/** -+ * This function verify Component State and Structure header -+ */ -+OMX_ERRORTYPE omx_base_component_ParameterSanityCheck(OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_U32 nPortIndex, -+ OMX_IN OMX_PTR pStructure, -+ OMX_IN size_t size) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)(((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate); -+ omx_base_PortType *pPort; -+ int nNumPorts; -+ -+ nNumPorts = omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts; -+ -+ if (nPortIndex >= nNumPorts) { -+ DEBUG(DEB_LEV_ERR, "Bad Port index %i when the component has %i ports\n", (int)nPortIndex, (int)nNumPorts); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ pPort = omx_base_component_Private->ports[nPortIndex]; -+ -+ if (omx_base_component_Private->state != OMX_StateLoaded && omx_base_component_Private->state != OMX_StateWaitForResources) { -+ if(PORT_IS_ENABLED(pPort)) { -+ DEBUG(DEB_LEV_ERR, "In %s Incorrect State=%x lineno=%d\n",__func__,omx_base_component_Private->state,__LINE__); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ } -+ -+ return checkHeader(pStructure , size); -+} -+ -+/** @brief Standard OpenMAX function -+ * -+ * it returns the version of the component. See OMX_Core.h -+ */ -+OMX_ERRORTYPE omx_base_component_GetComponentVersion(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) { -+ -+ OMX_COMPONENTTYPE* omx_component = (OMX_COMPONENTTYPE*)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omx_component->pComponentPrivate; -+ -+ OMX_U32 uuid[3]; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ /* Fill component name */ -+ strcpy(pComponentName, omx_base_component_Private->name); -+ -+ /* Fill component version */ -+ pComponentVersion->s.nVersionMajor = OMX_VERSION_MAJOR; -+ pComponentVersion->s.nVersionMinor = OMX_VERSION_MINOR; -+ pComponentVersion->s.nRevision = OMX_VERSION_REVISION; -+ pComponentVersion->s.nStep = OMX_VERSION_STEP; -+ -+ /* Fill spec version (copy from component field) */ -+ memcpy(pSpecVersion, &omx_component->nVersion, sizeof(OMX_VERSIONTYPE)); -+ -+ /* Fill UUID with handle address, PID and UID. -+ * This should guarantee uiniqness */ -+ uuid[0] = (OMX_U32)omx_component; -+ uuid[1] = getpid(); -+ uuid[2] = getuid(); -+ memcpy(*pComponentUUID, uuid, 3*sizeof(uuid)); -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s\n", __func__); -+ return OMX_ErrorNone; -+} -+ -+/** @brief Enumerates all the roles of the component. -+ * -+ * This function is intended to be used only by a core. The ST static core -+ * in any case does not use this function, because it can not be used before the -+ * creation of the component, but uses a static list. -+ * It is implemented only for API completion,and it will be not overriden -+ * by a derived component -+ */ -+OMX_ERRORTYPE omx_base_component_ComponentRoleEnum( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_OUT OMX_U8 *cRole, -+ OMX_IN OMX_U32 nIndex) { -+ strcat((char*)cRole, "\0"); -+ return OMX_ErrorNoMore; -+} -+ -+/** @brief standard OpenMAX function -+ * -+ * it sets the callback functions given by the IL client. -+ * See OMX_Component.h -+ */ -+OMX_ERRORTYPE omx_base_component_SetCallbacks( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_CALLBACKTYPE* pCallbacks, -+ OMX_IN OMX_PTR pAppData) { -+ -+ OMX_COMPONENTTYPE *omxcomponent = (OMX_COMPONENTTYPE*)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxcomponent->pComponentPrivate; -+ omx_base_PortType *pPort; -+ OMX_U32 i,j; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ omx_base_component_Private->callbacks = pCallbacks; -+ omx_base_component_Private->callbackData = pAppData; -+ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort = omx_base_component_Private->ports[i]; -+ if (pPort->sPortParam.eDir == OMX_DirInput) { -+ pPort->BufferProcessedCallback = omx_base_component_Private->callbacks->EmptyBufferDone; -+ } else { -+ pPort->BufferProcessedCallback = omx_base_component_Private->callbacks->FillBufferDone; -+ } -+ } -+ } -+ return OMX_ErrorNone; -+} -+ -+/** @brief Part of the standard OpenMAX function -+ * -+ * This function return the parameters not related to any port. -+ * These parameters are handled in the derived components -+ * See OMX_Core.h for standard reference -+ * -+ * @return OMX_ErrorUnsupportedIndex if the index is not supported or not handled here -+ */ -+OMX_ERRORTYPE omx_base_component_GetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_INOUT OMX_PTR ComponentParameterStructure) { -+ -+ OMX_COMPONENTTYPE *omxcomponent = (OMX_COMPONENTTYPE*)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxcomponent->pComponentPrivate; -+ OMX_PRIORITYMGMTTYPE* pPrioMgmt; -+ OMX_PARAM_PORTDEFINITIONTYPE *pPortDef; -+ OMX_PARAM_BUFFERSUPPLIERTYPE *pBufferSupplier; -+ omx_base_PortType *pPort; -+ OMX_PORT_PARAM_TYPE* pPortDomains; -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ OMX_VENDOR_PROP_TUNNELSETUPTYPE *pPropTunnelSetup; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ DEBUG(DEB_LEV_PARAMS, "Getting parameter %i\n", nParamIndex); -+ if (ComponentParameterStructure == NULL) { -+ return OMX_ErrorBadParameter; -+ } -+ switch(nParamIndex) { -+ case OMX_IndexParamAudioInit: -+ case OMX_IndexParamVideoInit: -+ case OMX_IndexParamImageInit: -+ case OMX_IndexParamOtherInit: -+ pPortDomains = (OMX_PORT_PARAM_TYPE*)ComponentParameterStructure; -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ pPortDomains->nPorts = 0; -+ pPortDomains->nStartPortNumber = 0; -+ break; -+ case OMX_IndexParamPortDefinition: -+ pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE*) ComponentParameterStructure; -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PARAM_PORTDEFINITIONTYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ if (pPortDef->nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ memcpy(pPortDef, &omx_base_component_Private->ports[pPortDef->nPortIndex]->sPortParam, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); -+ break; -+ case OMX_IndexParamPriorityMgmt: -+ pPrioMgmt = (OMX_PRIORITYMGMTTYPE*)ComponentParameterStructure; -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PRIORITYMGMTTYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ pPrioMgmt->nGroupPriority = omx_base_component_Private->nGroupPriority; -+ pPrioMgmt->nGroupID = omx_base_component_Private->nGroupID; -+ break; -+ case OMX_IndexParamCompBufferSupplier: -+ pBufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE*)ComponentParameterStructure; -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ if (pBufferSupplier->nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ pPort = omx_base_component_Private->ports[pBufferSupplier->nPortIndex]; -+ -+ if (pPort->sPortParam.eDir == OMX_DirInput) { -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ pBufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; -+ } else if (PORT_IS_TUNNELED(pPort)) { -+ pBufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; -+ } else { -+ pBufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; -+ } -+ } else { -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ pBufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; -+ } else if (PORT_IS_TUNNELED(pPort)) { -+ pBufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; -+ } else { -+ pBufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; -+ } -+ } -+ break; -+ case OMX_IndexVendorCompPropTunnelFlags: -+ pPropTunnelSetup = (OMX_VENDOR_PROP_TUNNELSETUPTYPE*)ComponentParameterStructure; -+ -+ if (pPropTunnelSetup->nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ -+ DEBUG(DEB_LEV_ERR,"In %s OMX_IndexVendorCompPropTunnelFlags nPortIndex=%d Line=%d \n", -+ __func__,(int)pPropTunnelSetup->nPortIndex,__LINE__); -+ -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ pPort = omx_base_component_Private->ports[pPropTunnelSetup->nPortIndex]; -+ -+ pPropTunnelSetup->nTunnelSetup.nTunnelFlags = pPort->nTunnelFlags; -+ pPropTunnelSetup->nTunnelSetup.eSupplier = pPort->eBufferSupplier; -+ break; -+ default: -+ err = OMX_ErrorUnsupportedIndex; -+ break; -+ } -+ return err; -+} -+ -+/** @brief Part of the standard OpenMAX function -+ * -+ * This function sets the parameters not related to any port. -+ * These parameters are handled in the derived components -+ * See OMX_Core.h for standard reference -+ * -+ * @return OMX_ErrorUnsupportedIndex if the index is not supported or not handled here -+ */ -+OMX_ERRORTYPE omx_base_component_SetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_IN OMX_PTR ComponentParameterStructure) { -+ -+ OMX_PRIORITYMGMTTYPE* pPrioMgmt; -+ OMX_PARAM_PORTDEFINITIONTYPE *pPortDef; -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ OMX_COMPONENTTYPE *omxcomponent = (OMX_COMPONENTTYPE*)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxcomponent->pComponentPrivate; -+ OMX_PARAM_BUFFERSUPPLIERTYPE *pBufferSupplier; -+ omx_base_PortType *pPort; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ DEBUG(DEB_LEV_PARAMS, "Setting parameter %x\n", nParamIndex); -+ if (ComponentParameterStructure == NULL) { -+ DEBUG(DEB_LEV_ERR, "In %s parameter provided is null! err = %x\n", __func__, err); -+ return OMX_ErrorBadParameter; -+ } -+ -+ switch(nParamIndex) { -+ case OMX_IndexParamAudioInit: -+ case OMX_IndexParamVideoInit: -+ case OMX_IndexParamImageInit: -+ case OMX_IndexParamOtherInit: -+ /* pPortParam = (OMX_PORT_PARAM_TYPE* ) ComponentParameterStructure;*/ -+ if (omx_base_component_Private->state != OMX_StateLoaded && -+ omx_base_component_Private->state != OMX_StateWaitForResources) { -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ err = OMX_ErrorUndefined; -+ break; -+ case OMX_IndexParamPortDefinition: -+ pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE*) ComponentParameterStructure; -+ DEBUG(DEB_LEV_PARAMS, "Setting parameter OMX_IndexParamPortDefinition for port %d\n", pPortDef->nPortIndex); -+ err = omx_base_component_ParameterSanityCheck(hComponent, pPortDef->nPortIndex, pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n",__func__,err); -+ break; -+ } -+ { -+ OMX_PARAM_PORTDEFINITIONTYPE *pPortParam; -+ OMX_U32 j,old_nBufferCountActual=0; -+ pPortParam = &omx_base_component_Private->ports[pPortDef->nPortIndex]->sPortParam; -+ if(pPortDef->nBufferCountActual < pPortParam->nBufferCountMin) { -+ DEBUG(DEB_LEV_ERR, "In %s nBufferCountActual of param (%i) is < of nBufferCountMin of port(%i)\n",__func__, (int)pPortDef->nBufferCountActual, (int)pPortParam->nBufferCountMin); -+ err = OMX_ErrorBadParameter; -+ break; -+ } -+ old_nBufferCountActual = pPortParam->nBufferCountActual; -+ pPortParam->nBufferCountActual = pPortDef->nBufferCountActual; -+ -+ switch(pPortDef->eDomain) { -+ case OMX_PortDomainAudio: -+ memcpy(&pPortParam->format.audio, &pPortDef->format.audio, sizeof(OMX_AUDIO_PORTDEFINITIONTYPE)); -+ break; -+ case OMX_PortDomainVideo: -+ pPortParam->format.video.pNativeRender = pPortDef->format.video.pNativeRender; -+ pPortParam->format.video.nFrameWidth = pPortDef->format.video.nFrameWidth; -+ pPortParam->format.video.nFrameHeight = pPortDef->format.video.nFrameHeight; -+ pPortParam->format.video.nStride = pPortDef->format.video.nStride; -+ pPortParam->format.video.xFramerate = pPortDef->format.video.xFramerate; -+ pPortParam->format.video.bFlagErrorConcealment = pPortDef->format.video.bFlagErrorConcealment; -+ pPortParam->format.video.eCompressionFormat = pPortDef->format.video.eCompressionFormat; -+ pPortParam->format.video.eColorFormat = pPortDef->format.video.eColorFormat; -+ pPortParam->format.video.pNativeWindow = pPortDef->format.video.pNativeWindow; -+ break; -+ case OMX_PortDomainImage: -+ pPortParam->format.image.nFrameWidth = pPortDef->format.image.nFrameWidth; -+ pPortParam->format.image.nFrameHeight = pPortDef->format.image.nFrameHeight; -+ pPortParam->format.image.nStride = pPortDef->format.image.nStride; -+ pPortParam->format.image.bFlagErrorConcealment = pPortDef->format.image.bFlagErrorConcealment; -+ pPortParam->format.image.eCompressionFormat = pPortDef->format.image.eCompressionFormat; -+ pPortParam->format.image.eColorFormat = pPortDef->format.image.eColorFormat; -+ pPortParam->format.image.pNativeWindow = pPortDef->format.image.pNativeWindow; -+ break; -+ case OMX_PortDomainOther: -+ memcpy(&pPortParam->format.other, &pPortDef->format.other, sizeof(OMX_OTHER_PORTDEFINITIONTYPE)); -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s wrong port domain. Out of OpenMAX scope\n",__func__); -+ err = OMX_ErrorBadParameter; -+ break; -+ } -+ -+ /*If component state Idle/Pause/Executing and re-alloc the following private variables */ -+ if ((omx_base_component_Private->state == OMX_StateIdle || -+ omx_base_component_Private->state == OMX_StatePause || -+ omx_base_component_Private->state == OMX_StateExecuting) && -+ (pPortParam->nBufferCountActual > old_nBufferCountActual)) { -+ -+ pPort = omx_base_component_Private->ports[pPortDef->nPortIndex]; -+ if(pPort->pInternalBufferStorage) { -+ if(PORT_IS_TUNNELED(pPort)){ -+ DEBUG(DEB_LEV_ERR, "In %s Attempt to reallocate tunneled buffers!\n",__func__); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ pPort->pInternalBufferStorage = (OMX_BUFFERHEADERTYPE**)realloc(pPort->pInternalBufferStorage,pPort->sPortParam.nBufferCountActual*sizeof(OMX_BUFFERHEADERTYPE *)); -+ } -+ -+ if(pPort->bBufferStateAllocated) { -+ pPort->bBufferStateAllocated = (BUFFER_STATUS_FLAG*)realloc(pPort->bBufferStateAllocated,pPort->sPortParam.nBufferCountActual*sizeof(BUFFER_STATUS_FLAG)); -+ for(j=0; j < pPort->sPortParam.nBufferCountActual; j++) { -+ pPort->bBufferStateAllocated[j] = BUFFER_FREE; -+ } -+ } -+ } -+ } -+ break; -+ case OMX_IndexParamPriorityMgmt: -+ if (omx_base_component_Private->state != OMX_StateLoaded && -+ omx_base_component_Private->state != OMX_StateWaitForResources) { -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ pPrioMgmt = (OMX_PRIORITYMGMTTYPE*)ComponentParameterStructure; -+ if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PRIORITYMGMTTYPE))) != OMX_ErrorNone) { -+ break; -+ } -+ omx_base_component_Private->nGroupPriority = pPrioMgmt->nGroupPriority; -+ omx_base_component_Private->nGroupID = pPrioMgmt->nGroupID; -+ break; -+ case OMX_IndexParamCompBufferSupplier: -+ pBufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE*)ComponentParameterStructure; -+ -+ DEBUG(DEB_LEV_PARAMS, "In %s Buf Sup Port index=%d\n", __func__,(int)pBufferSupplier->nPortIndex); -+ -+ if(pBufferSupplier == NULL) { -+ DEBUG(DEB_LEV_ERR, "In %s pBufferSupplier is null!\n",__func__); -+ return OMX_ErrorBadParameter; -+ } -+ if(pBufferSupplier->nPortIndex > (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ err = omx_base_component_ParameterSanityCheck(hComponent, pBufferSupplier->nPortIndex, pBufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); -+ if(err==OMX_ErrorIncorrectStateOperation) { -+ if (PORT_IS_ENABLED(omx_base_component_Private->ports[pBufferSupplier->nPortIndex])) { -+ DEBUG(DEB_LEV_ERR, "In %s Incorrect State=%x\n",__func__,omx_base_component_Private->state); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ } else if (err != OMX_ErrorNone) { -+ break; -+ } -+ -+ if (pBufferSupplier->eBufferSupplier == OMX_BufferSupplyUnspecified) { -+ DEBUG(DEB_LEV_PARAMS, "In %s: port is already buffer supplier unspecified\n", __func__); -+ return OMX_ErrorNone; -+ } -+ if ((PORT_IS_TUNNELED(omx_base_component_Private->ports[pBufferSupplier->nPortIndex])) == 0) { -+ return OMX_ErrorNone; -+ } -+ -+ pPort = omx_base_component_Private->ports[pBufferSupplier->nPortIndex]; -+ -+ if ((pBufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) && -+ (pPort->sPortParam.eDir == OMX_DirInput)) { -+ /** These two cases regard the first stage of client override */ -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ err = OMX_ErrorNone; -+ } -+ pPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ pBufferSupplier->nPortIndex = pPort->nTunneledPort; -+ err = OMX_SetParameter(pPort->hTunneledComponent, OMX_IndexParamCompBufferSupplier, pBufferSupplier); -+ } else if ((pBufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) && -+ (pPort->sPortParam.eDir == OMX_DirInput)) { -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ pPort->nTunnelFlags &= ~TUNNEL_IS_SUPPLIER; -+ pBufferSupplier->nPortIndex = pPort->nTunneledPort; -+ err = OMX_SetParameter(pPort->hTunneledComponent, OMX_IndexParamCompBufferSupplier, pBufferSupplier); -+ } -+ err = OMX_ErrorNone; -+ } else if ((pBufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) && -+ (pPort->sPortParam.eDir == OMX_DirOutput)) { -+ /** these two cases regard the second stage of client override */ -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ err = OMX_ErrorNone; -+ } -+ pPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ } else { -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ pPort->nTunnelFlags &= ~TUNNEL_IS_SUPPLIER; -+ err = OMX_ErrorNone; -+ } -+ err = OMX_ErrorNone; -+ } -+ DEBUG(DEB_LEV_PARAMS, "In %s port %d Tunnel flag=%x \n", __func__,(int)pBufferSupplier->nPortIndex, (int)pPort->nTunnelFlags); -+ break; -+ default: -+ err = OMX_ErrorUnsupportedIndex; -+ break; -+ } -+ return err; -+} -+ -+/** @brief base GetConfig function -+ * -+ * This base function is not implemented. If a derived component -+ * needs to support any config, it must implement a derived -+ * version of this function and assign it to the correct pointer -+ * in the private component descriptor -+ */ -+OMX_ERRORTYPE omx_base_component_GetConfig( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nIndex, -+ OMX_INOUT OMX_PTR pComponentConfigStructure) { -+ return OMX_ErrorNotImplemented; -+} -+ -+/** @brief base SetConfig function -+ * -+ * This base function is not implemented. If a derived component -+ * needs to support any config, it must implement a derived -+ * version of this function and assign it to the correct pointer -+ * in the private component descriptor -+ */ -+OMX_ERRORTYPE omx_base_component_SetConfig( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nIndex, -+ OMX_IN OMX_PTR pComponentConfigStructure) { -+ // TODO: For now, do not return OMX_ErrorNotImplemented here because it breaks current COMXAudio -+ return OMX_ErrorNone; -+} -+ -+/** @brief base function not implemented -+ * -+ * This function can be eventually implemented by a -+ * derived component if needed -+ */ -+OMX_ERRORTYPE omx_base_component_GetExtensionIndex( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_STRING cParameterName, -+ OMX_OUT OMX_INDEXTYPE* pIndexType) { -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME,"In %s \n",__func__); -+ -+ return OMX_ErrorBadParameter; -+} -+ -+/** @return the state of the component -+ * -+ * This function does not need any override by derived components -+ */ -+OMX_ERRORTYPE omx_base_component_GetState( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_OUT OMX_STATETYPE* pState) { -+ OMX_COMPONENTTYPE *omxcomponent = (OMX_COMPONENTTYPE*)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxcomponent->pComponentPrivate; -+ *pState = omx_base_component_Private->state; -+ return OMX_ErrorNone; -+} -+ -+/** @brief standard SendCommand function -+ * -+ * In general this function does not need a overwrite, but -+ * a special derived component could do it. -+ */ -+OMX_ERRORTYPE omx_base_component_SendCommand( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_COMMANDTYPE Cmd, -+ OMX_IN OMX_U32 nParam, -+ OMX_IN OMX_PTR pCmdData) { -+ OMX_COMPONENTTYPE* omxComponent = (OMX_COMPONENTTYPE*)hComponent; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ internalRequestMessageType *message; -+ omx_queue_t* messageQueue; -+ omx_tsem_t* messageSem; -+ OMX_U32 i,j,k; -+ omx_base_PortType *pPort; -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ messageQueue = omx_base_component_Private->messageQueue; -+ messageSem = omx_base_component_Private->messageSem; -+ -+ if (omx_base_component_Private->state == OMX_StateInvalid) { -+ return OMX_ErrorInvalidState; -+ } -+ -+ message = (internalRequestMessageType*)calloc(1,sizeof(internalRequestMessageType)); -+ message->messageParam = nParam; -+ message->pCmdData=pCmdData; -+ /** Fill in the message */ -+ switch (Cmd) { -+ case OMX_CommandStateSet: -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s OMX_CommandStateSet desired state=%d\n", __func__, nParam); -+ message->messageType = OMX_CommandStateSet; -+ if ((nParam == OMX_StateIdle) && (omx_base_component_Private->state == OMX_StateLoaded)) { -+ /*Allocate Internal Buffer Storage and Buffer Allocation State flags*/ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ -+ pPort = omx_base_component_Private->ports[i]; -+ -+ if(pPort->pInternalBufferStorage == NULL) { -+ pPort->pInternalBufferStorage = (OMX_BUFFERHEADERTYPE**)calloc(pPort->sPortParam.nBufferCountActual,sizeof(OMX_BUFFERHEADERTYPE *)); -+ } -+ -+ if(pPort->bBufferStateAllocated == NULL) { -+ pPort->bBufferStateAllocated = (BUFFER_STATUS_FLAG*)calloc(pPort->sPortParam.nBufferCountActual,sizeof(BUFFER_STATUS_FLAG)); -+ for(k=0; k < pPort->sPortParam.nBufferCountActual; k++) -+ { -+ pPort->bBufferStateAllocated[k] = BUFFER_FREE; -+ } -+ } -+ } -+ } -+ -+ omx_base_component_Private->transientState = OMX_TransStateLoadedToIdle; -+ } else if ((nParam == OMX_StateLoaded) && (omx_base_component_Private->state == OMX_StateIdle)) { -+ omx_base_component_Private->transientState = OMX_TransStateIdleToLoaded; -+ } else if ((nParam == OMX_StateIdle) && (omx_base_component_Private->state == OMX_StateExecuting)) { -+ omx_base_component_Private->transientState = OMX_TransStateExecutingToIdle; -+ } -+ break; -+ case OMX_CommandFlush: -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s OMX_CommandFlush port=%d\n", __func__, nParam); -+ if (nParam >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) && nParam != OMX_ALL) { -+ return OMX_ErrorBadPortIndex; -+ } -+ message->messageType = OMX_CommandFlush; -+ break; -+ case OMX_CommandPortDisable: -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s OMX_CommandPortDisable port=%d\n", __func__, nParam); -+ if (nParam >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) && nParam != OMX_ALL) { -+ return OMX_ErrorBadPortIndex; -+ } -+ message->messageType = OMX_CommandPortDisable; -+ if(message->messageParam == OMX_ALL) { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ omx_base_component_Private->ports[i]->bIsTransientToDisabled = OMX_TRUE; -+ } -+ } -+ } else { -+ omx_base_component_Private->ports[message->messageParam]->bIsTransientToDisabled = OMX_TRUE; -+ } -+ break; -+ case OMX_CommandPortEnable: -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s OMX_CommandPortEnable port=%d\n", __func__, nParam); -+ if (nParam >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) && nParam != OMX_ALL) { -+ return OMX_ErrorBadPortIndex; -+ } -+ message->messageType = OMX_CommandPortEnable; -+ if(message->messageParam == OMX_ALL) { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ omx_base_component_Private->ports[i]->bIsTransientToEnabled = OMX_TRUE; -+ } -+ } -+ } else { -+ omx_base_component_Private->ports[message->messageParam]->bIsTransientToEnabled = OMX_TRUE; -+ } -+ break; -+ case OMX_CommandMarkBuffer: -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s OMX_CommandMarkBuffer port=%d\n", __func__, nParam); -+ if (nParam >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts) && nParam != OMX_ALL) { -+ return OMX_ErrorBadPortIndex; -+ } -+ message->messageType = OMX_CommandMarkBuffer; -+ break; -+ default: -+ err = OMX_ErrorUnsupportedIndex; -+ break; -+ } -+ -+ if (err == OMX_ErrorNone) -+ { -+ omx_queue(messageQueue, message); -+ omx_tsem_up(messageSem); -+ } -+ -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s messageSem up param=%d\n", __func__,message->messageParam); -+ -+ return err; -+} -+ -+/** @brief Component's message handler thread function -+ * -+ * Handles all messages coming from components and -+ * processes them by dispatching them back to the -+ * triggering component. -+ */ -+void* compMessageHandlerFunction(void* param) { -+ OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE *)param; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ internalRequestMessageType *message; -+ -+ while(1){ -+ if (omx_base_component_Private == NULL) { -+ break; -+ } -+ -+ /* Wait for an incoming message */ -+ omx_tsem_down(omx_base_component_Private->messageSem); -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ /*Destructor has been called. So exit from the loop*/ -+ if(omx_base_component_Private->state == OMX_StateInvalid) { -+ break; -+ } -+ -+ /* Dequeue it */ -+ message = (internalRequestMessageType*)omx_dequeue(omx_base_component_Private->messageQueue); -+ if(message == NULL){ -+ DEBUG(DEB_LEV_ERR, "In %s: ouch!! had null message!\n", __func__); -+ break; -+ } -+ /* Process it by calling component's message handler method */ -+ omx_base_component_Private->messageHandler(openmaxStandComp,message); -+ /* Message ownership has been transferred to us -+ * so we gonna free it when finished. -+ */ -+ free(message); -+ message = NULL; -+ } -+ DEBUG(DEB_LEV_FUNCTION_NAME,"Exiting Message Handler thread\n"); -+ return NULL; -+} -+ -+/** This is called by the component message entry point. -+ * In thea base version this function is named compMessageHandlerFunction -+ * -+ * A request is made by the component when some asynchronous services are needed: -+ * 1) A SendCommand() is to be processed -+ * 2) An error needs to be notified -+ * 3) ... -+ * -+ * @param openmaxStandComp the component itself -+ * @param message the message that has been passed to core -+ */ -+OMX_ERRORTYPE omx_base_component_MessageHandler(OMX_COMPONENTTYPE *openmaxStandComp,internalRequestMessageType* message) { -+ omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ OMX_U32 i,j,k; -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ omx_base_PortType* pPort; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ /* Dealing with a SendCommand call. -+ * -messageType contains the command to execute -+ * -messageParam contains the parameter of the command -+ * (destination state in case of a state change command). -+ */ -+ switch(message->messageType){ -+ case OMX_CommandStateSet: { -+ /* Do the actual state change */ -+ err = (*(omx_base_component_Private->DoStateSet))(openmaxStandComp, message->messageParam); -+ if (err != OMX_ErrorNone) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventError, /* The command was completed */ -+ err, /* The commands was a OMX_CommandStateSet */ -+ 0, /* The state has been changed in message->messageParam */ -+ NULL); -+ } else { -+ /* And run the callback */ -+ DEBUG(DEB_LEV_FULL_SEQ,"running callback in %s\n",__func__); -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandStateSet, /* The commands was a OMX_CommandStateSet */ -+ message->messageParam, /* The state has been changed in message->messageParam */ -+ NULL); -+ } -+ } -+ break; -+ case OMX_CommandFlush: { -+ /*Flush port/s*/ -+ if(message->messageParam == OMX_ALL) { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ omx_base_component_Private->ports[i]->bIsPortFlushed = OMX_TRUE; -+ } -+ } -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort=omx_base_component_Private->ports[i]; -+ err = pPort->FlushProcessingBuffers(pPort); -+ } -+ } -+ } -+ else { -+ pPort=omx_base_component_Private->ports[message->messageParam]; -+ err = pPort->FlushProcessingBuffers(pPort); -+ } -+ if (err != OMX_ErrorNone) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventError, /* The command was completed */ -+ err, /* The commands was a OMX_CommandStateSet */ -+ 0, /* The state has been changed in message->messageParam */ -+ NULL); -+ } else { -+ if(message->messageParam == OMX_ALL){ /*Flush all port*/ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandFlush, /* The commands was a OMX_CommandStateSet */ -+ i, /* The state has been changed in message->messageParam */ -+ NULL); -+ -+ pPort=omx_base_component_Private->ports[i]; -+ /* Signal the buffer Semaphore and the buffer managment semaphore, to restart the exchange of buffers after flush */ -+ if (PORT_IS_TUNNELED(pPort) && PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ for(k=0;k<pPort->nNumTunnelBuffer;k++) { -+ omx_tsem_up(pPort->pBufferSem); -+ /*signal buffer management thread availability of buffers*/ -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ } -+ } -+ } else {/*Flush input/output port*/ -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandFlush, /* The commands was a OMX_CommandStateSet */ -+ message->messageParam, /* The state has been changed in message->messageParam */ -+ NULL); -+ /* Signal the buffer Semaphore and the buffer managment semaphore, to restart the exchange of buffers after flush */ -+ if (PORT_IS_TUNNELED(omx_base_component_Private->ports[message->messageParam]) -+ && PORT_IS_BUFFER_SUPPLIER(omx_base_component_Private->ports[message->messageParam])) { -+ for(j=0;j<omx_base_component_Private->ports[message->messageParam]->nNumTunnelBuffer;j++) { -+ omx_tsem_up(omx_base_component_Private->ports[message->messageParam]->pBufferSem); -+ /*signal buffer management thread availability of buffers*/ -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ } -+ } -+ } -+ break; -+ case OMX_CommandPortDisable: { -+ /*Flush port/s*/ -+ if(message->messageParam == OMX_ALL) { -+ /*If Component is not in loaded state,then First Flush all buffers then disable the port*/ -+ if(omx_base_component_Private->state!=OMX_StateLoaded) { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort=omx_base_component_Private->ports[i]; -+ err = pPort->FlushProcessingBuffers(pPort); -+ } -+ } -+ } -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort=omx_base_component_Private->ports[i]; -+ err = pPort->Port_DisablePort(pPort); -+ } -+ } -+ } -+ else { -+ pPort=omx_base_component_Private->ports[message->messageParam]; -+ if(omx_base_component_Private->state!=OMX_StateLoaded) { -+ err = pPort->FlushProcessingBuffers(pPort); -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Port Flush completed for Comp %s\n",__func__,omx_base_component_Private->name); -+ } -+ err = pPort->Port_DisablePort(pPort); -+ } -+ /** This condition is added to pass the tests, it is not significant for the environment */ -+ if (err != OMX_ErrorNone) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventError, /* The command was completed */ -+ err, /* The commands was a OMX_CommandStateSet */ -+ 0, /* The state has been changed in message->messageParam */ -+ NULL); -+ } else { -+ if(message->messageParam == OMX_ALL){ /*Disable all ports*/ -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandPortDisable, /* The commands was a OMX_CommandStateSet */ -+ i, /* The state has been changed in message->messageParam */ -+ NULL); -+ } -+ } -+ } else { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandPortDisable, /* The commands was a OMX_CommandStateSet */ -+ message->messageParam, /* The state has been changed in message->messageParam */ -+ NULL); -+ } -+ } -+ } -+ break; -+ case OMX_CommandPortEnable:{ -+ /*Flush port/s*/ -+ if(message->messageParam == OMX_ALL) { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort=omx_base_component_Private->ports[i]; -+ err = pPort->Port_EnablePort(pPort); -+ } -+ } -+ } else { -+ pPort=omx_base_component_Private->ports[message->messageParam]; -+ err = pPort->Port_EnablePort(pPort); -+ } -+ if (err != OMX_ErrorNone) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventError, /* The command was completed */ -+ err, /* The commands was a OMX_CommandStateSet */ -+ 0, /* The state has been changed in message->messageParam */ -+ NULL); -+ } else { -+ if(message->messageParam != OMX_ALL) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandPortEnable, /* The commands was a OMX_CommandStateSet */ -+ message->messageParam, /* The state has been changed in message->messageParam */ -+ NULL); -+ -+ if (omx_base_component_Private->state==OMX_StateExecuting) { -+ pPort=omx_base_component_Private->ports[message->messageParam]; -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ for(i=0; i < pPort->sPortParam.nBufferCountActual;i++) { -+ omx_tsem_up(pPort->pBufferSem); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ } -+ -+ } else { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventCmdComplete, /* The command was completed */ -+ OMX_CommandPortEnable, /* The commands was a OMX_CommandStateSet */ -+ i, /* The state has been changed in message->messageParam */ -+ NULL); -+ } -+ } -+ -+ if (omx_base_component_Private->state==OMX_StateExecuting) { -+ /* for all ports */ -+ for(j = 0; j < NUM_DOMAINS; j++) { -+ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; -+ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + -+ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { -+ pPort=omx_base_component_Private->ports[i]; -+ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { -+ for(k=0; k < pPort->sPortParam.nBufferCountActual;k++) { -+ omx_tsem_up(pPort->pBufferSem); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ break; -+ case OMX_CommandMarkBuffer: { -+ omx_base_component_Private->pMark.hMarkTargetComponent = ((OMX_MARKTYPE *)message->pCmdData)->hMarkTargetComponent; -+ omx_base_component_Private->pMark.pMarkData = ((OMX_MARKTYPE *)message->pCmdData)->pMarkData; -+ } -+ break; -+ default: -+ DEBUG(DEB_LEV_ERR, "In %s: Unrecognized command %i\n", __func__, message->messageType); -+ break; -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Returning from %s: \n", __func__); -+ return OMX_ErrorNone; -+} -+ -+OMX_ERRORTYPE omx_base_component_AllocateBuffer( -+ 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) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ omx_base_PortType *pPort; -+ -+ if (nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ pPort = omx_base_component_Private->ports[nPortIndex]; -+ -+ return pPort->Port_AllocateBuffer(pPort, -+ ppBuffer, -+ nPortIndex, -+ pAppPrivate, -+ nSizeBytes); -+} -+ -+OMX_ERRORTYPE omx_base_component_UseBuffer( -+ 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) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ omx_base_PortType *pPort; -+ -+ if (nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ pPort = omx_base_component_Private->ports[nPortIndex]; -+ -+ return pPort->Port_UseBuffer(pPort, -+ ppBufferHdr, -+ nPortIndex, -+ pAppPrivate, -+ nSizeBytes, -+ pBuffer); -+} ++#include <stdlib.h> ++#include <pthread.h> ++#include <alsa/asoundlib.h> ++#include <IL/OMX_Core.h> ++#include <IL/OMX_Component.h> ++#include <IL/OMX_Broadcom.h> + -+OMX_ERRORTYPE omx_base_component_UseEGLImage ( -+ OMX_HANDLETYPE hComponent, -+ OMX_BUFFERHEADERTYPE** ppBufferHdr, -+ OMX_U32 nPortIndex, -+ OMX_PTR pAppPrivate, -+ void* eglImage) { -+ return OMX_ErrorNotImplemented; -+} ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + -+OMX_ERRORTYPE omx_base_component_FreeBuffer( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_U32 nPortIndex, -+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ omx_base_PortType *pPort; -+ -+ if (nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ pPort = omx_base_component_Private->ports[nPortIndex]; -+ -+ return pPort->Port_FreeBuffer(pPort, -+ nPortIndex, -+ pBuffer); -+} ++struct _GOMX_COMMAND; ++struct _GOMX_PORT; ++struct _GOMX_COMPONENT; + -+OMX_ERRORTYPE omx_base_component_EmptyThisBuffer( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ omx_base_PortType *pPort; -+ //DEBUG(DEB_LEV_FUNCTION_NAME, "In %s pBuffer=0x%x pBuffer->pBuffer=0x%x nInputPortIndex=%d nOutputPortIndex=%d nAllocLen=%d nFilledLen=%d\n", -+ // __func__, pBuffer, pBuffer->pBuffer, pBuffer->nInputPortIndex, pBuffer->nOutputPortIndex, pBuffer->nAllocLen, pBuffer->nFilledLen); -+ -+ if (pBuffer->nInputPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ pPort = omx_base_component_Private->ports[pBuffer->nInputPortIndex]; -+ if (pPort->sPortParam.eDir != OMX_DirInput) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port direction in Component %s\n", __func__,omx_base_component_Private->name); -+ return OMX_ErrorBadPortIndex; -+ } -+ return pPort->Port_SendBufferFunction(pPort, pBuffer); ++template <class X> static inline X max(X a, X b) ++{ ++ return (a > b) ? a : b; +} + -+OMX_ERRORTYPE omx_base_component_FillThisBuffer( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { -+ -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ omx_base_PortType *pPort; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ if (pBuffer->nOutputPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ pPort = omx_base_component_Private->ports[pBuffer->nOutputPortIndex]; -+ if (pPort->sPortParam.eDir != OMX_DirOutput) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port direction in Component %s\n", __func__,omx_base_component_Private->name); -+ return OMX_ErrorBadPortIndex; -+ } -+ return pPort->Port_SendBufferFunction(pPort, pBuffer); ++template <class X> static OMX_ERRORTYPE omx_cast(X* &toptr, OMX_PTR fromptr) ++{ ++ toptr = (X*) fromptr; ++ if (toptr->nSize < sizeof(X)) return OMX_ErrorBadParameter; ++ if (toptr->nVersion.nVersion != OMX_VERSION) return OMX_ErrorVersionMismatch; ++ return OMX_ErrorNone; +} + -+OMX_ERRORTYPE omx_base_component_ComponentTunnelRequest( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_U32 nPort, -+ OMX_IN OMX_HANDLETYPE hTunneledComp, -+ OMX_IN OMX_U32 nTunneledPort, -+ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { -+ -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ omx_base_PortType *pPort; -+ -+ if (nPort >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + -+ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ pPort = omx_base_component_Private->ports[nPort]; -+ -+ return pPort->ComponentTunnelRequest(pPort, hTunneledComp, nTunneledPort, pTunnelSetup); ++template <class X> static void omx_init(X &omx) ++{ ++ omx.nSize = sizeof(X); ++ omx.nVersion.nVersion = OMX_VERSION; +} -diff --git a/alsa/omx_base_component.h b/alsa/omx_base_component.h -new file mode 100644 -index 0000000..9134119 ---- /dev/null -+++ b/alsa/omx_base_component.h -@@ -0,0 +1,412 @@ -+/** -+ @file src/base/omx_base_component.h -+ -+ OpenMAX base component. This component does not perform any multimedia -+ processing.It is used as a base component for new components development. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-09-11 11:45:59 +0200 (Thu, 11 Sep 2008) $ -+ Revision $Rev: 613 $ -+ Author $Author: pankaj_sen $ -+ -+*/ -+#ifndef _OMX_BASE_COMPONENT_H_ -+#define _OMX_BASE_COMPONENT_H_ -+ -+#include <pthread.h> -+ -+#include "omx_semaphore.h" -+#include "omx_queue.h" -+#include "omx_classmagic.h" -+#include "omx_base_port.h" -+ -+/** Default size of the internal input buffer */ -+#define DEFAULT_IN_BUFFER_SIZE 4 * 1024 -+/** Default size of the internal output buffer */ -+#define DEFAULT_OUT_BUFFER_SIZE 16 * 1024 /*32 * 1024*/ /*16 * 1024 */ // TODO - check this size is ok -+/** Default MIME string length */ -+#define DEFAULT_MIME_STRING_LENGTH 128 -+ -+#define NUM_DOMAINS 4 -+ -+/* Check if Component is deinitalizing*/ -+#define IS_COMPONENT_DEINIT(component_Private, exit_condition) \ -+ pthread_mutex_lock(&component_Private->exit_mutex) ,\ -+ exit_condition = component_Private->bIsComponentDeinit ,\ -+ pthread_mutex_unlock(&component_Private->exit_mutex) ,\ -+ (exit_condition == OMX_TRUE) ? OMX_TRUE:OMX_FALSE \ -+ -+typedef struct OMX_VENDOR_EXTRADATATYPE { -+ OMX_U32 nPortIndex; -+ OMX_U32 nDataSize; // Size of the supporting data to follow -+ OMX_U8 *pData; // Supporting data hint -+} OMX_VENDOR_EXTRADATATYPE; -+ -+typedef struct OMX_VENDOR_PROP_TUNNELSETUPTYPE { -+ OMX_U32 nPortIndex; -+ OMX_TUNNELSETUPTYPE nTunnelSetup; // Tunnel setup flags -+} OMX_VENDOR_PROP_TUNNELSETUPTYPE; -+ -+/** this is the list of custom vendor index */ -+typedef enum OMX_INDEXVENDORTYPE { -+ /** only one index for file reader component input file */ -+ OMX_IndexVendorFileReadInputFilename = 0xFF000001, -+ OMX_IndexVendorParser3gpInputFilename = 0xFF000002, -+ OMX_IndexVendorVideoExtraData = 0xFF000003, -+ OMX_IndexVendorAudioExtraData = 0xFF000004, -+ OMX_IndexVendorCompPropTunnelFlags = 0xFF000005 /* Will use OMX_TUNNELSETUPTYPE structure*/ -+} OMX_INDEXVENDORTYPE; -+ -+/** This enum defines the transition states of the Component*/ -+typedef enum OMX_TRANS_STATETYPE { -+ OMX_TransStateInvalid, -+ OMX_TransStateLoadedToIdle, -+ OMX_TransStateIdleToPause, -+ OMX_TransStatePauseToExecuting, -+ OMX_TransStateIdleToExecuting, -+ OMX_TransStateExecutingToIdle, -+ OMX_TransStateExecutingToPause, -+ OMX_TransStatePauseToIdle, -+ OMX_TransStateIdleToLoaded, -+ OMX_TransStateMax = 0X7FFFFFFF -+} OMX_TRANS_STATETYPE; -+ -+/** @brief Enumerates all the possible types of messages -+ * handled internally by the component -+ */ -+typedef enum INTERNAL_MESSAGE_TYPE { -+ SENDCOMMAND_MSG_TYPE = 1,/**< this flag specifies that the message send is a command */ -+ ERROR_MSG_TYPE,/**< this flag specifies that the message send is an error message */ -+ WARNING_MSG_TYPE /**< this flag specifies that the message send is a warning message */ -+} INTERNAL_MESSAGE_TYPE; -+ -+/** @brief The container of an internal message -+ * -+ * This structure contains a generic OpenMAX request (from send command). -+ * It is processed by the internal message handler thread -+ */ -+typedef struct internalRequestMessageType { -+ int messageType; /**< the flag that specifies if the message is a command, a warning or an error */ -+ int messageParam; /**< the second field of the message. Its use is the same as specified for the command in OpenMAX spec */ -+ OMX_PTR pCmdData; /**< This pointer could contain some proprietary data not covered by the standard */ -+} internalRequestMessageType; -+ -+/** -+ * @brief the base descriptor for a ST component -+ */ -+CLASS(omx_base_component_PrivateType) -+#define omx_base_component_PrivateType_FIELDS \ -+ OMX_COMPONENTTYPE *openmaxStandComp; /**< The OpenMAX standard data structure describing a component */ \ -+ omx_base_PortType **ports; /** @param ports The ports of the component */ \ -+ OMX_PORT_PARAM_TYPE sPortTypesParam[NUM_DOMAINS]; /** @param sPortTypesParam OpenMAX standard parameter that contains a short description of the available ports */ \ -+ char uniqueID; /**< ID code that identifies an ST static component*/ \ -+ char* name; /**< component name */\ -+ OMX_STATETYPE state; /**< The state of the component */ \ -+ OMX_TRANS_STATETYPE transientState; /**< The transient state in case of transition between \ -+ Loaded/waitForResources - Idle. It is equal to \ -+ Invalid if the state or transition are not corect \ -+ Loaded when the transition is from Idle to Loaded \ -+ Idle when the transition is from Loaded to Idle */ \ -+ OMX_CALLBACKTYPE* callbacks; /**< pointer to every client callback function, \ -+ as specified by the standard*/ \ -+ OMX_PTR callbackData;/**< Private data that can be send with \ -+ the client callbacks. Not specified by the standard */ \ -+ omx_queue_t* messageQueue;/**< the queue of all the messages recevied by the component */\ -+ omx_tsem_t* messageSem;/**< the semaphore that coordinates the access to the message queue */\ -+ OMX_U32 nGroupPriority; /**< @param nGroupPriority Resource management field: component priority (common to a group of components) */\ -+ OMX_U32 nGroupID; /**< @param nGroupID ID of a group of components that share the same logical chain */\ -+ OMX_MARKTYPE pMark; /**< @param pMark This field holds the private data associated with a mark request, if any */\ -+ pthread_mutex_t flush_mutex; /** @param flush_mutex mutex for the flush condition from buffers */ \ -+ omx_tsem_t* flush_all_condition; /** @param flush_all_condition condition for the flush all buffers */ \ -+ omx_tsem_t* flush_condition; /** @param The flush_condition condition */ \ -+ omx_tsem_t* bMgmtSem;/**< @param bMgmtSem the semaphore that control BufferMgmtFunction processing */\ -+ omx_tsem_t* bStateSem;/**< @param bMgmtSem the semaphore that control BufferMgmtFunction processing */\ -+ int messageHandlerThreadID; /** @param messageHandlerThreadID The ID of the pthread that handles the messages for the components */ \ -+ pthread_t messageHandlerThread; /** @param messageHandlerThread This field contains the reference to the thread that receives messages for the components */ \ -+ int bufferMgmtThreadID; /** @param bufferMgmtThreadID The ID of the pthread that process buffers */ \ -+ pthread_t bufferMgmtThread; /** @param bufferMgmtThread This field contains the reference to the thread that process buffers */ \ -+ void *loader; /**< pointer to the loader that created this component, used for destruction */ \ -+ void* (*BufferMgmtFunction)(void* param); /** @param BufferMgmtFunction This function processes input output buffers */ \ -+ OMX_ERRORTYPE (*messageHandler)(OMX_COMPONENTTYPE*,internalRequestMessageType*);/** This function receives messages from the message queue. It is needed for each Linux ST OpenMAX component */ \ -+ OMX_ERRORTYPE (*DoStateSet)(OMX_COMPONENTTYPE *openmaxStandComp, OMX_U32); /**< @param DoStateSet internal function called when a generic state transition is requested*/ \ -+ OMX_ERRORTYPE (*destructor)(OMX_COMPONENTTYPE *openmaxStandComp); /** Component Destructor*/ -+ENDCLASS(omx_base_component_PrivateType) -+ -+/** -+ * @brief The base contructor for the OpenMAX ST components -+ * -+ * This function is executed by the ST static component loader. -+ * It takes care of constructing the instance of the component. -+ * For the base_component component, the following is done: -+ * -+ * 1) Fills the basic OpenMAX structure. The fields can be overwritten -+ * by derived components. -+ * 2) Allocates (if needed) the omx_base_component_PrivateType private structure -+ * -+ * @param openmaxStandComp the ST component to be initialized -+ * @param cComponentName the OpenMAX string that describes the component -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+OMX_ERRORTYPE omx_base_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName); -+ -+/** @brief the base destructor for ST OpenMAX components -+ * -+ * This function is called by the standard function ComponentDeInit() -+ * that is called by the IL core during the execution of the FreeHandle() -+ * -+ * @param openmaxStandComp the ST OpenMAX component to be disposed -+ */ -+OMX_ERRORTYPE omx_base_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp); -+ -+/** Changes the state of a component taking proper actions depending on -+ * the transiotion requested. This base function cover only the state -+ * changes that do not involve any port -+ * -+ * @param openmaxStandComp the OpenMAX component which state is to be changed -+ * @param destinationState the requested target state -+ * -+ * @return OMX_ErrorNotImplemented if the state change is noty handled -+ * in this base class, but needs a specific handling -+ */ -+OMX_ERRORTYPE omx_base_component_DoStateSet( -+ OMX_COMPONENTTYPE *openmaxStandComp, -+ OMX_U32 destinationState); -+ -+/** @brief Checks the header of a structure for consistency -+ * with size and spec version -+ * -+ * @param header Pointer to the structure to be checked -+ * @param size Size of the structure. it is in general obtained -+ * with a sizeof call applied to the structure -+ * -+ * @return OMX error code. If the header has failed the check, -+ * OMX_ErrorVersionMismatch is returned. -+ * If the header fails the size check OMX_ErrorBadParameter is returned -+ */ -+OMX_ERRORTYPE checkHeader(OMX_PTR header, OMX_U32 size); -+ -+/** @brief Simply fills the first two fields in any OMX structure -+ * with the size and the version -+ * -+ * @param header pointer to the structure to be filled -+ * @param size size of the structure. It can be obtained with -+ * a call to sizeof of the structure type -+ */ -+void setHeader(OMX_PTR header, OMX_U32 size); -+ -+/** @brief standard openmax function -+ * -+ * it returns the version of the component. See OMX_Core.h -+ */ -+OMX_ERRORTYPE omx_base_component_GetComponentVersion(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); -+ -+/** @brief Enumerates all the role of the component. -+ * -+ * This function is intended to be used only by a core. The ST static core -+ * in any case does not use this function, because it can not be used before the -+ * creation of the component, but uses a static list. -+ * It is implemented only for API completion, and it will be not overriden -+ * by a derived component. -+ * -+ * @param hComponent handle of the component -+ * @param cRole the output string containing the n-role of the component -+ * @param nIndex the index of the role requested -+ */ -+OMX_ERRORTYPE omx_base_component_ComponentRoleEnum( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_OUT OMX_U8 *cRole, -+ OMX_IN OMX_U32 nIndex); -+ -+/** @brief standard OpenMAX function -+ * -+ * it sets the callback functions given by the IL client. -+ * See OMX_Component.h -+ */ -+OMX_ERRORTYPE omx_base_component_SetCallbacks( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_CALLBACKTYPE* pCallbacks, -+ OMX_IN OMX_PTR pAppData); -+ -+/** @brief Part of the standard OpenMAX function -+ * -+ * This function return the parameters not related to any port. -+ * These parameters are handled in the derived components -+ * See OMX_Core.h for standard reference. -+ */ -+OMX_ERRORTYPE omx_base_component_GetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_INOUT OMX_PTR ComponentParameterStructure); -+ -+/** @brief part of the standard openmax function -+ * -+ * This function return the parameters not related to any port, -+ * These parameters are handled in the derived components -+ * See OMX_Core.h for standard reference. -+ * -+ * @return OMX_ErrorUnsupportedIndex if the index is not supported or not handled here -+ */ -+OMX_ERRORTYPE omx_base_component_SetParameter( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nParamIndex, -+ OMX_IN OMX_PTR ComponentParameterStructure); -+ -+/** @brief base GetConfig function -+ * -+ * This base function is not implemented. If a derived component -+ * needs to support any config, it must implement a derived -+ * version of this function and assign it to the correct pointer -+ * in the private component descriptor. -+ */ -+OMX_ERRORTYPE omx_base_component_GetConfig( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nIndex, -+ OMX_INOUT OMX_PTR pComponentConfigStructure); -+ -+/** @brief base SetConfig function -+ * -+ * This base function is not implemented. If a derived component -+ * needs to support any config, it must implement a derived -+ * version of this function and assign it to the correct pointer -+ * in the private component descriptor. -+ */ -+OMX_ERRORTYPE omx_base_component_SetConfig( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_INDEXTYPE nIndex, -+ OMX_IN OMX_PTR pComponentConfigStructure); -+ -+/** @brief base function not implemented -+ * -+ * This function can be eventually implemented by a -+ * derived component if needed. -+ */ -+OMX_ERRORTYPE omx_base_component_GetExtensionIndex( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_STRING cParameterName, -+ OMX_OUT OMX_INDEXTYPE* pIndexType); -+ -+/** @returns the state of the component -+ * -+ * This function does not need any override by derived components. -+ */ -+OMX_ERRORTYPE omx_base_component_GetState( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_OUT OMX_STATETYPE* pState); -+ -+/** @brief standard SendCommand function -+ * -+ * In general this function does not need a overwrite, but -+ * a special derived component could do it. -+ */ -+OMX_ERRORTYPE omx_base_component_SendCommand( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_COMMANDTYPE Cmd, -+ OMX_IN OMX_U32 nParam, -+ OMX_IN OMX_PTR pCmdData); -+ -+/** @brief This standard functionality is called when the component is -+ * destroyed in the FreeHandle standard call. -+ * -+ * In this way the implementation of the FreeHandle is standard, -+ * and it does not need a support by a specific component loader. -+ * The implementaiton of the ComponentDeInit contains the -+ * implementation specific part of the destroying phase. -+ */ -+OMX_ERRORTYPE omx_base_component_ComponentDeInit( -+ OMX_IN OMX_HANDLETYPE hComponent); -+ -+/** @brief Component's message handler thread function -+ * -+ * Handles all messages coming from components and -+ * processes them by dispatching them back to the -+ * triggering component. -+ */ -+void* compMessageHandlerFunction(void*); -+ -+/** This is called by the component message entry point. -+ * In thea base version this function is named compMessageHandlerFunction -+ * -+ * A request is made by the component when some asynchronous services are needed: -+ * 1) A SendCommand() is to be processed -+ * 2) An error needs to be notified -+ * 3) ... -+ * -+ * @param openmaxStandComp the component itself -+ * @param message the message that has been passed to core -+ */ -+OMX_ERRORTYPE omx_base_component_MessageHandler(OMX_COMPONENTTYPE *openmaxStandComp,internalRequestMessageType* message); -+ -+/** -+ * This function verify Component State and Structure header -+ */ -+OMX_ERRORTYPE omx_base_component_ParameterSanityCheck( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_U32 nPortIndex, -+ OMX_IN OMX_PTR pStructure, -+ OMX_IN size_t size); -+ -+OMX_ERRORTYPE omx_base_component_AllocateBuffer( -+ 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); -+ -+OMX_ERRORTYPE omx_base_component_UseBuffer( -+ 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); -+ -+OMX_ERRORTYPE omx_base_component_UseEGLImage ( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, -+ OMX_IN OMX_U32 nPortIndex, -+ OMX_IN OMX_PTR pAppPrivate, -+ OMX_IN void* eglImage); -+ -+OMX_ERRORTYPE omx_base_component_FreeBuffer( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_U32 nPortIndex, -+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); -+ -+OMX_ERRORTYPE omx_base_component_EmptyThisBuffer( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); -+ -+OMX_ERRORTYPE omx_base_component_FillThisBuffer( -+ OMX_IN OMX_HANDLETYPE hComponent, -+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); -+ -+OMX_ERRORTYPE omx_base_component_ComponentTunnelRequest( -+ 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); + ++#if 1 ++#include <utils/log.h> ++#define CLOG(notice, comp, port, msg, ...) do { \ ++ struct _GOMX_PORT *_port = (struct _GOMX_PORT *) port; \ ++ if (_port) CLog::Log(notice ? LOGNOTICE : LOGDEBUG, "[%p port %d]: %s: " msg "\n", comp, _port->def.nPortIndex, __func__ , ##__VA_ARGS__); \ ++ else CLog::Log(notice ? LOGNOTICE : LOGDEBUG, "[%p] %s: " msg "\n", comp, __func__ , ##__VA_ARGS__); \ ++} while (0) ++#else ++#define CLOG(notice, comp, port, msg, ...) do { \ ++ struct _GOMX_PORT *_port = (struct _GOMX_PORT *) port; \ ++ if (_port) fprintf(stderr, "[%p port %d]: %s: " msg "\n", comp, _port->def.nPortIndex, __func__ , ##__VA_ARGS__); \ ++ else fprintf(stderr, "[%p] %s: " msg "\n", comp, __func__ , ##__VA_ARGS__); \ ++} while (0) +#endif -diff --git a/alsa/omx_base_port.cpp b/alsa/omx_base_port.cpp -new file mode 100644 -index 0000000..67d003a ---- /dev/null -+++ b/alsa/omx_base_port.cpp -@@ -0,0 +1,1163 @@ -+/** -+ @file src/base/omx_base_port.c -+ -+ Base class for OpenMAX ports to be used in derived components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. + -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. ++#define CINFO(comp, port, msg, ...) CLOG(1, comp, port, msg , ##__VA_ARGS__) ++#define CDEBUG(comp, port, msg, ...) CLOG(0, comp, port, msg , ##__VA_ARGS__) + -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA ++/* Generic OMX helpers */ + -+ $Date: 2008-09-11 15:28:59 +0200 (Thu, 11 Sep 2008) $ -+ Revision $Rev: 614 $ -+ Author $Author: gsent $ -+*/ ++typedef struct _GOMX_QUEUE { ++ void *head, *tail; ++ ptrdiff_t offset; ++ size_t num; ++} GOMX_QUEUE; + -+#include <stdlib.h> -+#include <string.h> -+#include <unistd.h> -+//#include <IL/OMX_Core.h> -+//#include <IL/OMX_Component.h> -+ -+#include "omx_base_component.h" -+#include "omx_base_port.h" -+ -+/** The default value for the number of needed buffers for each port. */ -+#define DEFAULT_NUMBER_BUFFERS_PER_PORT 4 -+/** The default value for the minimum number of needed buffers for each port. */ -+#define DEFAULT_MIN_NUMBER_BUFFERS_PER_PORT 4 -+/** -+ * @brief The base contructor for the generic OpenMAX ST port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of constructing the instance of the port and -+ * every object needed by the base port. -+ * -+ * @param openmaxStandComp in the component that holds the port -+ * @param openmaxStandPort the ST port to be initialized -+ * @param nPortIndex the index of the port -+ * @param isInput specifices if the port is an input or an output -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+ -+OMX_ERRORTYPE base_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput) { -+ -+ /* omx_base_component_PrivateType* omx_base_component_Private; */ -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ /* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; */ -+ -+ // create ports, but only if the subclass hasn't done it -+ if (!(*openmaxStandPort)) { -+ *openmaxStandPort = (omx_base_PortType*)calloc(1,sizeof (omx_base_PortType)); -+ } -+ -+ if (!(*openmaxStandPort)) { -+ return OMX_ErrorInsufficientResources; -+ } -+ -+ (*openmaxStandPort)->hTunneledComponent = NULL; -+ (*openmaxStandPort)->nTunnelFlags=0; -+ (*openmaxStandPort)->nTunneledPort=0; -+ (*openmaxStandPort)->eBufferSupplier=OMX_BufferSupplyUnspecified; -+ (*openmaxStandPort)->nNumTunnelBuffer=0; -+ (*openmaxStandPort)->bTunnelTearDown = OMX_FALSE; -+ -+ if((*openmaxStandPort)->pAllocSem==NULL) { -+ (*openmaxStandPort)->pAllocSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ if((*openmaxStandPort)->pAllocSem==NULL) { -+ return OMX_ErrorInsufficientResources; -+ } -+ omx_tsem_init((*openmaxStandPort)->pAllocSem, 0); -+ } -+ (*openmaxStandPort)->nNumBufferFlushed=0; -+ (*openmaxStandPort)->bIsPortFlushed=OMX_FALSE; -+ /** Allocate and initialize buffer queue */ -+ if(!(*openmaxStandPort)->pBufferQueue) { -+ (*openmaxStandPort)->pBufferQueue = (omx_queue_t*)calloc(1,sizeof(omx_queue_t)); -+ if((*openmaxStandPort)->pBufferQueue==NULL) return OMX_ErrorInsufficientResources; -+ omx_queue_init((*openmaxStandPort)->pBufferQueue); -+ } -+ /*Allocate and initialise port semaphores*/ -+ if(!(*openmaxStandPort)->pBufferSem) { -+ (*openmaxStandPort)->pBufferSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); -+ if((*openmaxStandPort)->pBufferSem==NULL) return OMX_ErrorInsufficientResources; -+ omx_tsem_init((*openmaxStandPort)->pBufferSem, 0); -+ } -+ -+ (*openmaxStandPort)->nNumAssignedBuffers=0; -+ setHeader(&(*openmaxStandPort)->sPortParam, sizeof (OMX_PARAM_PORTDEFINITIONTYPE)); -+ (*openmaxStandPort)->sPortParam.nPortIndex = nPortIndex; -+ (*openmaxStandPort)->sPortParam.nBufferCountActual = DEFAULT_NUMBER_BUFFERS_PER_PORT; -+ (*openmaxStandPort)->sPortParam.nBufferCountMin = DEFAULT_MIN_NUMBER_BUFFERS_PER_PORT; -+ (*openmaxStandPort)->sPortParam.bEnabled = OMX_TRUE; -+ (*openmaxStandPort)->sPortParam.bPopulated = OMX_FALSE; -+ (*openmaxStandPort)->sPortParam.eDir = (isInput == OMX_TRUE)?OMX_DirInput:OMX_DirOutput; -+ -+ (*openmaxStandPort)->standCompContainer=openmaxStandComp; -+ (*openmaxStandPort)->bIsTransientToEnabled=OMX_FALSE; -+ (*openmaxStandPort)->bIsTransientToDisabled=OMX_FALSE; -+ (*openmaxStandPort)->bIsFullOfBuffers=OMX_FALSE; -+ (*openmaxStandPort)->bIsEmptyOfBuffers=OMX_FALSE; -+ (*openmaxStandPort)->bBufferStateAllocated = NULL; -+ (*openmaxStandPort)->pInternalBufferStorage = NULL; -+ -+ (*openmaxStandPort)->PortDestructor = &base_port_Destructor; -+ (*openmaxStandPort)->Port_AllocateBuffer = &base_port_AllocateBuffer; -+ (*openmaxStandPort)->Port_UseBuffer = &base_port_UseBuffer; -+ (*openmaxStandPort)->Port_FreeBuffer = &base_port_FreeBuffer; -+ (*openmaxStandPort)->Port_DisablePort = &base_port_DisablePort; -+ (*openmaxStandPort)->Port_EnablePort = &base_port_EnablePort; -+ (*openmaxStandPort)->Port_SendBufferFunction = &base_port_SendBufferFunction; -+ (*openmaxStandPort)->FlushProcessingBuffers = &base_port_FlushProcessingBuffers; -+ (*openmaxStandPort)->ReturnBufferFunction = &base_port_ReturnBufferFunction; -+ (*openmaxStandPort)->ComponentTunnelRequest = &base_port_ComponentTunnelRequest; -+ (*openmaxStandPort)->Port_AllocateTunnelBuffer = &base_port_AllocateTunnelBuffer; -+ (*openmaxStandPort)->Port_FreeTunnelBuffer = &base_port_FreeTunnelBuffer; -+ -+ return OMX_ErrorNone; -+} -+ -+OMX_ERRORTYPE base_port_Destructor(omx_base_PortType *openmaxStandPort){ -+ -+ if(openmaxStandPort->pAllocSem) { -+ omx_tsem_deinit(openmaxStandPort->pAllocSem); -+ free(openmaxStandPort->pAllocSem); -+ openmaxStandPort->pAllocSem=NULL; -+ } -+ /** Allocate and initialize buffer queue */ -+ if(openmaxStandPort->pBufferQueue) { -+ omx_queue_deinit(openmaxStandPort->pBufferQueue); -+ free(openmaxStandPort->pBufferQueue); -+ openmaxStandPort->pBufferQueue=NULL; -+ } -+ /*Allocate and initialise port semaphores*/ -+ if(openmaxStandPort->pBufferSem) { -+ omx_tsem_deinit(openmaxStandPort->pBufferSem); -+ free(openmaxStandPort->pBufferSem); -+ openmaxStandPort->pBufferSem=NULL; -+ } -+ -+ free(openmaxStandPort); -+ openmaxStandPort = NULL; -+ return OMX_ErrorNone; -+} -+ -+/** @brief Releases buffers under processing. -+ * This function must be implemented in the derived classes, for the -+ * specific processing -+ */ -+OMX_ERRORTYPE base_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort) { -+ omx_base_component_PrivateType* omx_base_component_Private; -+ OMX_BUFFERHEADERTYPE* pBuffer; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; -+ -+ if(openmaxStandPort->sPortParam.eDomain!=OMX_PortDomainOther) { /* clock buffers not used in the clients buffer managment function */ -+ pthread_mutex_lock(&omx_base_component_Private->flush_mutex); -+ openmaxStandPort->bIsPortFlushed=OMX_TRUE; -+ /*Signal the buffer management thread of port flush,if it is waiting for buffers*/ -+ if(omx_base_component_Private->bMgmtSem->semval==0) { -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ -+ if(omx_base_component_Private->state==OMX_StatePause ) { -+ /*Waiting at paused state*/ -+ omx_tsem_signal(omx_base_component_Private->bStateSem); -+ } -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s waiting for flush all condition port index =%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); -+ /* Wait until flush is completed */ -+ pthread_mutex_unlock(&omx_base_component_Private->flush_mutex); -+ omx_tsem_down(omx_base_component_Private->flush_all_condition); -+ } -+ -+ omx_tsem_reset(omx_base_component_Private->bMgmtSem); -+ -+ /* Flush all the buffers not under processing */ -+ while (openmaxStandPort->pBufferSem->semval > 0) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s TFlag=%x Flusing Port=%d,Semval=%d Qelem=%d\n", -+ __func__,(int)openmaxStandPort->nTunnelFlags,(int)openmaxStandPort->sPortParam.nPortIndex, -+ (int)openmaxStandPort->pBufferSem->semval,(int)openmaxStandPort->pBufferQueue->nelem); -+ -+ omx_tsem_down(openmaxStandPort->pBufferSem); -+ pBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(openmaxStandPort->pBufferQueue); -+ if (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s is returning io:%d buffer\n", -+ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); -+ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ } else { -+ ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ } -+ } else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ omx_queue(openmaxStandPort->pBufferQueue,pBuffer); -+ } else { -+ (*(openmaxStandPort->BufferProcessedCallback))( -+ openmaxStandPort->standCompContainer, -+ omx_base_component_Private->callbackData, -+ pBuffer); -+ } -+ } -+ /*Port is tunneled and supplier and didn't received all it's buffer then wait for the buffers*/ -+ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ while(openmaxStandPort->pBufferQueue->nelem!= openmaxStandPort->nNumAssignedBuffers){ -+ omx_tsem_down(openmaxStandPort->pBufferSem); -+ DEBUG(DEB_LEV_PARAMS, "In %s Got a buffer qelem=%d\n",__func__,openmaxStandPort->pBufferQueue->nelem); -+ } -+ omx_tsem_reset(openmaxStandPort->pBufferSem); -+ } -+ -+ pthread_mutex_lock(&omx_base_component_Private->flush_mutex); -+ openmaxStandPort->bIsPortFlushed=OMX_FALSE; -+ pthread_mutex_unlock(&omx_base_component_Private->flush_mutex); -+ -+ omx_tsem_up(omx_base_component_Private->flush_condition); -+ -+ DEBUG(DEB_LEV_FULL_SEQ, "Out %s Port Index=%d bIsPortFlushed=%d Component %s\n", __func__, -+ (int)openmaxStandPort->sPortParam.nPortIndex,(int)openmaxStandPort->bIsPortFlushed,omx_base_component_Private->name); -+ -+ DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__, -+ (int)openmaxStandPort->nTunnelFlags, -+ (int)openmaxStandPort->pBufferQueue->nelem, -+ (int)openmaxStandPort->pBufferSem->semval, -+ (int)omx_base_component_Private->bMgmtSem->semval, -+ omx_base_component_Private->name); -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); -+ -+ return OMX_ErrorNone; ++static void gomxq_init(GOMX_QUEUE *q, ptrdiff_t offset) ++{ ++ q->head = q->tail = 0; ++ q->offset = offset; ++ q->num = 0; +} + -+/** @brief Disables the port. -+ * -+ * This function is called due to a request by the IL client -+ * -+ * @param openmaxStandPort the reference to the port -+ * -+ */ -+OMX_ERRORTYPE base_port_DisablePort(omx_base_PortType *openmaxStandPort) { -+ omx_base_component_PrivateType* omx_base_component_Private; -+ OMX_ERRORTYPE err=OMX_ErrorNone; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); -+ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; -+ if (! PORT_IS_ENABLED(openmaxStandPort)) { -+ return OMX_ErrorNone; -+ } -+ -+ if(omx_base_component_Private->state!=OMX_StateLoaded) { -+ if(!PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { -+ /*Signal Buffer Mgmt Thread if it's holding any buffer*/ -+ if(omx_base_component_Private->bMgmtSem->semval==0) { -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ /*Wait till all buffers are freed*/ -+ omx_tsem_down(openmaxStandPort->pAllocSem); -+ omx_tsem_reset(omx_base_component_Private->bMgmtSem); -+ } else { -+ /*Since port is being disabled then remove buffers from the queue*/ -+ while(openmaxStandPort->pBufferQueue->nelem > 0) { -+ omx_dequeue(openmaxStandPort->pBufferQueue); -+ } -+ -+ err = openmaxStandPort->Port_FreeTunnelBuffer(openmaxStandPort,openmaxStandPort->sPortParam.nPortIndex); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Freeing Tunnel Buffer Error=%x\n",__func__,err); -+ } -+ DEBUG(DEB_LEV_PARAMS, "In %s Qelem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem); -+ } -+ -+ if(openmaxStandPort->bTunnelTearDown == OMX_TRUE){ -+ DEBUG(DEB_LEV_PARAMS, "In %s TearDown tunnel\n", __func__); -+ openmaxStandPort->hTunneledComponent = 0; -+ openmaxStandPort->nTunneledPort = 0; -+ openmaxStandPort->nTunnelFlags = 0; -+ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyUnspecified; -+ openmaxStandPort->bTunnelTearDown = OMX_FALSE; -+ } -+ } -+ -+ DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__, -+ (int)openmaxStandPort->nTunnelFlags, -+ (int)openmaxStandPort->pBufferQueue->nelem, -+ (int)openmaxStandPort->pBufferSem->semval, -+ (int)omx_base_component_Private->bMgmtSem->semval, -+ omx_base_component_Private->name); -+ openmaxStandPort->bIsTransientToDisabled = OMX_FALSE; -+ openmaxStandPort->sPortParam.bEnabled = OMX_FALSE; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d isEnabled=%d\n", __func__, -+ (int)openmaxStandPort->sPortParam.nPortIndex, -+ (int)openmaxStandPort->sPortParam.bEnabled); -+ return err; ++static void **gomxq_nextptr(GOMX_QUEUE *q, void *item) ++{ ++ return (void**) ((uint8_t*)item + q->offset); +} + -+/** @brief Enables the port. -+ * -+ * This function is called due to a request by the IL client -+ * -+ * @param openmaxStandPort the reference to the port -+ * -+ */ -+OMX_ERRORTYPE base_port_EnablePort(omx_base_PortType *openmaxStandPort) { -+ omx_base_component_PrivateType* omx_base_component_Private; -+ OMX_ERRORTYPE err=OMX_ErrorNone; -+ OMX_U32 i; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ if (PORT_IS_ENABLED(openmaxStandPort)) { -+ return OMX_ErrorNone; -+ } -+ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; -+ -+ openmaxStandPort->sPortParam.bEnabled = OMX_TRUE; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s port T flag=%x popu=%d state=%x\n", __func__, -+ (int)openmaxStandPort->nTunnelFlags, -+ (int)openmaxStandPort->sPortParam.bPopulated, -+ (int)omx_base_component_Private->state); -+ -+ -+ if (!PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { -+ /*Wait Till All buffers are allocated if the component state is not Loaded*/ -+ if (omx_base_component_Private->state!=OMX_StateLoaded && omx_base_component_Private->state!=OMX_StateWaitForResources) { -+ omx_tsem_down(openmaxStandPort->pAllocSem); -+ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; -+ } -+ } else { //Port Tunneled and supplier. Then allocate tunnel buffers -+ err= openmaxStandPort->Port_AllocateTunnelBuffer(openmaxStandPort, openmaxStandPort->sPortParam.nPortIndex, openmaxStandPort->sPortParam.nBufferSize); -+ if(err!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s Allocating Tunnel Buffer Error=%x\n",__func__,err); -+ return err; -+ } -+ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; -+ if (omx_base_component_Private->state==OMX_StateExecuting) { -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual;i++) { -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ } -+ } -+ DEBUG(DEB_LEV_PARAMS, "In %s Qelem=%d BSem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem,openmaxStandPort->pBufferSem->semval); -+ } -+ -+ openmaxStandPort->bIsTransientToEnabled = OMX_FALSE; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s\n", __func__); -+ -+ return OMX_ErrorNone; ++static void gomxq_enqueue(GOMX_QUEUE *q, void *item) ++{ ++ *gomxq_nextptr(q, item) = 0; ++ if (q->tail) { ++ *gomxq_nextptr(q, q->tail) = item; ++ q->tail = item; ++ } else { ++ q->head = q->tail = item; ++ } ++ q->num++; +} + -+/** @brief Called by the standard allocate buffer, it implements a base functionality. -+ * -+ * This function can be overriden if the allocation of the buffer is not a simply calloc call. -+ * The parameters are the same as the standard function, except for the handle of the port -+ * instead of the handler of the component -+ * When the buffers needed by this port are all assigned or allocated, the variable -+ * bIsFullOfBuffers becomes equal to OMX_TRUE -+ */ -+OMX_ERRORTYPE base_port_AllocateBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE** pBuffer, -+ OMX_U32 nPortIndex, -+ OMX_PTR pAppPrivate, -+ OMX_U32 nSizeBytes) { -+ -+ unsigned int i; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ return OMX_ErrorBadPortIndex; -+ } -+ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if ((omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) || (omx_base_component_Private->state!=OMX_StateLoaded)) { -+ if (!openmaxStandPort->bIsTransientToEnabled) { -+ DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__); -+ return OMX_ErrorIncorrectStateTransition; -+ } -+ } -+ -+ if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { -+ DEBUG(DEB_LEV_ERR, "In %s: Requested Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, (unsigned long)nSizeBytes, (unsigned long)openmaxStandPort->sPortParam.nBufferSize); -+ return OMX_ErrorIncorrectStateTransition; -+ } -+ -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { -+ openmaxStandPort->pInternalBufferStorage[i] = (OMX_BUFFERHEADERTYPE*)calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); -+ if (!openmaxStandPort->pInternalBufferStorage[i]) { -+ return OMX_ErrorInsufficientResources; -+ } -+ setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); -+ /* allocate the buffer */ -+ openmaxStandPort->pInternalBufferStorage[i]->pBuffer = (OMX_U8*)calloc(1,nSizeBytes); -+ if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer==NULL) { -+ return OMX_ErrorInsufficientResources; -+ } -+ openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = nSizeBytes; -+ openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; -+ openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; -+ *pBuffer = openmaxStandPort->pInternalBufferStorage[i]; -+ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED; -+ openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; -+ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ } else { -+ openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ } -+ openmaxStandPort->nNumAssignedBuffers++; -+ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); -+ -+ if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { -+ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; -+ openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__,(int)nPortIndex); -+ omx_tsem_up(openmaxStandPort->pAllocSem); -+ } -+ return OMX_ErrorNone; -+ } -+ } -+ DEBUG(DEB_LEV_ERR, "In %s Error: no available buffers\n",__func__); -+ return OMX_ErrorInsufficientResources; ++static void *gomxq_peek(GOMX_QUEUE *q) ++{ ++ return q->head; +} + -+/** @brief Called by the standard use buffer, it implements a base functionality. -+ * -+ * This function can be overriden if the use buffer implicate more complicated operations. -+ * The parameters are the same as the standard function, except for the handle of the port -+ * instead of the handler of the component. -+ * When the buffers needed by this port are all assigned or allocated, the variable -+ * bIsFullOfBuffers becomes equal to OMX_TRUE -+ */ -+OMX_ERRORTYPE base_port_UseBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE** ppBufferHdr, -+ OMX_U32 nPortIndex, -+ OMX_PTR pAppPrivate, -+ OMX_U32 nSizeBytes, -+ OMX_U8* pBuffer) { -+ -+ unsigned int i; -+ OMX_BUFFERHEADERTYPE* returnBufferHeader; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ return OMX_ErrorBadPortIndex; -+ } -+ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { -+ if (!openmaxStandPort->bIsTransientToEnabled) { -+ DEBUG(DEB_LEV_ERR, "In %s: The port of Comp %s is not allowed to receive buffers\n", __func__,omx_base_component_Private->name); -+ return OMX_ErrorIncorrectStateTransition; -+ } -+ } -+ -+ /// AND -+ /* -+ if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { -+ DEBUG(DEB_LEV_ERR, "In %s: Given Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, nSizeBytes, openmaxStandPort->sPortParam.nBufferSize); -+ return OMX_ErrorIncorrectStateTransition; -+ } -+ */ -+ /// AND -+ -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { -+ openmaxStandPort->pInternalBufferStorage[i] = (OMX_BUFFERHEADERTYPE*)calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); -+ if (!openmaxStandPort->pInternalBufferStorage[i]) { -+ return OMX_ErrorInsufficientResources; -+ } -+ openmaxStandPort->bIsEmptyOfBuffers = OMX_FALSE; -+ setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); -+ -+ openmaxStandPort->pInternalBufferStorage[i]->pBuffer = pBuffer; -+ openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = nSizeBytes; -+ openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; -+ openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; -+ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ASSIGNED; -+ openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; -+ returnBufferHeader = (OMX_BUFFERHEADERTYPE*)calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); -+ if (!returnBufferHeader) { -+ return OMX_ErrorInsufficientResources; -+ } -+ setHeader(returnBufferHeader, sizeof(OMX_BUFFERHEADERTYPE)); -+ returnBufferHeader->pBuffer = pBuffer; -+ returnBufferHeader->nAllocLen = nSizeBytes; -+ returnBufferHeader->pPlatformPrivate = openmaxStandPort; -+ returnBufferHeader->pAppPrivate = pAppPrivate; -+ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ returnBufferHeader->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ } else { -+ openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ returnBufferHeader->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ } -+ *ppBufferHdr = returnBufferHeader; -+ openmaxStandPort->nNumAssignedBuffers++; -+ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); -+ -+ if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { -+ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; -+ openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; -+ omx_tsem_up(openmaxStandPort->pAllocSem); -+ } -+ return OMX_ErrorNone; -+ } -+ } -+ DEBUG(DEB_LEV_ERR, "In %s Error: no available buffers CompName=%s\n",__func__,omx_base_component_Private->name); -+ return OMX_ErrorInsufficientResources; ++static void *gomxq_dequeue(GOMX_QUEUE *q) ++{ ++ void *item = q->head; ++ if (item) { ++ q->head = *gomxq_nextptr(q, item); ++ if (!q->head) q->tail = 0; ++ q->num--; ++ } ++ return item; ++} ++ ++typedef struct _GOMX_COMMAND { ++ void *next; ++ OMX_COMMANDTYPE cmd; ++ OMX_U32 param; ++ OMX_PTR data; ++} GOMX_COMMAND; ++ ++typedef struct _GOMX_PORT { ++ OMX_BOOL new_enabled; ++ OMX_PARAM_PORTDEFINITIONTYPE def; ++ ++ size_t num_buffers, num_buffers_old; ++ pthread_cond_t cond_no_buffers; ++ pthread_cond_t cond_populated; ++ pthread_cond_t cond_idle; ++ ++ OMX_HANDLETYPE tunnel_comp; ++ OMX_U32 tunnel_port; ++ bool tunnel_supplier; ++ GOMX_QUEUE tunnel_supplierq; ++ ++ OMX_ERRORTYPE (*do_buffer)(struct _GOMX_COMPONENT *, struct _GOMX_PORT *, OMX_BUFFERHEADERTYPE *); ++ OMX_ERRORTYPE (*flush)(struct _GOMX_COMPONENT *, struct _GOMX_PORT *); ++} GOMX_PORT; ++ ++typedef struct _GOMX_COMPONENT { ++ OMX_COMPONENTTYPE omx; ++ OMX_CALLBACKTYPE cb; ++ OMX_STATETYPE state, wanted_state; ++ ++ pthread_t component_thread, worker_thread; ++ pthread_mutex_t mutex; ++ pthread_cond_t cond; ++ ++ const char *name; ++ size_t nports; ++ GOMX_PORT *ports; ++ GOMX_QUEUE cmdq; ++ ++ void* (*worker)(void *); ++ OMX_ERRORTYPE (*statechange)(struct _GOMX_COMPONENT *); ++} GOMX_COMPONENT; ++ ++static GOMX_PORT *gomx_get_port(GOMX_COMPONENT *comp, size_t idx) ++{ ++ if (idx < 0 || idx >= comp->nports) return 0; ++ return &comp->ports[idx]; +} + -+/** @brief Called by the standard function. -+ * -+ * It frees the buffer header and in case also the buffer itself, if needed. -+ * When all the bufers are done, the variable bIsEmptyOfBuffers is set to OMX_TRUE -+ */ -+OMX_ERRORTYPE base_port_FreeBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_U32 nPortIndex, -+ OMX_BUFFERHEADERTYPE* pBuffer) { -+ -+ unsigned int i; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ return OMX_ErrorBadPortIndex; -+ } -+ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) { -+ if (!openmaxStandPort->bIsTransientToDisabled) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__); -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (omxComponent, -+ omx_base_component_Private->callbackData, -+ OMX_EventError, /* The command was completed */ -+ OMX_ErrorPortUnpopulated, /* The commands was a OMX_CommandStateSet */ -+ nPortIndex, /* The state has been changed in message->messageParam2 */ -+ NULL); -+ } -+ } -+ -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) { -+ -+ openmaxStandPort->bIsFullOfBuffers = OMX_FALSE; -+ if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) { -+ if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer){ -+ DEBUG(DEB_LEV_PARAMS, "In %s freeing %i pBuffer=%x\n",__func__, (int)i, (int)openmaxStandPort->pInternalBufferStorage[i]->pBuffer); -+ free(openmaxStandPort->pInternalBufferStorage[i]->pBuffer); -+ openmaxStandPort->pInternalBufferStorage[i]->pBuffer=NULL; -+ } -+ } else if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ASSIGNED) { -+ free(pBuffer); -+ } -+ if(openmaxStandPort->bBufferStateAllocated[i] & HEADER_ALLOCATED) { -+ free(openmaxStandPort->pInternalBufferStorage[i]); -+ openmaxStandPort->pInternalBufferStorage[i]=NULL; -+ } -+ -+ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; -+ -+ openmaxStandPort->nNumAssignedBuffers--; -+ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); -+ -+ if (openmaxStandPort->nNumAssignedBuffers == 0) { -+ openmaxStandPort->sPortParam.bPopulated = OMX_FALSE; -+ openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE; -+ omx_tsem_up(openmaxStandPort->pAllocSem); -+ } -+ return OMX_ErrorNone; -+ } -+ } -+ return OMX_ErrorInsufficientResources; ++OMX_ERRORTYPE gomx_get_component_version( ++ OMX_HANDLETYPE hComponent, OMX_STRING pComponentName, ++ OMX_VERSIONTYPE *pComponentVersion, OMX_VERSIONTYPE *pSpecVersion, OMX_UUIDTYPE *pComponentUUID) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ CDEBUG(comp, 0, "enter"); ++ strcpy(pComponentName, comp->name); ++ pComponentVersion->nVersion = OMX_VERSION; ++ pSpecVersion->nVersion = OMX_VERSION; ++ memcpy(pComponentUUID, &hComponent, sizeof hComponent); ++ return OMX_ErrorNone; +} + -+OMX_ERRORTYPE base_port_AllocateTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_U32 nSizeBytes) ++static OMX_ERRORTYPE gomx_get_parameter(OMX_HANDLETYPE hComponent, OMX_INDEXTYPE nParamIndex, OMX_PTR pComponentParameterStructure) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ GOMX_PORT *port; ++ OMX_PORT_PARAM_TYPE *ppt; ++ OMX_PARAM_PORTDEFINITIONTYPE *pdt; ++ OMX_ERRORTYPE r; ++ OMX_PORTDOMAINTYPE domain; ++ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ ++ CDEBUG(comp, 0, "called %x, %p", nParamIndex, pComponentParameterStructure); ++ switch (nParamIndex) { ++ case OMX_IndexParamAudioInit: ++ domain = OMX_PortDomainAudio; ++ goto param_init; ++ case OMX_IndexParamVideoInit: ++ domain = OMX_PortDomainVideo; ++ goto param_init; ++ case OMX_IndexParamImageInit: ++ domain = OMX_PortDomainImage; ++ goto param_init; ++ case OMX_IndexParamOtherInit: ++ domain = OMX_PortDomainOther; ++ goto param_init; ++ param_init: ++ if ((r = omx_cast(ppt, pComponentParameterStructure))) return r; ++ ppt->nPorts = 0; ++ ppt->nStartPortNumber = 0; ++ for (size_t i = 0; i < comp->nports; i++) { ++ if (comp->ports[i].def.eDomain != domain) ++ continue; ++ if (!ppt->nPorts) ++ ppt->nStartPortNumber = i; ++ ppt->nPorts++; ++ } ++ break; ++ case OMX_IndexParamPortDefinition: ++ if ((r = omx_cast(pdt, pComponentParameterStructure))) return r; ++ if (!(port = gomx_get_port(comp, pdt->nPortIndex))) return OMX_ErrorBadPortIndex; ++ memcpy(pComponentParameterStructure, &port->def, sizeof *pdt); ++ break; ++ default: ++ CINFO(comp, 0, "UNSUPPORTED %x, %p", nParamIndex, pComponentParameterStructure); ++ return OMX_ErrorNotImplemented; ++ } ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE gomx_get_state(OMX_HANDLETYPE hComponent, OMX_STATETYPE *pState) +{ -+ unsigned int i; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ OMX_U8* pBuffer=NULL; -+ OMX_ERRORTYPE eError=OMX_ErrorNone; -+ OMX_U32 numRetry=0; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s, nPortIndex=%d, nSizeBytes=%d, nBufferCountActual=%d\n", __func__, nPortIndex, nSizeBytes, openmaxStandPort->sPortParam.nBufferCountActual); -+ -+ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ DEBUG(DEB_LEV_ERR, "In %s: Bad Port Index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ if (! PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ DEBUG(DEB_LEV_ERR, "In %s: Port is not tunneled Flag=%x\n", __func__, (int)openmaxStandPort->nTunnelFlags); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { -+ if (!openmaxStandPort->bIsTransientToEnabled) { -+ DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__); -+ return OMX_ErrorIncorrectStateTransition; -+ } -+ } -+ -+ if( NULL == openmaxStandPort->bBufferStateAllocated ) -+ { -+ openmaxStandPort->bBufferStateAllocated = (BUFFER_STATUS_FLAG*)calloc(openmaxStandPort->sPortParam.nBufferCountActual, sizeof(openmaxStandPort->bBufferStateAllocated[0] )); -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) -+ { -+ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; -+ } -+ } -+ -+ if( NULL == openmaxStandPort->pInternalBufferStorage ) -+ { -+ openmaxStandPort->pInternalBufferStorage = (OMX_BUFFERHEADERTYPE**)calloc(openmaxStandPort->sPortParam.nBufferCountActual, sizeof(OMX_BUFFERHEADERTYPE*)); -+ /*for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) -+ { -+ //memset(&openmaxStandPort->pInternalBufferStorage[i], 0, sizeof(OMX_BUFFERHEADERTYPE*)); -+ setHeader(&openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE*)); -+ }*/ -+ } -+ -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { -+ pBuffer = (OMX_U8*)calloc(1,nSizeBytes); -+ if(pBuffer==NULL) { -+ return OMX_ErrorInsufficientResources; -+ } -+ /*Retry more than once, if the tunneled component is not in Loaded->Idle State*/ -+ while(numRetry <TUNNEL_USE_BUFFER_RETRY) { -+ eError=OMX_UseBuffer(openmaxStandPort->hTunneledComponent,&openmaxStandPort->pInternalBufferStorage[i], -+ openmaxStandPort->nTunneledPort,NULL,nSizeBytes,pBuffer); -+ if (checkHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)) != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header after OMX_UseBuffer\n", __func__); -+ return OMX_ErrorBadParameter; -+ } -+ if(eError!=OMX_ErrorNone) { -+ OMX_STATETYPE state; -+ OMX_GetState( openmaxStandPort->hTunneledComponent, &state ); -+ DEBUG(DEB_LEV_FULL_SEQ,"Tunneled Component Couldn't Use buffer %i From Comp=%s Retry=%d Other state=%d\n", -+ i,omx_base_component_Private->name,(int)numRetry, (int)state); -+ /// AND -+ // see 2.1.1 and 3.2 in http://www.khronos.org/registry/omxil/specs/OpenMAX_IL_1_1_2_Application_Note_318.pdf -+ //if((eError == OMX_ErrorIncorrectStateTransition) && numRetry<TUNNEL_USE_BUFFER_RETRY) { -+ if(((eError == OMX_ErrorIncorrectStateTransition)||(eError == OMX_ErrorIncorrectStateOperation)) && numRetry<TUNNEL_USE_BUFFER_RETRY) { -+ /// AND -+ DEBUG(DEB_LEV_FULL_SEQ,"Waiting for next try %i \n",(int)numRetry); -+ usleep(TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME); -+ numRetry++; -+ continue; -+ } -+ free(pBuffer); -+ pBuffer = NULL; -+ return eError; -+ } -+ else { -+ DEBUG(DEB_LEV_FULL_SEQ,"Tunneled Component Used buffer %i From Comp=%s Retry=%d\n", -+ i,omx_base_component_Private->name,(int)numRetry); -+ break; -+ } -+ } -+ if(eError!=OMX_ErrorNone) { -+ free(pBuffer); -+ pBuffer = NULL; -+ DEBUG(DEB_LEV_ERR,"In %s Tunneled Component Couldn't Use Buffer %x \n",__func__,(int)eError); -+ return eError; -+ } -+ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED; -+ openmaxStandPort->nNumAssignedBuffers++; -+ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); -+ -+ if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { -+ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; -+ openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__, (int)nPortIndex); -+ } -+ omx_queue(openmaxStandPort->pBufferQueue, openmaxStandPort->pInternalBufferStorage[i]); -+ } -+ } -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Allocated all buffers\n",__func__); -+ return OMX_ErrorNone; ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ *pState = comp->state; ++ return OMX_ErrorNone; +} + -+OMX_ERRORTYPE base_port_FreeTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex) ++static OMX_ERRORTYPE gomx_component_tunnel_request( ++ OMX_HANDLETYPE hComponent, OMX_U32 nPort, ++ OMX_HANDLETYPE hTunneledComp, OMX_U32 nTunneledPort, OMX_TUNNELSETUPTYPE* pTunnelSetup) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ GOMX_PORT *port = 0; ++ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ if (!(port = gomx_get_port(comp, nPort))) return OMX_ErrorBadPortIndex; ++ if (comp->state != OMX_StateLoaded && port->def.bEnabled) ++ return OMX_ErrorIncorrectStateOperation; ++ ++ if (hTunneledComp == 0 || pTunnelSetup == 0) { ++ port->tunnel_comp = 0; ++ return OMX_ErrorNone; ++ } ++ ++ if (port->def.eDir == OMX_DirInput) { ++ /* Negotiate parameters */ ++ OMX_PARAM_PORTDEFINITIONTYPE param; ++ omx_init(param); ++ param.nPortIndex = nTunneledPort; ++ if (OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m)) ++ goto not_compatible; ++ if (param.eDomain != port->def.eDomain) ++ goto not_compatible; ++ ++ param.nBufferCountActual = max(param.nBufferCountMin, port->def.nBufferCountMin); ++ param.nBufferSize = max(port->def.nBufferSize, param.nBufferSize); ++ param.nBufferAlignment = max(port->def.nBufferAlignment, param.nBufferAlignment); ++ port->def.nBufferCountActual = param.nBufferCountActual; ++ port->def.nBufferSize = param.nBufferSize; ++ port->def.nBufferAlignment = param.nBufferAlignment; ++ if (OMX_SetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m)) ++ goto not_compatible; ++ ++ /* Negotiate buffer supplier */ ++ OMX_PARAM_BUFFERSUPPLIERTYPE suppl; ++ omx_init(suppl); ++ suppl.nPortIndex = nTunneledPort; ++ if (OMX_GetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier, &suppl)) ++ goto not_compatible; ++ ++ /* Being supplier is not supported so ask the other side to be it */ ++ suppl.eBufferSupplier = ++ (pTunnelSetup->eSupplier == OMX_BufferSupplyOutput) ++ ? OMX_BufferSupplyOutput : OMX_BufferSupplyInput; ++ if (OMX_SetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier, &suppl)) ++ goto not_compatible; ++ ++ port->tunnel_comp = hTunneledComp; ++ port->tunnel_port = nTunneledPort; ++ port->tunnel_supplier = (suppl.eBufferSupplier == OMX_BufferSupplyInput); ++ pTunnelSetup->eSupplier = suppl.eBufferSupplier; ++ CINFO(comp, port, "ComponentTunnnelRequest: %p %d", hTunneledComp, nTunneledPort); ++ } else { ++ CINFO(comp, port, "OUTPUT TUNNEL UNSUPPORTED: %p, %d, %p", hTunneledComp, nTunneledPort, pTunnelSetup); ++ return OMX_ErrorNotImplemented; ++ } ++ return OMX_ErrorNone; ++ ++not_compatible: ++ CINFO(comp, port, "ComponentTunnnelRequest: %p %d - NOT COMPATIBLE", hTunneledComp, nTunneledPort); ++ return OMX_ErrorPortsNotCompatible; ++} ++ ++static void __gomx_event(GOMX_COMPONENT *comp, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData) +{ -+ unsigned int i; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ OMX_ERRORTYPE eError=OMX_ErrorNone; -+ OMX_U32 numRetry=0; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ DEBUG(DEB_LEV_ERR, "In %s: Bad Port Index\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ if (! PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { -+ DEBUG(DEB_LEV_ERR, "In %s: Port is not tunneled\n", __func__); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) { -+ if (!openmaxStandPort->bIsTransientToDisabled) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__); -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (omxComponent, -+ omx_base_component_Private->callbackData, -+ OMX_EventError, /* The command was completed */ -+ OMX_ErrorPortUnpopulated, /* The commands was a OMX_CommandStateSet */ -+ nPortIndex, /* The state has been changed in message->messageParam2 */ -+ NULL); -+ } -+ } -+ -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) { -+ -+ openmaxStandPort->bIsFullOfBuffers = OMX_FALSE; -+ if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) { -+ free(openmaxStandPort->pInternalBufferStorage[i]->pBuffer); -+ openmaxStandPort->pInternalBufferStorage[i]->pBuffer = NULL; -+ } -+ /*Retry more than once, if the tunneled component is not in Idle->Loaded State*/ -+ while(numRetry <TUNNEL_USE_BUFFER_RETRY) { -+ eError=OMX_FreeBuffer(openmaxStandPort->hTunneledComponent,openmaxStandPort->nTunneledPort,openmaxStandPort->pInternalBufferStorage[i]); -+ if(eError!=OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR,"Tunneled Component Couldn't free buffer %i \n",i); -+ // see 2.1.2 and 3.1 in http://www.khronos.org/registry/omxil/specs/OpenMAX_IL_1_1_2_Application_Note_318.pdf -+ if((eError == OMX_ErrorIncorrectStateTransition) && numRetry<TUNNEL_USE_BUFFER_RETRY) { -+ DEBUG(DEB_LEV_ERR,"Waiting for next try %i \n",(int)numRetry); -+ usleep(TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME); -+ numRetry++; -+ continue; -+ } -+ return eError; -+ } else { -+ break; -+ } -+ } -+ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; -+ -+ openmaxStandPort->nNumAssignedBuffers--; -+ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); -+ -+ if (openmaxStandPort->nNumAssignedBuffers == 0) { -+ openmaxStandPort->sPortParam.bPopulated = OMX_FALSE; -+ openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE; -+ //omx_tsem_up(openmaxStandPort->pAllocSem); -+ } -+ } -+ } -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Qelem=%d BSem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem,openmaxStandPort->pBufferSem->semval); -+ return OMX_ErrorNone; ++ if (!comp->cb.EventHandler) return; ++ pthread_mutex_unlock(&comp->mutex); ++ comp->cb.EventHandler((OMX_HANDLETYPE) comp, comp->omx.pApplicationPrivate, eEvent, nData1, nData2, pEventData); ++ pthread_mutex_lock(&comp->mutex); +} + -+/** @brief the entry point for sending buffers to the port -+ * -+ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on -+ * the nature of the port, that can be an input or output port. -+ */ -+OMX_ERRORTYPE base_port_SendBufferFunction( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE* pBuffer) { -+ -+ OMX_ERRORTYPE err; -+ OMX_U32 portIndex; -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+#if NO_GST_OMX_PATCH -+ unsigned int i; -+#endif -+ portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, (unsigned long)portIndex); -+ -+ if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { -+ DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); -+ return OMX_ErrorBadPortIndex; -+ } -+ -+ if(omx_base_component_Private->state == OMX_StateInvalid) { -+ DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); -+ return OMX_ErrorInvalidState; -+ } -+ -+ if(omx_base_component_Private->state != OMX_StateExecuting && -+ omx_base_component_Private->state != OMX_StatePause && -+ omx_base_component_Private->state != OMX_StateIdle) { -+ DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || -+ (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && -+ (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { -+ DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ -+ /* Temporarily disable this check for gst-openmax */ -+#if NO_GST_OMX_PATCH -+ { -+ OMX_BOOL foundBuffer = OMX_FALSE; -+ if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { -+ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ -+ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { -+ foundBuffer = OMX_TRUE; -+ break; -+ } -+ } -+ } -+ if (!foundBuffer) { -+ return OMX_ErrorBadParameter; -+ } -+ } -+#endif -+ -+ if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); -+ return err; -+ } -+ -+ /* And notify the buffer management thread we have a fresh new buffer to manage */ -+ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ -+ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); -+ omx_tsem_up(omx_base_component_Private->bMgmtSem); -+ }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", -+ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); -+ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); -+ omx_tsem_up(openmaxStandPort->pBufferSem); -+ } -+ else { // If port being flushed and not tunneled then return error -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); -+ return OMX_ErrorIncorrectStateOperation; -+ } -+ return OMX_ErrorNone; -+} ++static void __gomx_port_update_buffer_state(GOMX_COMPONENT *comp, GOMX_PORT *port) ++{ ++ if (port->num_buffers_old == port->num_buffers) ++ return; + -+/** -+ * Returns Input/Output Buffer to the IL client or Tunneled Component -+ */ -+OMX_ERRORTYPE base_port_ReturnBufferFunction(omx_base_PortType* openmaxStandPort,OMX_BUFFERHEADERTYPE* pBuffer){ -+ omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; -+ omx_queue_t* pQueue = openmaxStandPort->pBufferQueue; -+ omx_tsem_t* pSem = openmaxStandPort->pBufferSem; -+ OMX_ERRORTYPE eError = OMX_ErrorNone; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ if (PORT_IS_TUNNELED(openmaxStandPort) && -+ ! PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { -+ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ pBuffer->nOutputPortIndex = openmaxStandPort->nTunneledPort; -+ pBuffer->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ if(eError != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s eError %08x in FillThis Buffer from Component %s Non-Supplier\n", -+ __func__, eError,omx_base_component_Private->name); -+ } -+ } else { -+ pBuffer->nInputPortIndex = openmaxStandPort->nTunneledPort; -+ pBuffer->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; -+ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ if(eError != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR, "In %s eError %08x in EmptyThis Buffer from Component %s Non-Supplier\n", -+ __func__, eError,omx_base_component_Private->name); -+ } -+ } -+ } -+ else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort) && -+ !PORT_IS_BEING_FLUSHED(openmaxStandPort)) { -+ if (!PORT_IS_ENABLED(openmaxStandPort) || PORT_IS_BEING_DISABLED(openmaxStandPort)) { -+ omx_queue(pQueue, pBuffer); -+ omx_tsem_up(pSem); -+ } else if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ /// AND TODO: -+ /// see 2.2 of http://www.khronos.org/registry/omxil/specs/OpenMAX_IL_1_1_2_Application_Note_318.pdf -+ if(eError != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in FillThis Buffer from Component %s Supplier\n", -+ __func__, eError,omx_base_component_Private->name); -+ /*If Error Occured then queue the buffer*/ -+ omx_queue(pQueue, pBuffer); -+ omx_tsem_up(pSem); -+ } -+ } else { -+ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); -+ if(eError != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in EmptyThis Buffer from Component %s Supplier\n", -+ __func__, eError,omx_base_component_Private->name); -+ /*If Error Occured then queue the buffer*/ -+ omx_queue(pQueue, pBuffer); -+ omx_tsem_up(pSem); -+ } -+ } -+ }else if (! PORT_IS_TUNNELED(openmaxStandPort)){ -+ (*(openmaxStandPort->BufferProcessedCallback))( -+ openmaxStandPort->standCompContainer, -+ omx_base_component_Private->callbackData, -+ pBuffer); -+ } -+ else { -+ omx_queue(pQueue,pBuffer); -+ openmaxStandPort->nNumBufferFlushed++; -+ } -+ -+ return OMX_ErrorNone; ++ port->def.bPopulated = (port->num_buffers >= port->def.nBufferCountActual) ? OMX_TRUE : OMX_FALSE; ++ if (port->num_buffers == 0) ++ pthread_cond_signal(&port->cond_no_buffers); ++ else if (port->num_buffers == port->def.nBufferCountActual) ++ pthread_cond_signal(&port->cond_populated); +} + -+ -+OMX_ERRORTYPE base_port_ComponentTunnelRequest(omx_base_PortType* openmaxStandPort,OMX_IN OMX_HANDLETYPE hTunneledComp,OMX_IN OMX_U32 nTunneledPort,OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ OMX_PARAM_PORTDEFINITIONTYPE param; -+ OMX_PARAM_BUFFERSUPPLIERTYPE pSupplier; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); -+ -+ if (pTunnelSetup == NULL || hTunneledComp == 0) { -+ /* cancel previous tunnel */ -+ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; -+ if (PORT_IS_TUNNELED(openmaxStandPort) && (PORT_IS_BEING_DISABLED(openmaxStandPort) || (omx_base_component_Private->transientState == OMX_TransStateIdleToLoaded))) -+ { -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Scheduled TearDown port=%d PORT_IS_BEING_DISABLED(%d) transientState=%d\n", -+ __func__, openmaxStandPort->sPortParam.nPortIndex, PORT_IS_BEING_DISABLED(openmaxStandPort), omx_base_component_Private->transientState); -+ openmaxStandPort->bTunnelTearDown = OMX_TRUE; -+ } -+ else { -+ openmaxStandPort->hTunneledComponent = 0; -+ openmaxStandPort->nTunneledPort = 0; -+ openmaxStandPort->nTunnelFlags = 0; -+ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyUnspecified; -+ } -+ return OMX_ErrorNone; -+ } -+ -+ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { -+ /* Get Port Definition of the Tunnelled Component*/ -+ param.nPortIndex=nTunneledPort; -+ setHeader(¶m, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); -+ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m); -+ if (err != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR,"In %s Get Tunneled Port Definition error=0x%08x Line=%d\n",__func__,err,__LINE__); -+ // compatibility not reached -+ return OMX_ErrorPortsNotCompatible; -+ } -+ -+ // Negotiate buffer params -+ param.nBufferCountActual = param.nBufferCountMin > openmaxStandPort->sPortParam.nBufferCountMin ? -+ param.nBufferCountMin : openmaxStandPort->sPortParam.nBufferCountMin; -+ openmaxStandPort->sPortParam.nBufferCountActual = param.nBufferCountActual; -+ -+ param.nBufferSize = param.nBufferSize > openmaxStandPort->sPortParam.nBufferSize ? -+ param.nBufferSize : openmaxStandPort->sPortParam.nBufferSize; -+ openmaxStandPort->sPortParam.nBufferSize = param.nBufferSize; -+ -+ err = OMX_SetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m); -+ if (err != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR,"In %s Set Tunneled Port Definition error=0x%08x Line=%d\n",__func__,err,__LINE__); -+ return OMX_ErrorPortsNotCompatible; -+ } -+ -+ openmaxStandPort->nNumTunnelBuffer=param.nBufferCountActual; //nBufferCountMin; -+ -+ if(param.eDomain!=openmaxStandPort->sPortParam.eDomain) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ if(param.eDomain==OMX_PortDomainAudio) { -+ if(param.format.audio.eEncoding == OMX_AUDIO_CodingMax) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } else if(param.eDomain==OMX_PortDomainVideo) { -+ if(param.format.video.eCompressionFormat == OMX_VIDEO_CodingMax) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } else if(param.eDomain==OMX_PortDomainOther) { -+ if(param.format.other.eFormat == OMX_OTHER_FormatMax) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } -+ -+ /* Get Buffer Supplier type of the Tunnelled Component*/ -+ pSupplier.nPortIndex=nTunneledPort; -+ setHeader(&pSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); -+ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier, &pSupplier); -+ if (err != OMX_ErrorNone) { -+ // compatibility not reached -+ DEBUG(DEB_LEV_ERR,"In %s Tunneled Buffer Supplier error=0x%08x Line=%d\n",__func__,err,__LINE__); -+ return OMX_ErrorPortsNotCompatible; -+ } else { -+ DEBUG(DEB_LEV_FULL_SEQ,"Tunneled Port eBufferSupplier=%x\n",pSupplier.eBufferSupplier); -+ } -+ -+ // store the current callbacks, if defined -+ openmaxStandPort->hTunneledComponent = hTunneledComp; -+ openmaxStandPort->nTunneledPort = nTunneledPort; -+ -+ /*Check for and set proprietary communication flag. -+ In case a component support Deep Tunneling should set it's tunnel flag to PROPRIETARY_COMMUNICATION_ESTABLISHED */ -+ /// AND: No proprietary communication -+ /* -+ if(PORT_IS_DEEP_TUNNELED(openmaxStandPort)) { -+ OMX_VENDOR_PROP_TUNNELSETUPTYPE pPropTunnelSetup; -+ pPropTunnelSetup.nPortIndex = nTunneledPort; -+ -+ err = OMX_GetParameter(hTunneledComp, OMX_IndexVendorCompPropTunnelFlags, &pPropTunnelSetup); -+ if (err != OMX_ErrorNone) { -+ // compatibility not reached -+ DEBUG(DEB_LEV_ERR,"In %s Proprietary Tunneled Buffer Supplier nTunneledPort=%d error=0x%08x Line=%d \n", -+ __func__,(int)pPropTunnelSetup.nPortIndex,err,__LINE__); -+ openmaxStandPort->nTunnelFlags = 0; -+ } else { -+ openmaxStandPort->nTunnelFlags = PROPRIETARY_COMMUNICATION_ESTABLISHED; -+ } -+ } else { -+ openmaxStandPort->nTunnelFlags = 0; -+ } -+ */ -+ openmaxStandPort->nTunnelFlags = 0; -+ /// AND -+ -+ // Negotiation -+ if (pTunnelSetup->nTunnelFlags & OMX_PORTTUNNELFLAG_READONLY) { -+ // the buffer provider MUST be the output port provider -+ /// AND: WRONG!!!! -+ /* -+ pTunnelSetup->eSupplier = OMX_BufferSupplyInput; -+ openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; -+ */ -+ DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_PORTTUNNELFLAG_READONLY Line=%d\n",__func__,__LINE__); -+ pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; -+ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; -+ /// AND -+ } else { -+ //if (pTunnelSetup->eSupplier == OMX_BufferSupplyInput) { -+ // DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupplyInput Line=%d\n",__func__,__LINE__); -+ // openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ // openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; -+ //} else if (pTunnelSetup->eSupplier == OMX_BufferSupplyUnspecified) { -+ // /// AND TODO: Can be reversed???? -+ // DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupplyUnspecified Line=%d\n",__func__,__LINE__); -+ // pTunnelSetup->eSupplier = OMX_BufferSupplyInput; -+ // openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ // openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; -+ // //pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; -+ // //openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; -+ // /// AND -+ //} else if (pTunnelSetup->eSupplier == OMX_BufferSupplyOutput){ -+ // DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupplyOutput Line=%d\n",__func__,__LINE__); -+ // pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; -+ // openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; -+ //} else { -+ // DEBUG(DEB_LEV_ERR,"In %s --------------> undefined pTunnelSetup->eSupplier = %d Line=%d\n",__func__,(int)pTunnelSetup->eSupplier,__LINE__); -+ //} -+ -+ // fixed to work only in this direction -+ DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupply Line=%d\n",__func__,__LINE__); -+ pTunnelSetup->eSupplier = OMX_BufferSupplyInput; -+ openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; -+ /// AND -+ -+ } -+ openmaxStandPort->nTunnelFlags |= TUNNEL_ESTABLISHED; -+ -+ /* Set Buffer Supplier type of the Tunnelled Component after final negotiation*/ -+ pSupplier.nPortIndex=nTunneledPort; -+ pSupplier.eBufferSupplier=openmaxStandPort->eBufferSupplier; -+ err = OMX_SetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier, &pSupplier); -+ if (err != OMX_ErrorNone) { -+ // compatibility not reached -+ DEBUG(DEB_LEV_ERR,"In %s Tunneled Buffer Supplier error=0x%08x Line=%d\n",__func__,err,__LINE__); -+ openmaxStandPort->nTunnelFlags=0; -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } else { -+ // output port -+ // all the consistency checks are under other component responsibility -+ -+ /* Get Port Definition of the Tunnelled Component*/ -+ param.nPortIndex=nTunneledPort; -+ setHeader(¶m, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); -+ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m); -+ if (err != OMX_ErrorNone) { -+ DEBUG(DEB_LEV_ERR,"In %s Tunneled Port Definition error=0x%08x Line=%d\n",__func__,err,__LINE__); -+ // compatibility not reached -+ return OMX_ErrorPortsNotCompatible; -+ } -+ if(param.eDomain!=openmaxStandPort->sPortParam.eDomain) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ -+ if(param.eDomain==OMX_PortDomainAudio) { -+ if(param.format.audio.eEncoding == OMX_AUDIO_CodingMax) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } else if(param.eDomain==OMX_PortDomainVideo) { -+ if(param.format.video.eCompressionFormat == OMX_VIDEO_CodingMax) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } else if(param.eDomain==OMX_PortDomainOther) { -+ if(param.format.other.eFormat == OMX_OTHER_FormatMax) { -+ return OMX_ErrorPortsNotCompatible; -+ } -+ } -+ -+ /*Check for and set proprietary communication flag*/ -+ if(PORT_IS_DEEP_TUNNELED(openmaxStandPort)) { -+ OMX_VENDOR_PROP_TUNNELSETUPTYPE pPropTunnelSetup; -+ pPropTunnelSetup.nPortIndex = nTunneledPort; -+ -+ err = OMX_GetParameter(hTunneledComp, (OMX_INDEXTYPE)OMX_IndexVendorCompPropTunnelFlags, &pPropTunnelSetup); -+ if (err != OMX_ErrorNone) { -+ // compatibility not reached -+ DEBUG(DEB_LEV_ERR,"In %s Proprietary Tunneled Buffer Supplier nTunneledPort=%d error=0x%08x Line=%d \n", -+ __func__,(int)pPropTunnelSetup.nPortIndex,err,__LINE__); -+ openmaxStandPort->nTunnelFlags = 0; -+ } else { -+ openmaxStandPort->nTunnelFlags = PROPRIETARY_COMMUNICATION_ESTABLISHED; -+ } -+ } else { -+ openmaxStandPort->nTunnelFlags = 0; -+ } -+ -+ openmaxStandPort->nNumTunnelBuffer=param.nBufferCountMin; -+ -+ openmaxStandPort->hTunneledComponent = hTunneledComp; -+ openmaxStandPort->nTunneledPort = nTunneledPort; -+ pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; -+ openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; -+ openmaxStandPort->nTunnelFlags |= TUNNEL_ESTABLISHED; -+ -+ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; -+ } -+ -+ return OMX_ErrorNone; ++static OMX_ERRORTYPE gomx_use_buffer(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE **ppBufferHdr, ++ OMX_U32 nPortIndex, OMX_PTR pAppPrivate, OMX_U32 nSizeBytes, OMX_U8* pBuffer) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ OMX_BUFFERHEADERTYPE *hdr; ++ GOMX_PORT *port; ++ void *buf; ++ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ if (!(port = gomx_get_port(comp, nPortIndex))) return OMX_ErrorBadPortIndex; ++ ++ if (!((comp->state == OMX_StateLoaded && comp->wanted_state == OMX_StateIdle) || ++ (port->def.bEnabled == OMX_FALSE && ++ (comp->state == OMX_StateExecuting || ++ comp->state == OMX_StatePause || ++ comp->state == OMX_StateIdle)))) ++ return OMX_ErrorIncorrectStateOperation; ++ ++ buf = malloc(sizeof(OMX_BUFFERHEADERTYPE) + (pBuffer ? 0 : nSizeBytes)); ++ if (!buf) return OMX_ErrorInsufficientResources; ++ ++ hdr = (OMX_BUFFERHEADERTYPE *) buf; ++ memset(hdr, 0, sizeof *hdr); ++ omx_init(*hdr); ++ hdr->pBuffer = pBuffer ? (OMX_U8*)pBuffer : (OMX_U8*)((char*)buf + nSizeBytes); ++ hdr->nAllocLen = nSizeBytes; ++ hdr->pAppPrivate = pAppPrivate; ++ if (port->def.eDir == OMX_DirInput) { ++ hdr->nInputPortIndex = nPortIndex; ++ hdr->pOutputPortPrivate = pAppPrivate; ++ } else { ++ hdr->nOutputPortIndex = nPortIndex; ++ hdr->pInputPortPrivate = pAppPrivate; ++ } ++ pthread_mutex_lock(&comp->mutex); ++ port->num_buffers++; ++ __gomx_port_update_buffer_state(comp, port); ++ pthread_mutex_unlock(&comp->mutex); ++ ++ CDEBUG(comp, port, "allocated: %d, %p, %u, %p", nPortIndex, pAppPrivate, nSizeBytes, pBuffer); ++ *ppBufferHdr = hdr; ++ ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE gomx_allocate_buffer(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE **ppBufferHdr, ++ OMX_U32 nPortIndex, OMX_PTR pAppPrivate, OMX_U32 nSizeBytes) ++{ ++ return gomx_use_buffer(hComponent, ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes, 0); +} -diff --git a/alsa/omx_base_port.h b/alsa/omx_base_port.h -new file mode 100644 -index 0000000..3159b92 ---- /dev/null -+++ b/alsa/omx_base_port.h -@@ -0,0 +1,288 @@ -+/** -+ @file src/base/omx_base_port.h -+ -+ Base class for OpenMAX ports to be used in derived components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-08-08 06:56:06 +0200 (Fri, 08 Aug 2008) $ -+ Revision $Rev: 581 $ -+ Author $Author: pankaj_sen $ -+ -+*/ -+ -+#include "omx_comp_debug_levels.h" -+ -+#include "omx_semaphore.h" -+#include "omx_queue.h" -+#include "omx_classmagic.h" -+#pragma pack(4) -+//#include <IL/OMX_Types.h> -+#include <IL/OMX_Core.h> -+#include <IL/OMX_Component.h> -+#include <IL/OMX_Audio.h> -+#pragma pack() -+ -+#define OMX_ErrorIncorrectStateTransition OMX_ErrorIncorrectStateOperation -+ -+#ifndef __OMX_BASE_PORT_H__ -+#define __OMX_BASE_PORT_H__ -+ -+#define TUNNEL_USE_BUFFER_RETRY 20 -+#define TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME 5000 -+#define NO_GST_OMX_PATCH 1 -+ -+/** -+ * Port Specific Macro's -+ */ -+#define PORT_IS_BEING_FLUSHED(pPort) (pPort->bIsPortFlushed == OMX_TRUE) -+#define PORT_IS_BEING_DISABLED(pPort) (pPort->bIsTransientToDisabled == OMX_TRUE) -+#define PORT_IS_ENABLED(pPort) (pPort->sPortParam.bEnabled == OMX_TRUE) -+#define PORT_IS_POPULATED(pPort) (pPort->sPortParam.bPopulated == OMX_TRUE) -+#define PORT_IS_TUNNELED(pPort) (pPort->nTunnelFlags & TUNNEL_ESTABLISHED) -+#define PORT_IS_DEEP_TUNNELED(pPort) (pPort->nTunnelFlags & PROPRIETARY_COMMUNICATION_ESTABLISHED) -+#define PORT_IS_BUFFER_SUPPLIER(pPort) (pPort->nTunnelFlags & TUNNEL_IS_SUPPLIER) -+#define PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(pPort) ((pPort->nTunnelFlags & TUNNEL_ESTABLISHED) && (pPort->nTunnelFlags & TUNNEL_IS_SUPPLIER)) -+ -+/** The following enum values are used to characterize each buffer -+ * allocated or assigned to the component. A buffer list is -+ * created for each port of the component. The buffer can be assigned -+ * to the port, or owned by the port. The buffer flag are applied for each buffer -+ * in each port buffer list. The following use cases are currently implemented: -+ * - When the IL Client asks the component to allocate a buffer -+ * for a given port, with the call to AllocateBuffer, the -+ * buffer created is characterizeed by the flag BUFFER_ALLOCATED -+ * - When the IL Client asks the component to use a buffer allocated -+ * by the client itself, the buffer flag is BUFFER_ASSIGNED -+ * - When the component is tunneled by another component, and the first -+ * is supplier of the buffer, the buffer is marked with the -+ * BUFFER_ALLOCATED flag. -+ * - When the component is tunneled by another component, and the second -+ * is supplier of the buffer, the buffer is marked with the -+ * BUFFER_ASSIGNED flag. -+ * - The case of a buffer supplied by the first component but allocated by another -+ * component or another port inside the same component, as in the case -+ * of shared buffers, is not yet implemented in these components -+ * - During hte deallocation phase each buffer is marked with the BUFFER_FREE -+ * flag, so that the component can check if all the buffers have been deallocated -+ * before switch the component state to Loaded, as specified by -+ * the OpenMAX specs -+ */ -+typedef unsigned int BUFFER_STATUS_FLAG; -+ -+#define BUFFER_FREE 0 -+#define BUFFER_ALLOCATED 0x0001 /**< This flag is applied to a buffer when it is allocated -+ by the given port of the component */ -+#define BUFFER_ASSIGNED 0x0002 /**< This flag is applied to a buffer when it is assigned -+ from another port or by the IL client */ -+#define HEADER_ALLOCATED 0x0004 /**< This flag is applied to a buffer when buffer header is allocated -+ by the given port of the component */ -+ -+/** @brief the status of a port related to the tunneling with another component -+ */ -+typedef unsigned int TUNNEL_STATUS_FLAG; -+#define NO_TUNNEL 0 /**< No tunnel established */ -+#define TUNNEL_ESTABLISHED 0x0001 /**< the TUNNEL_ESTABLISHED specifies if a port is tunneled. -+ * It is assigned to a private field of the port if it is tunneled -+ */ -+#define TUNNEL_IS_SUPPLIER 0x0002 /**< the TUNNEL_IS_SUPPLIER specifies if a tunneled port is the supplier. -+ * It is assigned to a private field of the port if it is tunneled and also it is the buffer supplier for the tunnel. -+ */ -+#define PROPRIETARY_COMMUNICATION_ESTABLISHED 0x0004 /** The tunnel established is created between two components of the same -+ * vendor. These components can take advantage from a vendor specific -+ * communication -+ */ -+ -+/** -+ * @brief the base structure that describes each port. -+ * -+ * The data structure that describes a port contains the basic elements used in the -+ * base component. Other elements can be added in the derived components structures. -+ */ -+CLASS(omx_base_PortType) -+#define omx_base_PortType_FIELDS \ -+ OMX_HANDLETYPE hTunneledComponent; /**< @param hTunneledComponent Handle to the tunnelled component */\ -+ OMX_U32 nTunnelFlags; /**< This field contains one or more tags that describe the tunnel status of the port */\ -+ OMX_U32 nTunneledPort; /**< @param nTunneledPort Tunneled port number */ \ -+ OMX_BOOL bTunnelTearDown; /**< @param nTunneledPort Helper for assinc TearDown */ \ -+ OMX_BUFFERSUPPLIERTYPE eBufferSupplier; /**< @param eBufferSupplier the type of supplier in case of tunneling */\ -+ OMX_U32 nNumTunnelBuffer; /**< @param nNumTunnelBuffer Number of buffer to be tunnelled */\ -+ omx_tsem_t* pAllocSem; /**< @param pFlushSem Semaphore that locks the execution until the buffers have been flushed, if needed */ \ -+ OMX_U32 nNumBufferFlushed; /**< @param nNumBufferFlushed Number of buffer Flushed */\ -+ OMX_BOOL bIsPortFlushed;/**< @param bIsPortFlushed Boolean variables indicate port is being flushed at the moment */ \ -+ omx_queue_t* pBufferQueue; /**< @param pBufferQueue queue for buffer to be processed by the port */\ -+ omx_tsem_t* pBufferSem; /**< @param pBufferSem Semaphore for buffer queue access synchronization */\ -+ OMX_U32 nNumAssignedBuffers; /**< @param nNumAssignedBuffers Number of buffer assigned on each port */\ -+ OMX_PARAM_PORTDEFINITIONTYPE sPortParam; /**< @param sPortParam General OpenMAX port parameter */\ -+ OMX_BUFFERHEADERTYPE **pInternalBufferStorage; /**< This array contains the reference to all the buffers hadled by this port and already registered*/\ -+ BUFFER_STATUS_FLAG *bBufferStateAllocated; /**< @param bBufferStateAllocated The State of the Buffer whether assigned or allocated */\ -+ OMX_COMPONENTTYPE *standCompContainer;/**< The OpenMAX component reference that contains this port */\ -+ OMX_BOOL bIsTransientToEnabled;/**< It indicates that the port is going from disabled to enabled */ \ -+ OMX_BOOL bIsTransientToDisabled;/**< It indicates that the port is going from enabled to disabled */ \ -+ OMX_BOOL bIsFullOfBuffers; /**< It indicates if the port has all the buffers needed */ \ -+ OMX_BOOL bIsEmptyOfBuffers;/**< It indicates if the port has no buffers*/ \ -+ OMX_ERRORTYPE (*PortConstructor)(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput); /**< The contructor of the port. It fills all the other function pointers */ \ -+ OMX_ERRORTYPE (*PortDestructor)(omx_base_PortType *openmaxStandPort); /**< The destructor of the port*/ \ -+ OMX_ERRORTYPE (*Port_DisablePort)(omx_base_PortType *openmaxStandPort); /**< Disables the port */ \ -+ OMX_ERRORTYPE (*Port_EnablePort)(omx_base_PortType *openmaxStandPort); /**< Enables the port */ \ -+ OMX_ERRORTYPE (*Port_SendBufferFunction)(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer); /**< Holds the EmptyThisBuffer of FillThisBuffer function, if the port is input or output */ \ -+ OMX_ERRORTYPE (*Port_AllocateBuffer)(omx_base_PortType *openmaxStandPort,OMX_INOUT OMX_BUFFERHEADERTYPE** pBuffer,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_PTR pAppPrivate,OMX_IN OMX_U32 nSizeBytes);/**< Replaces the AllocateBuffer call for the base port. */ \ -+ OMX_ERRORTYPE (*Port_UseBuffer)(omx_base_PortType *openmaxStandPort,OMX_BUFFERHEADERTYPE** ppBufferHdr,OMX_U32 nPortIndex,OMX_PTR pAppPrivate,OMX_U32 nSizeBytes,OMX_U8* pBuffer);/**< The standard use buffer function applied to the port class */ \ -+ OMX_ERRORTYPE (*Port_FreeBuffer)(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex,OMX_BUFFERHEADERTYPE* pBuffer); /**< The standard free buffer function applied to the port class */ \ -+ OMX_ERRORTYPE (*Port_AllocateTunnelBuffer)(omx_base_PortType *openmaxStandPort,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_U32 nSizeBytes);/**< AllocateTunnelBuffer call for the base port. */ \ -+ OMX_ERRORTYPE (*Port_FreeTunnelBuffer)(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex); /**< The free buffer function used to free tunnelled buffers */ \ -+ OMX_ERRORTYPE (*BufferProcessedCallback)(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);/**< Holds the EmptyBufferDone or FillBufferDone callback, if the port is input or output port */ \ -+ OMX_ERRORTYPE (*FlushProcessingBuffers)(omx_base_PortType *openmaxStandPort); /**< release all the buffers currently under processing */ \ -+ OMX_ERRORTYPE (*ReturnBufferFunction)(omx_base_PortType* openmaxStandPort,OMX_BUFFERHEADERTYPE* pBuffer); /**< Call appropriate function to return buffers to peer or IL Client*/ \ -+ OMX_ERRORTYPE (*ComponentTunnelRequest)(omx_base_PortType* openmaxStandPort,OMX_IN OMX_HANDLETYPE hTunneledComp,OMX_IN OMX_U32 nTunneledPort,OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); /**< Setup tunnel with the port */ -+ENDCLASS(omx_base_PortType) -+ -+/** -+ * @brief The base contructor for the generic OpenMAX ST port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of constructing the instance of the port and -+ * every object needed by the base port. -+ * -+ * @param openmaxStandPort the ST port to be initialized -+ * -+ * @return OMX_ErrorInsufficientResources if a memory allocation fails -+ */ -+OMX_ERRORTYPE base_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput); -+ -+/** @brief The base destructor for the generic OpenMAX ST port -+ * -+ * This function is executed by the component that uses a port. -+ * The parameter contains the info about the component. -+ * It takes care of destructing the instance of the port and -+ * every object used by the base port. -+ * -+ * @param openmaxStandPort the ST port to be disposed -+ */ -+OMX_ERRORTYPE base_port_Destructor(omx_base_PortType *openmaxStandPort); -+ -+/** @brief Disables the port. -+ * -+ * This function is called due to a request by the IL client -+ * -+ * @param openmaxStandPort the reference to the port -+ * -+ */ -+OMX_ERRORTYPE base_port_DisablePort(omx_base_PortType *openmaxStandPort); + -+/** @brief Enables the port. -+ * -+ * This function is called due to a request by the IL client -+ * -+ * @param openmaxStandPort the reference to the port -+ * -+ */ -+OMX_ERRORTYPE base_port_EnablePort(omx_base_PortType *openmaxStandPort); ++static OMX_ERRORTYPE gomx_free_buffer(OMX_HANDLETYPE hComponent, OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE* pBuffer) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ GOMX_PORT *port; + -+/** @brief The entry point for sending buffers to the port -+ * -+ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on -+ * the nature of the port, that can be an input or output port. -+ */ -+OMX_ERRORTYPE base_port_SendBufferFunction( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE* pBuffer); ++ if (!(port = gomx_get_port(comp, nPortIndex))) return OMX_ErrorBadPortIndex; + -+/** @brief Called by the standard allocate buffer, it implements a base functionality. -+ * -+ * This function can be overriden if the allocation of the buffer is not a simply malloc call. -+ * The parameters are the same as the standard function, except for the handle of the port -+ * instead of the handler of the component -+ * When the buffers needed by this port are all assigned or allocated, the variable -+ * bIsFullOfBuffers becomes equal to OMX_TRUE -+ */ -+OMX_ERRORTYPE base_port_AllocateBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE** pBuffer, -+ OMX_U32 nPortIndex, -+ OMX_PTR pAppPrivate, -+ OMX_U32 nSizeBytes); -+ -+/** @brief Called by the standard use buffer, it implements a base functionality. -+ * -+ * This function can be overriden if the use buffer implicate more complicated operations. -+ * The parameters are the same as the standard function, except for the handle of the port -+ * instead of the handler of the component -+ * When the buffers needed by this port are all assigned or allocated, the variable -+ * bIsFullOfBuffers becomes equal to OMX_TRUE -+ */ -+OMX_ERRORTYPE base_port_UseBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_BUFFERHEADERTYPE** ppBufferHdr, -+ OMX_U32 nPortIndex, -+ OMX_PTR pAppPrivate, -+ OMX_U32 nSizeBytes, -+ OMX_U8* pBuffer); -+ -+/** @brief Called by the standard function. -+ * -+ * It frees the buffer header and in case also the buffer itself, if needed. -+ * When all the bufers are done, the variable bIsEmptyOfBuffers is set to OMX_TRUE -+ */ -+OMX_ERRORTYPE base_port_FreeBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_U32 nPortIndex, -+ OMX_BUFFERHEADERTYPE* pBuffer); ++ /* Freeing buffer is allowed in all states, so destructor can ++ * synchronize successfully. */ + -+/** @brief Releases buffers under processing. -+ * -+ * This function must be implemented in the derived classes, for the -+ * specific processing -+ */ -+OMX_ERRORTYPE base_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort); ++ pthread_mutex_lock(&comp->mutex); + -+/** @brief Returns buffers when processed. -+ * -+ * Call appropriate function to return buffers to peer or IL Client -+ */ ++ if (!((comp->state == OMX_StateIdle && comp->wanted_state == OMX_StateLoaded) || ++ (port->def.bEnabled == OMX_FALSE && ++ (comp->state == OMX_StateExecuting || ++ comp->state == OMX_StatePause || ++ comp->state == OMX_StateIdle)))) { ++ /* In unexpected states the port unpopulated error is sent. */ ++ if (port->num_buffers == port->def.nBufferCountActual) ++ __gomx_event(comp, OMX_EventError, OMX_ErrorPortUnpopulated, nPortIndex, 0); ++ /* FIXME? should we mark the port also down */ ++ } + -+OMX_ERRORTYPE base_port_ReturnBufferFunction( -+ omx_base_PortType* openmaxStandPort, -+ OMX_BUFFERHEADERTYPE* pBuffer); ++ port->num_buffers--; ++ __gomx_port_update_buffer_state(comp, port); + -+/** @brief Setup Tunnel with the port -+ */ ++ pthread_mutex_unlock(&comp->mutex); + -+OMX_ERRORTYPE base_port_ComponentTunnelRequest( -+ omx_base_PortType* openmaxStandPort, -+ OMX_IN OMX_HANDLETYPE hTunneledComp, -+ OMX_IN OMX_U32 nTunneledPort, -+ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); ++ free(pBuffer); + -+/** @brief Allocate Buffers for tunneling use -+ */ -+OMX_ERRORTYPE base_port_AllocateTunnelBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_IN OMX_U32 nPortIndex, -+ OMX_IN OMX_U32 nSizeBytes); -+ -+/** @brief Free buffers used in tunnel -+ */ -+OMX_ERRORTYPE base_port_FreeTunnelBuffer( -+ omx_base_PortType *openmaxStandPort, -+ OMX_U32 nPortIndex); -+ -+ -+#endif -diff --git a/alsa/omx_base_sink.cpp b/alsa/omx_base_sink.cpp -new file mode 100644 -index 0000000..ae8b3e3 ---- /dev/null -+++ b/alsa/omx_base_sink.cpp -@@ -0,0 +1,189 @@ -+/** -+ @file src/base/omx_base_sink.c -+ -+ OpenMAX base sink component. This component does not perform any multimedia -+ processing. It derives from base component and contains a single input port. -+ It can be used as base class for sink components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-09-12 08:12:11 +0200 (Fri, 12 Sep 2008) $ -+ Revision $Rev: 615 $ -+ Author $Author: pankaj_sen $ -+*/ -+ -+#include <omx_base_sink.h> -+ -+OMX_ERRORTYPE omx_base_sink_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) { -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ omx_base_sink_PrivateType* omx_base_sink_Private; -+ -+ if (openmaxStandComp->pComponentPrivate) { -+ omx_base_sink_Private = (omx_base_sink_PrivateType*)openmaxStandComp->pComponentPrivate; -+ } else { -+ omx_base_sink_Private = (omx_base_sink_PrivateType*)calloc(1,sizeof(omx_base_sink_PrivateType)); -+ if (!omx_base_sink_Private) { -+ return OMX_ErrorInsufficientResources; -+ } -+ } -+ -+ // we could create our own port structures here -+ // fixme maybe the base class could use a "port factory" function pointer? -+ err = omx_base_component_Constructor(openmaxStandComp,cComponentName); -+ -+ /* here we can override whatever defaults the base_component constructor set -+ * e.g. we can override the function pointers in the private struct */ -+ omx_base_sink_Private = (omx_base_sink_PrivateType*)openmaxStandComp->pComponentPrivate; -+ -+ omx_base_sink_Private->BufferMgmtFunction = omx_base_sink_BufferMgmtFunction; -+ -+ return err; ++ return OMX_ErrorNone; +} + -+OMX_ERRORTYPE omx_base_sink_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) ++static void __gomx_port_queue_supplier_buffer(GOMX_PORT *port, OMX_BUFFERHEADERTYPE *hdr) +{ -+ return omx_base_component_Destructor(openmaxStandComp); ++ gomxq_enqueue(&port->tunnel_supplierq, (void *) hdr); ++ if (port->tunnel_supplierq.num == port->num_buffers) ++ pthread_cond_broadcast(&port->cond_idle); +} + -+/** This is the central function for component processing. It -+ * is executed in a separate thread, is synchronized with -+ * semaphores at each port, those are released each time a new buffer -+ * is available on the given port. -+ */ -+void* omx_base_sink_BufferMgmtFunction (void* param) { -+ OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; -+ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; -+ omx_base_sink_PrivateType* omx_base_sink_Private = (omx_base_sink_PrivateType*)omx_base_component_Private; -+ omx_base_PortType *pInPort = (omx_base_PortType *)omx_base_sink_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; -+ omx_tsem_t* pInputSem = pInPort->pBufferSem; -+ omx_queue_t* pInputQueue = pInPort->pBufferQueue; -+ OMX_BUFFERHEADERTYPE* pInputBuffer = NULL; -+ OMX_COMPONENTTYPE* target_component; -+ OMX_BOOL isInputBufferNeeded = OMX_TRUE; -+ int inBufExchanged = 0; -+ -+ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__); -+ while(omx_base_component_Private->state == OMX_StateIdle || -+ omx_base_component_Private->state == OMX_StateExecuting || -+ omx_base_component_Private->state == OMX_StatePause || -+ omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){ -+ -+ /*Wait till the ports are being flushed*/ -+ pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); -+ while( PORT_IS_BEING_FLUSHED(pInPort)) { -+ pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); -+ -+ if(isInputBufferNeeded==OMX_FALSE) { -+ pInPort->ReturnBufferFunction(pInPort,pInputBuffer); -+ inBufExchanged--; -+ pInputBuffer=NULL; -+ isInputBufferNeeded=OMX_TRUE; -+ DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n"); -+ } -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__); -+ -+ omx_tsem_up(omx_base_sink_Private->flush_all_condition); -+ omx_tsem_down(omx_base_sink_Private->flush_condition); -+ pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); -+ } -+ pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); -+ -+ /*No buffer to process. So wait here*/ -+ if((pInputSem->semval==0 && isInputBufferNeeded==OMX_TRUE ) && -+ (omx_base_sink_Private->state != OMX_StateLoaded && omx_base_sink_Private->state != OMX_StateInvalid)) { -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer \n"); -+ omx_tsem_down(omx_base_sink_Private->bMgmtSem); -+ } -+ -+ if(omx_base_sink_Private->state == OMX_StateLoaded || omx_base_sink_Private->state == OMX_StateInvalid) { -+ DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); -+ break; -+ } -+ -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer semval=%d \n",pInputSem->semval); -+ if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) { -+ omx_tsem_down(pInputSem); -+ if(pInputQueue->nelem>0){ -+ inBufExchanged++; -+ isInputBufferNeeded=OMX_FALSE; -+ pInputBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(pInputQueue); -+ if(pInputBuffer == NULL){ -+ DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n"); -+ break; -+ } -+ } -+ } -+ -+ if(isInputBufferNeeded==OMX_FALSE) { -+ if(pInputBuffer->nFlags==OMX_BUFFERFLAG_EOS) { -+ DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in input buffer\n"); -+ -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventBufferFlag, /* The command was completed */ -+ 0, /* The commands was a OMX_CommandStateSet */ -+ pInputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ -+ NULL); -+ pInputBuffer->nFlags=0; -+ } -+ -+ target_component=(OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent; -+ if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) { -+ /*Clear the mark and generate an event*/ -+ (*(omx_base_component_Private->callbacks->EventHandler)) -+ (openmaxStandComp, -+ omx_base_component_Private->callbackData, -+ OMX_EventMark, /* The command was completed */ -+ 1, /* The commands was a OMX_CommandStateSet */ -+ 0, /* The state has been changed in message->messageParam2 */ -+ pInputBuffer->pMarkData); -+ } else if(pInputBuffer->hMarkTargetComponent!=NULL){ -+ /*If this is not the target component then pass the mark*/ -+ DEBUG(DEB_LEV_FULL_SEQ, "Can't Pass Mark. This is a Sink!!\n"); -+ } -+ if (omx_base_sink_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) { -+ (*(omx_base_sink_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer); -+ } -+ else { -+ /*If no buffer management call back the explicitly consume input buffer*/ -+ DEBUG(DEB_LEV_FULL_SEQ, "If no buffer management call back, explicitly consume input buffer. nInputPortIndex=%d BufferMgmtCallback=0x%p nFilledLen=%d\n", -+ (int)pInputBuffer->nInputPortIndex, omx_base_sink_Private->BufferMgmtCallback, (int)pInputBuffer->nFilledLen); -+ pInputBuffer->nFilledLen = 0; -+ } -+ /*Input Buffer has been completely consumed. So, get new input buffer*/ -+ -+ if(omx_base_sink_Private->state==OMX_StatePause && !PORT_IS_BEING_FLUSHED(pInPort)) { -+ /*Waiting at paused state*/ -+ omx_tsem_wait(omx_base_sink_Private->bStateSem); -+ } -+ -+ /*Input Buffer has been completely consumed. So, return input buffer*/ -+ if(pInputBuffer->nFilledLen==0) { -+ pInPort->ReturnBufferFunction(pInPort,pInputBuffer); -+ inBufExchanged--; -+ pInputBuffer=NULL; -+ isInputBufferNeeded = OMX_TRUE; -+ } -+ -+ } -+ } -+ DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); -+ return NULL; -+} -diff --git a/alsa/omx_base_sink.h b/alsa/omx_base_sink.h -new file mode 100644 -index 0000000..dfe7e9c ---- /dev/null -+++ b/alsa/omx_base_sink.h -@@ -0,0 +1,73 @@ -+/** -+ @file src/base/omx_base_sink.h -+ -+ OpenMAX base sink component. This component does not perform any multimedia -+ processing. It derives from base component and contains a single port. It can be used -+ as base class for sink components. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-08-28 17:50:08 +0200 (Thu, 28 Aug 2008) $ -+ Revision $Rev: 583 $ -+ Author $Author: gsent $ -+ -+*/ -+ -+#ifndef _OMX_BASE_SINK_COMPONENT_H_ -+#define _OMX_BASE_SINK_COMPONENT_H_ -+ -+//#include <OMX_Types.h> -+//#include <IL/OMX_Component.h> -+//#include <IL/OMX_Core.h> -+#include <pthread.h> -+#include "omx_base_component.h" -+#include <stdlib.h> -+ -+ -+#define OMX_BASE_SINK_INPUTPORT_INDEX 0 /* The index of the input port for the derived components */ -+#define OMX_BASE_SINK_CLOCKPORT_INDEX 1 /* The index of the clock port for the dervied components */ -+ -+/** OMX_BASE_SINK_ALLPORT_INDEX as the standard specifies, the -1 value for port index is used to point to all the ports -+ */ -+#define OMX_BASE_SINK_ALLPORT_INDEX -1 -+ -+/** base sink component private structure. -+ */ -+DERIVEDCLASS(omx_base_sink_PrivateType, omx_base_component_PrivateType) -+#define omx_base_sink_PrivateType_FIELDS omx_base_component_PrivateType_FIELDS \ -+ /** @param BufferMgmtCallback function pointer for algorithm callback */ \ -+ void (*BufferMgmtCallback)(OMX_COMPONENTTYPE* openmaxStandComp, OMX_BUFFERHEADERTYPE* inputbuffer); -+ENDCLASS(omx_base_sink_PrivateType) -+ -+/** Base sink contructor -+ */ -+OMX_ERRORTYPE omx_base_sink_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName); -+ -+/** The base sink destructor. It simply calls the base destructor -+ */ -+OMX_ERRORTYPE omx_base_sink_Destructor(OMX_COMPONENTTYPE *openmaxStandComp); -+ -+/** This is the central function for component processing. It -+ * is executed in a separate thread, is synchronized with -+ * semaphores at each port, those are released each time a new buffer -+ * is available on the given port. -+ */ -+void* omx_base_sink_BufferMgmtFunction(void* param); -+ -+#endif -diff --git a/alsa/omx_classmagic.h b/alsa/omx_classmagic.h -new file mode 100644 -index 0000000..2560041 ---- /dev/null -+++ b/alsa/omx_classmagic.h -@@ -0,0 +1,100 @@ -+/** -+ @file src/base/omx_classmagic.h -+ -+ This file contains class handling helper macros -+ It is left as an exercise to the reader how they do the magic (FIXME) -+ -+ Usage Rules: -+ 1) include this file -+ 2) if your don't inherit, start your class with CLASS(classname) -+ 3) if you inherit something, start your class with -+ DERIVEDCLASS(classname, inheritedclassname) -+ 4) end your class with ENDCLASS(classname) -+ 5) define your class variables with a #define classname_FIELDS inheritedclassname_FIELDS -+ inside your class and always add a backslash at the end of line (except last) -+ 6) if you want to use doxygen, use C-style comments inside the #define, and -+ enable macro expansion in doxyconf and predefine DOXYGEN_PREPROCESSING there, etc. -+ -+ See examples at the end of this file (in #if 0 block) -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ -+ Revision $Rev: 554 $ -+ Author $Author: pankaj_sen $ -+ -+*/ -+#ifndef OMX_CLASSMAGIC_H_ -+#define OMX_CLASSMAGIC_H_ -+ -+ -+#ifdef DOXYGEN_PREPROCESSING -+#define CLASS(a) class a { public: -+#define DERIVEDCLASS(a, b) class a : public b { public: -+#define ENDCLASS(a) a##_FIELDS }; -+#else -+#define CLASS(a) typedef struct a a; \ -+ struct a { -+#define DERIVEDCLASS(a, b) typedef struct a a; \ -+ struct a { -+#define ENDCLASS(a) a##_FIELDS }; -+#endif -+ -+#if 0 /*EXAMPLES*/ -+/** -+ * Class A is a nice class -+ */ -+CLASS(A) -+#define A_FIELDS \ -+/** @param a very nice parameter */ \ -+ int a; \ -+/** @param ash another very nice parameter */ \ -+ int ash; -+ENDCLASS(A) -+ -+/** -+ * Class B is a nice derived class -+ */ -+DERIVEDCLASS(B,A) -+#define B_FIELDS A_FIELDS \ -+/** @param b very nice parameter */ \ -+ int b; -+ENDCLASS(B) -+ -+/** -+ * Class B2 is a nice derived class -+ */ -+DERIVEDCLASS(B2,A) -+#define B2_FIELDS A_FIELDS \ -+/** @param b2 very nice parameter */ \ -+ int b2; -+ENDCLASS(B2) -+ -+/** -+ * Class C is an even nicer derived class. -+ */ -+DERIVEDCLASS(C,B) -+#define C_FIELDS B_FIELDS \ -+/** @param c very nice parameter */ \ -+ int c; -+ENDCLASS(C) -+ -+#endif /* 0 */ -+ -+#endif -diff --git a/alsa/omx_comp_debug_levels.h b/alsa/omx_comp_debug_levels.h -new file mode 100644 -index 0000000..dda6a79 ---- /dev/null -+++ b/alsa/omx_comp_debug_levels.h -@@ -0,0 +1,77 @@ -+/** -+ @file src/omx_comp_debug_levels.h -+ -+ Define the level of debug prints on standard err. The different levels can -+ be composed with binary OR. -+ The debug levels defined here belong to OpenMAX components and IL core -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-07-16 09:39:31 +0200 (Wed, 16 Jul 2008) $ -+ Revision $Rev: 577 $ -+ Author $Author: gsent $ -+ -+*/ -+ -+#ifndef __OMX_COMP_DEBUG_LEVELS_H__ -+#define __OMX_COMP_DEBUG_LEVELS_H__ -+ -+#include <stdio.h> -+ -+/** Remove all debug output lines -+ */ -+#define DEB_LEV_NO_OUTPUT 0 -+ -+/** Messages explaing the reason of critical errors -+ */ -+#define DEB_LEV_ERR 1 -+ -+/** Messages showing values related to the test and the component/s used -+ */ -+#define DEB_LEV_PARAMS 2 -+ -+/** Messages representing steps in the execution. These are the simple messages, because -+ * they avoid iterations -+ */ -+#define DEB_LEV_SIMPLE_SEQ 4 -+ -+/** Messages representing steps in the execution. All the steps are described, -+ * also with iterations. With this level of output the performances are -+ * seriously compromised -+ */ -+#define DEB_LEV_FULL_SEQ 8 -+ -+/** Messages that indicates the beginning and the end of a function. -+ * It can be used to trace the execution -+ */ -+#define DEB_LEV_FUNCTION_NAME 16 -+ -+/** All the messages - max value -+ */ -+#define DEB_ALL_MESS 255 -+ -+/** \def DEBUG_LEVEL is the current level do debug output on standard err */ -+#define DEBUG_LEVEL (DEB_ALL_MESS) -+#if DEBUG_LEVEL > 0 -+#define DEBUG(n, fmt, args...) do { if (DEBUG_LEVEL & (n)){fprintf(stdout, "OMX-" fmt, ##args);} } while (0) -+#else -+#define DEBUG(n, fmt, args...) -+#endif -+ -+#endif -diff --git a/alsa/omx_loader_XBMC.cpp b/alsa/omx_loader_XBMC.cpp -new file mode 100644 -index 0000000..5ea1855 ---- /dev/null -+++ b/alsa/omx_loader_XBMC.cpp -@@ -0,0 +1,69 @@ -+ -+#include "omx_loader_XBMC.h" -+#include <omx_alsasink_component.h> -+ -+OMX_ERRORTYPE OMX_GetHandle_XBMC(OMX_OUT OMX_HANDLETYPE* pHandle, -+ OMX_IN OMX_STRING cComponentName, -+ OMX_IN OMX_PTR pAppData, -+ OMX_IN OMX_CALLBACKTYPE* pCallBacks) ++static OMX_ERRORTYPE __gomx_empty_buffer_done(GOMX_COMPONENT *comp, OMX_BUFFERHEADERTYPE *hdr) +{ -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ OMX_COMPONENTTYPE* openmaxStandComp; -+ omx_base_component_PrivateType* priv; -+ -+ if(!strcmp("OMX.XBMC.alsa.alsasink", cComponentName)) -+ { -+ openmaxStandComp = (OMX_COMPONENTTYPE*)calloc(1,sizeof(OMX_COMPONENTTYPE)); -+ if (!openmaxStandComp) { -+ return OMX_ErrorInsufficientResources; -+ } -+ -+ err = omx_alsasink_component_Constructor(openmaxStandComp,cComponentName); -+ if (err != OMX_ErrorNone) -+ { -+ if (err == OMX_ErrorInsufficientResources) -+ { -+ *pHandle = openmaxStandComp; -+ priv = (omx_base_component_PrivateType *) openmaxStandComp->pComponentPrivate; -+ return OMX_ErrorInsufficientResources; -+ } -+ DEBUG(DEB_LEV_ERR, "Error during component construction\n"); -+ openmaxStandComp->ComponentDeInit(openmaxStandComp); -+ free(openmaxStandComp); -+ openmaxStandComp = NULL; -+ return OMX_ErrorComponentNotFound; -+ } -+ priv = (omx_base_component_PrivateType *) openmaxStandComp->pComponentPrivate; -+ -+ *pHandle = openmaxStandComp; -+ ((OMX_COMPONENTTYPE*)*pHandle)->SetCallbacks(*pHandle, pCallBacks, pAppData); -+ } -+ else -+ { -+ err = OMX_ErrorComponentNotFound; -+ } -+ -+ return err; -+} -+ -+ -+OMX_ERRORTYPE OMX_FreeHandle_XBMC(OMX_IN OMX_HANDLETYPE hComponent) ++ GOMX_PORT *port = gomx_get_port(comp, hdr->nInputPortIndex); ++ OMX_ERRORTYPE r; ++ ++ if (port->tunnel_comp) { ++ /* Buffers are sent to the tunneled port once emptied as long as ++ * the component is in the OMX_StateExecuting state */ ++ if ((comp->state == OMX_StateExecuting && port->def.bEnabled) || ++ !port->tunnel_supplier) { ++ pthread_mutex_unlock(&comp->mutex); ++ r = OMX_FillThisBuffer(port->tunnel_comp, hdr); ++ pthread_mutex_lock(&comp->mutex); ++ } else { ++ r = OMX_ErrorIncorrectStateOperation; ++ } ++ } else { ++ pthread_mutex_unlock(&comp->mutex); ++ r = comp->cb.EmptyBufferDone((OMX_HANDLETYPE) comp, hdr->pAppPrivate, hdr); ++ pthread_mutex_lock(&comp->mutex); ++ } ++ ++ if (r != OMX_ErrorNone && port->tunnel_supplier) { ++ __gomx_port_queue_supplier_buffer(port, hdr); ++ r = OMX_ErrorNone; ++ } ++ ++ return r; ++} ++ ++static OMX_ERRORTYPE gomx_empty_this_buffer(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ GOMX_PORT *port; ++ OMX_ERRORTYPE r; ++ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ if (comp->state != OMX_StatePause && comp->state != OMX_StateExecuting && ++ comp->wanted_state != OMX_StateExecuting) ++ return OMX_ErrorIncorrectStateOperation; ++ ++ if (!(port = gomx_get_port(comp, pBuffer->nInputPortIndex))) ++ return OMX_ErrorBadPortIndex; ++ ++ pthread_mutex_lock(&comp->mutex); ++ if (port->def.bEnabled) { ++ if (port->do_buffer) ++ r = port->do_buffer(comp, port, pBuffer); ++ else ++ r = __gomx_empty_buffer_done(comp, pBuffer); ++ } else { ++ if (port->tunnel_supplier) { ++ __gomx_port_queue_supplier_buffer(port, pBuffer); ++ r = OMX_ErrorNone; ++ } else { ++ r = OMX_ErrorIncorrectStateOperation; ++ } ++ } ++ pthread_mutex_unlock(&comp->mutex); ++ return r; ++} ++ ++static OMX_ERRORTYPE gomx_fill_this_buffer(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer) +{ -+ int i; -+ OMX_ERRORTYPE err = OMX_ErrorNone; -+ omx_base_component_PrivateType * priv = (omx_base_component_PrivateType *) ((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; -+ -+ if(!strcmp("OMX.XBMC.alsa.alsasink", priv->name)) -+ { -+ err = ((OMX_COMPONENTTYPE*)hComponent)->ComponentDeInit(hComponent); -+ -+ free((OMX_COMPONENTTYPE*)hComponent); -+ hComponent = NULL; -+ } -+ else -+ { -+ err = OMX_ErrorComponentNotFound; -+ } -+ -+ return err; ++ CDEBUG(hComponent, 0, "stub"); ++ return OMX_ErrorNotImplemented; +} -\ No newline at end of file -diff --git a/alsa/omx_loader_XBMC.h b/alsa/omx_loader_XBMC.h -new file mode 100644 -index 0000000..c835043 ---- /dev/null -+++ b/alsa/omx_loader_XBMC.h -@@ -0,0 +1,27 @@ -+#pragma once -+ -+ -+#ifndef __OMX_LOADER_XBMC__ -+#define __OMX_LOADER_XBMC__ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif /* __cplusplus */ + -+#pragma pack(4) -+#include <IL/OMX_Component.h> -+#include <IL/OMX_Types.h> -+#pragma pack() -+ -+OMX_ERRORTYPE OMX_GetHandle_XBMC(OMX_OUT OMX_HANDLETYPE* pHandle, -+ OMX_IN OMX_STRING cComponentName, -+ OMX_IN OMX_PTR pAppData, -+ OMX_IN OMX_CALLBACKTYPE* pCallBacks); -+ -+OMX_ERRORTYPE OMX_FreeHandle_XBMC(OMX_IN OMX_HANDLETYPE hComponent); -+ -+#ifdef __cplusplus ++static void __gomx_process_mark(GOMX_COMPONENT *comp, OMX_BUFFERHEADERTYPE *hdr) ++{ ++ if (hdr->hMarkTargetComponent == (OMX_HANDLETYPE) comp) { ++ __gomx_event(comp, OMX_EventMark, 0, 0, hdr->pMarkData); ++ hdr->hMarkTargetComponent = 0; ++ hdr->pMarkData = 0; ++ } +} -+#endif /* __cplusplus */ -+ -+#endif -\ No newline at end of file -diff --git a/alsa/omx_queue.cpp b/alsa/omx_queue.cpp -new file mode 100644 -index 0000000..e4ecd25 ---- /dev/null -+++ b/alsa/omx_queue.cpp -@@ -0,0 +1,136 @@ -+/** -+ @file src/queue.c -+ -+ Implements a simple LIFO structure used for queueing OMX buffers. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). + -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. ++static OMX_ERRORTYPE __gomx_port_unpopulate(GOMX_COMPONENT *comp, GOMX_PORT *port) ++{ ++ OMX_BUFFERHEADERTYPE *hdr; ++ void *buf; ++ ++ if (port->tunnel_supplier) { ++ CINFO(comp, port, "waiting for supplier buffers"); ++ while (port->tunnel_supplierq.num != port->num_buffers) ++ pthread_cond_wait(&port->cond_idle, &comp->mutex); ++ ++ CINFO(comp, port, "free tunnel buffers"); ++ while ((hdr = (OMX_BUFFERHEADERTYPE*)gomxq_dequeue(&port->tunnel_supplierq)) != 0) { ++ buf = hdr->pBuffer; ++ OMX_FreeBuffer(port->tunnel_comp, port->tunnel_port, hdr); ++ free(buf); ++ port->num_buffers--; ++ __gomx_port_update_buffer_state(comp, port); ++ } ++ } else { ++ /* Wait client / tunnel supplier to allocate buffers */ ++ CINFO(comp, port, "waiting buffers to be freed"); ++ while (port->num_buffers > 0) ++ pthread_cond_wait(&port->cond_no_buffers, &comp->mutex); ++ } ++ ++ CINFO(comp, port, "UNPOPULATED"); ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE __gomx_port_populate(GOMX_COMPONENT *comp, GOMX_PORT *port) ++{ ++ OMX_ERRORTYPE r; ++ OMX_BUFFERHEADERTYPE *hdr; ++ void *buf; ++ ++ if (port->tunnel_supplier) { ++ CINFO(comp, port, "Allocating tunnel buffers"); ++ while (port->num_buffers < port->def.nBufferCountActual) { ++ pthread_mutex_unlock(&comp->mutex); ++ r = OMX_ErrorInsufficientResources; ++ buf = malloc(port->def.nBufferSize); ++ if (buf) { ++ r = OMX_UseBuffer(port->tunnel_comp, &hdr, ++ port->tunnel_port, 0, ++ port->def.nBufferSize, (OMX_U8*) buf); ++ if (r != OMX_ErrorNone) free(buf); ++ } ++ if (r == OMX_ErrorInvalidState || ++ r == OMX_ErrorIncorrectStateOperation) { ++ /* Non-supplier is not transitioned yet. ++ * Wait for a bit and retry */ ++ usleep(1000); ++ pthread_mutex_lock(&comp->mutex); ++ continue; ++ } ++ pthread_mutex_lock(&comp->mutex); ++ ++ if (r != OMX_ErrorNone) { ++ /* Hard error. Cancel and bail out */ ++ __gomx_port_unpopulate(comp, port); ++ return r; ++ } ++ ++ if (port->def.eDir == OMX_DirInput) ++ hdr->nInputPortIndex = port->def.nPortIndex; ++ else ++ hdr->nOutputPortIndex = port->def.nPortIndex; ++ gomxq_enqueue(&port->tunnel_supplierq, (void*) hdr); ++ port->num_buffers++; ++ __gomx_port_update_buffer_state(comp, port); ++ } ++ } else { ++ /* Wait client / tunnel supplier to allocate buffers */ ++ CINFO(comp, port, "waiting buffers"); ++ while (!port->def.bPopulated) ++ pthread_cond_wait(&port->cond_populated, &comp->mutex); ++ } ++ ++ CINFO(comp, port, "POPULATED"); ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE gomx_send_command(OMX_HANDLETYPE hComponent, OMX_COMMANDTYPE Cmd, OMX_U32 nParam1, OMX_PTR pCmdData) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ GOMX_COMMAND *c; + -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. ++ /* OMX IL Specification is unclear which errors can be returned ++ * inline and which need to be reported with a callback. ++ * This just does minimal state checking, and queues everything ++ * to worker and reports any real errors via the callback. */ ++ if (!hComponent) return OMX_ErrorInvalidComponent; ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ if (!comp->cb.EventHandler) return OMX_ErrorNotReady; + -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA ++ c = (GOMX_COMMAND*) malloc(sizeof(GOMX_COMMAND)); ++ if (!c) return OMX_ErrorInsufficientResources; + -+ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ -+ Revision $Rev: 554 $ -+ Author $Author: pankaj_sen $ -+*/ ++ CINFO(comp, 0, "SendCommand %x, %x, %p", Cmd, nParam1, pCmdData); ++ c->cmd = Cmd; ++ c->param = nParam1; ++ c->data = pCmdData; + -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> ++ pthread_mutex_lock(&comp->mutex); ++ gomxq_enqueue(&comp->cmdq, (void*) c); ++ pthread_cond_signal(&comp->cond); ++ pthread_mutex_unlock(&comp->mutex); + -+#include "omx_queue.h" -+#include "omx_comp_debug_levels.h" -+ -+/** Initialize a queue descriptor -+ * -+ * @param queue The queue descriptor to initialize. -+ * The user needs to allocate the queue -+ */ -+void omx_queue_init(omx_queue_t* queue) { -+ int i; -+ omx_qelem_t* newelem; -+ omx_qelem_t* current; -+ queue->first = (omx_qelem_t*)malloc(sizeof(omx_qelem_t)); -+ memset(queue->first, 0, sizeof(omx_qelem_t)); -+ current = queue->last = queue->first; -+ queue->nelem = 0; -+ for (i = 0; i<MAX_QUEUE_ELEMENTS - 2; i++) { -+ newelem = (omx_qelem_t*)malloc(sizeof(omx_qelem_t)); -+ memset(newelem, 0, sizeof(omx_qelem_t)); -+ current->q_forw = newelem; -+ current = newelem; -+ } -+ current->q_forw = queue->first; -+ -+ pthread_mutex_init(&queue->mutex, NULL); ++ return OMX_ErrorNone; +} + -+/** Deinitialize a queue descriptor -+ * flushing all of its internal data -+ * -+ * @param queue the queue descriptor to dump -+ */ -+void omx_queue_deinit(omx_queue_t* queue) { -+ int i; -+ omx_qelem_t* current; -+ current = queue->first; -+ for (i = 0; i<MAX_QUEUE_ELEMENTS - 2; i++) { -+ if (current != NULL) { -+ current = current->q_forw; -+ free(queue->first); -+ queue->first = current; -+ } -+ } -+ if(queue->first) { -+ free(queue->first); -+ queue->first = NULL; -+ } -+ pthread_mutex_destroy(&queue->mutex); -+} ++#define GOMX_TRANS(a,b) ((((uint32_t)a) << 16) | (uint32_t)b) + -+/** Enqueue an element to the given queue descriptor -+ * -+ * @param queue the queue descritpor where to queue data -+ * -+ * @param data the data to be enqueued -+ */ -+void omx_queue(omx_queue_t* queue, void* data) { -+ if (queue->last->data != NULL) { -+ DEBUG(DEB_LEV_ERR, "In %s ERROR! Full queue\n",__func__); -+ return; -+ } -+ pthread_mutex_lock(&queue->mutex); -+ queue->last->data = data; -+ queue->last = queue->last->q_forw; -+ queue->nelem++; -+ pthread_mutex_unlock(&queue->mutex); ++static OMX_ERRORTYPE gomx_do_set_state(GOMX_COMPONENT *comp, GOMX_COMMAND *cmd) ++{ ++ OMX_STATETYPE new_state = (OMX_STATETYPE) cmd->param; ++ OMX_ERRORTYPE r; ++ GOMX_PORT *port; ++ size_t i; ++ ++ if (comp->state == new_state) return OMX_ErrorSameState; ++ ++ if (new_state == OMX_StateInvalid) { ++ /* Transition to invalid state is always valid and immediate */ ++ comp->state = new_state; ++ return OMX_ErrorNone; ++ } ++ ++ CDEBUG(comp, 0, "starting transition to state %d", new_state); ++ ++ comp->wanted_state = new_state; ++ ++ if (comp->statechange) { ++ r = comp->statechange(comp); ++ if (r != OMX_ErrorNone) goto err; ++ } ++ ++ switch (GOMX_TRANS(comp->state, new_state)) { ++ case GOMX_TRANS(OMX_StateLoaded, OMX_StateIdle): ++ /* populate or wait for all enabled ports to be populated */ ++ for (i = 0; i < comp->nports; i++) { ++ if (!comp->ports[i].def.bEnabled) continue; ++ r = __gomx_port_populate(comp, &comp->ports[i]); ++ if (r) goto err; ++ } ++ break; ++ case GOMX_TRANS(OMX_StateIdle, OMX_StateLoaded): ++ /* free or wait all ports to be unpopulated */ ++ for (i = 0; i < comp->nports; i++) { ++ r = __gomx_port_unpopulate(comp, &comp->ports[i]); ++ if (r) goto err; ++ } ++ break; ++ case GOMX_TRANS(OMX_StateIdle, OMX_StateExecuting): ++ /* start threads */ ++ r = OMX_ErrorInsufficientResources; ++ if (comp->worker && ++ pthread_create(&comp->worker_thread, 0, comp->worker, comp) != 0) ++ goto err; ++ break; ++ case GOMX_TRANS(OMX_StateExecuting, OMX_StateIdle): ++ /* stop/join threads & wait buffers to be returned to suppliers */ ++ if (comp->worker_thread) { ++ pthread_mutex_unlock(&comp->mutex); ++ pthread_join(comp->worker_thread, 0); ++ pthread_mutex_lock(&comp->mutex); ++ comp->worker_thread = 0; ++ } ++ for (i = 0; i < comp->nports; i++) { ++ port = &comp->ports[i]; ++ if (!port->tunnel_supplier || !port->def.bEnabled) continue; ++ while (port->tunnel_supplierq.num != port->num_buffers) ++ pthread_cond_wait(&port->cond_idle, &comp->mutex); ++ } ++ break; ++ default: ++ /* FIXME: Pause and WaitForResources states not supported */ ++ r = OMX_ErrorIncorrectStateTransition; ++ goto err; ++ } ++ comp->state = new_state; ++ CDEBUG(comp, 0, "transition to state %d: success", new_state); ++ return OMX_ErrorNone; ++err: ++ comp->wanted_state = comp->state; ++ CDEBUG(comp, 0, "transition to state %d: result %x", new_state, r); ++ return r; ++} ++ ++static OMX_ERRORTYPE gomx_do_port_command(GOMX_COMPONENT *comp, GOMX_PORT *port, GOMX_COMMAND *cmd) ++{ ++ OMX_ERRORTYPE r = OMX_ErrorNone; ++ ++ switch (cmd->cmd) { ++ case OMX_CommandFlush: ++ if (port->flush) ++ r = port->flush(comp, port); ++ break; ++ case OMX_CommandPortEnable: ++ port->def.bEnabled = OMX_TRUE; ++ r = __gomx_port_populate(comp, port); ++ if (r != OMX_ErrorNone) ++ port->def.bEnabled = OMX_FALSE; ++ break; ++ case OMX_CommandPortDisable: ++ port->def.bEnabled = OMX_FALSE; ++ r = __gomx_port_unpopulate(comp, port); ++ break; ++ default: ++ r = OMX_ErrorNotImplemented; ++ break; ++ } ++ return r; ++} ++ ++static OMX_ERRORTYPE gomx_do_command(GOMX_COMPONENT *comp, GOMX_COMMAND *cmd) ++{ ++ GOMX_PORT *port; ++ ++ switch (cmd->cmd) { ++ case OMX_CommandStateSet: ++ CINFO(comp, 0, "state %x", cmd->param); ++ return gomx_do_set_state(comp, cmd); ++ case OMX_CommandFlush: ++ case OMX_CommandPortEnable: ++ case OMX_CommandPortDisable: ++ /* FIXME: OMX_ALL is not supported (but not used in omxplayer) */ ++ if (!(port = gomx_get_port(comp, cmd->param))) ++ return OMX_ErrorBadPortIndex; ++ CINFO(comp, port, "command %x", cmd->cmd); ++ return gomx_do_port_command(comp, port, cmd); ++ case OMX_CommandMarkBuffer: ++ /* FIXME: Not implemented (but not used in omxplayer) */ ++ default: ++ CINFO(comp, 0, "UNSUPPORTED %x, %x, %p", cmd->cmd, cmd->param, cmd->data); ++ return OMX_ErrorNotImplemented; ++ } ++} ++ ++static void *gomx_worker(void *ptr) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) ptr; ++ GOMX_PORT *port; ++ GOMX_COMMAND *cmd; ++ OMX_BUFFERHEADERTYPE *hdr; ++ OMX_ERRORTYPE r; ++ ++ CINFO(comp, 0, "start"); ++ pthread_mutex_lock(&comp->mutex); ++ while (comp->state != OMX_StateInvalid) { ++ cmd = (GOMX_COMMAND *) gomxq_dequeue(&comp->cmdq); ++ if (cmd) { ++ r = gomx_do_command(comp, cmd); ++ if (r == OMX_ErrorNone) ++ __gomx_event(comp, OMX_EventCmdComplete, ++ cmd->cmd, cmd->param, cmd->data); ++ else ++ __gomx_event(comp, OMX_EventError, r, 0, 0); ++ } else { ++ pthread_cond_wait(&comp->cond, &comp->mutex); ++ } ++ ++ if (comp->state != OMX_StateExecuting) ++ continue; ++ ++ /* FIXME: Rate limit and retry if needed suppplier buffer enqueuing */ ++ for (size_t i = 0; i < comp->nports; i++) { ++ port = &comp->ports[i]; ++ while ((hdr = (OMX_BUFFERHEADERTYPE*)gomxq_dequeue(&port->tunnel_supplierq)) != 0) { ++ pthread_mutex_unlock(&comp->mutex); ++ r = OMX_FillThisBuffer(port->tunnel_comp, hdr); ++ pthread_mutex_lock(&comp->mutex); ++ if (r != OMX_ErrorNone) { ++ __gomx_port_queue_supplier_buffer(port, hdr); ++ break; ++ } ++ } ++ } ++ } ++ pthread_mutex_unlock(&comp->mutex); ++ /* FIXME: make sure all buffers are returned and worker threads stopped */ ++ CINFO(comp, 0, "stop"); ++ return 0; ++} ++ ++static OMX_ERRORTYPE gomx_set_callbacks(OMX_HANDLETYPE hComponent, OMX_CALLBACKTYPE* pCallbacks, OMX_PTR pAppData) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ if (comp->state != OMX_StateLoaded) return OMX_ErrorIncorrectStateOperation; ++ pthread_mutex_lock(&comp->mutex); ++ comp->omx.pApplicationPrivate = pAppData; ++ comp->cb = *pCallbacks; ++ pthread_mutex_unlock(&comp->mutex); ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE gomx_use_egl_image(OMX_HANDLETYPE hComponent, ++ OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, ++ OMX_PTR pAppPrivate, void* eglImage) ++{ ++ return OMX_ErrorNotImplemented; +} + -+/** Dequeue an element from the given queue descriptor -+ * -+ * @param queue the queue descriptor from which to dequeue the element -+ * -+ * @return the element that has bee dequeued. If the queue is empty -+ * a NULL value is returned -+ */ -+void* omx_dequeue(omx_queue_t* queue) { -+ void* data; -+ if (queue->first->data == NULL) { -+ DEBUG(DEB_LEV_ERR, "In %s ERROR! Empty queue\n",__func__); -+ return NULL; -+ } -+ pthread_mutex_lock(&queue->mutex); -+ data = queue->first->data; -+ queue->first->data = NULL; -+ queue->first = queue->first->q_forw; -+ queue->nelem--; -+ pthread_mutex_unlock(&queue->mutex); -+ -+ return data; ++static OMX_ERRORTYPE gomx_component_role_enum(OMX_HANDLETYPE hComponent, OMX_U8 *cRole, OMX_U32 nIndex) ++{ ++ return OMX_ErrorNotImplemented; +} + -+/** Returns the number of elements hold in the queue -+ * -+ * @param queue the requested queue -+ * -+ * @return the number of elements in the queue -+ */ -+int omx_getquenelem(omx_queue_t* queue) { -+ int qelem; -+ pthread_mutex_lock(&queue->mutex); -+ qelem = queue->nelem; -+ pthread_mutex_unlock(&queue->mutex); -+ return qelem; ++static void gomx_init(GOMX_COMPONENT *comp, const char *name, OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallbacks, GOMX_PORT *ports, size_t nports) ++{ ++ comp->omx.nSize = sizeof comp->omx; ++ comp->omx.nVersion.nVersion = OMX_VERSION; ++ comp->omx.pApplicationPrivate = pAppData; ++ comp->omx.GetComponentVersion = gomx_get_component_version; ++ comp->omx.SendCommand = gomx_send_command; ++ comp->omx.GetParameter = gomx_get_parameter; ++ comp->omx.GetState = gomx_get_state; ++ comp->omx.ComponentTunnelRequest = gomx_component_tunnel_request; ++ comp->omx.UseBuffer = gomx_use_buffer; ++ comp->omx.AllocateBuffer = gomx_allocate_buffer; ++ comp->omx.FreeBuffer = gomx_free_buffer; ++ comp->omx.EmptyThisBuffer = gomx_empty_this_buffer; ++ comp->omx.FillThisBuffer = gomx_fill_this_buffer; ++ comp->omx.SetCallbacks = gomx_set_callbacks; ++ comp->omx.UseEGLImage = gomx_use_egl_image; ++ comp->omx.ComponentRoleEnum = gomx_component_role_enum; ++ ++ comp->name = name; ++ comp->cb = *pCallbacks; ++ comp->state = OMX_StateLoaded; ++ comp->nports = nports; ++ comp->ports = ports; ++ ++ gomxq_init(&comp->cmdq, offsetof(GOMX_COMMAND, next)); ++ pthread_cond_init(&comp->cond, 0); ++ pthread_mutex_init(&comp->mutex, 0); ++ pthread_create(&comp->component_thread, 0, gomx_worker, comp); ++ ++ for (size_t i = 0; i < comp->nports; i++) { ++ GOMX_PORT *port = &comp->ports[i]; ++ pthread_cond_init(&port->cond_no_buffers, 0); ++ pthread_cond_init(&port->cond_populated, 0); ++ pthread_cond_init(&port->cond_idle, 0); ++ gomxq_init(&port->tunnel_supplierq, ++ port->def.eDir == OMX_DirInput ++ ? offsetof(OMX_BUFFERHEADERTYPE, pInputPortPrivate) ++ : offsetof(OMX_BUFFERHEADERTYPE, pOutputPortPrivate)); ++ } ++} ++ ++static void gomx_fini(GOMX_COMPONENT *comp) ++{ ++ CINFO(comp, 0, "destroying"); ++ pthread_mutex_lock(&comp->mutex); ++ comp->state = OMX_StateInvalid; ++ pthread_cond_broadcast(&comp->cond); ++ pthread_mutex_unlock(&comp->mutex); ++ pthread_join(comp->component_thread, 0); ++ ++ for (size_t i = 0; i < comp->nports; i++) { ++ GOMX_PORT *port = &comp->ports[i]; ++ pthread_cond_destroy(&port->cond_no_buffers); ++ pthread_cond_destroy(&port->cond_populated); ++ pthread_cond_destroy(&port->cond_idle); ++ } ++ pthread_mutex_destroy(&comp->mutex); ++ pthread_cond_destroy(&comp->cond); ++} ++ ++/* ALSA Sink OMX Component */ ++ ++#define OMXALSA_PORT_AUDIO 0 ++#define OMXALSA_PORT_CLOCK 1 ++ ++typedef struct _OMX_ALSASINK { ++ GOMX_COMPONENT gcomp; ++ GOMX_PORT port_data[2]; ++ GOMX_QUEUE playq; ++ pthread_cond_t cond_play; ++ size_t frame_size, sample_rate, play_queue_size; ++ int64_t starttime, timescale; ++ OMX_AUDIO_PARAM_PCMMODETYPE pcm; ++ snd_pcm_format_t pcm_format; ++ char device_name[16]; ++} OMX_ALSASINK; ++ ++static OMX_ERRORTYPE omxalsasink_set_parameter(OMX_HANDLETYPE hComponent, OMX_INDEXTYPE nParamIndex, OMX_PTR pComponentParameterStructure) ++{ ++ static const struct { ++ snd_pcm_format_t fmt; ++ unsigned char pcm_mode; ++ unsigned char bits_per_sample; ++ unsigned char numerical_data; ++ unsigned char endianess; ++ } fmtmap[] = { ++ { SND_PCM_FORMAT_S8, OMX_AUDIO_PCMModeLinear, 8, OMX_NumericalDataSigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_U8, OMX_AUDIO_PCMModeLinear, 8, OMX_NumericalDataUnsigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_S16_LE, OMX_AUDIO_PCMModeLinear, 16, OMX_NumericalDataSigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_U16_LE, OMX_AUDIO_PCMModeLinear, 16, OMX_NumericalDataUnsigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_S16_BE, OMX_AUDIO_PCMModeLinear, 16, OMX_NumericalDataSigned, OMX_EndianBig }, ++ { SND_PCM_FORMAT_U16_BE, OMX_AUDIO_PCMModeLinear, 16, OMX_NumericalDataUnsigned, OMX_EndianBig }, ++ { SND_PCM_FORMAT_S24_LE, OMX_AUDIO_PCMModeLinear, 24, OMX_NumericalDataSigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_U24_LE, OMX_AUDIO_PCMModeLinear, 24, OMX_NumericalDataUnsigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_S24_BE, OMX_AUDIO_PCMModeLinear, 24, OMX_NumericalDataSigned, OMX_EndianBig }, ++ { SND_PCM_FORMAT_U24_BE, OMX_AUDIO_PCMModeLinear, 24, OMX_NumericalDataUnsigned, OMX_EndianBig }, ++ { SND_PCM_FORMAT_S32_LE, OMX_AUDIO_PCMModeLinear, 32, OMX_NumericalDataSigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_U32_LE, OMX_AUDIO_PCMModeLinear, 32, OMX_NumericalDataUnsigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_S32_BE, OMX_AUDIO_PCMModeLinear, 32, OMX_NumericalDataSigned, OMX_EndianBig }, ++ { SND_PCM_FORMAT_U32_BE, OMX_AUDIO_PCMModeLinear, 32, OMX_NumericalDataUnsigned, OMX_EndianBig }, ++ { SND_PCM_FORMAT_A_LAW, OMX_AUDIO_PCMModeALaw, 8, OMX_NumericalDataUnsigned, OMX_EndianLittle }, ++ { SND_PCM_FORMAT_MU_LAW, OMX_AUDIO_PCMModeMULaw, 8, OMX_NumericalDataUnsigned, OMX_EndianLittle }, ++ }; ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) hComponent; ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ GOMX_PORT *port; ++ OMX_AUDIO_PARAM_PCMMODETYPE *pmt; ++ OMX_ERRORTYPE r; ++ snd_pcm_format_t pcm_format = SND_PCM_FORMAT_UNKNOWN; ++ ++ /* Valid in OMX_StateLoaded or on disabled port... so can't check ++ * state without port number which is in index specific struct. */ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ ++ switch (nParamIndex) { ++ case OMX_IndexParamAudioPcm: ++ if ((r = omx_cast(pmt, pComponentParameterStructure))) return r; ++ if (!(port = gomx_get_port(comp, pmt->nPortIndex))) return OMX_ErrorBadPortIndex; ++ if (pmt->nPortIndex != OMXALSA_PORT_AUDIO) return OMX_ErrorBadParameter; ++ ++ if (comp->state != OMX_StateLoaded && port->def.bEnabled) ++ return OMX_ErrorIncorrectStateOperation; ++ ++ for (size_t i = 0; i < ARRAY_SIZE(fmtmap); i++) { ++ if (fmtmap[i].pcm_mode == pmt->ePCMMode && ++ fmtmap[i].bits_per_sample == pmt->nBitPerSample && ++ fmtmap[i].numerical_data == pmt->eNumData && ++ fmtmap[i].endianess == pmt->eEndian) { ++ pcm_format = fmtmap[i].fmt; ++ break; ++ } ++ } ++ if (pcm_format == SND_PCM_FORMAT_UNKNOWN) ++ return OMX_ErrorBadParameter; ++ ++ memcpy(&sink->pcm, pmt, sizeof *pmt); ++ sink->pcm_format = pcm_format; ++ break; ++ default: ++ CINFO(comp, 0, "UNSUPPORTED %x, %p", nParamIndex, pComponentParameterStructure); ++ return OMX_ErrorNotImplemented; ++ } ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE omxalsasink_get_config(OMX_HANDLETYPE hComponent, OMX_INDEXTYPE nIndex, OMX_PTR pComponentConfigStructure) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) hComponent; ++ OMX_PARAM_U32TYPE *u32param; ++ OMX_ERRORTYPE r; ++ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ ++ switch (nIndex) { ++ case OMX_IndexConfigAudioRenderingLatency: ++ if ((r = omx_cast(u32param, pComponentConfigStructure))) return r; ++ /* Number of samples received but not played */ ++ pthread_mutex_lock(&comp->mutex); ++ if (sink->frame_size) ++ u32param->nU32 = sink->play_queue_size / sink->frame_size; ++ else ++ u32param->nU32 = 0; ++ pthread_mutex_unlock(&comp->mutex); ++ CDEBUG(comp, 0, "OMX_IndexConfigAudioRenderingLatency %d", u32param->nU32); ++ break; ++ default: ++ CINFO(comp, 0, "UNSUPPORTED %x, %p", nIndex, pComponentConfigStructure); ++ return OMX_ErrorNotImplemented; ++ } ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE omxalsasink_set_config(OMX_HANDLETYPE hComponent, OMX_INDEXTYPE nIndex, OMX_PTR pComponentConfigStructure) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT*) hComponent; ++ OMX_ALSASINK *sink = (OMX_ALSASINK*) hComponent; ++ OMX_CONFIG_BOOLEANTYPE *bt; ++ OMX_CONFIG_BRCMAUDIODESTINATIONTYPE *adest; ++ OMX_ERRORTYPE r; ++ ++ if (comp->state == OMX_StateInvalid) return OMX_ErrorInvalidState; ++ ++ switch (nIndex) { ++ case OMX_IndexConfigBrcmClockReferenceSource: ++ if ((r = omx_cast(bt, pComponentConfigStructure))) return r; ++ CDEBUG(comp, 0, "OMX_IndexConfigBrcmClockReferenceSource %d", bt->bEnabled); ++ break; ++ case OMX_IndexConfigBrcmAudioDestination: ++ if ((r = omx_cast(adest, pComponentConfigStructure))) return r; ++ strlcpy(sink->device_name, (const char*) adest->sName, sizeof sink->device_name); ++ CDEBUG(comp, 0, "OMX_IndexConfigBrcmAudioDestination %s", adest->sName); ++ break; ++ default: ++ CINFO(comp, 0, "UNSUPPORTED %x, %p", nIndex, pComponentConfigStructure); ++ return OMX_ErrorNotImplemented; ++ } ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE omxalsasink_get_extension_index(OMX_HANDLETYPE hComponent, OMX_STRING cParameterName, OMX_INDEXTYPE *pIndexType) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) hComponent; ++ CINFO(comp, 0, "UNSUPPORTED '%s', %p", cParameterName, pIndexType); ++ return OMX_ErrorNotImplemented; +} -diff --git a/alsa/omx_queue.h b/alsa/omx_queue.h -new file mode 100644 -index 0000000..bf80f90 ---- /dev/null -+++ b/alsa/omx_queue.h -@@ -0,0 +1,94 @@ -+/** -+ @file src/omx_queue.h -+ -+ Implements a simple LIFO structure used for queueing OMX buffers. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ -+ Revision $Rev: 554 $ -+ Author $Author: pankaj_sen $ -+*/ -+ -+#pragma once -+ -+#ifndef __OMX_QUEUE_H__ -+#define __OMX_QUEUE_H__ -+ -+#include <pthread.h> -+/** Maximum number of elements in a queue -+ */ -+#define MAX_QUEUE_ELEMENTS 20 -+/** Output port queue element. Contains an OMX buffer header type -+ */ -+typedef struct omx_qelem_t omx_qelem_t; -+struct omx_qelem_t{ -+ omx_qelem_t* q_forw; -+ void* data; -+}; -+ -+/** This structure contains the queue -+ */ -+typedef struct omx_queue_t{ -+ omx_qelem_t* first; /**< Output buffer queue head */ -+ omx_qelem_t* last; /**< Output buffer queue tail */ -+ int nelem; /**< Number of elements in the queue */ -+ pthread_mutex_t mutex; -+} omx_queue_t; -+ -+/** Initialize a queue descriptor -+ * -+ * @param queue The queue descriptor to initialize. -+ * The user needs to allocate the queue -+ */ -+void omx_queue_init(omx_queue_t* queue); -+ -+/** Deinitialize a queue descriptor -+ * flushing all of its internal data -+ * -+ * @param queue the queue descriptor to dump -+ */ -+void omx_queue_deinit(omx_queue_t* queue); + -+/** Enqueue an element to the given queue descriptor -+ * -+ * @param queue the queue descritpor where to queue data -+ * -+ * @param data the data to be enqueued -+ */ -+void omx_queue(omx_queue_t* queue, void* data); -+ -+/** Dequeue an element from the given queue descriptor -+ * -+ * @param queue the queue descriptor from which to dequeue the element -+ * -+ * @return the element that has bee dequeued. If the queue is empty -+ * a NULL value is returned -+ */ -+void* omx_dequeue(omx_queue_t* queue); -+ -+/** Returns the number of elements hold in the queue -+ * -+ * @param queue the requested queue -+ * -+ * @return the number of elements in the queue -+ */ -+int omx_getquenelem(omx_queue_t* queue); -+ -+#endif -diff --git a/alsa/omx_semaphore.cpp b/alsa/omx_semaphore.cpp -new file mode 100644 -index 0000000..eca3a0f ---- /dev/null -+++ b/alsa/omx_semaphore.cpp -@@ -0,0 +1,111 @@ -+/** -+ @file src/tsemaphore.c -+ -+ Implements a simple inter-thread semaphore so not to have to deal with IPC -+ creation and the like. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ -+ Revision $Rev: 554 $ -+ Author $Author: pankaj_sen $ -+*/ -+ -+#include <pthread.h> -+#include <sys/time.h> -+#include <errno.h> -+#include "omx_semaphore.h" -+//#include "omx_comp_debug_levels.h" -+ -+/** Initializes the semaphore at a given value -+ * -+ * @param tsem the semaphore to initialize -+ * @param val the initial value of the semaphore -+ * -+ */ -+void omx_tsem_init(omx_tsem_t* tsem, unsigned int val) { -+ pthread_cond_init(&tsem->condition, NULL); -+ pthread_mutex_init(&tsem->mutex, NULL); -+ tsem->semval = val; ++static OMX_ERRORTYPE omxalsasink_deinit(OMX_HANDLETYPE hComponent) ++{ ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) hComponent; ++ gomx_fini(&sink->gcomp); ++ free(sink); ++ return OMX_ErrorNone; +} + -+/** Destroy the semaphore -+ * -+ * @param tsem the semaphore to destroy -+ */ -+void omx_tsem_deinit(omx_tsem_t* tsem) { -+ pthread_cond_destroy(&tsem->condition); -+ pthread_mutex_destroy(&tsem->mutex); ++static void *omxalsasink_worker(void *ptr) ++{ ++ GOMX_COMPONENT *comp = (GOMX_COMPONENT *) ptr; ++ OMX_HANDLETYPE hComponent = (OMX_HANDLETYPE) comp; ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) hComponent; ++ OMX_BUFFERHEADERTYPE *buf; ++ GOMX_PORT *clock_port = &comp->ports[OMXALSA_PORT_CLOCK]; ++ snd_pcm_t *dev; ++ snd_pcm_sframes_t n; ++ snd_pcm_hw_params_t *hwp; ++ snd_pcm_uframes_t buffer_size, period_size, period_size_max; ++ unsigned int rate; ++ int err; ++ ++ CINFO(comp, 0, "worker started"); ++ ++ err = snd_pcm_open(&dev, sink->device_name, SND_PCM_STREAM_PLAYBACK, 0); ++ if (err < 0) goto alsa_error; ++ ++ rate = sink->pcm.nSamplingRate; ++ buffer_size = rate / 5; ++ period_size = buffer_size / 4; ++ period_size_max = buffer_size / 3; ++ ++ snd_pcm_hw_params_alloca(&hwp); ++ snd_pcm_hw_params_any(dev, hwp); ++ err = snd_pcm_hw_params_set_channels(dev, hwp, sink->pcm.nChannels); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params_set_access(dev, hwp, sink->pcm.bInterleaved ? SND_PCM_ACCESS_RW_INTERLEAVED : SND_PCM_ACCESS_RW_NONINTERLEAVED); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params_set_rate_near(dev, hwp, &rate, 0); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params_set_format(dev, hwp, sink->pcm_format); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params_set_period_size_max(dev, hwp, &period_size_max, 0); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params_set_buffer_size_near(dev, hwp, &buffer_size); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params_set_period_size_near(dev, hwp, &period_size, 0); ++ if (err) goto alsa_error; ++ err = snd_pcm_hw_params(dev, hwp); ++ if (err) goto alsa_error; ++ ++ err = snd_pcm_prepare(dev); ++ if (err < 0) goto alsa_error; ++ ++ sink->pcm.nSamplingRate = rate; ++ sink->frame_size = (sink->pcm.nChannels * sink->pcm.nBitPerSample) >> 3; ++ sink->sample_rate = rate; ++ ++ CINFO(comp, 0, "sample_rate %d, frame_size %d", rate, sink->frame_size); ++ ++ pthread_mutex_lock(&comp->mutex); ++ while (comp->wanted_state == OMX_StateExecuting) { ++ buf = (OMX_BUFFERHEADERTYPE*) gomxq_peek(&sink->playq); ++ if (!buf || sink->timescale == 0) { ++ pthread_cond_wait(&sink->cond_play, &comp->mutex); ++ continue; ++ } ++ ++ pthread_mutex_unlock(&comp->mutex); ++ if (buf->nOffset == 0 && clock_port->tunnel_comp && ++ !(buf->nFlags & OMX_BUFFERFLAG_TIME_UNKNOWN)) { ++ OMX_TIME_CONFIG_TIMESTAMPTYPE tst; ++ int64_t pts = omx_ticks_to_s64(buf->nTimeStamp); ++ snd_pcm_sframes_t delay = 0; ++ ++ omx_init(tst); ++ tst.nPortIndex = clock_port->tunnel_port; ++ tst.nTimestamp = buf->nTimeStamp; ++ ++ if (buf->nFlags & (OMX_BUFFERFLAG_STARTTIME|OMX_BUFFERFLAG_DISCONTINUITY)) { ++ OMX_SetConfig(clock_port->tunnel_comp, OMX_IndexConfigTimeClientStartTime, &tst); ++ sink->starttime = pts; ++ CINFO(comp, 0, "STARTTIME nTimeStamp=%llx", pts); ++ } ++ snd_pcm_delay(dev, &delay); ++ pts -= (int64_t)delay * OMX_TICKS_PER_SECOND / sink->sample_rate; ++ if (pts >= sink->starttime) { ++ tst.nTimestamp = omx_ticks_from_s64(pts); ++ OMX_SetConfig(clock_port->tunnel_comp, OMX_IndexConfigTimeCurrentAudioReference, &tst); ++ } ++ } ++ ++ n = 0; ++ if (buf->nFlags & (OMX_BUFFERFLAG_DECODEONLY|OMX_BUFFERFLAG_CODECCONFIG|OMX_BUFFERFLAG_DATACORRUPT)) { ++ CDEBUG(comp, 0, "skipping: %d bytes, flags %x", buf->nFilledLen, buf->nFlags); ++ n = buf->nFilledLen; ++ } else if (buf->nFilledLen) { ++ n = snd_pcm_writei(dev, buf->pBuffer + buf->nOffset, buf->nFilledLen / sink->frame_size); ++ if (n < 0) { ++ if (n != -EPIPE) { ++ CINFO(comp, 0, "alsa error: %ld", n); ++ pthread_mutex_lock(&comp->mutex); ++ break; ++ } ++ CINFO(comp, 0, "underrun"); ++ snd_pcm_prepare(dev); ++ n = 0; ++ } ++ n *= sink->frame_size; ++ } ++ pthread_mutex_lock(&comp->mutex); ++ ++ buf->nOffset += n; ++ buf->nFilledLen -= n; ++ sink->play_queue_size -= n; ++ ++ if (!buf->nFilledLen) { ++ __gomx_process_mark(comp, buf); ++ if (buf->nFlags & OMX_BUFFERFLAG_EOS) { ++ CDEBUG(comp, 0, "end-of-stream"); ++ __gomx_event(comp, OMX_EventBufferFlag, OMXALSA_PORT_AUDIO, buf->nFlags, 0); ++ } ++ if (gomxq_peek(&sink->playq) == (void*) buf) { ++ buf = (OMX_BUFFERHEADERTYPE*) gomxq_dequeue(&sink->playq); ++ __gomx_empty_buffer_done(comp, buf); ++ } ++ } ++ } ++ pthread_mutex_unlock(&comp->mutex); ++cleanup: ++ if (dev) snd_pcm_close(dev); ++ CINFO(comp, 0, "worker stopped"); ++ return 0; ++ ++alsa_error: ++ CINFO(comp, 0, "ALSA error: %s", snd_strerror(err)); ++ pthread_mutex_lock(&comp->mutex); ++ /* FIXME: Current we just go to invalid state, but we might go ++ * back to Idle with ErrorResourcesPreempted and let the client ++ * recover. However, omxplayer does not care about this. */ ++ comp->state = OMX_StateInvalid; ++ __gomx_event(comp, OMX_EventError, OMX_StateInvalid, 0, 0); ++ pthread_mutex_unlock(&comp->mutex); ++ goto cleanup; ++} ++ ++static OMX_ERRORTYPE omxalsasink_audio_do_buffer(GOMX_COMPONENT *comp, GOMX_PORT *port, OMX_BUFFERHEADERTYPE *buf) ++{ ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) comp; ++ gomxq_enqueue(&sink->playq, (void *) buf); ++ sink->play_queue_size += buf->nFilledLen; ++ pthread_cond_signal(&sink->cond_play); ++ return OMX_ErrorNone; +} + -+/** Decreases the value of the semaphore. Blocks if the semaphore -+ * value is zero. -+ * -+ * @param tsem the semaphore to decrease -+ */ -+void omx_tsem_down(omx_tsem_t* tsem) { -+ pthread_mutex_lock(&tsem->mutex); -+ while (tsem->semval == 0) { -+ pthread_cond_wait(&tsem->condition, &tsem->mutex); -+ } -+ tsem->semval--; -+ pthread_mutex_unlock(&tsem->mutex); ++static OMX_ERRORTYPE omxalsasink_audio_flush(GOMX_COMPONENT *comp, GOMX_PORT *port) ++{ ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) comp; ++ OMX_BUFFERHEADERTYPE *buf; ++ while ((buf = (OMX_BUFFERHEADERTYPE *) gomxq_dequeue(&sink->playq)) != 0) { ++ __gomx_empty_buffer_done(comp, buf); ++ sink->play_queue_size -= buf->nFilledLen; ++ } ++ return OMX_ErrorNone; +} + -+/** Increases the value of the semaphore -+ * -+ * @param tsem the semaphore to increase -+ */ -+void omx_tsem_up(omx_tsem_t* tsem) { -+ pthread_mutex_lock(&tsem->mutex); -+ tsem->semval++; -+ pthread_cond_signal(&tsem->condition); -+ pthread_mutex_unlock(&tsem->mutex); ++static OMX_ERRORTYPE omxalsasink_clock_do_buffer(GOMX_COMPONENT *comp, GOMX_PORT *port, OMX_BUFFERHEADERTYPE *buf) ++{ ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) comp; ++ OMX_TIME_MEDIATIMETYPE *pMediaTime; ++ int wake = 0; ++ ++ if (omx_cast(pMediaTime, buf->pBuffer) == OMX_ErrorNone) { ++ CDEBUG(comp, port, "%p: clock %u bytes, flags=%x, nTimeStamp=%llx, eState=%d, xScale=%x", ++ buf, buf->nFilledLen, buf->nFlags, omx_ticks_to_s64(buf->nTimeStamp), ++ pMediaTime->eState, pMediaTime->xScale); ++ wake = (!sink->timescale && pMediaTime->xScale); ++ sink->timescale = pMediaTime->xScale; ++ } else { ++ CDEBUG(comp, port, "%p: clock %u bytes, flags=%x, nTimeStamp=%llx", ++ buf, buf->nFilledLen, buf->nFlags, omx_ticks_to_s64(buf->nTimeStamp)); ++ } ++ __gomx_process_mark(comp, buf); ++ __gomx_empty_buffer_done(comp, buf); ++ if (wake) pthread_cond_signal(&sink->cond_play); ++ ++ return OMX_ErrorNone; ++} ++ ++static OMX_ERRORTYPE omxalsasink_statechange(GOMX_COMPONENT *comp) ++{ ++ OMX_ALSASINK *sink = (OMX_ALSASINK *) comp; ++ pthread_cond_signal(&sink->cond_play); ++ return OMX_ErrorNone; +} + -+/** Reset the value of the semaphore -+ * -+ * @param tsem the semaphore to reset -+ */ -+void omx_tsem_reset(omx_tsem_t* tsem) { -+ pthread_mutex_lock(&tsem->mutex); -+ tsem->semval=0; -+ pthread_mutex_unlock(&tsem->mutex); -+} ++static OMX_ERRORTYPE omxalsasink_create(OMX_HANDLETYPE *pHandle, OMX_PTR pAppData, OMX_CALLBACKTYPE *pCallbacks) ++{ ++ OMX_ALSASINK *sink; ++ GOMX_PORT *port; ++ ++ sink = (OMX_ALSASINK *) calloc(1, sizeof *sink); ++ if (!sink) return OMX_ErrorInsufficientResources; ++ ++ strlcpy(sink->device_name, "default", sizeof sink->device_name); ++ gomxq_init(&sink->playq, offsetof(OMX_BUFFERHEADERTYPE, pInputPortPrivate)); ++ ++ /* Audio port */ ++ port = &sink->port_data[OMXALSA_PORT_AUDIO]; ++ port->def.nSize = sizeof *port; ++ port->def.nVersion.nVersion = OMX_VERSION; ++ port->def.nPortIndex = OMXALSA_PORT_AUDIO; ++ port->def.eDir = OMX_DirInput; ++ port->def.nBufferCountMin = 4; ++ port->def.nBufferCountActual = 4; ++ port->def.nBufferSize = 8 * 1024; ++ port->def.bEnabled = OMX_TRUE; ++ port->def.eDomain = OMX_PortDomainAudio; ++ port->def.format.audio.cMIMEType = (char *) "raw/audio"; ++ port->def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; ++ port->def.nBufferAlignment = 4; ++ port->do_buffer = omxalsasink_audio_do_buffer; ++ port->flush = omxalsasink_audio_flush; ++ ++ /* Clock port */ ++ port = &sink->port_data[OMXALSA_PORT_CLOCK]; ++ port->def.nSize = sizeof *port; ++ port->def.nVersion.nVersion = OMX_VERSION; ++ port->def.nPortIndex = OMXALSA_PORT_CLOCK; ++ port->def.eDir = OMX_DirInput; ++ port->def.nBufferCountMin = 1; ++ port->def.nBufferCountActual = 1; ++ port->def.nBufferSize = sizeof(OMX_TIME_MEDIATIMETYPE); ++ port->def.bEnabled = OMX_TRUE; ++ port->def.eDomain = OMX_PortDomainOther; ++ port->def.format.other.eFormat = OMX_OTHER_FormatTime; ++ port->def.nBufferAlignment = 4; ++ port->do_buffer = omxalsasink_clock_do_buffer; ++ ++ gomx_init(&sink->gcomp, "OMX.alsa.audio_render", pAppData, pCallbacks, sink->port_data, ARRAY_SIZE(sink->port_data)); ++ sink->gcomp.omx.SetParameter = omxalsasink_set_parameter; ++ sink->gcomp.omx.GetConfig = omxalsasink_get_config; ++ sink->gcomp.omx.SetConfig = omxalsasink_set_config; ++ sink->gcomp.omx.GetExtensionIndex = omxalsasink_get_extension_index; ++ sink->gcomp.omx.ComponentDeInit = omxalsasink_deinit; ++ sink->gcomp.worker = omxalsasink_worker; ++ sink->gcomp.statechange = omxalsasink_statechange; ++ pthread_cond_init(&sink->cond_play, 0); ++ ++ *pHandle = (OMX_HANDLETYPE) sink; ++ return OMX_ErrorNone; ++} ++ ++/* OMX Glue to get the handle */ ++ ++#include <OMXAlsa.h> ++ ++OMX_ERRORTYPE OMXALSA_GetHandle(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_STRING cComponentName, ++ OMX_IN OMX_PTR pAppData, OMX_IN OMX_CALLBACKTYPE* pCallbacks) ++{ ++ if (strcmp(cComponentName, "OMX.alsa.audio_render") == 0) ++ return omxalsasink_create(pHandle, pAppData, pCallbacks); + -+/** Wait on the condition. -+ * -+ * @param tsem the semaphore to wait -+ */ -+void omx_tsem_wait(omx_tsem_t* tsem) { -+ pthread_mutex_lock(&tsem->mutex); -+ pthread_cond_wait(&tsem->condition, &tsem->mutex); -+ pthread_mutex_unlock(&tsem->mutex); ++ return OMX_ErrorComponentNotFound; +} + -+/** Signal the condition,if waiting -+ * -+ * @param tsem the semaphore to signal -+ */ -+void omx_tsem_signal(omx_tsem_t* tsem) { -+ pthread_mutex_lock(&tsem->mutex); -+ pthread_cond_signal(&tsem->condition); -+ pthread_mutex_unlock(&tsem->mutex); ++OMX_ERRORTYPE OMXALSA_FreeHandle(OMX_IN OMX_HANDLETYPE hComponent) ++{ ++ return ((OMX_COMPONENTTYPE*)hComponent)->ComponentDeInit(hComponent); +} -+ -diff --git a/alsa/omx_semaphore.h b/alsa/omx_semaphore.h +diff --git a/linux/OMXAlsa.h b/linux/OMXAlsa.h new file mode 100644 -index 0000000..1e3f3db +index 0000000..b849288 --- /dev/null -+++ b/alsa/omx_semaphore.h -@@ -0,0 +1,92 @@ -+/** -+ @file src/omx_semaphore.h -+ -+ Implements a simple inter-thread semaphore so not to have to deal with IPC -+ creation and the like. -+ -+ Copyright (C) 2007-2008 STMicroelectronics -+ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). -+ -+ This library is free software; you can redistribute it and/or modify it under -+ the terms of the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 2.1 of the License, or (at your option) -+ any later version. -+ -+ This library is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -+ details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this library; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St, Fifth Floor, Boston, MA -+ 02110-1301 USA -+ -+ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ -+ Revision $Rev: 554 $ -+ Author $Author: pankaj_sen $ -+ -+*/ -+ ++++ b/linux/OMXAlsa.h +@@ -0,0 +1,11 @@ +#pragma once ++#include <IL/OMX_Core.h> + -+#ifndef __OMX_SEMAPHORE_H__ -+#define __OMX_SEMAPHORE_H__ -+ -+#include <pthread.h> -+#include <semaphore.h> -+ -+/** The structure contains the semaphore value, mutex and green light flag -+ */ -+typedef struct omx_tsem_t { -+ pthread_cond_t condition; -+ pthread_mutex_t mutex; -+ unsigned int semval; -+} omx_tsem_t; -+ -+/** Initializes the semaphore at a given value -+ * -+ * @param tsem the semaphore to initialize -+ * -+ * @param val the initial value of the semaphore -+ */ -+void omx_tsem_init(omx_tsem_t* tsem, unsigned int val); -+ -+/** Destroy the semaphore -+ * -+ * @param tsem the semaphore to destroy -+ */ -+void omx_tsem_deinit(omx_tsem_t* tsem); -+ -+/** Decreases the value of the semaphore. Blocks if the semaphore -+ * value is zero. -+ * -+ * @param tsem the semaphore to decrease -+ */ -+void omx_tsem_down(omx_tsem_t* tsem); -+ -+/** Increases the value of the semaphore -+ * -+ * @param tsem the semaphore to increase -+ */ -+void omx_tsem_up(omx_tsem_t* tsem); -+ -+/** Reset the value of the semaphore -+ * -+ * @param tsem the semaphore to reset -+ */ -+void omx_tsem_reset(omx_tsem_t* tsem); -+ -+/** Wait on the condition. -+ * -+ * @param tsem the semaphore to wait -+ */ -+void omx_tsem_wait(omx_tsem_t* tsem); -+ -+/** Signal the condition,if waiting -+ * -+ * @param tsem the semaphore to signal -+ */ -+void omx_tsem_signal(omx_tsem_t* tsem); ++OMX_API OMX_ERRORTYPE OMX_APIENTRY OMXALSA_GetHandle( ++ OMX_OUT OMX_HANDLETYPE* pHandle, ++ OMX_IN OMX_STRING cComponentName, ++ OMX_IN OMX_PTR pAppData, ++ OMX_IN OMX_CALLBACKTYPE* pCallBacks); + -+#endif ++OMX_API OMX_ERRORTYPE OMX_APIENTRY OMXALSA_FreeHandle( ++ OMX_IN OMX_HANDLETYPE hComponent); diff --git a/omxplayer.cpp b/omxplayer.cpp -index b554a58..3e5b99b 100644 +index 3b5e6d2..4032ba3 100644 --- a/omxplayer.cpp +++ b/omxplayer.cpp -@@ -699,7 +699,7 @@ int main(int argc, char *argv[]) +@@ -574,6 +574,7 @@ int main(int argc, char *argv[]) + { "keys", no_argument, NULL, 'k' }, + { "aidx", required_argument, NULL, 'n' }, + { "adev", required_argument, NULL, 'o' }, ++ { "alsa", required_argument, NULL, 'A' }, + { "stats", no_argument, NULL, 's' }, + { "passthrough", no_argument, NULL, 'p' }, + { "vol", required_argument, NULL, vol_opt }, +@@ -640,7 +641,7 @@ int main(int argc, char *argv[]) + //Build default keymap just in case the --key-config option isn't used + map<int,int> keymap = KeyConfig::buildDefaultKeymap(); + +- while ((c = getopt_long(argc, argv, "wiIhvkn:l:o:cslbpd3:Myzt:rg", longopts, NULL)) != -1) ++ while ((c = getopt_long(argc, argv, "wiIhvkn:l:o:A:cslbpd3:Myzt:rg", longopts, NULL)) != -1) + { + switch (c) + { +@@ -708,6 +709,9 @@ int main(int argc, char *argv[]) + } + m_config_audio.device = "omx:" + m_config_audio.device; break; - case 'o': - m_config_audio.device = optarg; -- if(m_config_audio.device != "local" && m_config_audio.device != "hdmi" && m_config_audio.device != "both") -+ if(m_config_audio.device != "local" && m_config_audio.device != "hdmi" && m_config_audio.device != "both" && m_config_audio.device != "alsa") - { - print_usage(); - return 0; ++ case 'A': ++ m_config_audio.alsa_device = optarg; ++ break; + case 'i': + m_dump_format = true; + m_dump_format_exit = true; +-- +2.7.1 + |