From d5310f6748ee7eb460ac853824b8d5ca9b5f2a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 7 Dec 2015 14:24:32 +0000 Subject: main/omxplayer: add tentative support for alsa For playing videos with audio output via add-on board. Tentative version and subject for changes. This is basically the code from: https://github.com/stupid-boy/xbmc/commits/OMX_ALSA but it has been rebased, fitted to omxplayer and modified slightly to compile with omxplayer default compiler flags. --- main/omxplayer/APKBUILD | 8 +- main/omxplayer/omxplayer-alsa.patch | 6508 +++++++++++++++++++++++++++++++++++ 2 files changed, 6514 insertions(+), 2 deletions(-) create mode 100644 main/omxplayer/omxplayer-alsa.patch (limited to 'main') diff --git a/main/omxplayer/APKBUILD b/main/omxplayer/APKBUILD index 8ea504b2ee..438a2d6250 100644 --- a/main/omxplayer/APKBUILD +++ b/main/omxplayer/APKBUILD @@ -2,14 +2,14 @@ pkgname=omxplayer pkgver=0.20150911 _commitid=d99bd86c9fd80ea01f98761e130d7ac9a2bb7588 -pkgrel=1 +pkgrel=2 pkgdesc="Commandline OMX player for Raspberry Pi" url="https://github.com/popcornmix/omxplayer" arch="armhf" license="GPLv2" depends="ttf-freefont" makedepends="linux-headers raspberrypi-dev ffmpeg-dev pcre-dev - boost-dev freetype-dev dbus-dev" + boost-dev freetype-dev dbus-dev alsa-lib-dev" install="" subpackages="$pkgname-doc $pkgname-dbg" source="omxplayer-$pkgver.tar.gz::https://github.com/popcornmix/omxplayer/archive/$_commitid.tar.gz @@ -17,6 +17,7 @@ source="omxplayer-$pkgver.tar.gz::https://github.com/popcornmix/omxplayer/archiv issue-297.patch fix-makefile.patch default-font.patch + omxplayer-alsa.patch omxplayer.initd omxplayer.confd @@ -62,6 +63,7 @@ a900cdded87b7df503c6599ac43bd8de issue-260.patch 4cd10bfb7e995288f4efc312acbc4252 issue-297.patch d8f335e1dff4b34faf36c25ad2c2b881 fix-makefile.patch 9ebd96155288809fe0a657cf491e433f default-font.patch +628a9bc0b26f75547299e92542e65d47 omxplayer-alsa.patch b4054a311d76aef91aa10bacd68bc9c4 omxplayer.initd 80e37e7ac04402808015084e26e6072d omxplayer.confd" sha256sums="9be32352afd9198c733b74b1a2ec9a9b73a0ee2777c79e76914df00c9c6e5115 omxplayer-0.20150911.tar.gz @@ -69,6 +71,7 @@ sha256sums="9be32352afd9198c733b74b1a2ec9a9b73a0ee2777c79e76914df00c9c6e5115 om 75cf8af95b35bc734550c55036ef49dbff04b6940f3317b51eddea06866ecf3a issue-297.patch 799b0aba6aef8c665a685777cd912268315309d0d74ce76be5fdfd0dcffbb422 fix-makefile.patch 2bab3d05b12d730737220b8c0052498a34bbebc12b7beb8afb3c054beb0fb3bb default-font.patch +87dc80b61ce6c69a52637dffb64f526e7fa213e4c2b0c97177457c95851ec594 omxplayer-alsa.patch e2db0f7ffbe2488dd69ee0bfad006bd863f418554f078ca3432f643de7589d2f omxplayer.initd 530eb9aa50e72fb4828af410b965e0ec7653d1bed87aa86bf04fc340ff3232bd omxplayer.confd" sha512sums="a552b508981ebbed8c70fc92d3556502da97902d4ed1d2c4c68670d0eba0565759ddecf4d8821697dab7388bed1d3246673e0a9ee558ee1a817c1483db3c89f3 omxplayer-0.20150911.tar.gz @@ -76,5 +79,6 @@ c349eea5f7c513a07d82a6cf6467c4d21bcb29c053bc5e39d8f675b1212db9beef0abf5248d50ac5 606c71dc4e47bd1303ecb21bd6f265f61223f792e45661b724fbdc09619d4c0cf1f9c10fd2680a2889685516849076d1bddabfed5edbcbf09e9a246e92a25c4e issue-297.patch 3210242f9b834ffec9d3077d5a25caf8be84aa7f4f13c73eb7f61c0a406ec787e4055951fc5a6236f1da7897c95db94a5e11e25d1b3e859a6ea67f31fc6eb517 fix-makefile.patch 8aa58aaa07453186302dc68d92f28c1b50bf0f8fccd50359640a7fc8339b233b32a0c8c02284a9974599e56d69cc557acc25e76e6438c6d64d15afd9c1788a8e default-font.patch +bc11327631453026784a7b80efb259f6f86a670a12dfc3ba8b92b841611db73408ffab89b9c131bc7ff59695a5eef6f3e94af19136ffcfcbac9a9a7362a93f5f omxplayer-alsa.patch 3ddd32235d87a46478d0237ee9b253edeb75729e377b09a33069ecdca2ee230d2851f308897ee75ff69a9f3bdd2876f490bc1667a572dce1c186f80fddcf6df3 omxplayer.initd 4f906ada035869a0e515e7615056b18b0f6906ce4b3a2d34081c0efa79bb9455380f729e7c5270180f5ace89c53a7ac7c93f609e6761825f639f44aa22346bb2 omxplayer.confd" diff --git a/main/omxplayer/omxplayer-alsa.patch b/main/omxplayer/omxplayer-alsa.patch new file mode 100644 index 0000000000..0886b896a3 --- /dev/null +++ b/main/omxplayer/omxplayer-alsa.patch @@ -0,0 +1,6508 @@ +diff --git a/Makefile b/Makefile +index 9fc45de..921b449 100644 +--- a/Makefile ++++ b/Makefile +@@ -8,7 +8,21 @@ INCLUDES+=-I./ -Ilinux -Iffmpeg_compiled/usr/local/include/ -I /usr/include/dbus + + DIST ?= omxplayer-dist + +-SRC=linux/XMemUtils.cpp \ ++INCLUDES+=-Ialsa ++LDFLAGS+=-lasound ++SRC += \ ++ alsa/omx_semaphore.cpp \ ++ alsa/omx_alsasink_component.cpp \ ++ alsa/omx_base_audio_port.cpp \ ++ alsa/omx_base_clock_port.cpp \ ++ alsa/omx_base_component.cpp \ ++ alsa/omx_base_port.cpp \ ++ alsa/omx_base_sink.cpp \ ++ alsa/omx_queue.cpp \ ++ alsa/omx_loader_XBMC.cpp ++ ++SRC += \ ++ linux/XMemUtils.cpp \ + utils/log.cpp \ + DynamicDll.cpp \ + utils/PCMRemap.cpp \ +@@ -34,8 +48,9 @@ SRC=linux/XMemUtils.cpp \ + Srt.cpp \ + KeyConfig.cpp \ + OMXControl.cpp \ +- Keyboard.cpp \ +- omxplayer.cpp \ ++ Keyboard.cpp ++ ++SRC += omxplayer.cpp + + OBJS+=$(filter %.o,$(SRC:.cpp=.o)) + +diff --git a/Makefile.include b/Makefile.include +index 58e9560..3b99d3b 100644 +--- a/Makefile.include ++++ b/Makefile.include +@@ -1,40 +1,5 @@ +-USE_BUILDROOT=0 +-FLOAT=hard +- +-ifeq ($(USE_BUILDROOT), 1) +-BUILDROOT :=/opt/xbmc-bcm/buildroot +-SDKSTAGE :=$(BUILDROOT)/output/staging +-TARGETFS :=$(BUILDROOT)/output/target +-TOOLCHAIN :=$(BUILDROOT)/output/host/usr/ +-HOST :=arm-unknown-linux-gnueabi +-SYSROOT :=$(BUILDROOT)/output/host/usr/arm-unknown-linux-gnueabi/sysroot +-else +-BUILDROOT :=/opt/bcm-rootfs +-SDKSTAGE :=/opt/bcm-rootfs +-TARGETFS :=/opt/bcm-rootfs +-TOOLCHAIN :=/home/dc4/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/ +-HOST :=arm-linux-gnueabihf +-#SYSROOT :=$(TOOLCHAIN)/arm-bcm2708hardfp-linux-gnueabi/sysroot +-SYSROOT :=/opt/bcm-rootfs +-endif +- +-JOBS=7 +- +-CFLAGS := -isystem$(PREFIX)/include +-CXXFLAGS := $(CFLAGS) +-CPPFLAGS := $(CFLAGS) +-LDFLAGS := -L$(BUILDROOT)/lib +-LD := $(TOOLCHAIN)/bin/$(HOST)-ld --sysroot=$(SYSROOT) +-CC := $(TOOLCHAIN)/bin/$(HOST)-gcc --sysroot=$(SYSROOT) +-CXX := $(TOOLCHAIN)/bin/$(HOST)-g++ --sysroot=$(SYSROOT) +-OBJDUMP := $(TOOLCHAIN)/bin/$(HOST)-objdump +-RANLIB := $(TOOLCHAIN)/bin/$(HOST)-ranlib +-STRIP := $(TOOLCHAIN)/bin/$(HOST)-strip +-AR := $(TOOLCHAIN)/bin/$(HOST)-ar +-CXXCP := $(CXX) -E +-PATH := $(PREFIX)/bin:$(BUILDROOT)/output/host/usr/bin:$(PATH) +- +-CFLAGS += -pipe -mfloat-abi=$(FLOAT) -mcpu=arm1176jzf-s -fomit-frame-pointer -mabi=aapcs-linux -mtune=arm1176jzf-s -mfpu=vfp -Wno-psabi -mno-apcs-stack-check -g -mstructure-size-boundary=32 -mno-sched-prolog +-LDFLAGS += -L$(SDKSTAGE)/lib -L$(SDKSTAGE)/usr/lib -L$(SDKSTAGE)/opt/vc/lib/ -Lpcre/build +-#INCLUDES += -isystem$(SDKSTAGE)/usr/include -isystem$(SDKSTAGE)/opt/vc/include -isystem$(SYSROOT)/usr/include -isystem$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -isystem$(SDKSTAGE)/usr/include/freetype2 +-INCLUDES += -isystem$(SDKSTAGE)/opt/vc/include -isystem$(SYSROOT)/usr/include -isystem$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -Ipcre/build -Iboost-trunk -Ifreetype2/include ++INCLUDES:=-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux ++INCLUDES+=-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include ++LDFLAGS:=-L/opt/vc/lib -Wl,-rpath,/opt/vc/lib ++LDFLAGS+=-lfreetype -ldbus-1 ++STRIP:=echo +diff --git a/OMXAudio.cpp b/OMXAudio.cpp +index 41f282d..e1e82c4 100644 +--- a/OMXAudio.cpp ++++ b/OMXAudio.cpp +@@ -112,6 +112,11 @@ bool COMXAudio::PortSettingsChanged() + if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; + } ++ if (m_config.device == "omx:alsa") ++ { ++ if(!m_omx_render_analog.Initialize("OMX.XBMC.alsa.alsasink", OMX_IndexParamAudioInit)) ++ return false; ++ } + + UpdateAttenuation(); + +diff --git a/OMXCore.cpp b/OMXCore.cpp +index 9d5fe61..389c41e 100644 +--- a/OMXCore.cpp ++++ b/OMXCore.cpp +@@ -35,6 +35,7 @@ + + #ifdef TARGET_LINUX + #include "XMemUtils.h" ++#include "alsa/omx_loader_XBMC.h" + #endif + + //#define OMX_DEBUG_EVENTS +@@ -1430,6 +1431,12 @@ bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEX + if(!m_handle) + { + omx_err = m_DllOMX->OMX_GetHandle(&m_handle, (char*)component_name.c_str(), this, &m_callbacks); ++#ifdef TARGET_LINUX ++ if (strncmp("OMX.XBMC.", component_name.c_str(), 9) == 0) ++ omx_err = OMX_GetHandle_XBMC(&m_handle, (char*) component_name.c_str(), this, &m_callbacks); ++ else ++#endif ++ omx_err = m_DllOMX->OMX_GetHandle(&m_handle, (char*)component_name.c_str(), this, &m_callbacks); + if (!m_handle || omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "COMXCoreComponent::Initialize - could not get component handle for %s omx_err(0x%08x)\n", +@@ -1505,6 +1512,11 @@ bool COMXCoreComponent::Deinitialize() + + CLog::Log(LOGDEBUG, "COMXCoreComponent::Deinitialize : %s handle %p\n", + m_componentName.c_str(), m_handle); ++#ifdef TARGET_LINUX ++ if (strncmp("OMX.XBMC.", m_componentName.c_str(), 9) == 0) ++ omx_err = OMX_FreeHandle_XBMC(m_handle); ++ else ++#endif + omx_err = m_DllOMX->OMX_FreeHandle(m_handle); + if (omx_err != OMX_ErrorNone) + { +diff --git a/README.md b/README.md +index 2eb78f3..f70d73c 100644 +--- a/README.md ++++ b/README.md +@@ -55,7 +55,7 @@ Usage: omxplayer [OPTIONS] [FILE] + -v --version Print version info + -k --keys Print key bindings + -n --aidx index Audio stream index : e.g. 1 +- -o --adev device Audio out device : e.g. hdmi/local/both ++ -o --adev device Audio out device : e.g. hdmi/local/both/alsa + -i --info Dump stream format and exit + -I --with-info dump stream format before playback + -s --stats Pts and buffer stats +diff --git a/alsa/omx_alsasink_component.cpp b/alsa/omx_alsasink_component.cpp +new file mode 100644 +index 0000000..9803e63 +--- /dev/null ++++ b/alsa/omx_alsasink_component.cpp +@@ -0,0 +1,1035 @@ ++/** ++ @file src/components/alsa/omx_alsasink_component.c ++ ++ OpenMAX ALSA sink component. This component is an audio sink that uses ALSA library. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-08-08 06:56:06 +0200 (Fri, 08 Aug 2008) $ ++ Revision $Rev: 581 $ ++ Author $Author: pankaj_sen $ ++ ++*/ ++ ++#undef OMX_SKIP64BIT ++#include ++#include ++#include ++#include ++ ++/** 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 ++//#include ++//#include ++//#include ++#include ++#include ++#include ++ ++/** 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 ++#include ++#include ++//#include ++//#include ++ ++#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 ++#include ++#include ++//#include ++//#include ++#include "omx_base_component.h" ++#include "omx_base_clock_port.h" ++ ++/** ++ * @brief the base contructor for the generic openmax ST Clock port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the component. ++ * It takes care of constructing the instance of the port and ++ * every object needed by the base port. ++ * ++ * @param openmaxStandComp pointer to the Handle of the component ++ * @param openmaxStandPort the ST port to be initialized ++ * @param nPortIndex Index of the port to be constructed ++ * @param isInput specifices if the port is an input or an output ++ * ++ * @return OMX_ErrorInsufficientResources if a memory allocation fails ++ */ ++ ++OMX_ERRORTYPE base_clock_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput) { ++ ++ omx_base_clock_PortType *omx_base_clock_Port; ++ ++ if (!(*openmaxStandPort)) { ++ *openmaxStandPort = (omx_base_PortType*)calloc(1,sizeof (omx_base_clock_PortType)); ++ } ++ ++ if (!(*openmaxStandPort)) { ++ return OMX_ErrorInsufficientResources; ++ } ++ ++ base_port_Constructor(openmaxStandComp,openmaxStandPort,nPortIndex, isInput); ++ ++ omx_base_clock_Port = (omx_base_clock_PortType *)*openmaxStandPort; ++ ++ setHeader(&omx_base_clock_Port->sOtherParam, sizeof(OMX_OTHER_PARAM_PORTFORMATTYPE)); ++ omx_base_clock_Port->sOtherParam.nPortIndex = nPortIndex; ++ omx_base_clock_Port->sOtherParam.nIndex = 0; ++ omx_base_clock_Port->sOtherParam.eFormat = OMX_OTHER_FormatTime; ++ ++ omx_base_clock_Port->sPortParam.eDomain = OMX_PortDomainOther; ++ omx_base_clock_Port->sPortParam.format.other.eFormat = OMX_OTHER_FormatTime; ++ omx_base_clock_Port->sPortParam.nBufferSize = sizeof(OMX_TIME_MEDIATIMETYPE) ; ++ omx_base_clock_Port->sPortParam.nBufferCountActual = 1; ++ omx_base_clock_Port->sPortParam.nBufferCountMin = 1; ++ omx_base_clock_Port->sPortParam.format.other.eFormat = OMX_OTHER_FormatTime; ++ ++ setHeader(&omx_base_clock_Port->sTimeStamp, sizeof(OMX_TIME_CONFIG_TIMESTAMPTYPE)); ++ omx_base_clock_Port->sTimeStamp.nPortIndex = nPortIndex; ++ omx_base_clock_Port->sTimeStamp.nTimestamp = 0x00; ++ ++ ++ setHeader(&omx_base_clock_Port->sMediaTime, sizeof(OMX_TIME_MEDIATIMETYPE)); ++ omx_base_clock_Port->sMediaTime.nClientPrivate = 0; ++ omx_base_clock_Port->sMediaTime.nOffset = 0x0; ++ omx_base_clock_Port->sMediaTime.xScale = 1; ++ ++ setHeader(&omx_base_clock_Port->sMediaTimeRequest, sizeof(OMX_TIME_MEDIATIMETYPE)); ++ omx_base_clock_Port->sMediaTimeRequest.nPortIndex = nPortIndex; ++ omx_base_clock_Port->sMediaTimeRequest.pClientPrivate = NULL; ++ omx_base_clock_Port->sMediaTimeRequest.nOffset = 0x0; ++ ++ omx_base_clock_Port->Port_SendBufferFunction = &base_clock_port_SendBufferFunction; ++ omx_base_clock_Port->PortDestructor = &base_clock_port_Destructor; ++ ++ return OMX_ErrorNone; ++} ++ ++/** ++ * @brief the base clock port destructor for the generic openmax ST clock port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the port. ++ * It takes care of destructing the instance of the port ++ * ++ * @param openmaxStandPort the ST port to be destructed ++ * ++ * @return OMX_ErrorNone ++ */ ++ ++OMX_ERRORTYPE base_clock_port_Destructor(omx_base_PortType *openmaxStandPort){ ++ ++ base_port_Destructor(openmaxStandPort); ++ ++ return OMX_ErrorNone; ++} ++ ++/** @brief the entry point for sending buffers to the port ++ * ++ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on ++ * the nature of the port, that can be an input or output port. ++ */ ++OMX_ERRORTYPE base_clock_port_SendBufferFunction( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE* pBuffer) { ++ ++ OMX_ERRORTYPE err; ++ OMX_U32 portIndex; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++#if NO_GST_OMX_PATCH ++ unsigned int i; ++#endif ++ portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, (unsigned long)portIndex); ++ ++ if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if(omx_base_component_Private->state == OMX_StateInvalid) { ++ DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); ++ return OMX_ErrorInvalidState; ++ } ++ ++ if(omx_base_component_Private->state != OMX_StateExecuting && ++ omx_base_component_Private->state != OMX_StatePause && ++ omx_base_component_Private->state != OMX_StateIdle) { ++ DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); ++ return OMX_ErrorIncorrectStateOperation; ++ } ++ if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || ++ (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && ++ (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { ++ DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); ++ return OMX_ErrorIncorrectStateOperation; ++ } ++ ++ /* Temporarily disable this check for gst-openmax */ ++#if NO_GST_OMX_PATCH ++ { ++ OMX_BOOL foundBuffer = OMX_FALSE; ++ if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { ++ foundBuffer = OMX_TRUE; ++ break; ++ } ++ } ++ } ++ if (!foundBuffer) { ++ return OMX_ErrorBadParameter; ++ } ++ } ++#endif ++ ++ if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); ++ return err; ++ } ++ /*If port is not tunneled then simply return the buffer except paused state*/ ++ if (!PORT_IS_TUNNELED(openmaxStandPort) && (omx_base_component_Private->state != OMX_StatePause)) { ++ openmaxStandPort->ReturnBufferFunction(openmaxStandPort,pBuffer); ++ return OMX_ErrorNone; ++ } ++ ++ /* And notify the buffer management thread we have a fresh new buffer to manage */ ++ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ ++ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); ++ omx_tsem_up(openmaxStandPort->pBufferSem); ++ DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", ++ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); ++ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); ++ omx_tsem_up(openmaxStandPort->pBufferSem); ++ } ++ else { // If port being flushed and not tunneled then return error ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); ++ return OMX_ErrorIncorrectStateOperation; ++ } ++ return OMX_ErrorNone; ++} +diff --git a/alsa/omx_base_clock_port.h b/alsa/omx_base_clock_port.h +new file mode 100644 +index 0000000..97f543e +--- /dev/null ++++ b/alsa/omx_base_clock_port.h +@@ -0,0 +1,95 @@ ++/** ++ @file src/base/omx_base_clock_port.h ++ ++ Base Clock Port class for OpenMAX clock ports to be used in derived components. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-07-04 11:48:31 +0200 (Fri, 04 Jul 2008) $ ++ Revision $Rev: 560 $ ++ Author $Author: gsent $ ++ ++*/ ++ ++#include "omx_classmagic.h" ++#include "omx_base_port.h" ++ ++#ifndef __OMX_BASE_CLOCK_PORT_H__ ++#define __OMX_BASE_CLOCK_PORT_H__ ++ ++/** ++ * @brief the base clock domain structure that describes each port. ++ * ++ * The data structure is derived from base port class and contain clock ++ * domain specific parameters. ++ * Other elements can be added in the derived components structures. ++ * ++ * @param sOtherParam Domain specific (other) OpenMAX port parameter ++ */ ++ ++DERIVEDCLASS(omx_base_clock_PortType, omx_base_PortType) ++#define omx_base_clock_PortType_FIELDS omx_base_PortType_FIELDS \ ++ OMX_TIME_CONFIG_TIMESTAMPTYPE sTimeStamp; /**< General OpenMAX configuration time stamp parameter */ \ ++ OMX_TIME_MEDIATIMETYPE sMediaTime; \ ++ OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE sMediaTimeRequest; \ ++ OMX_OTHER_PARAM_PORTFORMATTYPE sOtherParam; /**< Domain specific (other) OpenMAX port parameter */ ++ENDCLASS(omx_base_clock_PortType) ++ ++/** ++ * @brief the base contructor for the generic openmax ST clock port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the component. ++ * It takes care of constructing the instance of the port and ++ * every object needed by the base port. ++ * ++ * @param openmaxStandComp pointer to the Handle of the component ++ * @param openmaxStandPort the ST port to be initialized ++ * @param nPortIndex Index of the port to be constructed ++ * @param isInput specifices if the port is an input or an output ++ * ++ * @return OMX_ErrorInsufficientResources if a memory allocation fails ++ */ ++ ++OMX_ERRORTYPE base_clock_port_Constructor( ++ OMX_COMPONENTTYPE *openmaxStandComp, ++ omx_base_PortType **openmaxStandPort, ++ OMX_U32 nPortIndex, ++ OMX_BOOL isInput); ++ ++/** ++ * @brief the base clock port destructor for the generic openmax ST clock port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the port. ++ * It takes care of destructing the instance of the port ++ * ++ * @param openmaxStandPort the ST port to be destructed ++ * ++ * @return OMX_ErrorNone ++ */ ++ ++OMX_ERRORTYPE base_clock_port_Destructor( ++ omx_base_PortType *openmaxStandPort); ++ ++OMX_ERRORTYPE base_clock_port_SendBufferFunction( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE* pBuffer); ++ ++#endif +diff --git a/alsa/omx_base_component.cpp b/alsa/omx_base_component.cpp +new file mode 100644 +index 0000000..8396979 +--- /dev/null ++++ b/alsa/omx_base_component.cpp +@@ -0,0 +1,1755 @@ ++/** ++ @file src/base/omx_base_component.c ++ ++ OpenMAX base_component component. This component does not perform any multimedia ++ processing. It is used as a base_component for new components development. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-09-16 15:59:45 +0200 (Tue, 16 Sep 2008) $ ++ Revision $Rev: 621 $ ++ Author $Author: gsent $ ++ ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++//#include ++//#include ++ ++#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;isPortTypesParam[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;knNumTunnelBuffer;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;knNumTunnelBuffer;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;jports[message->messageParam]->nNumTunnelBuffer;j++) { ++ omx_tsem_up(omx_base_component_Private->ports[message->messageParam]->pBufferSem); ++ /*signal buffer management thread availability of buffers*/ ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ } ++ } ++ } ++ } ++ } ++ break; ++ case OMX_CommandPortDisable: { ++ /*Flush port/s*/ ++ if(message->messageParam == OMX_ALL) { ++ /*If Component is not in loaded state,then First Flush all buffers then disable the port*/ ++ if(omx_base_component_Private->state!=OMX_StateLoaded) { ++ /* for all ports */ ++ for(j = 0; j < NUM_DOMAINS; j++) { ++ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; ++ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + ++ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { ++ pPort=omx_base_component_Private->ports[i]; ++ err = pPort->FlushProcessingBuffers(pPort); ++ } ++ } ++ } ++ /* for all ports */ ++ for(j = 0; j < NUM_DOMAINS; j++) { ++ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; ++ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + ++ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { ++ pPort=omx_base_component_Private->ports[i]; ++ err = pPort->Port_DisablePort(pPort); ++ } ++ } ++ } ++ else { ++ pPort=omx_base_component_Private->ports[message->messageParam]; ++ if(omx_base_component_Private->state!=OMX_StateLoaded) { ++ err = pPort->FlushProcessingBuffers(pPort); ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Port Flush completed for Comp %s\n",__func__,omx_base_component_Private->name); ++ } ++ err = pPort->Port_DisablePort(pPort); ++ } ++ /** This condition is added to pass the tests, it is not significant for the environment */ ++ if (err != OMX_ErrorNone) { ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventError, /* The command was completed */ ++ err, /* The commands was a OMX_CommandStateSet */ ++ 0, /* The state has been changed in message->messageParam */ ++ NULL); ++ } else { ++ if(message->messageParam == OMX_ALL){ /*Disable all ports*/ ++ /* for all ports */ ++ for(j = 0; j < NUM_DOMAINS; j++) { ++ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; ++ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + ++ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventCmdComplete, /* The command was completed */ ++ OMX_CommandPortDisable, /* The commands was a OMX_CommandStateSet */ ++ i, /* The state has been changed in message->messageParam */ ++ NULL); ++ } ++ } ++ } else { ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventCmdComplete, /* The command was completed */ ++ OMX_CommandPortDisable, /* The commands was a OMX_CommandStateSet */ ++ message->messageParam, /* The state has been changed in message->messageParam */ ++ NULL); ++ } ++ } ++ } ++ break; ++ case OMX_CommandPortEnable:{ ++ /*Flush port/s*/ ++ if(message->messageParam == OMX_ALL) { ++ /* for all ports */ ++ for(j = 0; j < NUM_DOMAINS; j++) { ++ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; ++ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + ++ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { ++ pPort=omx_base_component_Private->ports[i]; ++ err = pPort->Port_EnablePort(pPort); ++ } ++ } ++ } else { ++ pPort=omx_base_component_Private->ports[message->messageParam]; ++ err = pPort->Port_EnablePort(pPort); ++ } ++ if (err != OMX_ErrorNone) { ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventError, /* The command was completed */ ++ err, /* The commands was a OMX_CommandStateSet */ ++ 0, /* The state has been changed in message->messageParam */ ++ NULL); ++ } else { ++ if(message->messageParam != OMX_ALL) { ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventCmdComplete, /* The command was completed */ ++ OMX_CommandPortEnable, /* The commands was a OMX_CommandStateSet */ ++ message->messageParam, /* The state has been changed in message->messageParam */ ++ NULL); ++ ++ if (omx_base_component_Private->state==OMX_StateExecuting) { ++ pPort=omx_base_component_Private->ports[message->messageParam]; ++ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { ++ for(i=0; i < pPort->sPortParam.nBufferCountActual;i++) { ++ omx_tsem_up(pPort->pBufferSem); ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ } ++ } ++ } ++ ++ } else { ++ /* for all ports */ ++ for(j = 0; j < NUM_DOMAINS; j++) { ++ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; ++ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + ++ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventCmdComplete, /* The command was completed */ ++ OMX_CommandPortEnable, /* The commands was a OMX_CommandStateSet */ ++ i, /* The state has been changed in message->messageParam */ ++ NULL); ++ } ++ } ++ ++ if (omx_base_component_Private->state==OMX_StateExecuting) { ++ /* for all ports */ ++ for(j = 0; j < NUM_DOMAINS; j++) { ++ for(i = omx_base_component_Private->sPortTypesParam[j].nStartPortNumber; ++ i < omx_base_component_Private->sPortTypesParam[j].nStartPortNumber + ++ omx_base_component_Private->sPortTypesParam[j].nPorts; i++) { ++ pPort=omx_base_component_Private->ports[i]; ++ if (PORT_IS_BUFFER_SUPPLIER(pPort)) { ++ for(k=0; k < pPort->sPortParam.nBufferCountActual;k++) { ++ omx_tsem_up(pPort->pBufferSem); ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ case OMX_CommandMarkBuffer: { ++ omx_base_component_Private->pMark.hMarkTargetComponent = ((OMX_MARKTYPE *)message->pCmdData)->hMarkTargetComponent; ++ omx_base_component_Private->pMark.pMarkData = ((OMX_MARKTYPE *)message->pCmdData)->pMarkData; ++ } ++ break; ++ default: ++ DEBUG(DEB_LEV_ERR, "In %s: Unrecognized command %i\n", __func__, message->messageType); ++ break; ++ } ++ DEBUG(DEB_LEV_SIMPLE_SEQ, "Returning from %s: \n", __func__); ++ return OMX_ErrorNone; ++} ++ ++OMX_ERRORTYPE omx_base_component_AllocateBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_PTR pAppPrivate, ++ OMX_IN OMX_U32 nSizeBytes) { ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ omx_base_PortType *pPort; ++ ++ if (nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ pPort = omx_base_component_Private->ports[nPortIndex]; ++ ++ return pPort->Port_AllocateBuffer(pPort, ++ ppBuffer, ++ nPortIndex, ++ pAppPrivate, ++ nSizeBytes); ++} ++ ++OMX_ERRORTYPE omx_base_component_UseBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_PTR pAppPrivate, ++ OMX_IN OMX_U32 nSizeBytes, ++ OMX_IN OMX_U8* pBuffer) { ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ omx_base_PortType *pPort; ++ ++ if (nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ pPort = omx_base_component_Private->ports[nPortIndex]; ++ ++ return pPort->Port_UseBuffer(pPort, ++ ppBufferHdr, ++ nPortIndex, ++ pAppPrivate, ++ nSizeBytes, ++ pBuffer); ++} ++ ++OMX_ERRORTYPE omx_base_component_UseEGLImage ( ++ OMX_HANDLETYPE hComponent, ++ OMX_BUFFERHEADERTYPE** ppBufferHdr, ++ OMX_U32 nPortIndex, ++ OMX_PTR pAppPrivate, ++ void* eglImage) { ++ return OMX_ErrorNotImplemented; ++} ++ ++OMX_ERRORTYPE omx_base_component_FreeBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ omx_base_PortType *pPort; ++ ++ if (nPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ pPort = omx_base_component_Private->ports[nPortIndex]; ++ ++ return pPort->Port_FreeBuffer(pPort, ++ nPortIndex, ++ pBuffer); ++} ++ ++OMX_ERRORTYPE omx_base_component_EmptyThisBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ omx_base_PortType *pPort; ++ //DEBUG(DEB_LEV_FUNCTION_NAME, "In %s pBuffer=0x%x pBuffer->pBuffer=0x%x nInputPortIndex=%d nOutputPortIndex=%d nAllocLen=%d nFilledLen=%d\n", ++ // __func__, pBuffer, pBuffer->pBuffer, pBuffer->nInputPortIndex, pBuffer->nOutputPortIndex, pBuffer->nAllocLen, pBuffer->nFilledLen); ++ ++ if (pBuffer->nInputPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ pPort = omx_base_component_Private->ports[pBuffer->nInputPortIndex]; ++ if (pPort->sPortParam.eDir != OMX_DirInput) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port direction in Component %s\n", __func__,omx_base_component_Private->name); ++ return OMX_ErrorBadPortIndex; ++ } ++ return pPort->Port_SendBufferFunction(pPort, pBuffer); ++} ++ ++OMX_ERRORTYPE omx_base_component_FillThisBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { ++ ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ omx_base_PortType *pPort; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ if (pBuffer->nOutputPortIndex >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ pPort = omx_base_component_Private->ports[pBuffer->nOutputPortIndex]; ++ if (pPort->sPortParam.eDir != OMX_DirOutput) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port direction in Component %s\n", __func__,omx_base_component_Private->name); ++ return OMX_ErrorBadPortIndex; ++ } ++ return pPort->Port_SendBufferFunction(pPort, pBuffer); ++} ++ ++OMX_ERRORTYPE omx_base_component_ComponentTunnelRequest( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_U32 nPort, ++ OMX_IN OMX_HANDLETYPE hTunneledComp, ++ OMX_IN OMX_U32 nTunneledPort, ++ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { ++ ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ omx_base_PortType *pPort; ++ ++ if (nPort >= (omx_base_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts + ++ omx_base_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) { ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ pPort = omx_base_component_Private->ports[nPort]; ++ ++ return pPort->ComponentTunnelRequest(pPort, hTunneledComp, nTunneledPort, pTunnelSetup); ++} +diff --git a/alsa/omx_base_component.h b/alsa/omx_base_component.h +new file mode 100644 +index 0000000..9134119 +--- /dev/null ++++ b/alsa/omx_base_component.h +@@ -0,0 +1,412 @@ ++/** ++ @file src/base/omx_base_component.h ++ ++ OpenMAX base component. This component does not perform any multimedia ++ processing.It is used as a base component for new components development. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-09-11 11:45:59 +0200 (Thu, 11 Sep 2008) $ ++ Revision $Rev: 613 $ ++ Author $Author: pankaj_sen $ ++ ++*/ ++#ifndef _OMX_BASE_COMPONENT_H_ ++#define _OMX_BASE_COMPONENT_H_ ++ ++#include ++ ++#include "omx_semaphore.h" ++#include "omx_queue.h" ++#include "omx_classmagic.h" ++#include "omx_base_port.h" ++ ++/** Default size of the internal input buffer */ ++#define DEFAULT_IN_BUFFER_SIZE 4 * 1024 ++/** Default size of the internal output buffer */ ++#define DEFAULT_OUT_BUFFER_SIZE 16 * 1024 /*32 * 1024*/ /*16 * 1024 */ // TODO - check this size is ok ++/** Default MIME string length */ ++#define DEFAULT_MIME_STRING_LENGTH 128 ++ ++#define NUM_DOMAINS 4 ++ ++/* Check if Component is deinitalizing*/ ++#define IS_COMPONENT_DEINIT(component_Private, exit_condition) \ ++ pthread_mutex_lock(&component_Private->exit_mutex) ,\ ++ exit_condition = component_Private->bIsComponentDeinit ,\ ++ pthread_mutex_unlock(&component_Private->exit_mutex) ,\ ++ (exit_condition == OMX_TRUE) ? OMX_TRUE:OMX_FALSE \ ++ ++typedef struct OMX_VENDOR_EXTRADATATYPE { ++ OMX_U32 nPortIndex; ++ OMX_U32 nDataSize; // Size of the supporting data to follow ++ OMX_U8 *pData; // Supporting data hint ++} OMX_VENDOR_EXTRADATATYPE; ++ ++typedef struct OMX_VENDOR_PROP_TUNNELSETUPTYPE { ++ OMX_U32 nPortIndex; ++ OMX_TUNNELSETUPTYPE nTunnelSetup; // Tunnel setup flags ++} OMX_VENDOR_PROP_TUNNELSETUPTYPE; ++ ++/** this is the list of custom vendor index */ ++typedef enum OMX_INDEXVENDORTYPE { ++ /** only one index for file reader component input file */ ++ OMX_IndexVendorFileReadInputFilename = 0xFF000001, ++ OMX_IndexVendorParser3gpInputFilename = 0xFF000002, ++ OMX_IndexVendorVideoExtraData = 0xFF000003, ++ OMX_IndexVendorAudioExtraData = 0xFF000004, ++ OMX_IndexVendorCompPropTunnelFlags = 0xFF000005 /* Will use OMX_TUNNELSETUPTYPE structure*/ ++} OMX_INDEXVENDORTYPE; ++ ++/** This enum defines the transition states of the Component*/ ++typedef enum OMX_TRANS_STATETYPE { ++ OMX_TransStateInvalid, ++ OMX_TransStateLoadedToIdle, ++ OMX_TransStateIdleToPause, ++ OMX_TransStatePauseToExecuting, ++ OMX_TransStateIdleToExecuting, ++ OMX_TransStateExecutingToIdle, ++ OMX_TransStateExecutingToPause, ++ OMX_TransStatePauseToIdle, ++ OMX_TransStateIdleToLoaded, ++ OMX_TransStateMax = 0X7FFFFFFF ++} OMX_TRANS_STATETYPE; ++ ++/** @brief Enumerates all the possible types of messages ++ * handled internally by the component ++ */ ++typedef enum INTERNAL_MESSAGE_TYPE { ++ SENDCOMMAND_MSG_TYPE = 1,/**< this flag specifies that the message send is a command */ ++ ERROR_MSG_TYPE,/**< this flag specifies that the message send is an error message */ ++ WARNING_MSG_TYPE /**< this flag specifies that the message send is a warning message */ ++} INTERNAL_MESSAGE_TYPE; ++ ++/** @brief The container of an internal message ++ * ++ * This structure contains a generic OpenMAX request (from send command). ++ * It is processed by the internal message handler thread ++ */ ++typedef struct internalRequestMessageType { ++ int messageType; /**< the flag that specifies if the message is a command, a warning or an error */ ++ int messageParam; /**< the second field of the message. Its use is the same as specified for the command in OpenMAX spec */ ++ OMX_PTR pCmdData; /**< This pointer could contain some proprietary data not covered by the standard */ ++} internalRequestMessageType; ++ ++/** ++ * @brief the base descriptor for a ST component ++ */ ++CLASS(omx_base_component_PrivateType) ++#define omx_base_component_PrivateType_FIELDS \ ++ OMX_COMPONENTTYPE *openmaxStandComp; /**< The OpenMAX standard data structure describing a component */ \ ++ omx_base_PortType **ports; /** @param ports The ports of the component */ \ ++ OMX_PORT_PARAM_TYPE sPortTypesParam[NUM_DOMAINS]; /** @param sPortTypesParam OpenMAX standard parameter that contains a short description of the available ports */ \ ++ char uniqueID; /**< ID code that identifies an ST static component*/ \ ++ char* name; /**< component name */\ ++ OMX_STATETYPE state; /**< The state of the component */ \ ++ OMX_TRANS_STATETYPE transientState; /**< The transient state in case of transition between \ ++ Loaded/waitForResources - Idle. It is equal to \ ++ Invalid if the state or transition are not corect \ ++ Loaded when the transition is from Idle to Loaded \ ++ Idle when the transition is from Loaded to Idle */ \ ++ OMX_CALLBACKTYPE* callbacks; /**< pointer to every client callback function, \ ++ as specified by the standard*/ \ ++ OMX_PTR callbackData;/**< Private data that can be send with \ ++ the client callbacks. Not specified by the standard */ \ ++ omx_queue_t* messageQueue;/**< the queue of all the messages recevied by the component */\ ++ omx_tsem_t* messageSem;/**< the semaphore that coordinates the access to the message queue */\ ++ OMX_U32 nGroupPriority; /**< @param nGroupPriority Resource management field: component priority (common to a group of components) */\ ++ OMX_U32 nGroupID; /**< @param nGroupID ID of a group of components that share the same logical chain */\ ++ OMX_MARKTYPE pMark; /**< @param pMark This field holds the private data associated with a mark request, if any */\ ++ pthread_mutex_t flush_mutex; /** @param flush_mutex mutex for the flush condition from buffers */ \ ++ omx_tsem_t* flush_all_condition; /** @param flush_all_condition condition for the flush all buffers */ \ ++ omx_tsem_t* flush_condition; /** @param The flush_condition condition */ \ ++ omx_tsem_t* bMgmtSem;/**< @param bMgmtSem the semaphore that control BufferMgmtFunction processing */\ ++ omx_tsem_t* bStateSem;/**< @param bMgmtSem the semaphore that control BufferMgmtFunction processing */\ ++ int messageHandlerThreadID; /** @param messageHandlerThreadID The ID of the pthread that handles the messages for the components */ \ ++ pthread_t messageHandlerThread; /** @param messageHandlerThread This field contains the reference to the thread that receives messages for the components */ \ ++ int bufferMgmtThreadID; /** @param bufferMgmtThreadID The ID of the pthread that process buffers */ \ ++ pthread_t bufferMgmtThread; /** @param bufferMgmtThread This field contains the reference to the thread that process buffers */ \ ++ void *loader; /**< pointer to the loader that created this component, used for destruction */ \ ++ void* (*BufferMgmtFunction)(void* param); /** @param BufferMgmtFunction This function processes input output buffers */ \ ++ OMX_ERRORTYPE (*messageHandler)(OMX_COMPONENTTYPE*,internalRequestMessageType*);/** This function receives messages from the message queue. It is needed for each Linux ST OpenMAX component */ \ ++ OMX_ERRORTYPE (*DoStateSet)(OMX_COMPONENTTYPE *openmaxStandComp, OMX_U32); /**< @param DoStateSet internal function called when a generic state transition is requested*/ \ ++ OMX_ERRORTYPE (*destructor)(OMX_COMPONENTTYPE *openmaxStandComp); /** Component Destructor*/ ++ENDCLASS(omx_base_component_PrivateType) ++ ++/** ++ * @brief The base contructor for the OpenMAX ST components ++ * ++ * This function is executed by the ST static component loader. ++ * It takes care of constructing the instance of the component. ++ * For the base_component component, the following is done: ++ * ++ * 1) Fills the basic OpenMAX structure. The fields can be overwritten ++ * by derived components. ++ * 2) Allocates (if needed) the omx_base_component_PrivateType private structure ++ * ++ * @param openmaxStandComp the ST component to be initialized ++ * @param cComponentName the OpenMAX string that describes the component ++ * ++ * @return OMX_ErrorInsufficientResources if a memory allocation fails ++ */ ++OMX_ERRORTYPE omx_base_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName); ++ ++/** @brief the base destructor for ST OpenMAX components ++ * ++ * This function is called by the standard function ComponentDeInit() ++ * that is called by the IL core during the execution of the FreeHandle() ++ * ++ * @param openmaxStandComp the ST OpenMAX component to be disposed ++ */ ++OMX_ERRORTYPE omx_base_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp); ++ ++/** Changes the state of a component taking proper actions depending on ++ * the transiotion requested. This base function cover only the state ++ * changes that do not involve any port ++ * ++ * @param openmaxStandComp the OpenMAX component which state is to be changed ++ * @param destinationState the requested target state ++ * ++ * @return OMX_ErrorNotImplemented if the state change is noty handled ++ * in this base class, but needs a specific handling ++ */ ++OMX_ERRORTYPE omx_base_component_DoStateSet( ++ OMX_COMPONENTTYPE *openmaxStandComp, ++ OMX_U32 destinationState); ++ ++/** @brief Checks the header of a structure for consistency ++ * with size and spec version ++ * ++ * @param header Pointer to the structure to be checked ++ * @param size Size of the structure. it is in general obtained ++ * with a sizeof call applied to the structure ++ * ++ * @return OMX error code. If the header has failed the check, ++ * OMX_ErrorVersionMismatch is returned. ++ * If the header fails the size check OMX_ErrorBadParameter is returned ++ */ ++OMX_ERRORTYPE checkHeader(OMX_PTR header, OMX_U32 size); ++ ++/** @brief Simply fills the first two fields in any OMX structure ++ * with the size and the version ++ * ++ * @param header pointer to the structure to be filled ++ * @param size size of the structure. It can be obtained with ++ * a call to sizeof of the structure type ++ */ ++void setHeader(OMX_PTR header, OMX_U32 size); ++ ++/** @brief standard openmax function ++ * ++ * it returns the version of the component. See OMX_Core.h ++ */ ++OMX_ERRORTYPE omx_base_component_GetComponentVersion(OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_OUT OMX_STRING pComponentName, ++ OMX_OUT OMX_VERSIONTYPE* pComponentVersion, ++ OMX_OUT OMX_VERSIONTYPE* pSpecVersion, ++ OMX_OUT OMX_UUIDTYPE* pComponentUUID); ++ ++/** @brief Enumerates all the role of the component. ++ * ++ * This function is intended to be used only by a core. The ST static core ++ * in any case does not use this function, because it can not be used before the ++ * creation of the component, but uses a static list. ++ * It is implemented only for API completion, and it will be not overriden ++ * by a derived component. ++ * ++ * @param hComponent handle of the component ++ * @param cRole the output string containing the n-role of the component ++ * @param nIndex the index of the role requested ++ */ ++OMX_ERRORTYPE omx_base_component_ComponentRoleEnum( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_OUT OMX_U8 *cRole, ++ OMX_IN OMX_U32 nIndex); ++ ++/** @brief standard OpenMAX function ++ * ++ * it sets the callback functions given by the IL client. ++ * See OMX_Component.h ++ */ ++OMX_ERRORTYPE omx_base_component_SetCallbacks( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_CALLBACKTYPE* pCallbacks, ++ OMX_IN OMX_PTR pAppData); ++ ++/** @brief Part of the standard OpenMAX function ++ * ++ * This function return the parameters not related to any port. ++ * These parameters are handled in the derived components ++ * See OMX_Core.h for standard reference. ++ */ ++OMX_ERRORTYPE omx_base_component_GetParameter( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_INDEXTYPE nParamIndex, ++ OMX_INOUT OMX_PTR ComponentParameterStructure); ++ ++/** @brief part of the standard openmax function ++ * ++ * This function return the parameters not related to any port, ++ * These parameters are handled in the derived components ++ * See OMX_Core.h for standard reference. ++ * ++ * @return OMX_ErrorUnsupportedIndex if the index is not supported or not handled here ++ */ ++OMX_ERRORTYPE omx_base_component_SetParameter( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_INDEXTYPE nParamIndex, ++ OMX_IN OMX_PTR ComponentParameterStructure); ++ ++/** @brief base GetConfig function ++ * ++ * This base function is not implemented. If a derived component ++ * needs to support any config, it must implement a derived ++ * version of this function and assign it to the correct pointer ++ * in the private component descriptor. ++ */ ++OMX_ERRORTYPE omx_base_component_GetConfig( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_INDEXTYPE nIndex, ++ OMX_INOUT OMX_PTR pComponentConfigStructure); ++ ++/** @brief base SetConfig function ++ * ++ * This base function is not implemented. If a derived component ++ * needs to support any config, it must implement a derived ++ * version of this function and assign it to the correct pointer ++ * in the private component descriptor. ++ */ ++OMX_ERRORTYPE omx_base_component_SetConfig( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_INDEXTYPE nIndex, ++ OMX_IN OMX_PTR pComponentConfigStructure); ++ ++/** @brief base function not implemented ++ * ++ * This function can be eventually implemented by a ++ * derived component if needed. ++ */ ++OMX_ERRORTYPE omx_base_component_GetExtensionIndex( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_STRING cParameterName, ++ OMX_OUT OMX_INDEXTYPE* pIndexType); ++ ++/** @returns the state of the component ++ * ++ * This function does not need any override by derived components. ++ */ ++OMX_ERRORTYPE omx_base_component_GetState( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_OUT OMX_STATETYPE* pState); ++ ++/** @brief standard SendCommand function ++ * ++ * In general this function does not need a overwrite, but ++ * a special derived component could do it. ++ */ ++OMX_ERRORTYPE omx_base_component_SendCommand( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_COMMANDTYPE Cmd, ++ OMX_IN OMX_U32 nParam, ++ OMX_IN OMX_PTR pCmdData); ++ ++/** @brief This standard functionality is called when the component is ++ * destroyed in the FreeHandle standard call. ++ * ++ * In this way the implementation of the FreeHandle is standard, ++ * and it does not need a support by a specific component loader. ++ * The implementaiton of the ComponentDeInit contains the ++ * implementation specific part of the destroying phase. ++ */ ++OMX_ERRORTYPE omx_base_component_ComponentDeInit( ++ OMX_IN OMX_HANDLETYPE hComponent); ++ ++/** @brief Component's message handler thread function ++ * ++ * Handles all messages coming from components and ++ * processes them by dispatching them back to the ++ * triggering component. ++ */ ++void* compMessageHandlerFunction(void*); ++ ++/** This is called by the component message entry point. ++ * In thea base version this function is named compMessageHandlerFunction ++ * ++ * A request is made by the component when some asynchronous services are needed: ++ * 1) A SendCommand() is to be processed ++ * 2) An error needs to be notified ++ * 3) ... ++ * ++ * @param openmaxStandComp the component itself ++ * @param message the message that has been passed to core ++ */ ++OMX_ERRORTYPE omx_base_component_MessageHandler(OMX_COMPONENTTYPE *openmaxStandComp,internalRequestMessageType* message); ++ ++/** ++ * This function verify Component State and Structure header ++ */ ++OMX_ERRORTYPE omx_base_component_ParameterSanityCheck( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_PTR pStructure, ++ OMX_IN size_t size); ++ ++OMX_ERRORTYPE omx_base_component_AllocateBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_PTR pAppPrivate, ++ OMX_IN OMX_U32 nSizeBytes); ++ ++OMX_ERRORTYPE omx_base_component_UseBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_PTR pAppPrivate, ++ OMX_IN OMX_U32 nSizeBytes, ++ OMX_IN OMX_U8* pBuffer); ++ ++OMX_ERRORTYPE omx_base_component_UseEGLImage ( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_PTR pAppPrivate, ++ OMX_IN void* eglImage); ++ ++OMX_ERRORTYPE omx_base_component_FreeBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); ++ ++OMX_ERRORTYPE omx_base_component_EmptyThisBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); ++ ++OMX_ERRORTYPE omx_base_component_FillThisBuffer( ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); ++ ++OMX_ERRORTYPE omx_base_component_ComponentTunnelRequest( ++ OMX_IN OMX_HANDLETYPE hComp, ++ OMX_IN OMX_U32 nPort, ++ OMX_IN OMX_HANDLETYPE hTunneledComp, ++ OMX_IN OMX_U32 nTunneledPort, ++ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); ++ ++#endif +diff --git a/alsa/omx_base_port.cpp b/alsa/omx_base_port.cpp +new file mode 100644 +index 0000000..67d003a +--- /dev/null ++++ b/alsa/omx_base_port.cpp +@@ -0,0 +1,1163 @@ ++/** ++ @file src/base/omx_base_port.c ++ ++ Base class for OpenMAX ports to be used in derived components. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-09-11 15:28:59 +0200 (Thu, 11 Sep 2008) $ ++ Revision $Rev: 614 $ ++ Author $Author: gsent $ ++*/ ++ ++#include ++#include ++#include ++//#include ++//#include ++ ++#include "omx_base_component.h" ++#include "omx_base_port.h" ++ ++/** The default value for the number of needed buffers for each port. */ ++#define DEFAULT_NUMBER_BUFFERS_PER_PORT 4 ++/** The default value for the minimum number of needed buffers for each port. */ ++#define DEFAULT_MIN_NUMBER_BUFFERS_PER_PORT 4 ++/** ++ * @brief The base contructor for the generic OpenMAX ST port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the component. ++ * It takes care of constructing the instance of the port and ++ * every object needed by the base port. ++ * ++ * @param openmaxStandComp in the component that holds the port ++ * @param openmaxStandPort the ST port to be initialized ++ * @param nPortIndex the index of the port ++ * @param isInput specifices if the port is an input or an output ++ * ++ * @return OMX_ErrorInsufficientResources if a memory allocation fails ++ */ ++ ++OMX_ERRORTYPE base_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput) { ++ ++ /* omx_base_component_PrivateType* omx_base_component_Private; */ ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ /* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; */ ++ ++ // create ports, but only if the subclass hasn't done it ++ if (!(*openmaxStandPort)) { ++ *openmaxStandPort = (omx_base_PortType*)calloc(1,sizeof (omx_base_PortType)); ++ } ++ ++ if (!(*openmaxStandPort)) { ++ return OMX_ErrorInsufficientResources; ++ } ++ ++ (*openmaxStandPort)->hTunneledComponent = NULL; ++ (*openmaxStandPort)->nTunnelFlags=0; ++ (*openmaxStandPort)->nTunneledPort=0; ++ (*openmaxStandPort)->eBufferSupplier=OMX_BufferSupplyUnspecified; ++ (*openmaxStandPort)->nNumTunnelBuffer=0; ++ (*openmaxStandPort)->bTunnelTearDown = OMX_FALSE; ++ ++ if((*openmaxStandPort)->pAllocSem==NULL) { ++ (*openmaxStandPort)->pAllocSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); ++ if((*openmaxStandPort)->pAllocSem==NULL) { ++ return OMX_ErrorInsufficientResources; ++ } ++ omx_tsem_init((*openmaxStandPort)->pAllocSem, 0); ++ } ++ (*openmaxStandPort)->nNumBufferFlushed=0; ++ (*openmaxStandPort)->bIsPortFlushed=OMX_FALSE; ++ /** Allocate and initialize buffer queue */ ++ if(!(*openmaxStandPort)->pBufferQueue) { ++ (*openmaxStandPort)->pBufferQueue = (omx_queue_t*)calloc(1,sizeof(omx_queue_t)); ++ if((*openmaxStandPort)->pBufferQueue==NULL) return OMX_ErrorInsufficientResources; ++ omx_queue_init((*openmaxStandPort)->pBufferQueue); ++ } ++ /*Allocate and initialise port semaphores*/ ++ if(!(*openmaxStandPort)->pBufferSem) { ++ (*openmaxStandPort)->pBufferSem = (omx_tsem_t*)calloc(1,sizeof(omx_tsem_t)); ++ if((*openmaxStandPort)->pBufferSem==NULL) return OMX_ErrorInsufficientResources; ++ omx_tsem_init((*openmaxStandPort)->pBufferSem, 0); ++ } ++ ++ (*openmaxStandPort)->nNumAssignedBuffers=0; ++ setHeader(&(*openmaxStandPort)->sPortParam, sizeof (OMX_PARAM_PORTDEFINITIONTYPE)); ++ (*openmaxStandPort)->sPortParam.nPortIndex = nPortIndex; ++ (*openmaxStandPort)->sPortParam.nBufferCountActual = DEFAULT_NUMBER_BUFFERS_PER_PORT; ++ (*openmaxStandPort)->sPortParam.nBufferCountMin = DEFAULT_MIN_NUMBER_BUFFERS_PER_PORT; ++ (*openmaxStandPort)->sPortParam.bEnabled = OMX_TRUE; ++ (*openmaxStandPort)->sPortParam.bPopulated = OMX_FALSE; ++ (*openmaxStandPort)->sPortParam.eDir = (isInput == OMX_TRUE)?OMX_DirInput:OMX_DirOutput; ++ ++ (*openmaxStandPort)->standCompContainer=openmaxStandComp; ++ (*openmaxStandPort)->bIsTransientToEnabled=OMX_FALSE; ++ (*openmaxStandPort)->bIsTransientToDisabled=OMX_FALSE; ++ (*openmaxStandPort)->bIsFullOfBuffers=OMX_FALSE; ++ (*openmaxStandPort)->bIsEmptyOfBuffers=OMX_FALSE; ++ (*openmaxStandPort)->bBufferStateAllocated = NULL; ++ (*openmaxStandPort)->pInternalBufferStorage = NULL; ++ ++ (*openmaxStandPort)->PortDestructor = &base_port_Destructor; ++ (*openmaxStandPort)->Port_AllocateBuffer = &base_port_AllocateBuffer; ++ (*openmaxStandPort)->Port_UseBuffer = &base_port_UseBuffer; ++ (*openmaxStandPort)->Port_FreeBuffer = &base_port_FreeBuffer; ++ (*openmaxStandPort)->Port_DisablePort = &base_port_DisablePort; ++ (*openmaxStandPort)->Port_EnablePort = &base_port_EnablePort; ++ (*openmaxStandPort)->Port_SendBufferFunction = &base_port_SendBufferFunction; ++ (*openmaxStandPort)->FlushProcessingBuffers = &base_port_FlushProcessingBuffers; ++ (*openmaxStandPort)->ReturnBufferFunction = &base_port_ReturnBufferFunction; ++ (*openmaxStandPort)->ComponentTunnelRequest = &base_port_ComponentTunnelRequest; ++ (*openmaxStandPort)->Port_AllocateTunnelBuffer = &base_port_AllocateTunnelBuffer; ++ (*openmaxStandPort)->Port_FreeTunnelBuffer = &base_port_FreeTunnelBuffer; ++ ++ return OMX_ErrorNone; ++} ++ ++OMX_ERRORTYPE base_port_Destructor(omx_base_PortType *openmaxStandPort){ ++ ++ if(openmaxStandPort->pAllocSem) { ++ omx_tsem_deinit(openmaxStandPort->pAllocSem); ++ free(openmaxStandPort->pAllocSem); ++ openmaxStandPort->pAllocSem=NULL; ++ } ++ /** Allocate and initialize buffer queue */ ++ if(openmaxStandPort->pBufferQueue) { ++ omx_queue_deinit(openmaxStandPort->pBufferQueue); ++ free(openmaxStandPort->pBufferQueue); ++ openmaxStandPort->pBufferQueue=NULL; ++ } ++ /*Allocate and initialise port semaphores*/ ++ if(openmaxStandPort->pBufferSem) { ++ omx_tsem_deinit(openmaxStandPort->pBufferSem); ++ free(openmaxStandPort->pBufferSem); ++ openmaxStandPort->pBufferSem=NULL; ++ } ++ ++ free(openmaxStandPort); ++ openmaxStandPort = NULL; ++ return OMX_ErrorNone; ++} ++ ++/** @brief Releases buffers under processing. ++ * This function must be implemented in the derived classes, for the ++ * specific processing ++ */ ++OMX_ERRORTYPE base_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort) { ++ omx_base_component_PrivateType* omx_base_component_Private; ++ OMX_BUFFERHEADERTYPE* pBuffer; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; ++ ++ if(openmaxStandPort->sPortParam.eDomain!=OMX_PortDomainOther) { /* clock buffers not used in the clients buffer managment function */ ++ pthread_mutex_lock(&omx_base_component_Private->flush_mutex); ++ openmaxStandPort->bIsPortFlushed=OMX_TRUE; ++ /*Signal the buffer management thread of port flush,if it is waiting for buffers*/ ++ if(omx_base_component_Private->bMgmtSem->semval==0) { ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ } ++ ++ if(omx_base_component_Private->state==OMX_StatePause ) { ++ /*Waiting at paused state*/ ++ omx_tsem_signal(omx_base_component_Private->bStateSem); ++ } ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s waiting for flush all condition port index =%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); ++ /* Wait until flush is completed */ ++ pthread_mutex_unlock(&omx_base_component_Private->flush_mutex); ++ omx_tsem_down(omx_base_component_Private->flush_all_condition); ++ } ++ ++ omx_tsem_reset(omx_base_component_Private->bMgmtSem); ++ ++ /* Flush all the buffers not under processing */ ++ while (openmaxStandPort->pBufferSem->semval > 0) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s TFlag=%x Flusing Port=%d,Semval=%d Qelem=%d\n", ++ __func__,(int)openmaxStandPort->nTunnelFlags,(int)openmaxStandPort->sPortParam.nPortIndex, ++ (int)openmaxStandPort->pBufferSem->semval,(int)openmaxStandPort->pBufferQueue->nelem); ++ ++ omx_tsem_down(openmaxStandPort->pBufferSem); ++ pBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(openmaxStandPort->pBufferQueue); ++ if (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s is returning io:%d buffer\n", ++ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); ++ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ++ ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); ++ } else { ++ ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); ++ } ++ } else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ omx_queue(openmaxStandPort->pBufferQueue,pBuffer); ++ } else { ++ (*(openmaxStandPort->BufferProcessedCallback))( ++ openmaxStandPort->standCompContainer, ++ omx_base_component_Private->callbackData, ++ pBuffer); ++ } ++ } ++ /*Port is tunneled and supplier and didn't received all it's buffer then wait for the buffers*/ ++ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ while(openmaxStandPort->pBufferQueue->nelem!= openmaxStandPort->nNumAssignedBuffers){ ++ omx_tsem_down(openmaxStandPort->pBufferSem); ++ DEBUG(DEB_LEV_PARAMS, "In %s Got a buffer qelem=%d\n",__func__,openmaxStandPort->pBufferQueue->nelem); ++ } ++ omx_tsem_reset(openmaxStandPort->pBufferSem); ++ } ++ ++ pthread_mutex_lock(&omx_base_component_Private->flush_mutex); ++ openmaxStandPort->bIsPortFlushed=OMX_FALSE; ++ pthread_mutex_unlock(&omx_base_component_Private->flush_mutex); ++ ++ omx_tsem_up(omx_base_component_Private->flush_condition); ++ ++ DEBUG(DEB_LEV_FULL_SEQ, "Out %s Port Index=%d bIsPortFlushed=%d Component %s\n", __func__, ++ (int)openmaxStandPort->sPortParam.nPortIndex,(int)openmaxStandPort->bIsPortFlushed,omx_base_component_Private->name); ++ ++ DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__, ++ (int)openmaxStandPort->nTunnelFlags, ++ (int)openmaxStandPort->pBufferQueue->nelem, ++ (int)openmaxStandPort->pBufferSem->semval, ++ (int)omx_base_component_Private->bMgmtSem->semval, ++ omx_base_component_Private->name); ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); ++ ++ return OMX_ErrorNone; ++} ++ ++/** @brief Disables the port. ++ * ++ * This function is called due to a request by the IL client ++ * ++ * @param openmaxStandPort the reference to the port ++ * ++ */ ++OMX_ERRORTYPE base_port_DisablePort(omx_base_PortType *openmaxStandPort) { ++ omx_base_component_PrivateType* omx_base_component_Private; ++ OMX_ERRORTYPE err=OMX_ErrorNone; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Port Index=%d\n", __func__,(int)openmaxStandPort->sPortParam.nPortIndex); ++ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; ++ if (! PORT_IS_ENABLED(openmaxStandPort)) { ++ return OMX_ErrorNone; ++ } ++ ++ if(omx_base_component_Private->state!=OMX_StateLoaded) { ++ if(!PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { ++ /*Signal Buffer Mgmt Thread if it's holding any buffer*/ ++ if(omx_base_component_Private->bMgmtSem->semval==0) { ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ } ++ /*Wait till all buffers are freed*/ ++ omx_tsem_down(openmaxStandPort->pAllocSem); ++ omx_tsem_reset(omx_base_component_Private->bMgmtSem); ++ } else { ++ /*Since port is being disabled then remove buffers from the queue*/ ++ while(openmaxStandPort->pBufferQueue->nelem > 0) { ++ omx_dequeue(openmaxStandPort->pBufferQueue); ++ } ++ ++ err = openmaxStandPort->Port_FreeTunnelBuffer(openmaxStandPort,openmaxStandPort->sPortParam.nPortIndex); ++ if(err!=OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR, "In %s Freeing Tunnel Buffer Error=%x\n",__func__,err); ++ } ++ DEBUG(DEB_LEV_PARAMS, "In %s Qelem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem); ++ } ++ ++ if(openmaxStandPort->bTunnelTearDown == OMX_TRUE){ ++ DEBUG(DEB_LEV_PARAMS, "In %s TearDown tunnel\n", __func__); ++ openmaxStandPort->hTunneledComponent = 0; ++ openmaxStandPort->nTunneledPort = 0; ++ openmaxStandPort->nTunnelFlags = 0; ++ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyUnspecified; ++ openmaxStandPort->bTunnelTearDown = OMX_FALSE; ++ } ++ } ++ ++ DEBUG(DEB_LEV_PARAMS, "In %s TFlag=%x Qelem=%d BSem=%d bMgmtsem=%d component=%s\n", __func__, ++ (int)openmaxStandPort->nTunnelFlags, ++ (int)openmaxStandPort->pBufferQueue->nelem, ++ (int)openmaxStandPort->pBufferSem->semval, ++ (int)omx_base_component_Private->bMgmtSem->semval, ++ omx_base_component_Private->name); ++ openmaxStandPort->bIsTransientToDisabled = OMX_FALSE; ++ openmaxStandPort->sPortParam.bEnabled = OMX_FALSE; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "Out %s Port Index=%d isEnabled=%d\n", __func__, ++ (int)openmaxStandPort->sPortParam.nPortIndex, ++ (int)openmaxStandPort->sPortParam.bEnabled); ++ return err; ++} ++ ++/** @brief Enables the port. ++ * ++ * This function is called due to a request by the IL client ++ * ++ * @param openmaxStandPort the reference to the port ++ * ++ */ ++OMX_ERRORTYPE base_port_EnablePort(omx_base_PortType *openmaxStandPort) { ++ omx_base_component_PrivateType* omx_base_component_Private; ++ OMX_ERRORTYPE err=OMX_ErrorNone; ++ OMX_U32 i; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ if (PORT_IS_ENABLED(openmaxStandPort)) { ++ return OMX_ErrorNone; ++ } ++ omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; ++ ++ openmaxStandPort->sPortParam.bEnabled = OMX_TRUE; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s port T flag=%x popu=%d state=%x\n", __func__, ++ (int)openmaxStandPort->nTunnelFlags, ++ (int)openmaxStandPort->sPortParam.bPopulated, ++ (int)omx_base_component_Private->state); ++ ++ ++ if (!PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { ++ /*Wait Till All buffers are allocated if the component state is not Loaded*/ ++ if (omx_base_component_Private->state!=OMX_StateLoaded && omx_base_component_Private->state!=OMX_StateWaitForResources) { ++ omx_tsem_down(openmaxStandPort->pAllocSem); ++ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; ++ } ++ } else { //Port Tunneled and supplier. Then allocate tunnel buffers ++ err= openmaxStandPort->Port_AllocateTunnelBuffer(openmaxStandPort, openmaxStandPort->sPortParam.nPortIndex, openmaxStandPort->sPortParam.nBufferSize); ++ if(err!=OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR, "In %s Allocating Tunnel Buffer Error=%x\n",__func__,err); ++ return err; ++ } ++ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; ++ if (omx_base_component_Private->state==OMX_StateExecuting) { ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual;i++) { ++ omx_tsem_up(openmaxStandPort->pBufferSem); ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ } ++ } ++ DEBUG(DEB_LEV_PARAMS, "In %s Qelem=%d BSem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem,openmaxStandPort->pBufferSem->semval); ++ } ++ ++ openmaxStandPort->bIsTransientToEnabled = OMX_FALSE; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "Out of %s\n", __func__); ++ ++ return OMX_ErrorNone; ++} ++ ++/** @brief Called by the standard allocate buffer, it implements a base functionality. ++ * ++ * This function can be overriden if the allocation of the buffer is not a simply calloc call. ++ * The parameters are the same as the standard function, except for the handle of the port ++ * instead of the handler of the component ++ * When the buffers needed by this port are all assigned or allocated, the variable ++ * bIsFullOfBuffers becomes equal to OMX_TRUE ++ */ ++OMX_ERRORTYPE base_port_AllocateBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE** pBuffer, ++ OMX_U32 nPortIndex, ++ OMX_PTR pAppPrivate, ++ OMX_U32 nSizeBytes) { ++ ++ unsigned int i; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ ++ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ return OMX_ErrorBadPortIndex; ++ } ++ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if ((omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) || (omx_base_component_Private->state!=OMX_StateLoaded)) { ++ if (!openmaxStandPort->bIsTransientToEnabled) { ++ DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__); ++ return OMX_ErrorIncorrectStateTransition; ++ } ++ } ++ ++ if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { ++ DEBUG(DEB_LEV_ERR, "In %s: Requested Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, (unsigned long)nSizeBytes, (unsigned long)openmaxStandPort->sPortParam.nBufferSize); ++ return OMX_ErrorIncorrectStateTransition; ++ } ++ ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { ++ openmaxStandPort->pInternalBufferStorage[i] = (OMX_BUFFERHEADERTYPE*)calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); ++ if (!openmaxStandPort->pInternalBufferStorage[i]) { ++ return OMX_ErrorInsufficientResources; ++ } ++ setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); ++ /* allocate the buffer */ ++ openmaxStandPort->pInternalBufferStorage[i]->pBuffer = (OMX_U8*)calloc(1,nSizeBytes); ++ if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer==NULL) { ++ return OMX_ErrorInsufficientResources; ++ } ++ openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = nSizeBytes; ++ openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; ++ openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; ++ *pBuffer = openmaxStandPort->pInternalBufferStorage[i]; ++ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED; ++ openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; ++ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ++ openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ } else { ++ openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ } ++ openmaxStandPort->nNumAssignedBuffers++; ++ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); ++ ++ if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { ++ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; ++ openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; ++ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__,(int)nPortIndex); ++ omx_tsem_up(openmaxStandPort->pAllocSem); ++ } ++ return OMX_ErrorNone; ++ } ++ } ++ DEBUG(DEB_LEV_ERR, "In %s Error: no available buffers\n",__func__); ++ return OMX_ErrorInsufficientResources; ++} ++ ++/** @brief Called by the standard use buffer, it implements a base functionality. ++ * ++ * This function can be overriden if the use buffer implicate more complicated operations. ++ * The parameters are the same as the standard function, except for the handle of the port ++ * instead of the handler of the component. ++ * When the buffers needed by this port are all assigned or allocated, the variable ++ * bIsFullOfBuffers becomes equal to OMX_TRUE ++ */ ++OMX_ERRORTYPE base_port_UseBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE** ppBufferHdr, ++ OMX_U32 nPortIndex, ++ OMX_PTR pAppPrivate, ++ OMX_U32 nSizeBytes, ++ OMX_U8* pBuffer) { ++ ++ unsigned int i; ++ OMX_BUFFERHEADERTYPE* returnBufferHeader; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ return OMX_ErrorBadPortIndex; ++ } ++ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { ++ if (!openmaxStandPort->bIsTransientToEnabled) { ++ DEBUG(DEB_LEV_ERR, "In %s: The port of Comp %s is not allowed to receive buffers\n", __func__,omx_base_component_Private->name); ++ return OMX_ErrorIncorrectStateTransition; ++ } ++ } ++ ++ /// AND ++ /* ++ if(nSizeBytes < openmaxStandPort->sPortParam.nBufferSize) { ++ DEBUG(DEB_LEV_ERR, "In %s: Given Buffer Size %lu is less than Minimum Buffer Size %lu\n", __func__, nSizeBytes, openmaxStandPort->sPortParam.nBufferSize); ++ return OMX_ErrorIncorrectStateTransition; ++ } ++ */ ++ /// AND ++ ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { ++ openmaxStandPort->pInternalBufferStorage[i] = (OMX_BUFFERHEADERTYPE*)calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); ++ if (!openmaxStandPort->pInternalBufferStorage[i]) { ++ return OMX_ErrorInsufficientResources; ++ } ++ openmaxStandPort->bIsEmptyOfBuffers = OMX_FALSE; ++ setHeader(openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE)); ++ ++ openmaxStandPort->pInternalBufferStorage[i]->pBuffer = pBuffer; ++ openmaxStandPort->pInternalBufferStorage[i]->nAllocLen = nSizeBytes; ++ openmaxStandPort->pInternalBufferStorage[i]->pPlatformPrivate = openmaxStandPort; ++ openmaxStandPort->pInternalBufferStorage[i]->pAppPrivate = pAppPrivate; ++ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ASSIGNED; ++ openmaxStandPort->bBufferStateAllocated[i] |= HEADER_ALLOCATED; ++ returnBufferHeader = (OMX_BUFFERHEADERTYPE*)calloc(1,sizeof(OMX_BUFFERHEADERTYPE)); ++ if (!returnBufferHeader) { ++ return OMX_ErrorInsufficientResources; ++ } ++ setHeader(returnBufferHeader, sizeof(OMX_BUFFERHEADERTYPE)); ++ returnBufferHeader->pBuffer = pBuffer; ++ returnBufferHeader->nAllocLen = nSizeBytes; ++ returnBufferHeader->pPlatformPrivate = openmaxStandPort; ++ returnBufferHeader->pAppPrivate = pAppPrivate; ++ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ++ openmaxStandPort->pInternalBufferStorage[i]->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ returnBufferHeader->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ } else { ++ openmaxStandPort->pInternalBufferStorage[i]->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ returnBufferHeader->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ } ++ *ppBufferHdr = returnBufferHeader; ++ openmaxStandPort->nNumAssignedBuffers++; ++ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); ++ ++ if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { ++ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; ++ openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; ++ omx_tsem_up(openmaxStandPort->pAllocSem); ++ } ++ return OMX_ErrorNone; ++ } ++ } ++ DEBUG(DEB_LEV_ERR, "In %s Error: no available buffers CompName=%s\n",__func__,omx_base_component_Private->name); ++ return OMX_ErrorInsufficientResources; ++} ++ ++/** @brief Called by the standard function. ++ * ++ * It frees the buffer header and in case also the buffer itself, if needed. ++ * When all the bufers are done, the variable bIsEmptyOfBuffers is set to OMX_TRUE ++ */ ++OMX_ERRORTYPE base_port_FreeBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_U32 nPortIndex, ++ OMX_BUFFERHEADERTYPE* pBuffer) { ++ ++ unsigned int i; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ ++ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ return OMX_ErrorBadPortIndex; ++ } ++ if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) { ++ if (!openmaxStandPort->bIsTransientToDisabled) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__); ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (omxComponent, ++ omx_base_component_Private->callbackData, ++ OMX_EventError, /* The command was completed */ ++ OMX_ErrorPortUnpopulated, /* The commands was a OMX_CommandStateSet */ ++ nPortIndex, /* The state has been changed in message->messageParam2 */ ++ NULL); ++ } ++ } ++ ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) { ++ ++ openmaxStandPort->bIsFullOfBuffers = OMX_FALSE; ++ if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) { ++ if(openmaxStandPort->pInternalBufferStorage[i]->pBuffer){ ++ DEBUG(DEB_LEV_PARAMS, "In %s freeing %i pBuffer=%x\n",__func__, (int)i, (int)openmaxStandPort->pInternalBufferStorage[i]->pBuffer); ++ free(openmaxStandPort->pInternalBufferStorage[i]->pBuffer); ++ openmaxStandPort->pInternalBufferStorage[i]->pBuffer=NULL; ++ } ++ } else if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ASSIGNED) { ++ free(pBuffer); ++ } ++ if(openmaxStandPort->bBufferStateAllocated[i] & HEADER_ALLOCATED) { ++ free(openmaxStandPort->pInternalBufferStorage[i]); ++ openmaxStandPort->pInternalBufferStorage[i]=NULL; ++ } ++ ++ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; ++ ++ openmaxStandPort->nNumAssignedBuffers--; ++ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); ++ ++ if (openmaxStandPort->nNumAssignedBuffers == 0) { ++ openmaxStandPort->sPortParam.bPopulated = OMX_FALSE; ++ openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE; ++ omx_tsem_up(openmaxStandPort->pAllocSem); ++ } ++ return OMX_ErrorNone; ++ } ++ } ++ return OMX_ErrorInsufficientResources; ++} ++ ++OMX_ERRORTYPE base_port_AllocateTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_U32 nSizeBytes) ++{ ++ unsigned int i; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++ OMX_U8* pBuffer=NULL; ++ OMX_ERRORTYPE eError=OMX_ErrorNone; ++ OMX_U32 numRetry=0; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s, nPortIndex=%d, nSizeBytes=%d, nBufferCountActual=%d\n", __func__, nPortIndex, nSizeBytes, openmaxStandPort->sPortParam.nBufferCountActual); ++ ++ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ DEBUG(DEB_LEV_ERR, "In %s: Bad Port Index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ if (! PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ DEBUG(DEB_LEV_ERR, "In %s: Port is not tunneled Flag=%x\n", __func__, (int)openmaxStandPort->nTunnelFlags); ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if (omx_base_component_Private->transientState != OMX_TransStateLoadedToIdle) { ++ if (!openmaxStandPort->bIsTransientToEnabled) { ++ DEBUG(DEB_LEV_ERR, "In %s: The port is not allowed to receive buffers\n", __func__); ++ return OMX_ErrorIncorrectStateTransition; ++ } ++ } ++ ++ if( NULL == openmaxStandPort->bBufferStateAllocated ) ++ { ++ openmaxStandPort->bBufferStateAllocated = (BUFFER_STATUS_FLAG*)calloc(openmaxStandPort->sPortParam.nBufferCountActual, sizeof(openmaxStandPort->bBufferStateAllocated[0] )); ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) ++ { ++ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_FREE; ++ } ++ } ++ ++ if( NULL == openmaxStandPort->pInternalBufferStorage ) ++ { ++ openmaxStandPort->pInternalBufferStorage = (OMX_BUFFERHEADERTYPE**)calloc(openmaxStandPort->sPortParam.nBufferCountActual, sizeof(OMX_BUFFERHEADERTYPE*)); ++ /*for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++) ++ { ++ //memset(&openmaxStandPort->pInternalBufferStorage[i], 0, sizeof(OMX_BUFFERHEADERTYPE*)); ++ setHeader(&openmaxStandPort->pInternalBufferStorage[i], sizeof(OMX_BUFFERHEADERTYPE*)); ++ }*/ ++ } ++ ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (openmaxStandPort->bBufferStateAllocated[i] == BUFFER_FREE) { ++ pBuffer = (OMX_U8*)calloc(1,nSizeBytes); ++ if(pBuffer==NULL) { ++ return OMX_ErrorInsufficientResources; ++ } ++ /*Retry more than once, if the tunneled component is not in Loaded->Idle State*/ ++ while(numRetry 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) && numRetryname,(int)numRetry); ++ break; ++ } ++ } ++ if(eError!=OMX_ErrorNone) { ++ free(pBuffer); ++ pBuffer = NULL; ++ DEBUG(DEB_LEV_ERR,"In %s Tunneled Component Couldn't Use Buffer %x \n",__func__,(int)eError); ++ return eError; ++ } ++ openmaxStandPort->bBufferStateAllocated[i] = BUFFER_ALLOCATED; ++ openmaxStandPort->nNumAssignedBuffers++; ++ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); ++ ++ if (openmaxStandPort->sPortParam.nBufferCountActual == openmaxStandPort->nNumAssignedBuffers) { ++ openmaxStandPort->sPortParam.bPopulated = OMX_TRUE; ++ openmaxStandPort->bIsFullOfBuffers = OMX_TRUE; ++ DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s nPortIndex=%d\n",__func__, (int)nPortIndex); ++ } ++ omx_queue(openmaxStandPort->pBufferQueue, openmaxStandPort->pInternalBufferStorage[i]); ++ } ++ } ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Allocated all buffers\n",__func__); ++ return OMX_ErrorNone; ++} ++ ++OMX_ERRORTYPE base_port_FreeTunnelBuffer(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex) ++{ ++ unsigned int i; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++ OMX_ERRORTYPE eError=OMX_ErrorNone; ++ OMX_U32 numRetry=0; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ ++ if (nPortIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ DEBUG(DEB_LEV_ERR, "In %s: Bad Port Index\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ if (! PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) { ++ DEBUG(DEB_LEV_ERR, "In %s: Port is not tunneled\n", __func__); ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if (omx_base_component_Private->transientState != OMX_TransStateIdleToLoaded) { ++ if (!openmaxStandPort->bIsTransientToDisabled) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s: The port is not allowed to free the buffers\n", __func__); ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (omxComponent, ++ omx_base_component_Private->callbackData, ++ OMX_EventError, /* The command was completed */ ++ OMX_ErrorPortUnpopulated, /* The commands was a OMX_CommandStateSet */ ++ nPortIndex, /* The state has been changed in message->messageParam2 */ ++ NULL); ++ } ++ } ++ ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (openmaxStandPort->bBufferStateAllocated[i] & (BUFFER_ASSIGNED | BUFFER_ALLOCATED)) { ++ ++ openmaxStandPort->bIsFullOfBuffers = OMX_FALSE; ++ if (openmaxStandPort->bBufferStateAllocated[i] & BUFFER_ALLOCATED) { ++ free(openmaxStandPort->pInternalBufferStorage[i]->pBuffer); ++ openmaxStandPort->pInternalBufferStorage[i]->pBuffer = NULL; ++ } ++ /*Retry more than once, if the tunneled component is not in Idle->Loaded State*/ ++ while(numRetry 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) && numRetrybBufferStateAllocated[i] = BUFFER_FREE; ++ ++ openmaxStandPort->nNumAssignedBuffers--; ++ DEBUG(DEB_LEV_PARAMS, "openmaxStandPort->nNumAssignedBuffers %i\n", (int)openmaxStandPort->nNumAssignedBuffers); ++ ++ if (openmaxStandPort->nNumAssignedBuffers == 0) { ++ openmaxStandPort->sPortParam.bPopulated = OMX_FALSE; ++ openmaxStandPort->bIsEmptyOfBuffers = OMX_TRUE; ++ //omx_tsem_up(openmaxStandPort->pAllocSem); ++ } ++ } ++ } ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Qelem=%d BSem=%d\n", __func__,openmaxStandPort->pBufferQueue->nelem,openmaxStandPort->pBufferSem->semval); ++ return OMX_ErrorNone; ++} ++ ++/** @brief the entry point for sending buffers to the port ++ * ++ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on ++ * the nature of the port, that can be an input or output port. ++ */ ++OMX_ERRORTYPE base_port_SendBufferFunction( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE* pBuffer) { ++ ++ OMX_ERRORTYPE err; ++ OMX_U32 portIndex; ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++#if NO_GST_OMX_PATCH ++ unsigned int i; ++#endif ++ portIndex = (openmaxStandPort->sPortParam.eDir == OMX_DirInput)?pBuffer->nInputPortIndex:pBuffer->nOutputPortIndex; ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s portIndex %lu\n", __func__, (unsigned long)portIndex); ++ ++ if (portIndex != openmaxStandPort->sPortParam.nPortIndex) { ++ DEBUG(DEB_LEV_ERR, "In %s: wrong port for this operation portIndex=%d port->portIndex=%d\n", __func__, (int)portIndex, (int)openmaxStandPort->sPortParam.nPortIndex); ++ return OMX_ErrorBadPortIndex; ++ } ++ ++ if(omx_base_component_Private->state == OMX_StateInvalid) { ++ DEBUG(DEB_LEV_ERR, "In %s: we are in OMX_StateInvalid\n", __func__); ++ return OMX_ErrorInvalidState; ++ } ++ ++ if(omx_base_component_Private->state != OMX_StateExecuting && ++ omx_base_component_Private->state != OMX_StatePause && ++ omx_base_component_Private->state != OMX_StateIdle) { ++ DEBUG(DEB_LEV_ERR, "In %s: we are not in executing/paused/idle state, but in %d\n", __func__, omx_base_component_Private->state); ++ return OMX_ErrorIncorrectStateOperation; ++ } ++ if (!PORT_IS_ENABLED(openmaxStandPort) || (PORT_IS_BEING_DISABLED(openmaxStandPort) && !PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort)) || ++ (omx_base_component_Private->transientState == OMX_TransStateExecutingToIdle && ++ (PORT_IS_TUNNELED(openmaxStandPort) && !PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)))) { ++ DEBUG(DEB_LEV_ERR, "In %s: Port %d is disabled comp = %s \n", __func__, (int)portIndex,omx_base_component_Private->name); ++ return OMX_ErrorIncorrectStateOperation; ++ } ++ ++ /* Temporarily disable this check for gst-openmax */ ++#if NO_GST_OMX_PATCH ++ { ++ OMX_BOOL foundBuffer = OMX_FALSE; ++ if(pBuffer!=NULL && pBuffer->pBuffer!=NULL) { ++ for(i=0; i < openmaxStandPort->sPortParam.nBufferCountActual; i++){ ++ if (pBuffer->pBuffer == openmaxStandPort->pInternalBufferStorage[i]->pBuffer) { ++ foundBuffer = OMX_TRUE; ++ break; ++ } ++ } ++ } ++ if (!foundBuffer) { ++ return OMX_ErrorBadParameter; ++ } ++ } ++#endif ++ ++ if ((err = checkHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE))) != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR, "In %s: received wrong buffer header on input port\n", __func__); ++ return err; ++ } ++ ++ /* And notify the buffer management thread we have a fresh new buffer to manage */ ++ if(!PORT_IS_BEING_FLUSHED(openmaxStandPort) && !(PORT_IS_BEING_DISABLED(openmaxStandPort) && PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort))){ ++ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); ++ omx_tsem_up(openmaxStandPort->pBufferSem); ++ DEBUG(DEB_LEV_PARAMS, "In %s Signalling bMgmtSem Port Index=%d\n",__func__, (int)portIndex); ++ omx_tsem_up(omx_base_component_Private->bMgmtSem); ++ }else if(PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)){ ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s: Comp %s received io:%d buffer\n", ++ __func__,omx_base_component_Private->name,(int)openmaxStandPort->sPortParam.nPortIndex); ++ omx_queue(openmaxStandPort->pBufferQueue, pBuffer); ++ omx_tsem_up(openmaxStandPort->pBufferSem); ++ } ++ else { // If port being flushed and not tunneled then return error ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s \n", __func__); ++ return OMX_ErrorIncorrectStateOperation; ++ } ++ return OMX_ErrorNone; ++} ++ ++/** ++ * Returns Input/Output Buffer to the IL client or Tunneled Component ++ */ ++OMX_ERRORTYPE base_port_ReturnBufferFunction(omx_base_PortType* openmaxStandPort,OMX_BUFFERHEADERTYPE* pBuffer){ ++ omx_base_component_PrivateType* omx_base_component_Private=(omx_base_component_PrivateType*)openmaxStandPort->standCompContainer->pComponentPrivate; ++ omx_queue_t* pQueue = openmaxStandPort->pBufferQueue; ++ omx_tsem_t* pSem = openmaxStandPort->pBufferSem; ++ OMX_ERRORTYPE eError = OMX_ErrorNone; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ if (PORT_IS_TUNNELED(openmaxStandPort) && ++ ! PORT_IS_BUFFER_SUPPLIER(openmaxStandPort)) { ++ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ++ pBuffer->nOutputPortIndex = openmaxStandPort->nTunneledPort; ++ pBuffer->nInputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); ++ if(eError != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR, "In %s eError %08x in FillThis Buffer from Component %s Non-Supplier\n", ++ __func__, eError,omx_base_component_Private->name); ++ } ++ } else { ++ pBuffer->nInputPortIndex = openmaxStandPort->nTunneledPort; ++ pBuffer->nOutputPortIndex = openmaxStandPort->sPortParam.nPortIndex; ++ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); ++ if(eError != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR, "In %s eError %08x in EmptyThis Buffer from Component %s Non-Supplier\n", ++ __func__, eError,omx_base_component_Private->name); ++ } ++ } ++ } ++ else if (PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(openmaxStandPort) && ++ !PORT_IS_BEING_FLUSHED(openmaxStandPort)) { ++ if (!PORT_IS_ENABLED(openmaxStandPort) || PORT_IS_BEING_DISABLED(openmaxStandPort)) { ++ omx_queue(pQueue, pBuffer); ++ omx_tsem_up(pSem); ++ } else if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ++ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->FillThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); ++ /// AND TODO: ++ /// see 2.2 of http://www.khronos.org/registry/omxil/specs/OpenMAX_IL_1_1_2_Application_Note_318.pdf ++ if(eError != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in FillThis Buffer from Component %s Supplier\n", ++ __func__, eError,omx_base_component_Private->name); ++ /*If Error Occured then queue the buffer*/ ++ omx_queue(pQueue, pBuffer); ++ omx_tsem_up(pSem); ++ } ++ } else { ++ eError = ((OMX_COMPONENTTYPE*)(openmaxStandPort->hTunneledComponent))->EmptyThisBuffer(openmaxStandPort->hTunneledComponent, pBuffer); ++ if(eError != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s eError %08x in EmptyThis Buffer from Component %s Supplier\n", ++ __func__, eError,omx_base_component_Private->name); ++ /*If Error Occured then queue the buffer*/ ++ omx_queue(pQueue, pBuffer); ++ omx_tsem_up(pSem); ++ } ++ } ++ }else if (! PORT_IS_TUNNELED(openmaxStandPort)){ ++ (*(openmaxStandPort->BufferProcessedCallback))( ++ openmaxStandPort->standCompContainer, ++ omx_base_component_Private->callbackData, ++ pBuffer); ++ } ++ else { ++ omx_queue(pQueue,pBuffer); ++ openmaxStandPort->nNumBufferFlushed++; ++ } ++ ++ return OMX_ErrorNone; ++} ++ ++ ++OMX_ERRORTYPE base_port_ComponentTunnelRequest(omx_base_PortType* openmaxStandPort,OMX_IN OMX_HANDLETYPE hTunneledComp,OMX_IN OMX_U32 nTunneledPort,OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { ++ OMX_ERRORTYPE err = OMX_ErrorNone; ++ OMX_PARAM_PORTDEFINITIONTYPE param; ++ OMX_PARAM_BUFFERSUPPLIERTYPE pSupplier; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s\n", __func__); ++ ++ if (pTunnelSetup == NULL || hTunneledComp == 0) { ++ /* cancel previous tunnel */ ++ OMX_COMPONENTTYPE* omxComponent = openmaxStandPort->standCompContainer; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)omxComponent->pComponentPrivate; ++ if (PORT_IS_TUNNELED(openmaxStandPort) && (PORT_IS_BEING_DISABLED(openmaxStandPort) || (omx_base_component_Private->transientState == OMX_TransStateIdleToLoaded))) ++ { ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s Scheduled TearDown port=%d PORT_IS_BEING_DISABLED(%d) transientState=%d\n", ++ __func__, openmaxStandPort->sPortParam.nPortIndex, PORT_IS_BEING_DISABLED(openmaxStandPort), omx_base_component_Private->transientState); ++ openmaxStandPort->bTunnelTearDown = OMX_TRUE; ++ } ++ else { ++ openmaxStandPort->hTunneledComponent = 0; ++ openmaxStandPort->nTunneledPort = 0; ++ openmaxStandPort->nTunnelFlags = 0; ++ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyUnspecified; ++ } ++ return OMX_ErrorNone; ++ } ++ ++ if (openmaxStandPort->sPortParam.eDir == OMX_DirInput) { ++ /* Get Port Definition of the Tunnelled Component*/ ++ param.nPortIndex=nTunneledPort; ++ setHeader(¶m, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); ++ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m); ++ if (err != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR,"In %s Get Tunneled Port Definition error=0x%08x Line=%d\n",__func__,err,__LINE__); ++ // compatibility not reached ++ return OMX_ErrorPortsNotCompatible; ++ } ++ ++ // Negotiate buffer params ++ param.nBufferCountActual = param.nBufferCountMin > openmaxStandPort->sPortParam.nBufferCountMin ? ++ param.nBufferCountMin : openmaxStandPort->sPortParam.nBufferCountMin; ++ openmaxStandPort->sPortParam.nBufferCountActual = param.nBufferCountActual; ++ ++ param.nBufferSize = param.nBufferSize > openmaxStandPort->sPortParam.nBufferSize ? ++ param.nBufferSize : openmaxStandPort->sPortParam.nBufferSize; ++ openmaxStandPort->sPortParam.nBufferSize = param.nBufferSize; ++ ++ err = OMX_SetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m); ++ if (err != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR,"In %s Set Tunneled Port Definition error=0x%08x Line=%d\n",__func__,err,__LINE__); ++ return OMX_ErrorPortsNotCompatible; ++ } ++ ++ openmaxStandPort->nNumTunnelBuffer=param.nBufferCountActual; //nBufferCountMin; ++ ++ if(param.eDomain!=openmaxStandPort->sPortParam.eDomain) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ if(param.eDomain==OMX_PortDomainAudio) { ++ if(param.format.audio.eEncoding == OMX_AUDIO_CodingMax) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } else if(param.eDomain==OMX_PortDomainVideo) { ++ if(param.format.video.eCompressionFormat == OMX_VIDEO_CodingMax) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } else if(param.eDomain==OMX_PortDomainOther) { ++ if(param.format.other.eFormat == OMX_OTHER_FormatMax) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } ++ ++ /* Get Buffer Supplier type of the Tunnelled Component*/ ++ pSupplier.nPortIndex=nTunneledPort; ++ setHeader(&pSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); ++ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier, &pSupplier); ++ if (err != OMX_ErrorNone) { ++ // compatibility not reached ++ DEBUG(DEB_LEV_ERR,"In %s Tunneled Buffer Supplier error=0x%08x Line=%d\n",__func__,err,__LINE__); ++ return OMX_ErrorPortsNotCompatible; ++ } else { ++ DEBUG(DEB_LEV_FULL_SEQ,"Tunneled Port eBufferSupplier=%x\n",pSupplier.eBufferSupplier); ++ } ++ ++ // store the current callbacks, if defined ++ openmaxStandPort->hTunneledComponent = hTunneledComp; ++ openmaxStandPort->nTunneledPort = nTunneledPort; ++ ++ /*Check for and set proprietary communication flag. ++ In case a component support Deep Tunneling should set it's tunnel flag to PROPRIETARY_COMMUNICATION_ESTABLISHED */ ++ /// AND: No proprietary communication ++ /* ++ if(PORT_IS_DEEP_TUNNELED(openmaxStandPort)) { ++ OMX_VENDOR_PROP_TUNNELSETUPTYPE pPropTunnelSetup; ++ pPropTunnelSetup.nPortIndex = nTunneledPort; ++ ++ err = OMX_GetParameter(hTunneledComp, OMX_IndexVendorCompPropTunnelFlags, &pPropTunnelSetup); ++ if (err != OMX_ErrorNone) { ++ // compatibility not reached ++ DEBUG(DEB_LEV_ERR,"In %s Proprietary Tunneled Buffer Supplier nTunneledPort=%d error=0x%08x Line=%d \n", ++ __func__,(int)pPropTunnelSetup.nPortIndex,err,__LINE__); ++ openmaxStandPort->nTunnelFlags = 0; ++ } else { ++ openmaxStandPort->nTunnelFlags = PROPRIETARY_COMMUNICATION_ESTABLISHED; ++ } ++ } else { ++ openmaxStandPort->nTunnelFlags = 0; ++ } ++ */ ++ openmaxStandPort->nTunnelFlags = 0; ++ /// AND ++ ++ // Negotiation ++ if (pTunnelSetup->nTunnelFlags & OMX_PORTTUNNELFLAG_READONLY) { ++ // the buffer provider MUST be the output port provider ++ /// AND: WRONG!!!! ++ /* ++ pTunnelSetup->eSupplier = OMX_BufferSupplyInput; ++ openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; ++ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; ++ */ ++ DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_PORTTUNNELFLAG_READONLY Line=%d\n",__func__,__LINE__); ++ pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; ++ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; ++ /// AND ++ } else { ++ //if (pTunnelSetup->eSupplier == OMX_BufferSupplyInput) { ++ // DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupplyInput Line=%d\n",__func__,__LINE__); ++ // openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; ++ // openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; ++ //} else if (pTunnelSetup->eSupplier == OMX_BufferSupplyUnspecified) { ++ // /// AND TODO: Can be reversed???? ++ // DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupplyUnspecified Line=%d\n",__func__,__LINE__); ++ // pTunnelSetup->eSupplier = OMX_BufferSupplyInput; ++ // openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; ++ // openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; ++ // //pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; ++ // //openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; ++ // /// AND ++ //} else if (pTunnelSetup->eSupplier == OMX_BufferSupplyOutput){ ++ // DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupplyOutput Line=%d\n",__func__,__LINE__); ++ // pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; ++ // openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; ++ //} else { ++ // DEBUG(DEB_LEV_ERR,"In %s --------------> undefined pTunnelSetup->eSupplier = %d Line=%d\n",__func__,(int)pTunnelSetup->eSupplier,__LINE__); ++ //} ++ ++ // fixed to work only in this direction ++ DEBUG(DEB_LEV_ERR,"In %s --------------> OMX_BufferSupply Line=%d\n",__func__,__LINE__); ++ pTunnelSetup->eSupplier = OMX_BufferSupplyInput; ++ openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; ++ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyInput; ++ /// AND ++ ++ } ++ openmaxStandPort->nTunnelFlags |= TUNNEL_ESTABLISHED; ++ ++ /* Set Buffer Supplier type of the Tunnelled Component after final negotiation*/ ++ pSupplier.nPortIndex=nTunneledPort; ++ pSupplier.eBufferSupplier=openmaxStandPort->eBufferSupplier; ++ err = OMX_SetParameter(hTunneledComp, OMX_IndexParamCompBufferSupplier, &pSupplier); ++ if (err != OMX_ErrorNone) { ++ // compatibility not reached ++ DEBUG(DEB_LEV_ERR,"In %s Tunneled Buffer Supplier error=0x%08x Line=%d\n",__func__,err,__LINE__); ++ openmaxStandPort->nTunnelFlags=0; ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } else { ++ // output port ++ // all the consistency checks are under other component responsibility ++ ++ /* Get Port Definition of the Tunnelled Component*/ ++ param.nPortIndex=nTunneledPort; ++ setHeader(¶m, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); ++ err = OMX_GetParameter(hTunneledComp, OMX_IndexParamPortDefinition, ¶m); ++ if (err != OMX_ErrorNone) { ++ DEBUG(DEB_LEV_ERR,"In %s Tunneled Port Definition error=0x%08x Line=%d\n",__func__,err,__LINE__); ++ // compatibility not reached ++ return OMX_ErrorPortsNotCompatible; ++ } ++ if(param.eDomain!=openmaxStandPort->sPortParam.eDomain) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ ++ if(param.eDomain==OMX_PortDomainAudio) { ++ if(param.format.audio.eEncoding == OMX_AUDIO_CodingMax) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } else if(param.eDomain==OMX_PortDomainVideo) { ++ if(param.format.video.eCompressionFormat == OMX_VIDEO_CodingMax) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } else if(param.eDomain==OMX_PortDomainOther) { ++ if(param.format.other.eFormat == OMX_OTHER_FormatMax) { ++ return OMX_ErrorPortsNotCompatible; ++ } ++ } ++ ++ /*Check for and set proprietary communication flag*/ ++ if(PORT_IS_DEEP_TUNNELED(openmaxStandPort)) { ++ OMX_VENDOR_PROP_TUNNELSETUPTYPE pPropTunnelSetup; ++ pPropTunnelSetup.nPortIndex = nTunneledPort; ++ ++ err = OMX_GetParameter(hTunneledComp, (OMX_INDEXTYPE)OMX_IndexVendorCompPropTunnelFlags, &pPropTunnelSetup); ++ if (err != OMX_ErrorNone) { ++ // compatibility not reached ++ DEBUG(DEB_LEV_ERR,"In %s Proprietary Tunneled Buffer Supplier nTunneledPort=%d error=0x%08x Line=%d \n", ++ __func__,(int)pPropTunnelSetup.nPortIndex,err,__LINE__); ++ openmaxStandPort->nTunnelFlags = 0; ++ } else { ++ openmaxStandPort->nTunnelFlags = PROPRIETARY_COMMUNICATION_ESTABLISHED; ++ } ++ } else { ++ openmaxStandPort->nTunnelFlags = 0; ++ } ++ ++ openmaxStandPort->nNumTunnelBuffer=param.nBufferCountMin; ++ ++ openmaxStandPort->hTunneledComponent = hTunneledComp; ++ openmaxStandPort->nTunneledPort = nTunneledPort; ++ pTunnelSetup->eSupplier = OMX_BufferSupplyOutput; ++ openmaxStandPort->nTunnelFlags |= TUNNEL_IS_SUPPLIER; ++ openmaxStandPort->nTunnelFlags |= TUNNEL_ESTABLISHED; ++ ++ openmaxStandPort->eBufferSupplier=OMX_BufferSupplyOutput; ++ } ++ ++ return OMX_ErrorNone; ++} +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 ++#include ++#include ++#include ++#pragma pack() ++ ++#define OMX_ErrorIncorrectStateTransition OMX_ErrorIncorrectStateOperation ++ ++#ifndef __OMX_BASE_PORT_H__ ++#define __OMX_BASE_PORT_H__ ++ ++#define TUNNEL_USE_BUFFER_RETRY 20 ++#define TUNNEL_USE_BUFFER_RETRY_USLEEP_TIME 5000 ++#define NO_GST_OMX_PATCH 1 ++ ++/** ++ * Port Specific Macro's ++ */ ++#define PORT_IS_BEING_FLUSHED(pPort) (pPort->bIsPortFlushed == OMX_TRUE) ++#define PORT_IS_BEING_DISABLED(pPort) (pPort->bIsTransientToDisabled == OMX_TRUE) ++#define PORT_IS_ENABLED(pPort) (pPort->sPortParam.bEnabled == OMX_TRUE) ++#define PORT_IS_POPULATED(pPort) (pPort->sPortParam.bPopulated == OMX_TRUE) ++#define PORT_IS_TUNNELED(pPort) (pPort->nTunnelFlags & TUNNEL_ESTABLISHED) ++#define PORT_IS_DEEP_TUNNELED(pPort) (pPort->nTunnelFlags & PROPRIETARY_COMMUNICATION_ESTABLISHED) ++#define PORT_IS_BUFFER_SUPPLIER(pPort) (pPort->nTunnelFlags & TUNNEL_IS_SUPPLIER) ++#define PORT_IS_TUNNELED_N_BUFFER_SUPPLIER(pPort) ((pPort->nTunnelFlags & TUNNEL_ESTABLISHED) && (pPort->nTunnelFlags & TUNNEL_IS_SUPPLIER)) ++ ++/** The following enum values are used to characterize each buffer ++ * allocated or assigned to the component. A buffer list is ++ * created for each port of the component. The buffer can be assigned ++ * to the port, or owned by the port. The buffer flag are applied for each buffer ++ * in each port buffer list. The following use cases are currently implemented: ++ * - When the IL Client asks the component to allocate a buffer ++ * for a given port, with the call to AllocateBuffer, the ++ * buffer created is characterizeed by the flag BUFFER_ALLOCATED ++ * - When the IL Client asks the component to use a buffer allocated ++ * by the client itself, the buffer flag is BUFFER_ASSIGNED ++ * - When the component is tunneled by another component, and the first ++ * is supplier of the buffer, the buffer is marked with the ++ * BUFFER_ALLOCATED flag. ++ * - When the component is tunneled by another component, and the second ++ * is supplier of the buffer, the buffer is marked with the ++ * BUFFER_ASSIGNED flag. ++ * - The case of a buffer supplied by the first component but allocated by another ++ * component or another port inside the same component, as in the case ++ * of shared buffers, is not yet implemented in these components ++ * - During hte deallocation phase each buffer is marked with the BUFFER_FREE ++ * flag, so that the component can check if all the buffers have been deallocated ++ * before switch the component state to Loaded, as specified by ++ * the OpenMAX specs ++ */ ++typedef unsigned int BUFFER_STATUS_FLAG; ++ ++#define BUFFER_FREE 0 ++#define BUFFER_ALLOCATED 0x0001 /**< This flag is applied to a buffer when it is allocated ++ by the given port of the component */ ++#define BUFFER_ASSIGNED 0x0002 /**< This flag is applied to a buffer when it is assigned ++ from another port or by the IL client */ ++#define HEADER_ALLOCATED 0x0004 /**< This flag is applied to a buffer when buffer header is allocated ++ by the given port of the component */ ++ ++/** @brief the status of a port related to the tunneling with another component ++ */ ++typedef unsigned int TUNNEL_STATUS_FLAG; ++#define NO_TUNNEL 0 /**< No tunnel established */ ++#define TUNNEL_ESTABLISHED 0x0001 /**< the TUNNEL_ESTABLISHED specifies if a port is tunneled. ++ * It is assigned to a private field of the port if it is tunneled ++ */ ++#define TUNNEL_IS_SUPPLIER 0x0002 /**< the TUNNEL_IS_SUPPLIER specifies if a tunneled port is the supplier. ++ * It is assigned to a private field of the port if it is tunneled and also it is the buffer supplier for the tunnel. ++ */ ++#define PROPRIETARY_COMMUNICATION_ESTABLISHED 0x0004 /** The tunnel established is created between two components of the same ++ * vendor. These components can take advantage from a vendor specific ++ * communication ++ */ ++ ++/** ++ * @brief the base structure that describes each port. ++ * ++ * The data structure that describes a port contains the basic elements used in the ++ * base component. Other elements can be added in the derived components structures. ++ */ ++CLASS(omx_base_PortType) ++#define omx_base_PortType_FIELDS \ ++ OMX_HANDLETYPE hTunneledComponent; /**< @param hTunneledComponent Handle to the tunnelled component */\ ++ OMX_U32 nTunnelFlags; /**< This field contains one or more tags that describe the tunnel status of the port */\ ++ OMX_U32 nTunneledPort; /**< @param nTunneledPort Tunneled port number */ \ ++ OMX_BOOL bTunnelTearDown; /**< @param nTunneledPort Helper for assinc TearDown */ \ ++ OMX_BUFFERSUPPLIERTYPE eBufferSupplier; /**< @param eBufferSupplier the type of supplier in case of tunneling */\ ++ OMX_U32 nNumTunnelBuffer; /**< @param nNumTunnelBuffer Number of buffer to be tunnelled */\ ++ omx_tsem_t* pAllocSem; /**< @param pFlushSem Semaphore that locks the execution until the buffers have been flushed, if needed */ \ ++ OMX_U32 nNumBufferFlushed; /**< @param nNumBufferFlushed Number of buffer Flushed */\ ++ OMX_BOOL bIsPortFlushed;/**< @param bIsPortFlushed Boolean variables indicate port is being flushed at the moment */ \ ++ omx_queue_t* pBufferQueue; /**< @param pBufferQueue queue for buffer to be processed by the port */\ ++ omx_tsem_t* pBufferSem; /**< @param pBufferSem Semaphore for buffer queue access synchronization */\ ++ OMX_U32 nNumAssignedBuffers; /**< @param nNumAssignedBuffers Number of buffer assigned on each port */\ ++ OMX_PARAM_PORTDEFINITIONTYPE sPortParam; /**< @param sPortParam General OpenMAX port parameter */\ ++ OMX_BUFFERHEADERTYPE **pInternalBufferStorage; /**< This array contains the reference to all the buffers hadled by this port and already registered*/\ ++ BUFFER_STATUS_FLAG *bBufferStateAllocated; /**< @param bBufferStateAllocated The State of the Buffer whether assigned or allocated */\ ++ OMX_COMPONENTTYPE *standCompContainer;/**< The OpenMAX component reference that contains this port */\ ++ OMX_BOOL bIsTransientToEnabled;/**< It indicates that the port is going from disabled to enabled */ \ ++ OMX_BOOL bIsTransientToDisabled;/**< It indicates that the port is going from enabled to disabled */ \ ++ OMX_BOOL bIsFullOfBuffers; /**< It indicates if the port has all the buffers needed */ \ ++ OMX_BOOL bIsEmptyOfBuffers;/**< It indicates if the port has no buffers*/ \ ++ OMX_ERRORTYPE (*PortConstructor)(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput); /**< The contructor of the port. It fills all the other function pointers */ \ ++ OMX_ERRORTYPE (*PortDestructor)(omx_base_PortType *openmaxStandPort); /**< The destructor of the port*/ \ ++ OMX_ERRORTYPE (*Port_DisablePort)(omx_base_PortType *openmaxStandPort); /**< Disables the port */ \ ++ OMX_ERRORTYPE (*Port_EnablePort)(omx_base_PortType *openmaxStandPort); /**< Enables the port */ \ ++ OMX_ERRORTYPE (*Port_SendBufferFunction)(omx_base_PortType *openmaxStandPort, OMX_BUFFERHEADERTYPE* pBuffer); /**< Holds the EmptyThisBuffer of FillThisBuffer function, if the port is input or output */ \ ++ OMX_ERRORTYPE (*Port_AllocateBuffer)(omx_base_PortType *openmaxStandPort,OMX_INOUT OMX_BUFFERHEADERTYPE** pBuffer,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_PTR pAppPrivate,OMX_IN OMX_U32 nSizeBytes);/**< Replaces the AllocateBuffer call for the base port. */ \ ++ OMX_ERRORTYPE (*Port_UseBuffer)(omx_base_PortType *openmaxStandPort,OMX_BUFFERHEADERTYPE** ppBufferHdr,OMX_U32 nPortIndex,OMX_PTR pAppPrivate,OMX_U32 nSizeBytes,OMX_U8* pBuffer);/**< The standard use buffer function applied to the port class */ \ ++ OMX_ERRORTYPE (*Port_FreeBuffer)(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex,OMX_BUFFERHEADERTYPE* pBuffer); /**< The standard free buffer function applied to the port class */ \ ++ OMX_ERRORTYPE (*Port_AllocateTunnelBuffer)(omx_base_PortType *openmaxStandPort,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_U32 nSizeBytes);/**< AllocateTunnelBuffer call for the base port. */ \ ++ OMX_ERRORTYPE (*Port_FreeTunnelBuffer)(omx_base_PortType *openmaxStandPort,OMX_U32 nPortIndex); /**< The free buffer function used to free tunnelled buffers */ \ ++ OMX_ERRORTYPE (*BufferProcessedCallback)(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);/**< Holds the EmptyBufferDone or FillBufferDone callback, if the port is input or output port */ \ ++ OMX_ERRORTYPE (*FlushProcessingBuffers)(omx_base_PortType *openmaxStandPort); /**< release all the buffers currently under processing */ \ ++ OMX_ERRORTYPE (*ReturnBufferFunction)(omx_base_PortType* openmaxStandPort,OMX_BUFFERHEADERTYPE* pBuffer); /**< Call appropriate function to return buffers to peer or IL Client*/ \ ++ OMX_ERRORTYPE (*ComponentTunnelRequest)(omx_base_PortType* openmaxStandPort,OMX_IN OMX_HANDLETYPE hTunneledComp,OMX_IN OMX_U32 nTunneledPort,OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); /**< Setup tunnel with the port */ ++ENDCLASS(omx_base_PortType) ++ ++/** ++ * @brief The base contructor for the generic OpenMAX ST port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the component. ++ * It takes care of constructing the instance of the port and ++ * every object needed by the base port. ++ * ++ * @param openmaxStandPort the ST port to be initialized ++ * ++ * @return OMX_ErrorInsufficientResources if a memory allocation fails ++ */ ++OMX_ERRORTYPE base_port_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,omx_base_PortType **openmaxStandPort,OMX_U32 nPortIndex, OMX_BOOL isInput); ++ ++/** @brief The base destructor for the generic OpenMAX ST port ++ * ++ * This function is executed by the component that uses a port. ++ * The parameter contains the info about the component. ++ * It takes care of destructing the instance of the port and ++ * every object used by the base port. ++ * ++ * @param openmaxStandPort the ST port to be disposed ++ */ ++OMX_ERRORTYPE base_port_Destructor(omx_base_PortType *openmaxStandPort); ++ ++/** @brief Disables the port. ++ * ++ * This function is called due to a request by the IL client ++ * ++ * @param openmaxStandPort the reference to the port ++ * ++ */ ++OMX_ERRORTYPE base_port_DisablePort(omx_base_PortType *openmaxStandPort); ++ ++/** @brief Enables the port. ++ * ++ * This function is called due to a request by the IL client ++ * ++ * @param openmaxStandPort the reference to the port ++ * ++ */ ++OMX_ERRORTYPE base_port_EnablePort(omx_base_PortType *openmaxStandPort); ++ ++/** @brief The entry point for sending buffers to the port ++ * ++ * This function can be called by the EmptyThisBuffer or FillThisBuffer. It depends on ++ * the nature of the port, that can be an input or output port. ++ */ ++OMX_ERRORTYPE base_port_SendBufferFunction( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE* pBuffer); ++ ++/** @brief Called by the standard allocate buffer, it implements a base functionality. ++ * ++ * This function can be overriden if the allocation of the buffer is not a simply malloc call. ++ * The parameters are the same as the standard function, except for the handle of the port ++ * instead of the handler of the component ++ * When the buffers needed by this port are all assigned or allocated, the variable ++ * bIsFullOfBuffers becomes equal to OMX_TRUE ++ */ ++OMX_ERRORTYPE base_port_AllocateBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE** pBuffer, ++ OMX_U32 nPortIndex, ++ OMX_PTR pAppPrivate, ++ OMX_U32 nSizeBytes); ++ ++/** @brief Called by the standard use buffer, it implements a base functionality. ++ * ++ * This function can be overriden if the use buffer implicate more complicated operations. ++ * The parameters are the same as the standard function, except for the handle of the port ++ * instead of the handler of the component ++ * When the buffers needed by this port are all assigned or allocated, the variable ++ * bIsFullOfBuffers becomes equal to OMX_TRUE ++ */ ++OMX_ERRORTYPE base_port_UseBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_BUFFERHEADERTYPE** ppBufferHdr, ++ OMX_U32 nPortIndex, ++ OMX_PTR pAppPrivate, ++ OMX_U32 nSizeBytes, ++ OMX_U8* pBuffer); ++ ++/** @brief Called by the standard function. ++ * ++ * It frees the buffer header and in case also the buffer itself, if needed. ++ * When all the bufers are done, the variable bIsEmptyOfBuffers is set to OMX_TRUE ++ */ ++OMX_ERRORTYPE base_port_FreeBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_U32 nPortIndex, ++ OMX_BUFFERHEADERTYPE* pBuffer); ++ ++/** @brief Releases buffers under processing. ++ * ++ * This function must be implemented in the derived classes, for the ++ * specific processing ++ */ ++OMX_ERRORTYPE base_port_FlushProcessingBuffers(omx_base_PortType *openmaxStandPort); ++ ++/** @brief Returns buffers when processed. ++ * ++ * Call appropriate function to return buffers to peer or IL Client ++ */ ++ ++OMX_ERRORTYPE base_port_ReturnBufferFunction( ++ omx_base_PortType* openmaxStandPort, ++ OMX_BUFFERHEADERTYPE* pBuffer); ++ ++/** @brief Setup Tunnel with the port ++ */ ++ ++OMX_ERRORTYPE base_port_ComponentTunnelRequest( ++ omx_base_PortType* openmaxStandPort, ++ OMX_IN OMX_HANDLETYPE hTunneledComp, ++ OMX_IN OMX_U32 nTunneledPort, ++ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); ++ ++/** @brief Allocate Buffers for tunneling use ++ */ ++OMX_ERRORTYPE base_port_AllocateTunnelBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_IN OMX_U32 nPortIndex, ++ OMX_IN OMX_U32 nSizeBytes); ++ ++/** @brief Free buffers used in tunnel ++ */ ++OMX_ERRORTYPE base_port_FreeTunnelBuffer( ++ omx_base_PortType *openmaxStandPort, ++ OMX_U32 nPortIndex); ++ ++ ++#endif +diff --git a/alsa/omx_base_sink.cpp b/alsa/omx_base_sink.cpp +new file mode 100644 +index 0000000..ae8b3e3 +--- /dev/null ++++ b/alsa/omx_base_sink.cpp +@@ -0,0 +1,189 @@ ++/** ++ @file src/base/omx_base_sink.c ++ ++ OpenMAX base sink component. This component does not perform any multimedia ++ processing. It derives from base component and contains a single input port. ++ It can be used as base class for sink components. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-09-12 08:12:11 +0200 (Fri, 12 Sep 2008) $ ++ Revision $Rev: 615 $ ++ Author $Author: pankaj_sen $ ++*/ ++ ++#include ++ ++OMX_ERRORTYPE omx_base_sink_Constructor(OMX_COMPONENTTYPE *openmaxStandComp,OMX_STRING cComponentName) { ++ OMX_ERRORTYPE err = OMX_ErrorNone; ++ omx_base_sink_PrivateType* omx_base_sink_Private; ++ ++ if (openmaxStandComp->pComponentPrivate) { ++ omx_base_sink_Private = (omx_base_sink_PrivateType*)openmaxStandComp->pComponentPrivate; ++ } else { ++ omx_base_sink_Private = (omx_base_sink_PrivateType*)calloc(1,sizeof(omx_base_sink_PrivateType)); ++ if (!omx_base_sink_Private) { ++ return OMX_ErrorInsufficientResources; ++ } ++ } ++ ++ // we could create our own port structures here ++ // fixme maybe the base class could use a "port factory" function pointer? ++ err = omx_base_component_Constructor(openmaxStandComp,cComponentName); ++ ++ /* here we can override whatever defaults the base_component constructor set ++ * e.g. we can override the function pointers in the private struct */ ++ omx_base_sink_Private = (omx_base_sink_PrivateType*)openmaxStandComp->pComponentPrivate; ++ ++ omx_base_sink_Private->BufferMgmtFunction = omx_base_sink_BufferMgmtFunction; ++ ++ return err; ++} ++ ++OMX_ERRORTYPE omx_base_sink_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) ++{ ++ return omx_base_component_Destructor(openmaxStandComp); ++} ++ ++/** This is the central function for component processing. It ++ * is executed in a separate thread, is synchronized with ++ * semaphores at each port, those are released each time a new buffer ++ * is available on the given port. ++ */ ++void* omx_base_sink_BufferMgmtFunction (void* param) { ++ OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param; ++ omx_base_component_PrivateType* omx_base_component_Private = (omx_base_component_PrivateType*)openmaxStandComp->pComponentPrivate; ++ omx_base_sink_PrivateType* omx_base_sink_Private = (omx_base_sink_PrivateType*)omx_base_component_Private; ++ omx_base_PortType *pInPort = (omx_base_PortType *)omx_base_sink_Private->ports[OMX_BASE_SINK_INPUTPORT_INDEX]; ++ omx_tsem_t* pInputSem = pInPort->pBufferSem; ++ omx_queue_t* pInputQueue = pInPort->pBufferQueue; ++ OMX_BUFFERHEADERTYPE* pInputBuffer = NULL; ++ OMX_COMPONENTTYPE* target_component; ++ OMX_BOOL isInputBufferNeeded = OMX_TRUE; ++ int inBufExchanged = 0; ++ ++ DEBUG(DEB_LEV_FUNCTION_NAME, "In %s \n", __func__); ++ while(omx_base_component_Private->state == OMX_StateIdle || ++ omx_base_component_Private->state == OMX_StateExecuting || ++ omx_base_component_Private->state == OMX_StatePause || ++ omx_base_component_Private->transientState == OMX_TransStateLoadedToIdle){ ++ ++ /*Wait till the ports are being flushed*/ ++ pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); ++ while( PORT_IS_BEING_FLUSHED(pInPort)) { ++ pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); ++ ++ if(isInputBufferNeeded==OMX_FALSE) { ++ pInPort->ReturnBufferFunction(pInPort,pInputBuffer); ++ inBufExchanged--; ++ pInputBuffer=NULL; ++ isInputBufferNeeded=OMX_TRUE; ++ DEBUG(DEB_LEV_FULL_SEQ, "Ports are flushing,so returning input buffer\n"); ++ } ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s signalling flush all condition \n", __func__); ++ ++ omx_tsem_up(omx_base_sink_Private->flush_all_condition); ++ omx_tsem_down(omx_base_sink_Private->flush_condition); ++ pthread_mutex_lock(&omx_base_sink_Private->flush_mutex); ++ } ++ pthread_mutex_unlock(&omx_base_sink_Private->flush_mutex); ++ ++ /*No buffer to process. So wait here*/ ++ if((pInputSem->semval==0 && isInputBufferNeeded==OMX_TRUE ) && ++ (omx_base_sink_Private->state != OMX_StateLoaded && omx_base_sink_Private->state != OMX_StateInvalid)) { ++ DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer \n"); ++ omx_tsem_down(omx_base_sink_Private->bMgmtSem); ++ } ++ ++ if(omx_base_sink_Private->state == OMX_StateLoaded || omx_base_sink_Private->state == OMX_StateInvalid) { ++ DEBUG(DEB_LEV_FULL_SEQ, "In %s Buffer Management Thread is exiting\n",__func__); ++ break; ++ } ++ ++ DEBUG(DEB_LEV_SIMPLE_SEQ, "Waiting for input buffer semval=%d \n",pInputSem->semval); ++ if(pInputSem->semval>0 && isInputBufferNeeded==OMX_TRUE ) { ++ omx_tsem_down(pInputSem); ++ if(pInputQueue->nelem>0){ ++ inBufExchanged++; ++ isInputBufferNeeded=OMX_FALSE; ++ pInputBuffer = (OMX_BUFFERHEADERTYPE*)omx_dequeue(pInputQueue); ++ if(pInputBuffer == NULL){ ++ DEBUG(DEB_LEV_ERR, "Had NULL input buffer!!\n"); ++ break; ++ } ++ } ++ } ++ ++ if(isInputBufferNeeded==OMX_FALSE) { ++ if(pInputBuffer->nFlags==OMX_BUFFERFLAG_EOS) { ++ DEBUG(DEB_LEV_SIMPLE_SEQ, "Detected EOS flags in input buffer\n"); ++ ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventBufferFlag, /* The command was completed */ ++ 0, /* The commands was a OMX_CommandStateSet */ ++ pInputBuffer->nFlags, /* The state has been changed in message->messageParam2 */ ++ NULL); ++ pInputBuffer->nFlags=0; ++ } ++ ++ target_component=(OMX_COMPONENTTYPE*)pInputBuffer->hMarkTargetComponent; ++ if(target_component==(OMX_COMPONENTTYPE *)openmaxStandComp) { ++ /*Clear the mark and generate an event*/ ++ (*(omx_base_component_Private->callbacks->EventHandler)) ++ (openmaxStandComp, ++ omx_base_component_Private->callbackData, ++ OMX_EventMark, /* The command was completed */ ++ 1, /* The commands was a OMX_CommandStateSet */ ++ 0, /* The state has been changed in message->messageParam2 */ ++ pInputBuffer->pMarkData); ++ } else if(pInputBuffer->hMarkTargetComponent!=NULL){ ++ /*If this is not the target component then pass the mark*/ ++ DEBUG(DEB_LEV_FULL_SEQ, "Can't Pass Mark. This is a Sink!!\n"); ++ } ++ if (omx_base_sink_Private->BufferMgmtCallback && pInputBuffer->nFilledLen > 0) { ++ (*(omx_base_sink_Private->BufferMgmtCallback))(openmaxStandComp, pInputBuffer); ++ } ++ else { ++ /*If no buffer management call back the explicitly consume input buffer*/ ++ DEBUG(DEB_LEV_FULL_SEQ, "If no buffer management call back, explicitly consume input buffer. nInputPortIndex=%d BufferMgmtCallback=0x%p nFilledLen=%d\n", ++ (int)pInputBuffer->nInputPortIndex, omx_base_sink_Private->BufferMgmtCallback, (int)pInputBuffer->nFilledLen); ++ pInputBuffer->nFilledLen = 0; ++ } ++ /*Input Buffer has been completely consumed. So, get new input buffer*/ ++ ++ if(omx_base_sink_Private->state==OMX_StatePause && !PORT_IS_BEING_FLUSHED(pInPort)) { ++ /*Waiting at paused state*/ ++ omx_tsem_wait(omx_base_sink_Private->bStateSem); ++ } ++ ++ /*Input Buffer has been completely consumed. So, return input buffer*/ ++ if(pInputBuffer->nFilledLen==0) { ++ pInPort->ReturnBufferFunction(pInPort,pInputBuffer); ++ inBufExchanged--; ++ pInputBuffer=NULL; ++ isInputBufferNeeded = OMX_TRUE; ++ } ++ ++ } ++ } ++ DEBUG(DEB_LEV_SIMPLE_SEQ,"Exiting Buffer Management Thread\n"); ++ return NULL; ++} +diff --git a/alsa/omx_base_sink.h b/alsa/omx_base_sink.h +new file mode 100644 +index 0000000..dfe7e9c +--- /dev/null ++++ b/alsa/omx_base_sink.h +@@ -0,0 +1,73 @@ ++/** ++ @file src/base/omx_base_sink.h ++ ++ OpenMAX base sink component. This component does not perform any multimedia ++ processing. It derives from base component and contains a single port. It can be used ++ as base class for sink components. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-08-28 17:50:08 +0200 (Thu, 28 Aug 2008) $ ++ Revision $Rev: 583 $ ++ Author $Author: gsent $ ++ ++*/ ++ ++#ifndef _OMX_BASE_SINK_COMPONENT_H_ ++#define _OMX_BASE_SINK_COMPONENT_H_ ++ ++//#include ++//#include ++//#include ++#include ++#include "omx_base_component.h" ++#include ++ ++ ++#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 ++ ++/** 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_ERRORTYPE OMX_GetHandle_XBMC(OMX_OUT OMX_HANDLETYPE* pHandle, ++ OMX_IN OMX_STRING cComponentName, ++ OMX_IN OMX_PTR pAppData, ++ OMX_IN OMX_CALLBACKTYPE* pCallBacks) ++{ ++ OMX_ERRORTYPE err = OMX_ErrorNone; ++ OMX_COMPONENTTYPE* openmaxStandComp; ++ omx_base_component_PrivateType* priv; ++ ++ if(!strcmp("OMX.XBMC.alsa.alsasink", cComponentName)) ++ { ++ openmaxStandComp = (OMX_COMPONENTTYPE*)calloc(1,sizeof(OMX_COMPONENTTYPE)); ++ if (!openmaxStandComp) { ++ return OMX_ErrorInsufficientResources; ++ } ++ ++ err = omx_alsasink_component_Constructor(openmaxStandComp,cComponentName); ++ if (err != OMX_ErrorNone) ++ { ++ if (err == OMX_ErrorInsufficientResources) ++ { ++ *pHandle = openmaxStandComp; ++ priv = (omx_base_component_PrivateType *) openmaxStandComp->pComponentPrivate; ++ return OMX_ErrorInsufficientResources; ++ } ++ DEBUG(DEB_LEV_ERR, "Error during component construction\n"); ++ openmaxStandComp->ComponentDeInit(openmaxStandComp); ++ free(openmaxStandComp); ++ openmaxStandComp = NULL; ++ return OMX_ErrorComponentNotFound; ++ } ++ priv = (omx_base_component_PrivateType *) openmaxStandComp->pComponentPrivate; ++ ++ *pHandle = openmaxStandComp; ++ ((OMX_COMPONENTTYPE*)*pHandle)->SetCallbacks(*pHandle, pCallBacks, pAppData); ++ } ++ else ++ { ++ err = OMX_ErrorComponentNotFound; ++ } ++ ++ return err; ++} ++ ++ ++OMX_ERRORTYPE OMX_FreeHandle_XBMC(OMX_IN OMX_HANDLETYPE hComponent) ++{ ++ int i; ++ OMX_ERRORTYPE err = OMX_ErrorNone; ++ omx_base_component_PrivateType * priv = (omx_base_component_PrivateType *) ((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate; ++ ++ if(!strcmp("OMX.XBMC.alsa.alsasink", priv->name)) ++ { ++ err = ((OMX_COMPONENTTYPE*)hComponent)->ComponentDeInit(hComponent); ++ ++ free((OMX_COMPONENTTYPE*)hComponent); ++ hComponent = NULL; ++ } ++ else ++ { ++ err = OMX_ErrorComponentNotFound; ++ } ++ ++ return err; ++} +\ No newline at end of file +diff --git a/alsa/omx_loader_XBMC.h b/alsa/omx_loader_XBMC.h +new file mode 100644 +index 0000000..c835043 +--- /dev/null ++++ b/alsa/omx_loader_XBMC.h +@@ -0,0 +1,27 @@ ++#pragma once ++ ++ ++#ifndef __OMX_LOADER_XBMC__ ++#define __OMX_LOADER_XBMC__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++#pragma pack(4) ++#include ++#include ++#pragma pack() ++ ++OMX_ERRORTYPE OMX_GetHandle_XBMC(OMX_OUT OMX_HANDLETYPE* pHandle, ++ OMX_IN OMX_STRING cComponentName, ++ OMX_IN OMX_PTR pAppData, ++ OMX_IN OMX_CALLBACKTYPE* pCallBacks); ++ ++OMX_ERRORTYPE OMX_FreeHandle_XBMC(OMX_IN OMX_HANDLETYPE hComponent); ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif +\ No newline at end of file +diff --git a/alsa/omx_queue.cpp b/alsa/omx_queue.cpp +new file mode 100644 +index 0000000..e4ecd25 +--- /dev/null ++++ b/alsa/omx_queue.cpp +@@ -0,0 +1,136 @@ ++/** ++ @file src/queue.c ++ ++ Implements a simple LIFO structure used for queueing OMX buffers. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ ++ Revision $Rev: 554 $ ++ Author $Author: pankaj_sen $ ++*/ ++ ++#include ++#include ++#include ++ ++#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; iq_forw = newelem; ++ current = newelem; ++ } ++ current->q_forw = queue->first; ++ ++ pthread_mutex_init(&queue->mutex, NULL); ++} ++ ++/** Deinitialize a queue descriptor ++ * flushing all of its internal data ++ * ++ * @param queue the queue descriptor to dump ++ */ ++void omx_queue_deinit(omx_queue_t* queue) { ++ int i; ++ omx_qelem_t* current; ++ current = queue->first; ++ for (i = 0; iq_forw; ++ free(queue->first); ++ queue->first = current; ++ } ++ } ++ if(queue->first) { ++ free(queue->first); ++ queue->first = NULL; ++ } ++ pthread_mutex_destroy(&queue->mutex); ++} ++ ++/** Enqueue an element to the given queue descriptor ++ * ++ * @param queue the queue descritpor where to queue data ++ * ++ * @param data the data to be enqueued ++ */ ++void omx_queue(omx_queue_t* queue, void* data) { ++ if (queue->last->data != NULL) { ++ DEBUG(DEB_LEV_ERR, "In %s ERROR! Full queue\n",__func__); ++ return; ++ } ++ pthread_mutex_lock(&queue->mutex); ++ queue->last->data = data; ++ queue->last = queue->last->q_forw; ++ queue->nelem++; ++ pthread_mutex_unlock(&queue->mutex); ++} ++ ++/** Dequeue an element from the given queue descriptor ++ * ++ * @param queue the queue descriptor from which to dequeue the element ++ * ++ * @return the element that has bee dequeued. If the queue is empty ++ * a NULL value is returned ++ */ ++void* omx_dequeue(omx_queue_t* queue) { ++ void* data; ++ if (queue->first->data == NULL) { ++ DEBUG(DEB_LEV_ERR, "In %s ERROR! Empty queue\n",__func__); ++ return NULL; ++ } ++ pthread_mutex_lock(&queue->mutex); ++ data = queue->first->data; ++ queue->first->data = NULL; ++ queue->first = queue->first->q_forw; ++ queue->nelem--; ++ pthread_mutex_unlock(&queue->mutex); ++ ++ return data; ++} ++ ++/** Returns the number of elements hold in the queue ++ * ++ * @param queue the requested queue ++ * ++ * @return the number of elements in the queue ++ */ ++int omx_getquenelem(omx_queue_t* queue) { ++ int qelem; ++ pthread_mutex_lock(&queue->mutex); ++ qelem = queue->nelem; ++ pthread_mutex_unlock(&queue->mutex); ++ return qelem; ++} +diff --git a/alsa/omx_queue.h b/alsa/omx_queue.h +new file mode 100644 +index 0000000..bf80f90 +--- /dev/null ++++ b/alsa/omx_queue.h +@@ -0,0 +1,94 @@ ++/** ++ @file src/omx_queue.h ++ ++ Implements a simple LIFO structure used for queueing OMX buffers. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ ++ Revision $Rev: 554 $ ++ Author $Author: pankaj_sen $ ++*/ ++ ++#pragma once ++ ++#ifndef __OMX_QUEUE_H__ ++#define __OMX_QUEUE_H__ ++ ++#include ++/** 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 ++#include ++#include ++#include "omx_semaphore.h" ++//#include "omx_comp_debug_levels.h" ++ ++/** Initializes the semaphore at a given value ++ * ++ * @param tsem the semaphore to initialize ++ * @param val the initial value of the semaphore ++ * ++ */ ++void omx_tsem_init(omx_tsem_t* tsem, unsigned int val) { ++ pthread_cond_init(&tsem->condition, NULL); ++ pthread_mutex_init(&tsem->mutex, NULL); ++ tsem->semval = val; ++} ++ ++/** Destroy the semaphore ++ * ++ * @param tsem the semaphore to destroy ++ */ ++void omx_tsem_deinit(omx_tsem_t* tsem) { ++ pthread_cond_destroy(&tsem->condition); ++ pthread_mutex_destroy(&tsem->mutex); ++} ++ ++/** Decreases the value of the semaphore. Blocks if the semaphore ++ * value is zero. ++ * ++ * @param tsem the semaphore to decrease ++ */ ++void omx_tsem_down(omx_tsem_t* tsem) { ++ pthread_mutex_lock(&tsem->mutex); ++ while (tsem->semval == 0) { ++ pthread_cond_wait(&tsem->condition, &tsem->mutex); ++ } ++ tsem->semval--; ++ pthread_mutex_unlock(&tsem->mutex); ++} ++ ++/** Increases the value of the semaphore ++ * ++ * @param tsem the semaphore to increase ++ */ ++void omx_tsem_up(omx_tsem_t* tsem) { ++ pthread_mutex_lock(&tsem->mutex); ++ tsem->semval++; ++ pthread_cond_signal(&tsem->condition); ++ pthread_mutex_unlock(&tsem->mutex); ++} ++ ++/** Reset the value of the semaphore ++ * ++ * @param tsem the semaphore to reset ++ */ ++void omx_tsem_reset(omx_tsem_t* tsem) { ++ pthread_mutex_lock(&tsem->mutex); ++ tsem->semval=0; ++ pthread_mutex_unlock(&tsem->mutex); ++} ++ ++/** Wait on the condition. ++ * ++ * @param tsem the semaphore to wait ++ */ ++void omx_tsem_wait(omx_tsem_t* tsem) { ++ pthread_mutex_lock(&tsem->mutex); ++ pthread_cond_wait(&tsem->condition, &tsem->mutex); ++ pthread_mutex_unlock(&tsem->mutex); ++} ++ ++/** Signal the condition,if waiting ++ * ++ * @param tsem the semaphore to signal ++ */ ++void omx_tsem_signal(omx_tsem_t* tsem) { ++ pthread_mutex_lock(&tsem->mutex); ++ pthread_cond_signal(&tsem->condition); ++ pthread_mutex_unlock(&tsem->mutex); ++} ++ +diff --git a/alsa/omx_semaphore.h b/alsa/omx_semaphore.h +new file mode 100644 +index 0000000..1e3f3db +--- /dev/null ++++ b/alsa/omx_semaphore.h +@@ -0,0 +1,92 @@ ++/** ++ @file src/omx_semaphore.h ++ ++ Implements a simple inter-thread semaphore so not to have to deal with IPC ++ creation and the like. ++ ++ Copyright (C) 2007-2008 STMicroelectronics ++ Copyright (C) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). ++ ++ This library is free software; you can redistribute it and/or modify it under ++ the terms of the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 2.1 of the License, or (at your option) ++ any later version. ++ ++ This library is distributed in the hope that it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more ++ details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this library; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St, Fifth Floor, Boston, MA ++ 02110-1301 USA ++ ++ $Date: 2008-06-27 12:00:23 +0200 (Fri, 27 Jun 2008) $ ++ Revision $Rev: 554 $ ++ Author $Author: pankaj_sen $ ++ ++*/ ++ ++#pragma once ++ ++#ifndef __OMX_SEMAPHORE_H__ ++#define __OMX_SEMAPHORE_H__ ++ ++#include ++#include ++ ++/** The structure contains the semaphore value, mutex and green light flag ++ */ ++typedef struct omx_tsem_t { ++ pthread_cond_t condition; ++ pthread_mutex_t mutex; ++ unsigned int semval; ++} omx_tsem_t; ++ ++/** Initializes the semaphore at a given value ++ * ++ * @param tsem the semaphore to initialize ++ * ++ * @param val the initial value of the semaphore ++ */ ++void omx_tsem_init(omx_tsem_t* tsem, unsigned int val); ++ ++/** Destroy the semaphore ++ * ++ * @param tsem the semaphore to destroy ++ */ ++void omx_tsem_deinit(omx_tsem_t* tsem); ++ ++/** Decreases the value of the semaphore. Blocks if the semaphore ++ * value is zero. ++ * ++ * @param tsem the semaphore to decrease ++ */ ++void omx_tsem_down(omx_tsem_t* tsem); ++ ++/** Increases the value of the semaphore ++ * ++ * @param tsem the semaphore to increase ++ */ ++void omx_tsem_up(omx_tsem_t* tsem); ++ ++/** Reset the value of the semaphore ++ * ++ * @param tsem the semaphore to reset ++ */ ++void omx_tsem_reset(omx_tsem_t* tsem); ++ ++/** Wait on the condition. ++ * ++ * @param tsem the semaphore to wait ++ */ ++void omx_tsem_wait(omx_tsem_t* tsem); ++ ++/** Signal the condition,if waiting ++ * ++ * @param tsem the semaphore to signal ++ */ ++void omx_tsem_signal(omx_tsem_t* tsem); ++ ++#endif +diff --git a/omxplayer.cpp b/omxplayer.cpp +index b554a58..3e5b99b 100644 +--- a/omxplayer.cpp ++++ b/omxplayer.cpp +@@ -699,7 +699,7 @@ int main(int argc, char *argv[]) + break; + case 'o': + m_config_audio.device = optarg; +- if(m_config_audio.device != "local" && m_config_audio.device != "hdmi" && m_config_audio.device != "both") ++ if(m_config_audio.device != "local" && m_config_audio.device != "hdmi" && m_config_audio.device != "both" && m_config_audio.device != "alsa") + { + print_usage(); + return 0; -- cgit v1.2.3