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