aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/omxplayer/APKBUILD8
-rw-r--r--main/omxplayer/omxplayer-alsa.patch6508
2 files changed, 6514 insertions, 2 deletions
diff --git a/main/omxplayer/APKBUILD b/main/omxplayer/APKBUILD
index 8ea504b2ee..438a2d6250 100644
--- a/main/omxplayer/APKBUILD
+++ b/main/omxplayer/APKBUILD
@@ -2,14 +2,14 @@
pkgname=omxplayer
pkgver=0.20150911
_commitid=d99bd86c9fd80ea01f98761e130d7ac9a2bb7588
-pkgrel=1
+pkgrel=2
pkgdesc="Commandline OMX player for Raspberry Pi"
url="https://github.com/popcornmix/omxplayer"
arch="armhf"
license="GPLv2"
depends="ttf-freefont"
makedepends="linux-headers raspberrypi-dev ffmpeg-dev pcre-dev
- boost-dev freetype-dev dbus-dev"
+ boost-dev freetype-dev dbus-dev alsa-lib-dev"
install=""
subpackages="$pkgname-doc $pkgname-dbg"
source="omxplayer-$pkgver.tar.gz::https://github.com/popcornmix/omxplayer/archive/$_commitid.tar.gz
@@ -17,6 +17,7 @@ source="omxplayer-$pkgver.tar.gz::https://github.com/popcornmix/omxplayer/archiv
issue-297.patch
fix-makefile.patch
default-font.patch
+ omxplayer-alsa.patch
omxplayer.initd
omxplayer.confd
@@ -62,6 +63,7 @@ a900cdded87b7df503c6599ac43bd8de issue-260.patch
4cd10bfb7e995288f4efc312acbc4252 issue-297.patch
d8f335e1dff4b34faf36c25ad2c2b881 fix-makefile.patch
9ebd96155288809fe0a657cf491e433f default-font.patch
+628a9bc0b26f75547299e92542e65d47 omxplayer-alsa.patch
b4054a311d76aef91aa10bacd68bc9c4 omxplayer.initd
80e37e7ac04402808015084e26e6072d omxplayer.confd"
sha256sums="9be32352afd9198c733b74b1a2ec9a9b73a0ee2777c79e76914df00c9c6e5115 omxplayer-0.20150911.tar.gz
@@ -69,6 +71,7 @@ sha256sums="9be32352afd9198c733b74b1a2ec9a9b73a0ee2777c79e76914df00c9c6e5115 om
75cf8af95b35bc734550c55036ef49dbff04b6940f3317b51eddea06866ecf3a issue-297.patch
799b0aba6aef8c665a685777cd912268315309d0d74ce76be5fdfd0dcffbb422 fix-makefile.patch
2bab3d05b12d730737220b8c0052498a34bbebc12b7beb8afb3c054beb0fb3bb default-font.patch
+87dc80b61ce6c69a52637dffb64f526e7fa213e4c2b0c97177457c95851ec594 omxplayer-alsa.patch
e2db0f7ffbe2488dd69ee0bfad006bd863f418554f078ca3432f643de7589d2f omxplayer.initd
530eb9aa50e72fb4828af410b965e0ec7653d1bed87aa86bf04fc340ff3232bd omxplayer.confd"
sha512sums="a552b508981ebbed8c70fc92d3556502da97902d4ed1d2c4c68670d0eba0565759ddecf4d8821697dab7388bed1d3246673e0a9ee558ee1a817c1483db3c89f3 omxplayer-0.20150911.tar.gz
@@ -76,5 +79,6 @@ c349eea5f7c513a07d82a6cf6467c4d21bcb29c053bc5e39d8f675b1212db9beef0abf5248d50ac5
606c71dc4e47bd1303ecb21bd6f265f61223f792e45661b724fbdc09619d4c0cf1f9c10fd2680a2889685516849076d1bddabfed5edbcbf09e9a246e92a25c4e issue-297.patch
3210242f9b834ffec9d3077d5a25caf8be84aa7f4f13c73eb7f61c0a406ec787e4055951fc5a6236f1da7897c95db94a5e11e25d1b3e859a6ea67f31fc6eb517 fix-makefile.patch
8aa58aaa07453186302dc68d92f28c1b50bf0f8fccd50359640a7fc8339b233b32a0c8c02284a9974599e56d69cc557acc25e76e6438c6d64d15afd9c1788a8e default-font.patch
+bc11327631453026784a7b80efb259f6f86a670a12dfc3ba8b92b841611db73408ffab89b9c131bc7ff59695a5eef6f3e94af19136ffcfcbac9a9a7362a93f5f omxplayer-alsa.patch
3ddd32235d87a46478d0237ee9b253edeb75729e377b09a33069ecdca2ee230d2851f308897ee75ff69a9f3bdd2876f490bc1667a572dce1c186f80fddcf6df3 omxplayer.initd
4f906ada035869a0e515e7615056b18b0f6906ce4b3a2d34081c0efa79bb9455380f729e7c5270180f5ace89c53a7ac7c93f609e6761825f639f44aa22346bb2 omxplayer.confd"
diff --git a/main/omxplayer/omxplayer-alsa.patch b/main/omxplayer/omxplayer-alsa.patch
new file mode 100644
index 0000000000..0886b896a3
--- /dev/null
+++ b/main/omxplayer/omxplayer-alsa.patch
@@ -0,0 +1,6508 @@
+diff --git a/Makefile b/Makefile
+index 9fc45de..921b449 100644
+--- a/Makefile
++++ b/Makefile
+@@ -8,7 +8,21 @@ INCLUDES+=-I./ -Ilinux -Iffmpeg_compiled/usr/local/include/ -I /usr/include/dbus
+
+ 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 \
+ 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
+--- 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))
+ return false;
+ }
++ if (m_config.device == "omx:alsa")
++ {
++ if(!m_omx_render_analog.Initialize("OMX.XBMC.alsa.alsasink", OMX_IndexParamAudioInit))
++ return false;
++ }
+
+ UpdateAttenuation();
+
+diff --git a/OMXCore.cpp b/OMXCore.cpp
+index 9d5fe61..389c41e 100644
+--- a/OMXCore.cpp
++++ b/OMXCore.cpp
+@@ -35,6 +35,7 @@
+
+ #ifdef TARGET_LINUX
+ #include "XMemUtils.h"
++#include "alsa/omx_loader_XBMC.h"
+ #endif
+
+ //#define OMX_DEBUG_EVENTS
+@@ -1430,6 +1431,12 @@ bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEX
+ 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);
++ else
++#endif
++ 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()
+
+ 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);
++ 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
+--- a/README.md
++++ b/README.md
+@@ -55,7 +55,7 @@ Usage: omxplayer [OPTIONS] [FILE]
+ -v --version Print version info
+ -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
+ -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
+new file mode 100644
+index 0000000..97f543e
+--- /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.
++ *
++ * 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.
++ *
++ * @param sOtherParam Domain specific (other) OpenMAX port parameter
++ */
++
++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 <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);
++}
++
++OMX_ERRORTYPE omx_base_component_UseEGLImage (
++ OMX_HANDLETYPE hComponent,
++ OMX_BUFFERHEADERTYPE** ppBufferHdr,
++ OMX_U32 nPortIndex,
++ OMX_PTR pAppPrivate,
++ void* eglImage) {
++ return OMX_ErrorNotImplemented;
++}
++
++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);
++}
++
++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);
++}
++
++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);
++}
++
++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);
++}
+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);
++
++#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.
++
++ 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 15:28:59 +0200 (Thu, 11 Sep 2008) $
++ Revision $Rev: 614 $
++ Author $Author: gsent $
++*/
++
++#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;
++}
++
++/** @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;
++}
++
++/** @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;
++}
++
++/** @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;
++}
++
++/** @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;
++}
++
++/** @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 base_port_AllocateTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_IN OMX_U32 nPortIndex,OMX_IN 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;
++ 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;
++}
++
++OMX_ERRORTYPE base_port_FreeTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex)
++{
++ 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;
++}
++
++/** @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;
++}
++
++/**
++ * 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;
++}
++
++
++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(&param, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
++ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, &param);
++ 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, &param);
++ 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(&param, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
++ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, &param);
++ 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;
++}
+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);
++
++/** @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);
++
++/** @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);
++
++/** @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);
++
++/** @brief Returns buffers when processed.
++ *
++ * Call appropriate function to return buffers to peer or IL Client
++ */
++
++OMX_ERRORTYPE base_port_ReturnBufferFunction(
++ omx_base_PortType* openmaxStandPort,
++ OMX_BUFFERHEADERTYPE* pBuffer);
++
++/** @brief Setup Tunnel with the port
++ */
++
++OMX_ERRORTYPE base_port_ComponentTunnelRequest(
++ omx_base_PortType* openmaxStandPort,
++ OMX_IN OMX_HANDLETYPE hTunneledComp,
++ OMX_IN OMX_U32 nTunneledPort,
++ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup);
++
++/** @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;
++}
++
++OMX_ERRORTYPE omx_base_sink_Destructor(OMX_COMPONENTTYPE *openmaxStandComp)
++{
++ return omx_base_component_Destructor(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) {
++ 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)
++{
++ 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)
++{
++ 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;
++}
+\ 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
++}
++#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.
++
++ 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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#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);
++}
++
++/** 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);
++}
++
++/** 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);
++}
++
++/** 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;
++}
++
++/** 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;
++}
+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;
++}
++
++/** 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);
++}
++
++/** 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);
++}
++
++/** 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);
++}
++
++/** 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);
++}
++
++/** 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);
++}
++
++/** 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);
++}
++
+diff --git a/alsa/omx_semaphore.h b/alsa/omx_semaphore.h
+new file mode 100644
+index 0000000..1e3f3db
+--- /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 $
++
++*/
++
++#pragma once
++
++#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);
++
++#endif
+diff --git a/omxplayer.cpp b/omxplayer.cpp
+index b554a58..3e5b99b 100644
+--- a/omxplayer.cpp
++++ b/omxplayer.cpp
+@@ -699,7 +699,7 @@ int main(int argc, char *argv[])
+ 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;