diff options
author | Uday Kishore Pasupuleti <upasupul@codeaurora.org> | 2016-01-06 19:12:41 -0800 |
---|---|---|
committer | Prashant Malani <pmalani@google.com> | 2016-01-08 17:00:16 -0800 |
commit | 582e0a5e965897ea54ecfa5fe206797dab577a45 (patch) | |
tree | 3d99bdf637b54008f1e906975d75f7de7bfb6fb6 /msm8909/mm-audio | |
parent | befe610a877c3b150a6dd90cf358df4945b8f9a6 (diff) | |
download | hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.tar.gz hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.tar.bz2 hardware_qcom_audio-582e0a5e965897ea54ecfa5fe206797dab577a45.zip |
audio: msm8909w caf release LW.BR.1.0-00410-8x09w.0
MSM8909w Audio HAL code copied from CAF release
LW.BR.1.0-00410-8x09w.0
dbcce50 hal: Port wcd9326 changes to 8909
410c530 hal: update error handling for pcm_prepare failures
ff79309 hal: fix compilation issues with audio FM extention
762d7eb policy_hal: add support for fm device loopback
7c418f9 audio_policy: modify few methods to appropriately override base
8b12163 audio: Add support to enable split A2DP
a0559fa Revert "Revert "policy_hal: Function prototype correction for custom policy"."
Fixed makefiles to be compatible with PDK without kernel source
Change-Id: I9c6f2139adee62426b877516deeb41d4ed8052b2
Diffstat (limited to 'msm8909/mm-audio')
47 files changed, 28484 insertions, 0 deletions
diff --git a/msm8909/mm-audio/Android.mk b/msm8909/mm-audio/Android.mk new file mode 100644 index 00000000..3885afc6 --- /dev/null +++ b/msm8909/mm-audio/Android.mk @@ -0,0 +1,3 @@ +ifeq ($(strip $(TARGET_USES_QCOM_MM_AUDIO)),true) +include $(call all-subdir-makefiles) +endif diff --git a/msm8909/mm-audio/Makefile b/msm8909/mm-audio/Makefile new file mode 100644 index 00000000..2be93e92 --- /dev/null +++ b/msm8909/mm-audio/Makefile @@ -0,0 +1,10 @@ +all: + @echo "invoking omxaudio make" + $(MAKE) -C adec-mp3 + $(MAKE) -C adec-aac + $(MAKE) -C aenc-aac + +install: + $(MAKE) -C adec-mp3 install + $(MAKE) -C adec-aac install + $(MAKE) -C aenc-aac install diff --git a/msm8909/mm-audio/Makefile.am b/msm8909/mm-audio/Makefile.am new file mode 100644 index 00000000..e423acbb --- /dev/null +++ b/msm8909/mm-audio/Makefile.am @@ -0,0 +1,5 @@ +# Makefile.am - Automake script for mm-omxaudio +# +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = adec-aac adec-mp3 aenc-aac diff --git a/msm8909/mm-audio/aenc-aac/Android.mk b/msm8909/mm-audio/aenc-aac/Android.mk new file mode 100644 index 00000000..986e7c94 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/Android.mk @@ -0,0 +1,8 @@ +ifneq ($(filter arm aarch64 arm64, $(TARGET_ARCH)),) + + +AENC_AAC_PATH:= $(call my-dir) + +include $(AENC_AAC_PATH)/qdsp6/Android.mk + +endif diff --git a/msm8909/mm-audio/aenc-aac/Makefile b/msm8909/mm-audio/aenc-aac/Makefile new file mode 100644 index 00000000..83d822bb --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/Makefile @@ -0,0 +1,6 @@ +all: + @echo "invoking omxaudio make" + $(MAKE) -C qdsp6 + +install: + $(MAKE) -C qdsp6 install diff --git a/msm8909/mm-audio/aenc-aac/Makefile.am b/msm8909/mm-audio/aenc-aac/Makefile.am new file mode 100644 index 00000000..24c1af26 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = qdsp6 diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/Android.mk b/msm8909/mm-audio/aenc-aac/qdsp6/Android.mk new file mode 100644 index 00000000..1306ceee --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/Android.mk @@ -0,0 +1,68 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libOmxAacEnc-def := -g -O3 +libOmxAacEnc-def += -DQC_MODIFIED +libOmxAacEnc-def += -D_ANDROID_ +libOmxAacEnc-def += -D_ENABLE_QC_MSG_LOG_ +libOmxAacEnc-def += -DVERBOSE +libOmxAacEnc-def += -D_DEBUG +libOmxAacEnc-def += -Wconversion +libOmxAacEnc-def += -DAUDIOV2 + +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxAacEnc) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +libOmxAacEnc-inc := $(LOCAL_PATH)/inc +libOmxAacEnc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := libOmxAacEnc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxAacEnc-def) +LOCAL_C_INCLUDES := $(libOmxAacEnc-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libutils liblog + +LOCAL_SRC_FILES := src/aenc_svr.c +LOCAL_SRC_FILES += src/omx_aac_aenc.cpp + +include $(BUILD_SHARED_LIBRARY) + +# --------------------------------------------------------------------------------- +# Make the apps-test (mm-aenc-omxaac-test) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +mm-aac-enc-test-inc := $(LOCAL_PATH)/inc +mm-aac-enc-test-inc += $(LOCAL_PATH)/test +mm-aac-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-audio/audio-alsa +mm-aac-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := mm-aenc-omxaac-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxAacEnc-def) +LOCAL_C_INCLUDES := $(mm-aac-enc-test-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libmm-omxcore +LOCAL_SHARED_LIBRARIES += libOmxAacEnc +LOCAL_SHARED_LIBRARIES += libaudioalsa +LOCAL_SRC_FILES := test/omx_aac_enc_test.c + +include $(BUILD_EXECUTABLE) + +endif + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- + diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/Makefile b/msm8909/mm-audio/aenc-aac/qdsp6/Makefile new file mode 100644 index 00000000..5421d45b --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/Makefile @@ -0,0 +1,81 @@ +# --------------------------------------------------------------------------------- +# MM-AUDIO-OSS-8K-AENC-AAC +# --------------------------------------------------------------------------------- + +# cross-compiler flags +CFLAGS += -Wall +CFLAGS += -Wundef +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs + +# cross-compile flags specific to shared objects +CFLAGS_SO += -fpic + +# required pre-processor flags +CPPFLAGS := -D__packed__= +CPPFLAGS += -DIMAGE_APPS_PROC +CPPFLAGS += -DFEATURE_Q_SINGLE_LINK +CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR +CPPFLAGS += -DFEATURE_LINUX +CPPFLAGS += -DFEATURE_NATIVELINUX +CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS + +CPPFLAGS += -g +CPPFALGS += -D_DEBUG +CPPFLAGS += -Iinc + +# linker flags +LDFLAGS += -L$(SYSROOT)/usr/lib + +# linker flags for shared objects +LDFLAGS_SO := -shared + +# defintions +LIBMAJOR := $(basename $(basename $(LIBVER))) +LIBINSTALLDIR := $(DESTDIR)usr/lib +INCINSTALLDIR := $(DESTDIR)usr/include +BININSTALLDIR := $(DESTDIR)usr/bin + +# --------------------------------------------------------------------------------- +# BUILD +# --------------------------------------------------------------------------------- +all: libOmxAacEnc.so.$(LIBVER) mm-aenc-omxaac-test + +install: + echo "intalling aenc-aac in $(DESTDIR)" + if [ ! -d $(LIBINSTALLDIR) ]; then mkdir -p $(LIBINSTALLDIR); fi + if [ ! -d $(INCINSTALLDIR) ]; then mkdir -p $(INCINSTALLDIR); fi + if [ ! -d $(BININSTALLDIR) ]; then mkdir -p $(BININSTALLDIR); fi + install -m 555 libOmxAacEnc.so.$(LIBVER) $(LIBINSTALLDIR) + cd $(LIBINSTALLDIR) && ln -s libOmxAacEnc.so.$(LIBVER) libOmxAacEnc.so.$(LIBMAJOR) + cd $(LIBINSTALLDIR) && ln -s libOmxAacEnc.so.$(LIBMAJOR) libOmxAacEnc.so + install -m 555 mm-aenc-omxaac-test $(BININSTALLDIR) + +# --------------------------------------------------------------------------------- +# COMPILE LIBRARY +# --------------------------------------------------------------------------------- +LDLIBS := -lpthread +LDLIBS += -lstdc++ +LDLIBS += -lOmxCore + +SRCS := src/omx_aac_aenc.cpp +SRCS += src/aenc_svr.c + +libOmxAacEnc.so.$(LIBVER): $(SRCS) + $(CC) $(CPPFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxAacEnc.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# --------------------------------------------------------------------------------- +# COMPILE TEST APP +# --------------------------------------------------------------------------------- +TEST_LDLIBS := -lpthread +TEST_LDLIBS += -ldl +TEST_LDLIBS += -lOmxCore + +TEST_SRCS := test/omx_aac_enc_test.c + +mm-aenc-omxaac-test: libOmxAacEnc.so.$(LIBVER) $(TEST_SRCS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS) + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/Makefile.am b/msm8909/mm-audio/aenc-aac/qdsp6/Makefile.am new file mode 100644 index 00000000..5af028a0 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/Makefile.am @@ -0,0 +1,30 @@ +# sources and intermediate files are separated + +AM_CFLAGS = -Wall +AM_CFLAGS += -Wundef +AM_CFLAGS += -Wstrict-prototypes +AM_CFLAGS += -Wno-trigraphs +AM_CFLAGS += -g -O3 + +AM_CPPFLAGS = -D__packed__= +AM_CPPFLAGS += -DIMAGE_APPS_PROC +AM_CPPFLAGS += -DFEATURE_Q_SINGLE_LINK +AM_CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR +AM_CPPFLAGS += -DFEATURE_LINUX +AM_CPPFLAGS += -DFEATURE_NATIVELINUX +AM_CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS +AM_CPPFLAGS += -D_DEBUG +AM_CPPFLAGS += -Iinc + +c_sources =src/omx_aac_aenc.cpp +c_sources +=src/aenc_svr.c + +lib_LTLIBRARIES = libOmxAacEnc.la +libOmxAacEnc_la_SOURCES = $(c_sources) +libOmxAacEnc_la_CFLAGS = $(AM_CFLAGS) -fPIC +libOmxAacEnc_la_LDLIBS = -lOmxCore -lstdc++ -lpthread +libOmxAacEnc_la_LDFLAGS = -shared -version-info $(OMXAUDIO_LIBRARY_VERSION) + +bin_PROGRAMS = mm-aenc-omxaac-test +mm_aenc_omxaac_test_SOURCES = test/omx_aac_enc_test.c +mm_aenc_omxaac_test_LDADD = -lOmxCore -ldl -lpthread libOmxAacEnc.la diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/inc/Map.h b/msm8909/mm-audio/aenc-aac/qdsp6/inc/Map.h new file mode 100644 index 00000000..aac96fd1 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/inc/Map.h @@ -0,0 +1,244 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include <stdio.h> +using namespace std; + +template <typename T,typename T2> +class Map +{ + struct node + { + T data; + T2 data2; + node* prev; + node* next; + node(T t, T2 t2,node* p, node* n) : + data(t), data2(t2), prev(p), next(n) {} + }; + node* head; + node* tail; + node* tmp; + unsigned size_of_list; + static Map<T,T2> *m_self; +public: + Map() : head( NULL ), tail ( NULL ),tmp(head),size_of_list(0) {} + bool empty() const { return ( !head || !tail ); } + operator bool() const { return !empty(); } + void insert(T,T2); + void show(); + int size(); + T2 find(T); // Return VALUE + T find_ele(T);// Check if the KEY is present or not + T2 begin(); //give the first ele + bool erase(T); + bool eraseall(); + bool isempty(); + ~Map() + { + while(head) + { + node* temp(head); + head=head->next; + size_of_list--; + delete temp; + } + } +}; + +template <typename T,typename T2> +T2 Map<T,T2>::find(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data2; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T Map<T,T2>::find_ele(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T2 Map<T,T2>::begin() +{ + tmp = head; + if(tmp) + { + return (tmp->data2); + } + return 0; +} + +template <typename T,typename T2> +void Map<T,T2>::show() +{ + tmp = head; + while(tmp) + { + printf("%d-->%d\n",tmp->data,tmp->data2); + tmp = tmp->next; + } +} + +template <typename T,typename T2> +int Map<T,T2>::size() +{ + int count =0; + tmp = head; + while(tmp) + { + tmp = tmp->next; + count++; + } + return count; +} + +template <typename T,typename T2> +void Map<T,T2>::insert(T data, T2 data2) +{ + tail = new node(data, data2,tail, NULL); + if( tail->prev ) + tail->prev->next = tail; + + if( empty() ) + { + head = tail; + tmp=head; + } + tmp = head; + size_of_list++; +} + +template <typename T,typename T2> +bool Map<T,T2>::erase(T d) +{ + bool found = false; + tmp = head; + node* prevnode = tmp; + node *tempnode; + + while(tmp) + { + if((head == tail) && (head->data == d)) + { + found = true; + tempnode = head; + head = tail = NULL; + delete tempnode; + break; + } + if((tmp ==head) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + tmp = tmp->next; + tmp->prev = NULL; + head = tmp; + tempnode->next = NULL; + delete tempnode; + break; + } + if((tmp == tail) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + prevnode->next = NULL; + tmp->prev = NULL; + tail = prevnode; + delete tempnode; + break; + } + if(tmp->data == d) + { + found = true; + prevnode->next = tmp->next; + tmp->next->prev = prevnode->next; + tempnode = tmp; + //tmp = tmp->next; + delete tempnode; + break; + } + prevnode = tmp; + tmp = tmp->next; + } + if(found)size_of_list--; + return found; +} + +template <typename T,typename T2> +bool Map<T,T2>::eraseall() +{ + // Be careful while using this method + // it not only removes the node but FREES(not delete) the allocated + // memory. + node *tempnode; + tmp = head; + while(head) + { + tempnode = head; + head = head->next; + tempnode->next = NULL; + if(tempnode->data) + free(tempnode->data); + if(tempnode->data2) + free(tempnode->data2); + delete tempnode; + } + tail = head = NULL; + return true; +} + + +template <typename T,typename T2> +bool Map<T,T2>::isempty() +{ + if(!size_of_list) return true; + else return false; +} + +#endif // _MAP_H_ diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/inc/aenc_svr.h b/msm8909/mm-audio/aenc-aac/qdsp6/inc/aenc_svr.h new file mode 100644 index 00000000..9bc72009 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/inc/aenc_svr.h @@ -0,0 +1,120 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef AENC_SVR_H +#define AENC_SVR_H + +#ifdef __cplusplus +extern "C" { +#endif +#include <pthread.h> +#include <sched.h> +#include <utils/Log.h> + +#ifdef _ANDROID_ +#define LOG_TAG "QC_AACENC" +#endif + +#ifndef LOGE +#define LOGE ALOGE +#endif + +#ifndef LOGW +#define LOGW ALOGW +#endif + +#ifndef LOGD +#define LOGD ALOGD +#endif + +#ifndef LOGV +#define LOGV ALOGV +#endif + +#ifndef LOGI +#define LOGI ALOGI +#endif + +#define DEBUG_PRINT_ERROR LOGE +#define DEBUG_PRINT LOGV +#define DEBUG_DETAIL LOGV + +typedef void (*message_func)(void* client_data, unsigned char id); + +/** + @brief audio encoder ipc info structure + + */ +struct aac_ipc_info +{ + pthread_t thr; + int pipe_in; + int pipe_out; + int dead; + message_func process_msg_cb; + void *client_data; + char thread_name[128]; +}; + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to command server + */ +struct aac_ipc_info *omx_aac_thread_create(message_func cb, + void* client_data, + char *th_name); + +struct aac_ipc_info *omx_aac_event_thread_create(message_func cb, + void* client_data, + char *th_name); +/** + @brief This function stop command server + + @param svr handle to command server + @return none + */ +void omx_aac_thread_stop(struct aac_ipc_info *aac_ipc); + + +/** + @brief This function post message in the command server + + @param svr handle to command server + @return none + */ +void omx_aac_post_msg(struct aac_ipc_info *aac_ipc, + unsigned char id); + +#ifdef __cplusplus +} +#endif + +#endif /* AENC_SVR */ diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h b/msm8909/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h new file mode 100644 index 00000000..2e2abbf6 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/inc/omx_aac_aenc.h @@ -0,0 +1,629 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _AAC_ENC_H_ +#define _AAC_ENC_H_ +/*============================================================================ + Audio Encoder + +@file omx_aac_aenc.h +This module contains the class definition for openMAX encoder component. + + + +============================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +/* Uncomment out below line #define LOG_NDEBUG 0 if we want to see + * all DEBUG_PRINT or LOGV messaging */ +#include<stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <time.h> +#include <inttypes.h> +#include <unistd.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#include "OMX_Core.h" +#include "OMX_Audio.h" +#include "aenc_svr.h" +#include "qc_omx_component.h" +#include "Map.h" +#include <semaphore.h> +#include <linux/msm_audio.h> +#include <linux/msm_audio_aac.h> +extern "C" { + void * get_omx_component_factory_fn(void); +} + + +////////////////////////////////////////////////////////////////////////////// +// Module specific globals +////////////////////////////////////////////////////////////////////////////// + + + +#define OMX_SPEC_VERSION 0x00000101 +#define min(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (x >= y?x:y) + +////////////////////////////////////////////////////////////////////////////// +// Macros +////////////////////////////////////////////////////////////////////////////// +// + + +#define PrintFrameHdr(i,bufHdr) \ + DEBUG_PRINT("i=%d OMX bufHdr[%p]buf[%p]size[%d]TS[%lld]nFlags[0x%x]\n",\ + i,\ + bufHdr, \ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFlags) + + +// BitMask Management logic +#define BITS_PER_BYTE 8 +#define BITMASK_SIZE(mIndex) \ + (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) +#define BITMASK_OFFSET(mIndex)\ + ((mIndex)/BITS_PER_BYTE) +#define BITMASK_FLAG(mIndex) \ + (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITMASK_CLEAR(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] &= ~(BITMASK_FLAG(mIndex)) +#define BITMASK_SET(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] |= BITMASK_FLAG(mIndex) +#define BITMASK_PRESENT(mArray,mIndex)\ + ((mArray)[BITMASK_OFFSET(mIndex)] & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex)\ + (((mArray)[BITMASK_OFFSET(mIndex)] & \ + BITMASK_FLAG(mIndex)) == 0x0) + +#define OMX_CORE_NUM_INPUT_BUFFERS 2 +#define OMX_CORE_NUM_OUTPUT_BUFFERS 16 + +#define OMX_CORE_INPUT_BUFFER_SIZE 8192 +#define OMX_CORE_CONTROL_CMDQ_SIZE 100 +#define OMX_AENC_VOLUME_STEP 0x147 +#define OMX_AENC_MIN 0 +#define OMX_AENC_MAX 100 +#define NON_TUNNEL 1 +#define TUNNEL 0 +#define IP_PORT_BITMASK 0x02 +#define OP_PORT_BITMASK 0x01 +#define IP_OP_PORT_BITMASK 0x03 + +#define DEFAULT_SF 44100 +#define DEFAULT_CH_CFG 2 +#define DEFAULT_BITRATE 64000 +#define OMX_AAC_DEFAULT_VOL 25 +// 14 bytes for input meta data +#define OMX_AENC_SIZEOF_META_BUF (OMX_CORE_INPUT_BUFFER_SIZE+14) + +#define TRUE 1 +#define FALSE 0 + + +#define NUMOFFRAMES 1 +#define MAXFRAMELENGTH 1536 +#define OMX_AAC_OUTPUT_BUFFER_SIZE ((NUMOFFRAMES * (sizeof(ENC_META_OUT)+ MAXFRAMELENGTH + 1)\ + + 1023) & (~1023)) +//Raw Header +#define AUDAAC_MAX_MP4FF_HEADER_LENGTH 2 + +#define AUDAAC_MP4FF_OBJ_TYPE 5 +#define AUDAAC_MP4FF_FREQ_IDX 4 +#define AUDAAC_MP4FF_CH_CONFIG 4 + +//ADIF Header +#define AUDAAC_MAX_ADIF_HEADER_LENGTH 17 + +#define AAC_COPYRIGHT_PRESENT_SIZE 1 +#define AAC_ORIGINAL_COPY_SIZE 1 +#define AAC_HOME_SIZE 1 +#define AAC_BITSTREAM_TYPE_SIZE 1 +#define AAC_BITRATE_SIZE 23 +#define AAC_NUM_PFE_SIZE 4 +#define AAC_BUFFER_FULLNESS_SIZE 20 +#define AAC_ELEMENT_INSTANCE_TAG_SIZE 4 +#define AAC_NUM_FRONT_CHANNEL_ELEMENTS_SIZE 4 +#define AAC_NUM_SIDE_CHANNEL_ELEMENTS_SIZE 4 +#define AAC_NUM_BACK_CHANNEL_ELEMENTS_SIZE 4 +#define AAC_NUM_LFE_CHANNEL_ELEMENTS_SIZE 2 +#define AAC_NUM_ASSOC_DATA_ELEMENTS_SIZE 3 +#define AAC_NUM_VALID_CC_ELEMENTS_SIZE 4 +#define AAC_MONO_MIXDOWN_PRESENT_SIZE 1 +#define AAC_MONO_MIXDOWN_ELEMENT_SIZE 4 +#define AAC_STEREO_MIXDOWN_PRESENT_SIZE 1 +#define AAC_STEREO_MIXDOWN_ELEMENT_SIZE 4 +#define AAC_MATRIX_MIXDOWN_PRESENT_SIZE 1 +#define AAC_MATRIX_MIXDOWN_SIZE 3 +#define AAC_FCE_SIZE 5 +#define AAC_SCE_SIZE 5 +#define AAC_BCE_SIZE 5 +#define AAC_LFE_SIZE 4 +#define AAC_ADE_SIZE 4 +#define AAC_VCE_SIZE 5 +#define AAC_COMMENT_FIELD_BYTES_SIZE 8 +#define AAC_COMMENT_FIELD_DATA_SIZE 8 +#define AAC_SAMPLING_FREQ_INDEX_SIZE 4 +#define AAC_PROFILE_SIZE 2 + + + +//Raw Header +#define AUDAAC_MAX_RAW_HEADER_LENGTH 8 + +#define AUDAAC_RAW_OBJ_TYPE 8 +#define AUDAAC_RAW_FREQ_IDX 8 +#define AUDAAC_RAW_CH_CONFIG 8 +#define AUDAAC_RAW_SBR_PRESENT 8 +#define AUDAAC_RAW_SBR_PS_PRESENT 8 +#define AUDAAC_RAW_EXT_OBJ_TYPE 8 +#define AUDAAC_RAW_EXT_FREQ_IDX 8 +#define AUDAAC_RAW_EXT_CH_CONFIG 8 + +struct sample_rate_idx { + OMX_U32 sample_rate; + OMX_U32 sample_rate_idx; +}; +static struct sample_rate_idx sample_idx_tbl[10] = { + {8000, 0x0b}, + {11025, 0x0a}, + {12000, 0x09}, + {16000, 0x08}, + {22050, 0x07}, + {24000, 0x06}, + {32000, 0x05}, + {44100, 0x04}, + {48000, 0x03}, + {64000, 0x02}, +}; +class omx_aac_aenc; + +// OMX AAC audio encoder class +class omx_aac_aenc: public qc_omx_component +{ +public: + omx_aac_aenc(); // constructor + virtual ~omx_aac_aenc(); // destructor + + OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + + OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp); + + OMX_ERRORTYPE component_init(OMX_STRING role); + + OMX_ERRORTYPE component_role_enum(OMX_HANDLETYPE hComp, + OMX_U8 *role, + OMX_U32 index); + + OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_HANDLETYPE peerComponent, + OMX_U32 peerPort, + OMX_TUNNELSETUPTYPE *tunnelSetup); + + OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE hComp, + OMX_STRING componentName, + OMX_VERSIONTYPE *componentVersion, + OMX_VERSIONTYPE * specVersion, + OMX_UUIDTYPE *componentUUID); + + OMX_ERRORTYPE get_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE hComp, + OMX_STRING paramName, + OMX_INDEXTYPE *indexType); + + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp, + OMX_STATETYPE *state); + + static void process_in_port_msg(void *client_data, + unsigned char id); + + static void process_out_port_msg(void *client_data, + unsigned char id); + + static void process_command_msg(void *client_data, + unsigned char id); + + static void process_event_cb(void *client_data, + unsigned char id); + + + OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp, + OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData); + + OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + void * eglImage); + + bool post_command(unsigned int p1, unsigned int p2, + unsigned char id); + + // Deferred callback identifiers + enum + { + //Event Callbacks from the component thread context + OMX_COMPONENT_GENERATE_EVENT = 0x1, + //Buffer Done callbacks from component thread context + OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2, + OMX_COMPONENT_GENERATE_ETB = 0x3, + //Command + OMX_COMPONENT_GENERATE_COMMAND = 0x4, + OMX_COMPONENT_GENERATE_FRAME_DONE = 0x05, + OMX_COMPONENT_GENERATE_FTB = 0x06, + OMX_COMPONENT_GENERATE_EOS = 0x07, + OMX_COMPONENT_PORTSETTINGS_CHANGED = 0x08, + OMX_COMPONENT_SUSPEND = 0x09, + OMX_COMPONENT_RESUME = 0x0a + }; +private: + + /////////////////////////////////////////////////////////// + // Type definitions + /////////////////////////////////////////////////////////// + // Bit Positions + enum flags_bit_positions + { + // Defer transition to IDLE + OMX_COMPONENT_IDLE_PENDING =0x1, + // Defer transition to LOADING + OMX_COMPONENT_LOADING_PENDING =0x2, + + OMX_COMPONENT_MUTED =0x3, + + // Defer transition to Enable + OMX_COMPONENT_INPUT_ENABLE_PENDING =0x4, + // Defer transition to Enable + OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x5, + // Defer transition to Disable + OMX_COMPONENT_INPUT_DISABLE_PENDING =0x6, + // Defer transition to Disable + OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x7 + }; + + #define MIN_BITRATE 24000 + #define MAX_BITRATE 192000 + #define MAX_BITRATE_MULFACTOR 12 + #define BITRATE_DIVFACTOR 2 + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + input_buffer_map; + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + output_buffer_map; + + enum port_indexes + { + OMX_CORE_INPUT_PORT_INDEX =0, + OMX_CORE_OUTPUT_PORT_INDEX =1 + }; + + struct omx_event + { + unsigned long param1; + unsigned long param2; + unsigned char id; + }; + + struct omx_cmd_queue + { + omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE]; + unsigned m_read; + unsigned m_write; + unsigned m_size; + + omx_cmd_queue(); + ~omx_cmd_queue(); + bool insert_entry(unsigned long p1, unsigned long p2, unsigned char id); + bool pop_entry(unsigned long *p1,unsigned long *p2, unsigned char *id); + bool get_msg_id(unsigned char *id); + bool get_msg_with_id(unsigned *p1,unsigned *p2, unsigned id); + }; + + typedef struct TIMESTAMP + { + unsigned int LowPart; + unsigned int HighPart; + }__attribute__((packed)) TIMESTAMP; + + typedef struct metadata_input + { + unsigned short offsetVal; + TIMESTAMP nTimeStamp; + unsigned int nFlags; + }__attribute__((packed)) META_IN; + + typedef struct enc_meta_out + { + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; + } __attribute__ ((packed))ENC_META_OUT; + + typedef struct + { + OMX_U32 tot_in_buf_len; + OMX_U32 tot_out_buf_len; + OMX_TICKS tot_pb_time; + OMX_U32 fbd_cnt; + OMX_U32 ftb_cnt; + OMX_U32 etb_cnt; + OMX_U32 ebd_cnt; + }AAC_PB_STATS; + + /////////////////////////////////////////////////////////// + // Member variables + /////////////////////////////////////////////////////////// + OMX_U8 *m_tmp_meta_buf; + OMX_U8 *m_tmp_out_meta_buf; + OMX_U8 m_flush_cnt ; + OMX_U8 m_comp_deinit; + + // the below var doesnt hold good if combo of use and alloc bufs are used + OMX_U8 m_eos_bm; + OMX_S32 m_volume;//Unit to be determined + OMX_U8 audaac_header_adif[AUDAAC_MAX_ADIF_HEADER_LENGTH]; + OMX_U8 audaac_header_mp4ff[AUDAAC_MAX_MP4FF_HEADER_LENGTH]; + OMX_U16 audaac_hdr_bit_index; + OMX_S32 sample_idx; + OMX_S32 adif_flag; + OMX_S32 mp4ff_flag; + OMX_PTR m_app_data;// Application data + int nNumInputBuf; + int nNumOutputBuf; + int m_drv_fd; // Kernel device node file handle + bool bFlushinprogress; + bool is_in_th_sleep; + bool is_out_th_sleep; + unsigned int m_flags; //encapsulate the waiting states. + OMX_U64 nTimestamp; + OMX_U64 ts; + uint32_t m_frame_count; + unsigned int frameduration; + unsigned int pcm_input; //tunnel or non-tunnel + unsigned int m_inp_act_buf_count; // Num of Input Buffers + unsigned int m_out_act_buf_count; // Numb of Output Buffers + unsigned int m_inp_current_buf_count; // Num of Input Buffers + unsigned int m_out_current_buf_count; // Numb of Output Buffers + unsigned int output_buffer_size; + unsigned int input_buffer_size; + unsigned short m_session_id; + // store I/P PORT state + OMX_BOOL m_inp_bEnabled; + // store O/P PORT state + OMX_BOOL m_out_bEnabled; + //Input port Populated + OMX_BOOL m_inp_bPopulated; + //Output port Populated + OMX_BOOL m_out_bPopulated; + sem_t sem_States; + sem_t sem_read_msg; + sem_t sem_write_msg; + + volatile int m_is_event_done; + volatile int m_is_in_th_sleep; + volatile int m_is_out_th_sleep; + input_buffer_map m_input_buf_hdrs; + output_buffer_map m_output_buf_hdrs; + omx_cmd_queue m_input_q; + omx_cmd_queue m_input_ctrl_cmd_q; + omx_cmd_queue m_input_ctrl_ebd_q; + omx_cmd_queue m_command_q; + omx_cmd_queue m_output_q; + omx_cmd_queue m_output_ctrl_cmd_q; + omx_cmd_queue m_output_ctrl_fbd_q; + pthread_mutexattr_t m_outputlock_attr; + pthread_mutexattr_t m_commandlock_attr; + pthread_mutexattr_t m_lock_attr; + pthread_mutexattr_t m_state_attr; + pthread_mutexattr_t m_flush_attr; + pthread_mutexattr_t m_in_th_attr_1; + pthread_mutexattr_t m_out_th_attr_1; + pthread_mutexattr_t m_event_attr; + pthread_mutexattr_t m_in_th_attr; + pthread_mutexattr_t m_out_th_attr; + pthread_mutexattr_t out_buf_count_lock_attr; + pthread_mutexattr_t in_buf_count_lock_attr; + pthread_cond_t cond; + pthread_cond_t in_cond; + pthread_cond_t out_cond; + pthread_mutex_t m_lock; + pthread_mutex_t m_commandlock; + pthread_mutex_t m_outputlock; + // Mutexes for state change + pthread_mutex_t m_state_lock; + // Mutexes for flush acks from input and output threads + pthread_mutex_t m_flush_lock; + pthread_mutex_t m_event_lock; + pthread_mutex_t m_in_th_lock; + pthread_mutex_t m_out_th_lock; + pthread_mutex_t m_in_th_lock_1; + pthread_mutex_t m_out_th_lock_1; + pthread_mutex_t out_buf_count_lock; + pthread_mutex_t in_buf_count_lock; + + OMX_STATETYPE m_state; // OMX State + OMX_STATETYPE nState; + OMX_CALLBACKTYPE m_cb; // Application callbacks + AAC_PB_STATS m_aac_pb_stats; + struct aac_ipc_info *m_ipc_to_in_th; // for input thread + struct aac_ipc_info *m_ipc_to_out_th; // for output thread + struct aac_ipc_info *m_ipc_to_cmd_th; // for command thread + OMX_PRIORITYMGMTTYPE m_priority_mgm ; + OMX_AUDIO_PARAM_AACPROFILETYPE m_aac_param; // Cache AAC encoder parameter + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_param; // Cache pcm parameter + OMX_PARAM_COMPONENTROLETYPE component_Role; + OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier; + + /////////////////////////////////////////////////////////// + // Private methods + /////////////////////////////////////////////////////////// + OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port,OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE use_input_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE use_output_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + bool allocate_done(void); + + bool release_done(OMX_U32 param1); + + bool execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl=true); + + bool execute_input_omx_flush(void); + + bool execute_output_omx_flush(void); + + bool search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool post_input(unsigned long p1, unsigned long p2, + unsigned char id); + + bool post_output(unsigned long p1, unsigned long p2, + unsigned char id); + + void process_events(omx_aac_aenc *client_data); + + void buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void wait_for_event(); + + void event_complete(); + + void in_th_goto_sleep(); + + void in_th_wakeup(); + + void out_th_goto_sleep(); + + void out_th_wakeup(); + + void flush_ack(); + void deinit_encoder(); + void audaac_rec_install_adif_header_variable (OMX_U16 byte_num, + OMX_U32 sample_index, OMX_U8 channel_config); + void audaac_rec_install_mp4ff_header_variable (OMX_U16 byte_num, + OMX_U32 sample_index,OMX_U8 channel_config); + void audaac_rec_install_bits(OMX_U8 *input, + OMX_U8 num_bits_reqd, + OMX_U32 value, + OMX_U16 *hdr_bit_index); + int get_updated_bit_rate(int bitrate); + +}; +#endif diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/src/aenc_svr.c b/msm8909/mm-audio/aenc-aac/qdsp6/src/aenc_svr.c new file mode 100644 index 00000000..9a8448a9 --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/src/aenc_svr.c @@ -0,0 +1,206 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> +#include <errno.h> + +#include <aenc_svr.h> + +/** + @brief This function processes posted messages + + Once thread is being spawned, this function is run to + start processing commands posted by client + + @param info pointer to context + + */ +void *omx_aac_msg(void *info) +{ + struct aac_ipc_info *aac_info = (struct aac_ipc_info*)info; + unsigned char id; + ssize_t n; + + DEBUG_DETAIL("\n%s: message thread start\n", __FUNCTION__); + while (!aac_info->dead) + { + n = read(aac_info->pipe_in, &id, 1); + if (0 == n) break; + if (1 == n) + { + DEBUG_DETAIL("\n%s-->pipe_in=%d pipe_out=%d\n", + aac_info->thread_name, + aac_info->pipe_in, + aac_info->pipe_out); + + aac_info->process_msg_cb(aac_info->client_data, id); + } + if ((n < 0) && (errno != EINTR)) break; + } + DEBUG_DETAIL("%s: message thread stop\n", __FUNCTION__); + + return 0; +} + +void *omx_aac_events(void *info) +{ + struct aac_ipc_info *aac_info = (struct aac_ipc_info*)info; + unsigned char id = 0; + + DEBUG_DETAIL("%s: message thread start\n", aac_info->thread_name); + aac_info->process_msg_cb(aac_info->client_data, id); + DEBUG_DETAIL("%s: message thread stop\n", aac_info->thread_name); + return 0; +} + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to msging thread + */ +struct aac_ipc_info *omx_aac_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct aac_ipc_info *aac_info; + + aac_info = calloc(1, sizeof(struct aac_ipc_info)); + if (!aac_info) + { + return 0; + } + + aac_info->client_data = client_data; + aac_info->process_msg_cb = cb; + strlcpy(aac_info->thread_name, th_name, sizeof(aac_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT_ERROR("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + aac_info->pipe_in = fds[0]; + aac_info->pipe_out = fds[1]; + + r = pthread_create(&aac_info->thr, 0, omx_aac_msg, aac_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", aac_info->thread_name); + return aac_info; + + +fail_thread: + close(aac_info->pipe_in); + close(aac_info->pipe_out); + +fail_pipe: + free(aac_info); + + return 0; +} + +/** + * @brief This function starts command server + * + * @param cb pointer to callback function from the client + * @param client_data reference client wants to get back + * through callback + * @return handle to msging thread + * */ +struct aac_ipc_info *omx_aac_event_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct aac_ipc_info *aac_info; + + aac_info = calloc(1, sizeof(struct aac_ipc_info)); + if (!aac_info) + { + return 0; + } + + aac_info->client_data = client_data; + aac_info->process_msg_cb = cb; + strlcpy(aac_info->thread_name, th_name, sizeof(aac_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + aac_info->pipe_in = fds[0]; + aac_info->pipe_out = fds[1]; + + r = pthread_create(&aac_info->thr, 0, omx_aac_events, aac_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", aac_info->thread_name); + return aac_info; + + +fail_thread: + close(aac_info->pipe_in); + close(aac_info->pipe_out); + +fail_pipe: + free(aac_info); + + return 0; +} + +void omx_aac_thread_stop(struct aac_ipc_info *aac_info) { + DEBUG_DETAIL("%s stop server\n", __FUNCTION__); + close(aac_info->pipe_in); + close(aac_info->pipe_out); + pthread_join(aac_info->thr,NULL); + aac_info->pipe_out = -1; + aac_info->pipe_in = -1; + DEBUG_DETAIL("%s: message thread close fds%d %d\n", aac_info->thread_name, + aac_info->pipe_in,aac_info->pipe_out); + free(aac_info); +} + +void omx_aac_post_msg(struct aac_ipc_info *aac_info, unsigned char id) { + DEBUG_DETAIL("\n%s id=%d\n", __FUNCTION__,id); + + write(aac_info->pipe_out, &id, 1); +} diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp b/msm8909/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp new file mode 100644 index 00000000..6af9269c --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/src/omx_aac_aenc.cpp @@ -0,0 +1,5062 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ +@file omx_aenc_aac.c + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + + +#include<string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include "omx_aac_aenc.h" +#include <errno.h> + +using namespace std; + +#define SLEEP_MS 100 + +// omx_cmd_queue destructor +omx_aac_aenc::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_aac_aenc::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q, 0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_aac_aenc::omx_cmd_queue::insert_entry(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool ret = true; + if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full"); + } + return ret; +} + +bool omx_aac_aenc::omx_cmd_queue::pop_entry(unsigned long *p1, + unsigned long *p2, unsigned char *id) +{ + bool ret = true; + if (m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR Delete!!! Command Queue Empty"); + } + return ret; +} + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return(new omx_aac_aenc); +} +bool omx_aac_aenc::omx_cmd_queue::get_msg_id(unsigned char *id) +{ + if(m_size > 0) + { + *id = m_q[m_read].id; + DEBUG_PRINT("get_msg_id=%d\n",*id); + } + else{ + return false; + } + return true; +} +/*============================================================================= +FUNCTION: + wait_for_event + +DESCRIPTION: + waits for a particular event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_aac_aenc::wait_for_event() +{ + int rc; + struct timespec ts; + pthread_mutex_lock(&m_event_lock); + while (0 == m_is_event_done) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += (SLEEP_MS/1000); + ts.tv_nsec += ((SLEEP_MS%1000) * 1000000); + rc = pthread_cond_timedwait(&cond, &m_event_lock, &ts); + if (rc == ETIMEDOUT && !m_is_event_done) { + DEBUG_PRINT("Timed out waiting for flush"); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + } + } + m_is_event_done = 0; + pthread_mutex_unlock(&m_event_lock); +} + +/*============================================================================= +FUNCTION: + event_complete + +DESCRIPTION: + informs about the occurance of an event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_aac_aenc::event_complete() +{ + pthread_mutex_lock(&m_event_lock); + if (0 == m_is_event_done) + { + m_is_event_done = 1; + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&m_event_lock); +} + +// All this non-sense because of a single aac object +void omx_aac_aenc::in_th_goto_sleep() +{ + pthread_mutex_lock(&m_in_th_lock); + while (0 == m_is_in_th_sleep) + { + pthread_cond_wait(&in_cond, &m_in_th_lock); + } + m_is_in_th_sleep = 0; + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_aac_aenc::in_th_wakeup() +{ + pthread_mutex_lock(&m_in_th_lock); + if (0 == m_is_in_th_sleep) + { + m_is_in_th_sleep = 1; + pthread_cond_signal(&in_cond); + } + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_aac_aenc::out_th_goto_sleep() +{ + + pthread_mutex_lock(&m_out_th_lock); + while (0 == m_is_out_th_sleep) + { + pthread_cond_wait(&out_cond, &m_out_th_lock); + } + m_is_out_th_sleep = 0; + pthread_mutex_unlock(&m_out_th_lock); +} + +void omx_aac_aenc::out_th_wakeup() +{ + pthread_mutex_lock(&m_out_th_lock); + if (0 == m_is_out_th_sleep) + { + m_is_out_th_sleep = 1; + pthread_cond_signal(&out_cond); + } + pthread_mutex_unlock(&m_out_th_lock); +} +/* ====================================================================== +FUNCTION + omx_aac_aenc::omx_aac_aenc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_aac_aenc::omx_aac_aenc(): m_tmp_meta_buf(NULL), + m_tmp_out_meta_buf(NULL), + m_flush_cnt(255), + m_comp_deinit(0), + adif_flag(0), + mp4ff_flag(0), + m_app_data(NULL), + nNumOutputBuf(0), + m_drv_fd(-1), + bFlushinprogress(0), + is_in_th_sleep(false), + is_out_th_sleep(false), + m_flags(0), + nTimestamp(0), + ts(0), + frameduration(0), + m_inp_act_buf_count (OMX_CORE_NUM_INPUT_BUFFERS), + m_out_act_buf_count (OMX_CORE_NUM_OUTPUT_BUFFERS), + m_inp_current_buf_count(0), + m_out_current_buf_count(0), + output_buffer_size((OMX_U32)OMX_AAC_OUTPUT_BUFFER_SIZE), + input_buffer_size(OMX_CORE_INPUT_BUFFER_SIZE), + m_session_id(0), + m_inp_bEnabled(OMX_TRUE), + m_out_bEnabled(OMX_TRUE), + m_inp_bPopulated(OMX_FALSE), + m_out_bPopulated(OMX_FALSE), + m_is_event_done(0), + m_state(OMX_StateInvalid), + m_ipc_to_in_th(NULL), + m_ipc_to_out_th(NULL), + m_ipc_to_cmd_th(NULL) +{ + int cond_ret = 0; + component_Role.nSize = 0; + memset(&m_cmp, 0, sizeof(m_cmp)); + memset(&m_cb, 0, sizeof(m_cb)); + memset(&m_aac_pb_stats, 0, sizeof(m_aac_pb_stats)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + memset(&m_aac_param, 0, sizeof(m_aac_param)); + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + + pthread_mutexattr_init(&m_lock_attr); + pthread_mutex_init(&m_lock, &m_lock_attr); + pthread_mutexattr_init(&m_commandlock_attr); + pthread_mutex_init(&m_commandlock, &m_commandlock_attr); + + pthread_mutexattr_init(&m_outputlock_attr); + pthread_mutex_init(&m_outputlock, &m_outputlock_attr); + + pthread_mutexattr_init(&m_state_attr); + pthread_mutex_init(&m_state_lock, &m_state_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_flush_attr); + pthread_mutex_init(&m_flush_lock, &m_flush_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_in_th_attr); + pthread_mutex_init(&m_in_th_lock, &m_in_th_attr); + + pthread_mutexattr_init(&m_out_th_attr); + pthread_mutex_init(&m_out_th_lock, &m_out_th_attr); + + pthread_mutexattr_init(&m_in_th_attr_1); + pthread_mutex_init(&m_in_th_lock_1, &m_in_th_attr_1); + + pthread_mutexattr_init(&m_out_th_attr_1); + pthread_mutex_init(&m_out_th_lock_1, &m_out_th_attr_1); + + pthread_mutexattr_init(&out_buf_count_lock_attr); + pthread_mutex_init(&out_buf_count_lock, &out_buf_count_lock_attr); + + pthread_mutexattr_init(&in_buf_count_lock_attr); + pthread_mutex_init(&in_buf_count_lock, &in_buf_count_lock_attr); + if ((cond_ret = pthread_cond_init (&cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to \ + initialise condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&in_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for in_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to \ + initialise condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&out_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for out_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to \ + initialise condition variable\n"); + } + + sem_init(&sem_read_msg,0, 0); + sem_init(&sem_write_msg,0, 0); + sem_init(&sem_States,0, 0); + return; +} + + +/* ====================================================================== +FUNCTION + omx_aac_aenc::~omx_aac_aenc + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_aac_aenc::~omx_aac_aenc() +{ + DEBUG_PRINT_ERROR("AAC Object getting destroyed comp-deinit=%d\n", + m_comp_deinit); + if ( !m_comp_deinit ) + { + deinit_encoder(); + } + pthread_mutexattr_destroy(&m_lock_attr); + pthread_mutex_destroy(&m_lock); + + pthread_mutexattr_destroy(&m_commandlock_attr); + pthread_mutex_destroy(&m_commandlock); + + pthread_mutexattr_destroy(&m_outputlock_attr); + pthread_mutex_destroy(&m_outputlock); + + pthread_mutexattr_destroy(&m_state_attr); + pthread_mutex_destroy(&m_state_lock); + + pthread_mutexattr_destroy(&m_event_attr); + pthread_mutex_destroy(&m_event_lock); + + pthread_mutexattr_destroy(&m_flush_attr); + pthread_mutex_destroy(&m_flush_lock); + + pthread_mutexattr_destroy(&m_in_th_attr); + pthread_mutex_destroy(&m_in_th_lock); + + pthread_mutexattr_destroy(&m_out_th_attr); + pthread_mutex_destroy(&m_out_th_lock); + + pthread_mutexattr_destroy(&out_buf_count_lock_attr); + pthread_mutex_destroy(&out_buf_count_lock); + + pthread_mutexattr_destroy(&in_buf_count_lock_attr); + pthread_mutex_destroy(&in_buf_count_lock); + + pthread_mutexattr_destroy(&m_in_th_attr_1); + pthread_mutex_destroy(&m_in_th_lock_1); + + pthread_mutexattr_destroy(&m_out_th_attr_1); + pthread_mutex_destroy(&m_out_th_lock_1); + pthread_mutex_destroy(&out_buf_count_lock); + pthread_mutex_destroy(&in_buf_count_lock); + pthread_cond_destroy(&cond); + pthread_cond_destroy(&in_cond); + pthread_cond_destroy(&out_cond); + sem_destroy (&sem_read_msg); + sem_destroy (&sem_write_msg); + sem_destroy (&sem_States); + DEBUG_PRINT_ERROR("OMX AAC component destroyed\n"); + return; +} + +/** + @brief memory function for sending EmptyBufferDone event + back to IL client + + @param bufHdr OMX buffer header to be passed back to IL client + @return none + */ +void omx_aac_aenc::buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.EmptyBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_BUFFER_DONE,bufHdr); + bufHdr->nFilledLen = 0; + + m_cb.EmptyBufferDone(&m_cmp, m_app_data, bufHdr); + pthread_mutex_lock(&in_buf_count_lock); + m_aac_pb_stats.ebd_cnt++; + nNumInputBuf--; + DEBUG_DETAIL("EBD CB:: in_buf_len=%d nNumInputBuf=%d ebd_cnd %d\n",\ + m_aac_pb_stats.tot_in_buf_len, + nNumInputBuf, m_aac_pb_stats.ebd_cnt); + pthread_mutex_unlock(&in_buf_count_lock); + } + + return; +} + +/*============================================================================= +FUNCTION: + flush_ack + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_aac_aenc::flush_ack() +{ + // Decrement the FLUSH ACK count and notify the waiting recepients + pthread_mutex_lock(&m_flush_lock); + --m_flush_cnt; + if (0 == m_flush_cnt) + { + event_complete(); + } + DEBUG_PRINT("Rxed FLUSH ACK cnt=%d\n",m_flush_cnt); + pthread_mutex_unlock(&m_flush_lock); +} +void omx_aac_aenc::frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.FillBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_FRAME_DONE,bufHdr); + m_aac_pb_stats.fbd_cnt++; + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf--; + DEBUG_PRINT("FBD CB:: nNumOutputBuf=%d out_buf_len=%u fbd_cnt=%u\n",\ + nNumOutputBuf, + m_aac_pb_stats.tot_out_buf_len, + m_aac_pb_stats.fbd_cnt); + m_aac_pb_stats.tot_out_buf_len += bufHdr->nFilledLen; + m_aac_pb_stats.tot_pb_time = bufHdr->nTimeStamp; + DEBUG_PRINT("FBD:in_buf_len=%u out_buf_len=%u\n", + m_aac_pb_stats.tot_in_buf_len, + m_aac_pb_stats.tot_out_buf_len); + pthread_mutex_unlock(&out_buf_count_lock); + m_cb.FillBufferDone(&m_cmp, m_app_data, bufHdr); + } + return; +} + +/*============================================================================= +FUNCTION: + process_out_port_msg + +DESCRIPTION: + Function for handling all commands from IL client +IL client commands are processed and callbacks are generated through +this routine Audio Command Server provides the thread context for this routine + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_aac_aenc::process_out_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; // qsize + unsigned tot_qsize = 0; + omx_aac_aenc *pThis = (omx_aac_aenc *) client_data; + OMX_STATETYPE state; + +loopback_out: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" OUT: IN LOADED STATE RETURN\n"); + return; + } + pthread_mutex_lock(&pThis->m_outputlock); + + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + + if ( 0 == tot_qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_DETAIL("OUT-->BREAK FROM LOOP...%d\n",tot_qsize); + return; + } + if ( (state != OMX_StateExecuting) && !qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + DEBUG_DETAIL("OUT:1.SLEEPING OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + + if ( ((!pThis->m_output_ctrl_cmd_q.m_size) && !pThis->m_out_bEnabled) ) + { + // case where no port reconfig and nothing in the flush q + DEBUG_DETAIL("No flush/port reconfig qsize=%d tot_qsize=%d",\ + qsize,tot_qsize); + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + if(pThis->m_output_ctrl_cmd_q.m_size || !(pThis->bFlushinprogress)) + { + DEBUG_PRINT("OUT:2. SLEEPING OUT THREAD \n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + } + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_DETAIL("OUT-->QSIZE-flush=%d,fbd=%d QSIZE=%d state=%d\n",\ + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size,state); + + + if (qsize) + { + // process FLUSH message + pThis->m_output_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_ctrl_fbd_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_output_ctrl_fbd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // if no FLUSH and FBD's then process FTB's + pThis->m_output_q.pop_entry(&p1,&p2,&ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("OUT--> Empty Queue state=%d %d %d %d\n",state, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("OUT: SLEEPING AGAIN OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pthread_mutex_unlock(&pThis->m_outputlock); + pThis->out_th_goto_sleep(); + goto loopback_out; + } + } + pthread_mutex_unlock(&pThis->m_outputlock); + + if ( qsize > 0 ) + { + id = ident; + ident = 0; + DEBUG_DETAIL("OUT->state[%d]ident[%d]flushq[%d]fbd[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if ( OMX_COMPONENT_GENERATE_FRAME_DONE == id ) + { + pThis->frame_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_FTB == id ) + { + pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_EOS == id ) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + + } + else if(id == OMX_COMPONENT_RESUME) + { + DEBUG_PRINT("RESUMED...\n"); + } + else if(id == OMX_COMPONENT_GENERATE_COMMAND) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL("Executing FLUSH command on Output port\n"); + pThis->execute_output_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:OUT-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR: OUT--> Empty OUTPUTQ\n"); + } + + return; +} + +/*============================================================================= +FUNCTION: + process_command_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_aac_aenc::process_command_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + omx_aac_aenc *pThis = (omx_aac_aenc*)client_data; + pthread_mutex_lock(&pThis->m_commandlock); + + qsize = pThis->m_command_q.m_size; + DEBUG_DETAIL("CMD-->QSIZE=%d state=%d\n",pThis->m_command_q.m_size, + pThis->m_state); + + if (!qsize) + { + DEBUG_DETAIL("CMD-->BREAKING FROM LOOP\n"); + pthread_mutex_unlock(&pThis->m_commandlock); + return; + } else + { + pThis->m_command_q.pop_entry(&p1,&p2,&ident); + } + pthread_mutex_unlock(&pThis->m_commandlock); + + id = ident; + DEBUG_DETAIL("CMD->state[%d]id[%d]cmdq[%d]n",\ + pThis->m_state,ident, \ + pThis->m_command_q.m_size); + + if (OMX_COMPONENT_GENERATE_EVENT == id) + { + if (pThis->m_cb.EventHandler) + { + if (OMX_CommandStateSet == p1) + { + pthread_mutex_lock(&pThis->m_state_lock); + pThis->m_state = (OMX_STATETYPE) p2; + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_PRINT("CMD:Process->state set to %d \n", \ + pThis->m_state); + + if (pThis->m_state == OMX_StateExecuting || + pThis->m_state == OMX_StateLoaded) + { + + pthread_mutex_lock(&pThis->m_in_th_lock_1); + if (pThis->is_in_th_sleep) + { + pThis->is_in_th_sleep = false; + DEBUG_DETAIL("CMD:WAKING UP IN THREADS\n"); + pThis->in_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + + pthread_mutex_lock(&pThis->m_out_th_lock_1); + if (pThis->is_out_th_sleep) + { + DEBUG_DETAIL("CMD:WAKING UP OUT THREADS\n"); + pThis->is_out_th_sleep = false; + pThis->out_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + } + } + if (OMX_StateInvalid == pThis->m_state) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + } else if ((signed)p2 == OMX_ErrorPortUnpopulated) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + (OMX_U32)p2, + 0, + 0); + } else + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventCmdComplete, + (OMX_U32)p1, (OMX_U32)p2, NULL ); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:CMD-->EventHandler NULL \n"); + } + } else if (OMX_COMPONENT_GENERATE_COMMAND == id) + { + pThis->send_command_proxy(&pThis->m_cmp, + (OMX_COMMANDTYPE)p1, + (OMX_U32)p2,(OMX_PTR)NULL); + } else if (OMX_COMPONENT_PORTSETTINGS_CHANGED == id) + { + DEBUG_DETAIL("CMD-->RXED PORTSETTINGS_CHANGED"); + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventPortSettingsChanged, + 1, 1, NULL ); + } + else + { + DEBUG_PRINT_ERROR("CMD->state[%d]id[%d]\n",pThis->m_state,ident); + } + return; +} + +/*============================================================================= +FUNCTION: + process_in_port_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_aac_aenc::process_in_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + unsigned tot_qsize = 0; + omx_aac_aenc *pThis = (omx_aac_aenc *) client_data; + OMX_STATETYPE state; + + if (!pThis) + { + DEBUG_PRINT_ERROR("ERROR:IN--> Invalid Obj \n"); + return; + } +loopback_in: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" IN: IN LOADED STATE RETURN\n"); + return; + } + // Protect the shared queue data structure + pthread_mutex_lock(&pThis->m_lock); + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + if ( 0 == tot_qsize ) + { + DEBUG_DETAIL("IN-->BREAKING FROM IN LOOP"); + pthread_mutex_unlock(&pThis->m_lock); + return; + } + + if ( (state != OMX_StateExecuting) && ! (pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_DETAIL("SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + else if ((state == OMX_StatePause)) + { + if(!(pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + + DEBUG_DETAIL("IN: SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + } + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + DEBUG_DETAIL("Input-->QSIZE-flush=%d,ebd=%d QSIZE=%d state=%d\n",\ + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size, state); + + + if ( qsize ) + { + // process FLUSH message + pThis->m_input_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_input_ctrl_ebd_q.m_size) && + (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_input_ctrl_ebd_q.pop_entry(&p1,&p2,&ident); + } else if ((qsize = pThis->m_input_q.m_size) && + (state == OMX_StateExecuting)) + { + // if no FLUSH and EBD's then process ETB's + pThis->m_input_q.pop_entry(&p1, &p2, &ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("IN-->state[%d]cmdq[%d]ebdq[%d]in[%d]\n",\ + state,pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("IN: SLEEPING AGAIN IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pthread_mutex_unlock(&pThis->m_lock); + pThis->in_th_goto_sleep(); + goto loopback_in; + } + } + pthread_mutex_unlock(&pThis->m_lock); + + if ( qsize > 0 ) + { + id = ident; + DEBUG_DETAIL("Input->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + if ( OMX_COMPONENT_GENERATE_BUFFER_DONE == id ) + { + pThis->buffer_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } + else if(id == OMX_COMPONENT_GENERATE_EOS) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventBufferFlag, 0, 1, NULL ); + } else if ( OMX_COMPONENT_GENERATE_ETB == id ) + { + pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_COMMAND == id ) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL(" Executing FLUSH command on Input port\n"); + pThis->execute_input_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } + else + { + DEBUG_PRINT_ERROR("ERROR:IN-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR:IN-->Empty INPUT Q\n"); + } + return; +} + +/** + @brief member function for performing component initialization + + @param role C string mandating role of this component + @return Error status + */ +OMX_ERRORTYPE omx_aac_aenc::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + m_state = OMX_StateLoaded; + + /* DSP does not give information about the bitstream + randomly assign the value right now. Query will result in + incorrect param */ + memset(&m_aac_param, 0, sizeof(m_aac_param)); + m_aac_param.nSize = (OMX_U32)sizeof(m_aac_param); + m_aac_param.nChannels = DEFAULT_CH_CFG; + m_aac_param.nSampleRate = DEFAULT_SF; + m_aac_param.nBitRate = DEFAULT_BITRATE; + m_volume = OMX_AAC_DEFAULT_VOL; /* Close to unity gain */ + memset(&m_aac_pb_stats,0,sizeof(AAC_PB_STATS)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + m_pcm_param.nSize = (OMX_U32)sizeof(m_pcm_param); + m_pcm_param.nChannels = DEFAULT_CH_CFG; + m_pcm_param.nSamplingRate = DEFAULT_SF; + + nTimestamp = 0; + ts = 0; + m_frame_count = 0; + frameduration = 0; + nNumInputBuf = 0; + nNumOutputBuf = 0; + m_ipc_to_in_th = NULL; // Command server instance + m_ipc_to_out_th = NULL; // Client server instance + m_ipc_to_cmd_th = NULL; // command instance + m_is_out_th_sleep = 0; + m_is_in_th_sleep = 0; + is_out_th_sleep= false; + + is_in_th_sleep=false; + adif_flag = 0; + mp4ff_flag = 0; + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + m_priority_mgm.nGroupID =0; + m_priority_mgm.nGroupPriority=0; + + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + m_buffer_supplier.nPortIndex=OMX_BufferSupplyUnspecified; + + DEBUG_PRINT_ERROR(" component init: role = %s\n",role); + + DEBUG_PRINT(" component init: role = %s\n",role); + component_Role.nVersion.nVersion = OMX_SPEC_VERSION; + if (!strcmp(role,"OMX.qcom.audio.encoder.aac")) + { + pcm_input = 1; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.aac")) + { + pcm_input = 0; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else + { + component_Role.nSize = (OMX_U32)sizeof("\0"); + strlcpy((char *)component_Role.cRole, (const char*)"\0", + sizeof(component_Role.cRole)); + DEBUG_PRINT_ERROR("\ncomponent_init: Component %s LOADED is invalid\n", + role); + return OMX_ErrorInsufficientResources; + } + if(pcm_input) + { + m_tmp_meta_buf = (OMX_U8*) malloc(sizeof(OMX_U8) * + (OMX_CORE_INPUT_BUFFER_SIZE + sizeof(META_IN))); + + if (m_tmp_meta_buf == NULL) { + DEBUG_PRINT_ERROR("Mem alloc failed for in meta buf\n"); + return OMX_ErrorInsufficientResources; + } + } + m_tmp_out_meta_buf = + (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_AAC_OUTPUT_BUFFER_SIZE); + if ( m_tmp_out_meta_buf == NULL ) { + DEBUG_PRINT_ERROR("Mem alloc failed for out meta buf\n"); + return OMX_ErrorInsufficientResources; + } + + if(0 == pcm_input) + { + m_drv_fd = open("/dev/msm_aac_in",O_RDONLY); + } + else + { + m_drv_fd = open("/dev/msm_aac_in",O_RDWR); + } + if (m_drv_fd < 0) + { + DEBUG_PRINT_ERROR("Component_init Open Failed[%d] errno[%d]",\ + m_drv_fd,errno); + + return OMX_ErrorInsufficientResources; + } + if(ioctl(m_drv_fd, AUDIO_GET_SESSION_ID,&m_session_id) == -1) + { + DEBUG_PRINT_ERROR("AUDIO_GET_SESSION_ID FAILED\n"); + } + if(pcm_input) + { + if (!m_ipc_to_in_th) + { + m_ipc_to_in_th = omx_aac_thread_create(process_in_port_msg, + this, (char *)"INPUT_THREAD"); + if (!m_ipc_to_in_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start \ + Input port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + } + + if (!m_ipc_to_cmd_th) + { + m_ipc_to_cmd_th = omx_aac_thread_create(process_command_msg, + this, (char *)"CMD_THREAD"); + if (!m_ipc_to_cmd_th) + { + DEBUG_PRINT_ERROR("ERROR!!!Failed to start " + "command message thread\n"); + return OMX_ErrorInsufficientResources; + } + } + + if (!m_ipc_to_out_th) + { + m_ipc_to_out_th = omx_aac_thread_create(process_out_port_msg, + this, (char *)"OUTPUT_THREAD"); + if (!m_ipc_to_out_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start output " + "port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + return eRet; +} + +/** + + @brief member function to retrieve version of component + + + + @param hComp handle to this component instance + @param componentName name of component + @param componentVersion pointer to memory space which stores the + version number + @param specVersion pointer to memory sapce which stores version of + openMax specification + @param componentUUID + @return Error status + */ +OMX_ERRORTYPE omx_aac_aenc::get_component_version +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID) +{ + if((hComp == NULL) || (componentName == NULL) || + (specVersion == NULL) || (componentUUID == NULL)) + { + componentVersion = NULL; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + componentVersion->nVersion = OMX_SPEC_VERSION; + specVersion->nVersion = OMX_SPEC_VERSION; + return OMX_ErrorNone; +} +/** + @brief member function handles command from IL client + + This function simply queue up commands from IL client. + Commands will be processed in command server thread context later + + @param hComp handle to component instance + @param cmd type of command + @param param1 parameters associated with the command type + @param cmdData + @return Error status +*/ +OMX_ERRORTYPE omx_aac_aenc::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + int portIndex = (int)param1; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateInvalid == m_state) + { + return OMX_ErrorInvalidState; + } + if ( (cmd == OMX_CommandFlush) && (portIndex > 1) ) + { + return OMX_ErrorBadPortIndex; + } + post_command((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + DEBUG_PRINT("Send Command : returns with OMX_ErrorNone \n"); + DEBUG_PRINT("send_command : recieved state before semwait= %u\n",param1); + sem_wait (&sem_States); + DEBUG_PRINT("send_command : recieved state after semwait\n"); + return OMX_ErrorNone; +} + +/** + @brief member function performs actual processing of commands excluding + empty buffer call + + @param hComp handle to component + @param cmd command type + @param param1 parameter associated with the command + @param cmdData + + @return error status +*/ +OMX_ERRORTYPE omx_aac_aenc::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + // Handle only IDLE and executing + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1; + nState = eState; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_CommandStateSet == cmd) + { + /***************************/ + /* Current State is Loaded */ + /***************************/ + if (OMX_StateLoaded == m_state) + { + if (OMX_StateIdle == eState) + { + + if (allocate_done() || + (m_inp_bEnabled == OMX_FALSE + && m_out_bEnabled == OMX_FALSE)) + { + DEBUG_PRINT("SCP-->Allocate Done Complete\n"); + } + else + { + DEBUG_PRINT("SCP-->Loaded to Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + bFlag = 0; + } + + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Loaded\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } + + else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->WaitForResources\n"); + eRet = OMX_ErrorNone; + } + + else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Executing\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Pause\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Invalid\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + m_state = OMX_StateInvalid; + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP-->Loaded to Invalid(%d))\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if (OMX_StateIdle == m_state) + { + if (OMX_StateLoaded == eState) + { + if (release_done(-1)) + { + if (ioctl(m_drv_fd, AUDIO_STOP, 0) == -1) + { + DEBUG_PRINT_ERROR("SCP:Idle->Loaded,ioctl \ + stop failed %d\n", errno); + } + nTimestamp=0; + ts = 0; + frameduration = 0; + DEBUG_PRINT("SCP-->Idle to Loaded\n"); + } else + { + DEBUG_PRINT("SCP--> Idle to Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + else if (OMX_StateExecuting == eState) + { + + struct msm_audio_aac_enc_config drv_aac_enc_config; + struct msm_audio_aac_config drv_aac_config; + struct msm_audio_stream_config drv_stream_config; + struct msm_audio_buf_cfg buf_cfg; + struct msm_audio_config pcm_cfg; + if(ioctl(m_drv_fd, AUDIO_GET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + if(ioctl(m_drv_fd, AUDIO_SET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + + if(ioctl(m_drv_fd, AUDIO_GET_AAC_ENC_CONFIG, + &drv_aac_enc_config) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_AAC_ENC_CONFIG failed, \ + errno[%d]\n", errno); + } + drv_aac_enc_config.channels = m_aac_param.nChannels; + drv_aac_enc_config.sample_rate = m_aac_param.nSampleRate; + drv_aac_enc_config.bit_rate = + get_updated_bit_rate(m_aac_param.nBitRate); + DEBUG_PRINT("aac config %u,%u,%u %d updated bitrate %d\n", + m_aac_param.nChannels,m_aac_param.nSampleRate, + m_aac_param.nBitRate,m_aac_param.eAACStreamFormat, + drv_aac_enc_config.bit_rate); + switch(m_aac_param.eAACStreamFormat) + { + + case 0: + case 1: + { + drv_aac_enc_config.stream_format = 65535; + DEBUG_PRINT("Setting AUDIO_AAC_FORMAT_ADTS\n"); + break; + } + case 4: + case 5: + case 6: + { + drv_aac_enc_config.stream_format = AUDIO_AAC_FORMAT_RAW; + DEBUG_PRINT("Setting AUDIO_AAC_FORMAT_RAW\n"); + break; + } + default: + break; + } + DEBUG_PRINT("Stream format = %d\n", + drv_aac_enc_config.stream_format); + if(ioctl(m_drv_fd, AUDIO_SET_AAC_ENC_CONFIG, + &drv_aac_enc_config) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_AAC_ENC_CONFIG failed, \ + errno[%d]\n", errno); + } + if (ioctl(m_drv_fd, AUDIO_GET_AAC_CONFIG, &drv_aac_config) + == -1) { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_AAC_CONFIG failed, \ + errno[%d]\n", errno); + } + + drv_aac_config.sbr_on_flag = 0; + drv_aac_config.sbr_ps_on_flag = 0; + /* Other members of drv_aac_config are not used, + so not setting them */ + switch(m_aac_param.eAACProfile) + { + case OMX_AUDIO_AACObjectLC: + { + DEBUG_PRINT("AAC_Profile: OMX_AUDIO_AACObjectLC\n"); + drv_aac_config.sbr_on_flag = 0; + drv_aac_config.sbr_ps_on_flag = 0; + break; + } + case OMX_AUDIO_AACObjectHE: + { + DEBUG_PRINT("AAC_Profile: OMX_AUDIO_AACObjectHE\n"); + drv_aac_config.sbr_on_flag = 1; + drv_aac_config.sbr_ps_on_flag = 0; + break; + } + case OMX_AUDIO_AACObjectHE_PS: + { + DEBUG_PRINT("AAC_Profile: OMX_AUDIO_AACObjectHE_PS\n"); + drv_aac_config.sbr_on_flag = 1; + drv_aac_config.sbr_ps_on_flag = 1; + break; + } + default: + { + DEBUG_PRINT_ERROR("Unsupported AAC Profile Type = %d\n", + m_aac_param.eAACProfile); + break; + } + } + DEBUG_PRINT("sbr_flag = %d, sbr_ps_flag = %d\n", + drv_aac_config.sbr_on_flag, + drv_aac_config.sbr_ps_on_flag); + + if (ioctl(m_drv_fd, AUDIO_SET_AAC_CONFIG, &drv_aac_config) + == -1) { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_AAC_CONFIG failed, \ + errno[%d]\n", errno); + } + + if (ioctl(m_drv_fd, AUDIO_GET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_BUF_CFG, errno[%d]\n", + errno); + } + buf_cfg.meta_info_enable = 1; + buf_cfg.frames_per_buf = NUMOFFRAMES; + if (ioctl(m_drv_fd, AUDIO_SET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_BUF_CFG, errno[%d]\n", + errno); + } + if(pcm_input) + { + if (ioctl(m_drv_fd, AUDIO_GET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_CONFIG, errno[%d]\n", + errno); + } + pcm_cfg.channel_count = m_pcm_param.nChannels; + pcm_cfg.sample_rate = m_pcm_param.nSamplingRate; + pcm_cfg.buffer_size = input_buffer_size; + pcm_cfg.buffer_count = m_inp_current_buf_count; + DEBUG_PRINT("pcm config %u %u\n",m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + + if (ioctl(m_drv_fd, AUDIO_SET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_CONFIG, errno[%d]\n", + errno); + } + } + if(ioctl(m_drv_fd, AUDIO_START, 0) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_START failed, errno[%d]\n", + errno); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } + DEBUG_PRINT("SCP-->Idle to Executing\n"); + nState = eState; + frameduration = (1024*1000000)/m_aac_param.nSampleRate; + } else if (eState == OMX_StateIdle) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Idle\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Pause\n"); + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Idle to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if (OMX_StateExecuting == m_state) + { + if (OMX_StateIdle == eState) + { + DEBUG_PRINT("SCP-->Executing to Idle \n"); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + + } else if (OMX_StatePause == eState) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED PAUSE STATE\n"); + DEBUG_DETAIL("*************************\n"); + //ioctl(m_drv_fd, AUDIO_PAUSE, 0); + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Executing \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Executing to %d Not Handled\n", + eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if (OMX_StatePause == m_state) + { + if( (eState == OMX_StateExecuting || eState == OMX_StateIdle) ) + { + pthread_mutex_lock(&m_out_th_lock_1); + if(is_out_th_sleep) + { + DEBUG_DETAIL("PE: WAKING UP OUT THREAD\n"); + is_out_th_sleep = false; + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } + if ( OMX_StateExecuting == eState ) + { + nState = eState; + } else if ( OMX_StateIdle == eState ) + { + DEBUG_PRINT("SCP-->Paused to Idle \n"); + DEBUG_PRINT ("\n Internal flush issued"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + } else if ( eState == OMX_StateLoaded ) + { + DEBUG_PRINT("\n Pause --> loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n Pause --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("\n Pause --> Pause \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n Pause --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT("SCP-->Paused to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /**************************************/ + /* Current State is WaitForResources */ + /**************************************/ + else if (m_state == OMX_StateWaitForResources) + { + if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Loaded\n"); + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: \ + WaitForResources-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Executing\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Pause\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> %d to %d(Not Handled)\n", + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /****************************/ + /* Current State is Invalid */ + /****************************/ + else if (m_state == OMX_StateInvalid) + { + if (OMX_StateLoaded == eState || OMX_StateWaitForResources == eState + || OMX_StateIdle == eState || OMX_StateExecuting == eState + || OMX_StatePause == eState || OMX_StateInvalid == eState) + { + DEBUG_PRINT("OMXCORE-SM: Invalid-->Loaded/Idle/Executing" + "/Pause/Invalid/WaitForResources\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } + } else + { + DEBUG_PRINT_ERROR("OMXCORE-SM: %d --> %d(Not Handled)\n",\ + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } else if (OMX_CommandFlush == cmd) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED FLUSH COMMAND port=%u\n",param1); + DEBUG_DETAIL("*************************\n"); + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || + param1 == OMX_CORE_OUTPUT_PORT_INDEX || + (signed)param1 == -1 ) + { + execute_omx_flush(param1); + } else + { + eRet = OMX_ErrorBadPortIndex; + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError, + OMX_CommandFlush, OMX_ErrorBadPortIndex, NULL ); + } + } else if ( cmd == OMX_CommandPortDisable ) + { + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL ) + { + DEBUG_PRINT("SCP: Disabling Input port Indx\n"); + m_inp_bEnabled = OMX_FALSE; + if ( (m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(0) ) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_inp_bEnabled=%d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + + else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable in "\ + " param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + // Skip the event notification + + } + + } + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + + DEBUG_PRINT("SCP: Disabling Output port Indx\n"); + m_out_bEnabled = OMX_FALSE; + if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(1)) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_out_bEnabled=%d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable out "\ + "param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + // Skip the event notification + + } + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortDisable: disable wrong port ID"); + } + + } else if (cmd == OMX_CommandPortEnable) + { + bFlag = 0; + if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_TRUE; + DEBUG_PRINT("SCP: Enabling Input port Indx\n"); + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_inp_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + + } else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + + } + } + + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + DEBUG_PRINT("SCP: Enabling Output port Indx\n"); + m_out_bEnabled = OMX_TRUE; + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_out_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortEnable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + + } + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_PRINT("SCP:WAKING OUT THR, OMX_CommandPortEnable\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortEnable: disable wrong port ID"); + } + + } else + { + DEBUG_PRINT_ERROR("SCP-->ERROR: Invali Command [%d]\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + DEBUG_PRINT("posting sem_States\n"); + sem_post (&sem_States); + if (eRet == OMX_ErrorNone && bFlag) + { + post_command(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + return eRet; +} + +/*============================================================================= +FUNCTION: + execute_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + [IN] param1 + [IN] cmd_cmpl + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_aac_aenc::execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl) +{ + bool bRet = true; + + DEBUG_PRINT("Execute_omx_flush Port[%u]", param1); + struct timespec abs_timeout; + abs_timeout.tv_sec = 1; + abs_timeout.tv_nsec = 0; + + if ((signed)param1 == -1) + { + bFlushinprogress = true; + DEBUG_PRINT("Execute flush for both I/p O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + + // Send Flush commands to input and output threads + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + // Send Flush to the kernel so that the in and out buffers are released + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("FLush:ioctl flush failed errno=%d\n",errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + + // sleep till the FLUSH ACK are done by both the input and + // output threads + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + + DEBUG_PRINT("RECIEVED BOTH FLUSH ACK's param1=%u cmd_cmpl=%d",\ + param1,cmd_cmpl); + + // If not going to idle state, Send FLUSH complete message + // to the Client, now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + DEBUG_PRINT("Inside FLUSH.. sending FLUSH CMPL\n"); + } + bFlushinprogress = false; + } + else if (param1 == OMX_CORE_INPUT_PORT_INDEX) + { + DEBUG_PRINT("Execute FLUSH for I/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + //sleep till the FLUSH ACK are done by both the input and output threads + DEBUG_DETAIL("Executing FLUSH for I/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + DEBUG_DETAIL(" RECIEVED FLUSH ACK FOR I/P PORT param1=%d",param1); + + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == param1) + { + DEBUG_PRINT("Executing FLUSH for O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + DEBUG_DETAIL("Executing FLUSH for O/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) ==-1) + DEBUG_PRINT_ERROR("Flush:Output port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + // sleep till the FLUSH ACK are done by both the input + // and output threads + wait_for_event(); + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + } + DEBUG_DETAIL("RECIEVED FLUSH ACK FOR O/P PORT param1=%d",param1); + } else + { + DEBUG_PRINT("Invalid Port ID[%u]",param1); + } + return bRet; +} + +/*============================================================================= +FUNCTION: + execute_input_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_aac_aenc::execute_input_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on input port"); + + pthread_mutex_lock(&m_lock); + do + { + qsize = m_input_q.m_size; + tot_qsize = qsize; + tot_qsize += m_input_ctrl_ebd_q.m_size; + + DEBUG_DETAIL("Input FLUSH-->flushq[%d] ebd[%d]dataq[%d]",\ + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size,qsize); + if (!tot_qsize) + { + DEBUG_DETAIL("Input-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_lock); + break; + } + if (qsize) + { + m_input_q.pop_entry(&p1, &p2, &ident); + if ((ident == OMX_COMPONENT_GENERATE_ETB) || + (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Flush:Input dataq=%p \n", omx_buf); + omx_buf->nFilledLen = 0; + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else if (m_input_ctrl_ebd_q.m_size) + { + m_input_ctrl_ebd_q.pop_entry(&p1, &p2, &ident); + if (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + omx_buf->nFilledLen = 0; + DEBUG_DETAIL("Flush:ctrl dataq=%p \n", omx_buf); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else + { + } + }while (tot_qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("IN-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_lock); + return true; +} + +/*============================================================================= +FUNCTION: + execute_output_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_aac_aenc::execute_output_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on output port"); + + pthread_mutex_lock(&m_outputlock); + do + { + qsize = m_output_q.m_size; + DEBUG_DETAIL("OUT FLUSH-->flushq[%d] fbd[%d]dataq[%d]",\ + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size,qsize); + tot_qsize = qsize; + tot_qsize += m_output_ctrl_fbd_q.m_size; + if (!tot_qsize) + { + DEBUG_DETAIL("OUT-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_outputlock); + break; + } + if (qsize) + { + m_output_q.pop_entry(&p1,&p2,&ident); + if ( (OMX_COMPONENT_GENERATE_FTB == ident) || + (OMX_COMPONENT_GENERATE_FRAME_DONE == ident)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n",\ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FBD FROM FLUSH"); + } + } else if ((qsize = m_output_ctrl_fbd_q.m_size)) + { + m_output_ctrl_fbd_q.pop_entry(&p1, &p2, &ident); + if (OMX_COMPONENT_GENERATE_FRAME_DONE == ident) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n", \ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FROM CTRL-FBDQ FROM FLUSH"); + } + } + }while (qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("OUT-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_outputlock); + return true; +} + +/*============================================================================= +FUNCTION: + post_input + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_aac_aenc::post_input(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + pthread_mutex_lock(&m_lock); + + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND)) + { + // insert flush message and ebd + m_input_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ((OMX_COMPONENT_GENERATE_BUFFER_DONE == id)) + { + // insert ebd + m_input_ctrl_ebd_q.insert_entry(p1,p2,id); + } else + { + // ETBS in this queue + m_input_q.insert_entry(p1,p2,id); + } + + if (m_ipc_to_in_th) + { + bRet = true; + omx_aac_post_msg(m_ipc_to_in_th, id); + } + + DEBUG_DETAIL("PostInput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d] \n",\ + m_state, + id, + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size, + m_input_q.m_size); + + pthread_mutex_unlock(&m_lock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_command + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_aac_aenc::post_command(unsigned int p1, + unsigned int p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_commandlock); + + m_command_q.insert_entry(p1,p2,id); + + if (m_ipc_to_cmd_th) + { + bRet = true; + omx_aac_post_msg(m_ipc_to_cmd_th, id); + } + + DEBUG_DETAIL("PostCmd-->state[%d]id[%d]cmdq[%d]flags[%x]\n",\ + m_state, + id, + m_command_q.m_size, + m_flags >> 3); + + pthread_mutex_unlock(&m_commandlock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_output + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_aac_aenc::post_output(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_outputlock); + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND) + || (id == OMX_COMPONENT_RESUME)) + { + // insert flush message and fbd + m_output_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ( (OMX_COMPONENT_GENERATE_FRAME_DONE == id) ) + { + // insert flush message and fbd + m_output_ctrl_fbd_q.insert_entry(p1,p2,id); + } else + { + m_output_q.insert_entry(p1,p2,id); + } + if ( m_ipc_to_out_th ) + { + bRet = true; + omx_aac_post_msg(m_ipc_to_out_th, id); + } + DEBUG_DETAIL("PostOutput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + m_state, + id, + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size, + m_output_q.m_size); + + pthread_mutex_unlock(&m_outputlock); + return bRet; +} +/** + @brief member function that return parameters to IL client + + @param hComp handle to component instance + @param paramIndex Parameter type + @param paramData pointer to memory space which would hold the + paramter + @return error status +*/ +OMX_ERRORTYPE omx_aac_aenc::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (paramData == NULL) + { + DEBUG_PRINT("get_parameter: paramData is NULL\n"); + return OMX_ErrorBadParameter; + } + + switch ((int)paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + DEBUG_PRINT("OMX_IndexParamPortDefinition " \ + "portDefn->nPortIndex = %u\n", + portDefn->nPortIndex); + + portDefn->nVersion.nVersion = OMX_SPEC_VERSION; + portDefn->nSize = (OMX_U32)sizeof(portDefn); + portDefn->eDomain = OMX_PortDomainAudio; + + if (0 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirInput; + portDefn->bEnabled = m_inp_bEnabled; + portDefn->bPopulated = m_inp_bPopulated; + portDefn->nBufferCountActual = m_inp_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_INPUT_BUFFERS; + portDefn->nBufferSize = input_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingPCM; + portDefn->format.audio.pNativeRender = 0; + } else if (1 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirOutput; + portDefn->bEnabled = m_out_bEnabled; + portDefn->bPopulated = m_out_bPopulated; + portDefn->nBufferCountActual = m_out_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_OUTPUT_BUFFERS; + portDefn->nBufferSize = output_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingAAC; + portDefn->format.audio.pNativeRender = 0; + } else + { + portDefn->eDir = OMX_DirMax; + DEBUG_PRINT_ERROR("Bad Port idx %d\n",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioInit\n"); + + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 2; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioPortFormat\n"); + portFormatType->nVersion.nVersion = OMX_SPEC_VERSION; + portFormatType->nSize = (OMX_U32)sizeof(portFormatType); + + if (OMX_CORE_INPUT_PORT_INDEX == portFormatType->nPortIndex) + { + + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + portFormatType->nPortIndex) + { + DEBUG_PRINT("get_parameter: OMX_IndexParamAudioFormat: "\ + "%u\n", portFormatType->nIndex); + + portFormatType->eEncoding = OMX_AUDIO_CodingAAC; + } else + { + DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioAac: + { + OMX_AUDIO_PARAM_AACPROFILETYPE *aacParam = + (OMX_AUDIO_PARAM_AACPROFILETYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioAac\n"); + if (OMX_CORE_OUTPUT_PORT_INDEX== aacParam->nPortIndex) + { + memcpy(aacParam,&m_aac_param, + sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)); + + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioAac "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)aacParam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case QOMX_IndexParamAudioSessionId: + { + QOMX_AUDIO_STREAM_INFO_DATA *streaminfoparam = + (QOMX_AUDIO_STREAM_INFO_DATA *) paramData; + streaminfoparam->sessionId = (OMX_U8)m_session_id; + break; + } + + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam = + (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(pcmparam,&m_pcm_param,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + + DEBUG_PRINT("get_parameter: Sampling rate %u",\ + pcmparam->nSamplingRate); + DEBUG_PRINT("get_parameter: Number of channels %u",\ + pcmparam->nChannels); + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioPcm "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamComponentSuspended: + { + OMX_PARAM_SUSPENSIONTYPE *suspend = + (OMX_PARAM_SUSPENSIONTYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamComponentSuspended %p\n", + suspend); + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamVideoInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *priorityMgmtType = + (OMX_PRIORITYMGMTTYPE*)paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamPriorityMgmt\n"); + priorityMgmtType->nSize = (OMX_U32)sizeof(priorityMgmtType); + priorityMgmtType->nVersion.nVersion = OMX_SPEC_VERSION; + priorityMgmtType->nGroupID = m_priority_mgm.nGroupID; + priorityMgmtType->nGroupPriority = + m_priority_mgm.nGroupPriority; + break; + } + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamImageInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + + bufferSupplierType->nSize = (OMX_U32)sizeof(bufferSupplierType); + bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; + if (OMX_CORE_INPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else + { + DEBUG_PRINT_ERROR("get_parameter:"\ + "OMX_IndexParamCompBufferSupplier eRet"\ + "%08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamOtherInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + componentRole->nSize = component_Role.nSize; + componentRole->nVersion = component_Role.nVersion; + strlcpy((char *)componentRole->cRole, + (const char*)component_Role.cRole, + sizeof(componentRole->cRole)); + DEBUG_PRINT_ERROR("nSize = %d , nVersion = %d, cRole = %s\n", + component_Role.nSize, + component_Role.nVersion, + component_Role.cRole); + break; + + } + default: + { + DEBUG_PRINT_ERROR("unknown param %08x\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; + +} + +/** + @brief member function that set paramter from IL client + + @param hComp handle to component instance + @param paramIndex parameter type + @param paramData pointer to memory space which holds the paramter + @return error status + */ +OMX_ERRORTYPE omx_aac_aenc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int loop=0; + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("set_parameter is not in proper state\n"); + return OMX_ErrorIncorrectStateOperation; + } + if (paramData == NULL) + { + DEBUG_PRINT("param data is NULL"); + return OMX_ErrorBadParameter; + } + + switch (paramIndex) + { + case OMX_IndexParamAudioAac: + { + DEBUG_PRINT("OMX_IndexParamAudioAac"); + OMX_AUDIO_PARAM_AACPROFILETYPE *aacparam + = (OMX_AUDIO_PARAM_AACPROFILETYPE *) paramData; + memcpy(&m_aac_param,aacparam, + sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)); + + for (loop=0; loop< sizeof(sample_idx_tbl) / \ + sizeof(struct sample_rate_idx); \ + loop++) + { + if(sample_idx_tbl[loop].sample_rate == m_aac_param.nSampleRate) + { + sample_idx = sample_idx_tbl[loop].sample_rate_idx; + } + } + break; + } + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + if (((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources && + ((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == true)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == true))) + ||(((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == false)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == false)) && + (m_state != OMX_StateWaitForResources))) + { + DEBUG_PRINT("Set Parameter called in valid state\n"); + } else + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + DEBUG_PRINT("OMX_IndexParamPortDefinition portDefn->nPortIndex " + "= %u\n",portDefn->nPortIndex); + if (OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_INPUT_BUFFERS ) + { + m_inp_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_inp_act_buf_count =OMX_CORE_NUM_INPUT_BUFFERS; + } + input_buffer_size = portDefn->nBufferSize; + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_OUTPUT_BUFFERS ) + { + m_out_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_out_act_buf_count =OMX_CORE_NUM_OUTPUT_BUFFERS; + } + output_buffer_size = portDefn->nBufferSize; + } else + { + DEBUG_PRINT(" set_parameter: Bad Port idx %d",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamPriorityMgmt: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt\n"); + + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype + = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt %u\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT("set_parameter: priorityMgmtype %u\n", + priorityMgmtype->nGroupPriority); + + m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; + m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + case OMX_IndexParamAudioPortFormat: + { + + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPortFormat\n"); + + if (OMX_CORE_INPUT_PORT_INDEX== portFormatType->nPortIndex) + { + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + portFormatType->nPortIndex) + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioFormat:"\ + " %u\n", portFormatType->nIndex); + portFormatType->eEncoding = OMX_AUDIO_CodingAAC; + } else + { + DEBUG_PRINT_ERROR("set_parameter: Bad port index %d\n", \ + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("set_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("set_param: OMX_IndexParamCompBufferSupplier %d",\ + bufferSupplierType->eBufferSupplier); + + if (bufferSupplierType->nPortIndex == OMX_CORE_INPUT_PORT_INDEX + || bufferSupplierType->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT("set_parameter:\ + OMX_IndexParamCompBufferSupplier\n"); + m_buffer_supplier.eBufferSupplier = + bufferSupplierType->eBufferSupplier; + } else + { + DEBUG_PRINT_ERROR("set_param:IndexParamCompBufferSup\ + %08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + + break; } + + case OMX_IndexParamAudioPcm: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPcm\n"); + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam + = (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + + memcpy(&m_pcm_param,pcmparam,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + + DEBUG_PRINT("set_pcm_parameter: %u %u",\ + m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + } else + { + DEBUG_PRINT_ERROR("Set_parameter:OMX_IndexParamAudioPcm " + "OMX_ErrorBadPortIndex %d\n", + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamSuspensionPolicy: + { + eRet = OMX_ErrorNotImplemented; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + component_Role.nSize = componentRole->nSize; + component_Role.nVersion = componentRole->nVersion; + strlcpy((char *)component_Role.cRole, + (const char*)componentRole->cRole, + sizeof(component_Role.cRole)); + break; + } + + default: + { + DEBUG_PRINT_ERROR("unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *volume = + (OMX_AUDIO_CONFIG_VOLUMETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == volume->nPortIndex) + { + volume->nSize = (OMX_U32)sizeof(volume); + volume->nVersion.nVersion = OMX_SPEC_VERSION; + volume->bLinear = OMX_TRUE; + volume->sVolume.nValue = m_volume; + volume->sVolume.nMax = OMX_AENC_MAX; + volume->sVolume.nMin = OMX_AENC_MIN; + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = + (OMX_AUDIO_CONFIG_MUTETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == mute->nPortIndex) + { + mute->nSize = (OMX_U32)sizeof(mute); + mute->nVersion.nVersion = OMX_SPEC_VERSION; + mute->bMute = (BITMASK_PRESENT(&m_flags, + OMX_COMPONENT_MUTED)?OMX_TRUE:OMX_FALSE); + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Set Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if ( m_state == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *vol = + (OMX_AUDIO_CONFIG_VOLUMETYPE*)configData; + if (vol->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if ((vol->sVolume.nValue <= OMX_AENC_MAX) && + (vol->sVolume.nValue >= OMX_AENC_MIN)) + { + m_volume = vol->sVolume.nValue; + if (BITMASK_ABSENT(&m_flags, OMX_COMPONENT_MUTED)) + { + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + + } else + { + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = (OMX_AUDIO_CONFIG_MUTETYPE*) + configData; + if (mute->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if (mute->bMute == OMX_TRUE) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, 0); */ + } else + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. <TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::get_extension_index( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if((hComp == NULL) || (paramName == NULL) || (indexType == NULL)) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(strncmp(paramName,"OMX.Qualcomm.index.audio.sessionId", + strlen("OMX.Qualcomm.index.audio.sessionId")) == 0) + { + *indexType =(OMX_INDEXTYPE)QOMX_IndexParamAudioSessionId; + DEBUG_PRINT("Extension index type - %d\n", *indexType); + + } + else + { + return OMX_ErrorBadParameter; + + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::GetState + +DESCRIPTION + Returns the state information back to the caller.<TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + *state = m_state; + DEBUG_PRINT("Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. <TBD> + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::component_tunnel_request +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n"); + + if((hComp == NULL) || (peerComponent == NULL) || (tunnelSetup == NULL)) + { + port = port; + peerPort = peerPort; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::allocate_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + if(m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc((nBufSize + \ + sizeof(OMX_BUFFERHEADERTYPE)+sizeof(META_IN)) , 1); + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + free(buf_ptr); + return OMX_ErrorBadParameter; + } + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + sizeof(META_IN)+ + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + m_input_buf_hdrs.insert(bufHdr, NULL); + + m_inp_current_buf_count++; + DEBUG_PRINT("AIB:bufHdr %p bufHdr->pBuffer %p m_inp_buf_cnt=%d \ + bytes=%u",bufHdr, bufHdr->pBuffer,m_inp_current_buf_count, + bytes); + + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT("Input buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +OMX_ERRORTYPE omx_aac_aenc::allocate_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_out_current_buf_count < m_out_act_buf_count) + { + buf_ptr = (char *) calloc( (nBufSize + sizeof(OMX_BUFFERHEADERTYPE)),1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr)+ + sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + DEBUG_PRINT("AOB::bufHdr %p bufHdr->pBuffer %p m_out_buf_cnt=%d "\ + "bytes=%u",bufHdr, bufHdr->pBuffer,\ + m_out_current_buf_count, bytes); + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_aac_aenc::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::allocate_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + // What if the client calls again. + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n", + (int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("allocate_buffer: before allocate_done \n"); + if (allocate_done()) + { + DEBUG_PRINT("allocate_buffer: after allocate_done \n"); + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("allocate_buffer: post idle transition event \n"); + } + DEBUG_PRINT("allocate_buffer: complete \n"); + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + m_out_bEnabled = OMX_TRUE; + + DEBUG_PRINT("AllocBuf-->is_out_th_sleep=%d\n",is_out_th_sleep); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("AllocBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("AB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + } + DEBUG_PRINT("Allocate Buffer exit with ret Code %d\n", eRet); + return eRet; +} + +/*============================================================================= +FUNCTION: + use_buffer + +DESCRIPTION: + OMX Use Buffer method implementation. + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_aac_aenc::use_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("Checking for Output Allocate buffer Done"); + if (allocate_done()) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("UseBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("UB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + } + } + DEBUG_PRINT("Use Buffer for port[%u] eRet[%d]\n", port,eRet); + return eRet; +} +/*============================================================================= +FUNCTION: + use_input_buffer + +DESCRIPTION: + Helper function for Use buffer in the input pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_aac_aenc::use_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if(bytes < input_buffer_size) + { + /* return if i\p buffer size provided by client + is less than min i\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + if (m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_input_buffer:bufHdr %p bufHdr->pBuffer %p \ + bytes=%u", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + input_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_input_buf_hdrs.insert(bufHdr, NULL); + m_inp_current_buf_count++; + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Input buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +/*============================================================================= +FUNCTION: + use_output_buffer + +DESCRIPTION: + Helper function for Use buffer in the output pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_aac_aenc::use_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (bytes < output_buffer_size) + { + /* return if o\p buffer size provided by client + is less than min o\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT("Inside omx_aac_aenc::use_output_buffer"); + if (m_out_current_buf_count < m_out_act_buf_count) + { + + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + DEBUG_PRINT("BufHdr=%p buffer=%p\n",bufHdr,buffer); + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_output_buffer:bufHdr %p bufHdr->pBuffer %p \ + len=%u\n", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + output_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_aac_aenc::search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_input_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_input_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_aac_aenc::search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_output_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_output_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +// Free Buffer - API call +/** + @brief member function that handles free buffer command from IL client + + This function is a block-call function that handles IL client request to + freeing the buffer + + @param hComp handle to component instance + @param port id of port which holds the buffer + @param buffer buffer header + @return Error status +*/ +OMX_ERRORTYPE omx_aac_aenc::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("Free_Buffer buf %p\n", buffer); + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT(" free buffer while Component in Loading pending\n"); + } else if ((m_inp_bEnabled == OMX_FALSE && + port == OMX_CORE_INPUT_PORT_INDEX)|| + (m_out_bEnabled == OMX_FALSE && + port == OMX_CORE_OUTPUT_PORT_INDEX)) + { + DEBUG_PRINT("Free Buffer while port %u disabled\n", port); + } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT("Invalid state to free buffer,ports need to be disabled:\ + OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return eRet; + } else + { + DEBUG_PRINT("free_buffer: Invalid state to free buffer,ports need to be\ + disabled:OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + if (m_inp_current_buf_count != 0) + { + m_inp_bPopulated = OMX_FALSE; + if (true == search_input_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:in_buffer[%p]\n",buffer); + m_input_buf_hdrs.erase(buffer); + free(buffer); + m_inp_current_buf_count--; + } else + { + DEBUG_PRINT_ERROR("Free_Buf:Error-->free_buffer, \ + Invalid Input buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + DEBUG_PRINT_ERROR("Error: free_buffer,Port Index calculation \ + came out Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_done(0)) + { + DEBUG_PRINT("INPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + if (m_out_current_buf_count != 0) + { + m_out_bPopulated = OMX_FALSE; + if (true == search_output_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:out_buffer[%p]\n",buffer); + m_output_buf_hdrs.erase(buffer); + free(buffer); + m_out_current_buf_count--; + } else + { + DEBUG_PRINT("Free_Buf:Error-->free_buffer , \ + Invalid Output buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_done(1)) + { + DEBUG_PRINT("OUTPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + if ((OMX_ErrorNone == eRet) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if (release_done(-1)) + { + if(ioctl(m_drv_fd, AUDIO_STOP, 0) < 0) + DEBUG_PRINT_ERROR("AUDIO STOP in free buffer failed\n"); + else + DEBUG_PRINT("AUDIO STOP in free buffer passed\n"); + + DEBUG_PRINT("Free_Buf: Free buffer\n"); + + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + DEBUG_PRINT("Before OMX_StateLoaded \ + OMX_COMPONENT_GENERATE_EVENT\n"); + post_command(OMX_CommandStateSet, + OMX_StateLoaded,OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("After OMX_StateLoaded OMX_COMPONENT_GENERATE_EVENT\n"); + + } + } + return eRet; +} + + +/** + @brief member function that that handles empty this buffer command + + This function meremly queue up the command and data would be consumed + in command server thread context + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_aac_aenc::empty_this_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("ETB:Buf:%p Len %u TS %lld numInBuf=%d\n", \ + buffer, buffer->nFilledLen, buffer->nTimeStamp, (nNumInputBuf)); + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (!m_inp_bEnabled) + { + DEBUG_PRINT("empty_this_buffer OMX_ErrorIncorrectStateOperation "\ + "Port Status %d \n", m_inp_bEnabled); + return OMX_ErrorIncorrectStateOperation; + } + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_aac_aenc::etb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_aac_aenc::etb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + if ((m_state != OMX_StateExecuting) && + (m_state != OMX_StatePause)) + { + DEBUG_PRINT_ERROR("Invalid state\n"); + eRet = OMX_ErrorInvalidState; + } + if (OMX_ErrorNone == eRet) + { + if (search_input_bufhdr(buffer) == true) + { + post_input((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_ETB); + } else + { + DEBUG_PRINT_ERROR("Bad header %p \n", buffer); + eRet = OMX_ErrorBadParameter; + } + } + pthread_mutex_lock(&in_buf_count_lock); + nNumInputBuf++; + m_aac_pb_stats.etb_cnt++; + pthread_mutex_unlock(&in_buf_count_lock); + return eRet; +} +/** + @brief member function that writes data to kernel driver + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_aac_aenc::empty_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + META_IN meta_in; + //Pointer to the starting location of the data to be transcoded + OMX_U8 *srcStart; + //The total length of the data to be transcoded + srcStart = buffer->pBuffer; + OMX_U8 *data = NULL; + PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer); + memset(&meta_in,0,sizeof(meta_in)); + if ( search_input_bufhdr(buffer) == false ) + { + DEBUG_PRINT("ETBP: INVALID BUF HDR\n"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorBadParameter; + } + if (m_tmp_meta_buf) + { + data = m_tmp_meta_buf; + + // copy the metadata info from the BufHdr and insert to payload + meta_in.offsetVal = (OMX_U16)sizeof(META_IN); + meta_in.nTimeStamp.LowPart = + (unsigned int)((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp)& 0xFFFFFFFF); + meta_in.nTimeStamp.HighPart = + (unsigned int) (((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) >> 32) & 0xFFFFFFFF); + meta_in.nFlags &= ~OMX_BUFFERFLAG_EOS; + if(buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + DEBUG_PRINT("EOS OCCURED \n"); + meta_in.nFlags |= OMX_BUFFERFLAG_EOS; + } + memcpy(data,&meta_in, meta_in.offsetVal); + DEBUG_PRINT("meta_in.nFlags = %d\n",meta_in.nFlags); + } + + if (ts == 0) { + DEBUG_PRINT("Anchor time %lld", buffer->nTimeStamp); + ts = buffer->nTimeStamp; + } + + memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen); + write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN)); + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (OMX_StateExecuting == state) + { + DEBUG_DETAIL("In Exe state, EBD CB"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + } else + { + /* Assume empty this buffer function has already checked + validity of buffer */ + DEBUG_PRINT("Empty buffer %p to kernel driver\n", buffer); + post_input((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_BUFFER_DONE); + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_aac_aenc::fill_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + ENC_META_OUT *meta_out = NULL; + ssize_t nReadbytes = 0; + int szadifhr = 0; + int numframes = 0; + int metainfo = 0; + OMX_U8 *src = buffer->pBuffer; + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (true == search_output_bufhdr(buffer)) + { + if((m_aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatADIF) + && (adif_flag == 0)) + { + + DEBUG_PRINT("\nBefore Read..m_drv_fd = %d,\n",m_drv_fd); + nReadbytes = read(m_drv_fd,m_tmp_out_meta_buf,output_buffer_size ); + DEBUG_DETAIL("FTBP->Al_len[%lu]buf[%p]size[%d]numOutBuf[%d]\n",\ + buffer->nAllocLen,m_tmp_out_meta_buf, + nReadbytes,nNumOutputBuf); + if(*m_tmp_out_meta_buf <= 0) + return OMX_ErrorBadParameter; + szadifhr = AUDAAC_MAX_ADIF_HEADER_LENGTH; + numframes = *m_tmp_out_meta_buf; + metainfo = (int)((sizeof(ENC_META_OUT) * numframes)+ + sizeof(unsigned char)); + audaac_rec_install_adif_header_variable(0,sample_idx, + (OMX_U8)m_aac_param.nChannels); + memcpy(buffer->pBuffer,m_tmp_out_meta_buf,metainfo); + memcpy(buffer->pBuffer + metainfo,&audaac_header_adif[0],szadifhr); + memcpy(buffer->pBuffer + metainfo + szadifhr, + m_tmp_out_meta_buf + metainfo,(nReadbytes - metainfo)); + src += sizeof(unsigned char); + meta_out = (ENC_META_OUT *)src; + meta_out->frame_size += szadifhr; + numframes--; + while(numframes > 0) + { + src += sizeof(ENC_META_OUT); + meta_out = (ENC_META_OUT *)src; + meta_out->offset_to_frame += szadifhr; + numframes--; + } + buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG; + adif_flag++; + } + else if((m_aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) + &&(mp4ff_flag == 0)) + { + DEBUG_PRINT("OMX_AUDIO_AACStreamFormatMP4FF\n"); + audaac_rec_install_mp4ff_header_variable(0,sample_idx, + (OMX_U8)m_aac_param.nChannels); + memcpy(buffer->pBuffer,&audaac_header_mp4ff[0], + AUDAAC_MAX_MP4FF_HEADER_LENGTH); + buffer->nFilledLen = AUDAAC_MAX_MP4FF_HEADER_LENGTH; + buffer->nTimeStamp = 0; + buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + mp4ff_flag++; + return OMX_ErrorNone; + + } + else + { + + DEBUG_PRINT("\nBefore Read..m_drv_fd = %d,\n",m_drv_fd); + nReadbytes = read(m_drv_fd,buffer->pBuffer,output_buffer_size ); + DEBUG_DETAIL("FTBP->Al_len[%d]buf[%p]size[%d]numOutBuf[%d]\n",\ + buffer->nAllocLen,buffer->pBuffer, + nReadbytes,nNumOutputBuf); + if(nReadbytes <= 0) + { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorNone; + } + } + + meta_out = (ENC_META_OUT *)(buffer->pBuffer + sizeof(unsigned char)); + buffer->nTimeStamp = ts + (frameduration * m_frame_count); + ++m_frame_count; + nTimestamp = buffer->nTimeStamp; + buffer->nFlags |= meta_out->nflags; + buffer->nOffset = meta_out->offset_to_frame + 1; + buffer->nFilledLen = (OMX_U32)(nReadbytes - buffer->nOffset + szadifhr); + DEBUG_PRINT("nflags %d frame_size %d offset_to_frame %d \ + timestamp %lld\n", meta_out->nflags, + meta_out->frame_size, + meta_out->offset_to_frame, + buffer->nTimeStamp); + + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + DEBUG_PRINT("FTBP: Now, Send EOS flag to Client \n"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + DEBUG_PRINT("FTBP: END OF STREAM m_eos_bm=%d\n",m_eos_bm); + } + + return OMX_ErrorNone; + } + DEBUG_PRINT("nState %d \n",nState ); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (state == OMX_StatePause) + { + DEBUG_PRINT("FTBP:Post the FBD to event thread currstate=%d\n",\ + state); + post_output((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_FRAME_DONE); + } + else + { + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + DEBUG_PRINT("FTBP*******************************************\n"); + + } + + + } + else + DEBUG_PRINT("\n FTBP-->Invalid buffer in FTB \n"); + + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + + + +PARAMETERS + + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::fill_this_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_aac_aenc::ftb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (m_out_bEnabled == OMX_FALSE) + { + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_aac_aenc::ftb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf++; + m_aac_pb_stats.ftb_cnt++; + DEBUG_DETAIL("FTB:nNumOutputBuf is %d", nNumOutputBuf); + pthread_mutex_unlock(&out_buf_count_lock); + post_output((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_FTB); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + m_cb = *callbacks; + m_app_data = appData; + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateLoaded != m_state && OMX_StateInvalid != m_state) + { + DEBUG_PRINT_ERROR("Warning: Rxed DeInit when not in LOADED state %d\n", + m_state); + } + deinit_encoder(); + + DEBUG_PRINT_ERROR("%s:COMPONENT DEINIT...\n", __FUNCTION__); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::deinit_encoder + +DESCRIPTION + Closes all the threads and release memory allocated to the heap. + +PARAMETERS + None. + +RETURN VALUE + None. + +========================================================================== */ +void omx_aac_aenc::deinit_encoder() +{ + DEBUG_PRINT("Component-deinit being processed\n"); + DEBUG_PRINT("********************************\n"); + DEBUG_PRINT("STATS: in-buf-len[%u]out-buf-len[%u] tot-pb-time[%lld]",\ + m_aac_pb_stats.tot_in_buf_len, + m_aac_pb_stats.tot_out_buf_len, + m_aac_pb_stats.tot_pb_time); + DEBUG_PRINT("STATS: fbd-cnt[%u]ftb-cnt[%u]etb-cnt[%u]ebd-cnt[%u]",\ + m_aac_pb_stats.fbd_cnt,m_aac_pb_stats.ftb_cnt, + m_aac_pb_stats.etb_cnt, + m_aac_pb_stats.ebd_cnt); + memset(&m_aac_pb_stats,0,sizeof(AAC_PB_STATS)); + + if((OMX_StateLoaded != m_state) && (OMX_StateInvalid != m_state)) + { + DEBUG_PRINT_ERROR("%s,Deinit called in state[%d]\n",__FUNCTION__,\ + m_state); + // Get back any buffers from driver + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + // force state change to loaded so that all threads can be exited + pthread_mutex_lock(&m_state_lock); + m_state = OMX_StateLoaded; + pthread_mutex_unlock(&m_state_lock); + DEBUG_PRINT_ERROR("Freeing Buf:inp_current_buf_count[%d][%d]\n",\ + m_inp_current_buf_count, + m_input_buf_hdrs.size()); + m_input_buf_hdrs.eraseall(); + DEBUG_PRINT_ERROR("Freeing Buf:out_current_buf_count[%d][%d]\n",\ + m_out_current_buf_count, + m_output_buf_hdrs.size()); + m_output_buf_hdrs.eraseall(); + + } + if(pcm_input) + { + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("Deinit:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + if(pcm_input) + { + if (m_ipc_to_in_th != NULL) + { + omx_aac_thread_stop(m_ipc_to_in_th); + m_ipc_to_in_th = NULL; + } + } + + if (m_ipc_to_cmd_th != NULL) + { + omx_aac_thread_stop(m_ipc_to_cmd_th); + m_ipc_to_cmd_th = NULL; + } + if (m_ipc_to_out_th != NULL) + { + DEBUG_DETAIL("Inside omx_aac_thread_stop\n"); + omx_aac_thread_stop(m_ipc_to_out_th); + m_ipc_to_out_th = NULL; + } + + + if(ioctl(m_drv_fd, AUDIO_STOP, 0) <0) + DEBUG_PRINT_ERROR("De-init: AUDIO_STOP FAILED\n"); + + if(pcm_input && m_tmp_meta_buf ) + { + free(m_tmp_meta_buf); + } + + if(m_tmp_out_meta_buf) + { + free(m_tmp_out_meta_buf); + } + nNumInputBuf = 0; + nNumOutputBuf = 0; + m_inp_current_buf_count=0; + m_out_current_buf_count=0; + m_out_act_buf_count = 0; + m_inp_act_buf_count = 0; + m_inp_bEnabled = OMX_FALSE; + m_out_bEnabled = OMX_FALSE; + m_inp_bPopulated = OMX_FALSE; + m_out_bPopulated = OMX_FALSE; + adif_flag = 0; + mp4ff_flag = 0; + ts = 0; + nTimestamp = 0; + frameduration = 0; + if ( m_drv_fd >= 0 ) + { + if(close(m_drv_fd) < 0) + DEBUG_PRINT("De-init: Driver Close Failed \n"); + m_drv_fd = -1; + } + else + { + DEBUG_PRINT_ERROR(" AAC device already closed\n"); + } + m_comp_deinit=1; + m_is_out_th_sleep = 1; + m_is_in_th_sleep = 1; + DEBUG_PRINT("************************************\n"); + DEBUG_PRINT(" DEINIT COMPLETED"); + DEBUG_PRINT("************************************\n"); + +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation <TBD>. + +PARAMETERS + <TBD>. + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::use_EGL_image +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + DEBUG_PRINT_ERROR("Error : use_EGL_image: Not Implemented \n"); + + if((hComp == NULL) || (appData == NULL) || (eglImage == NULL)) + { + bufferHdr = bufferHdr; + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_aac_aenc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_aac_aenc::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + const char *cmp_role = "audio_encoder.aac"; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (index == 0 && role) + { + memcpy(role, cmp_role, strlen(cmp_role)); + *(((char *) role) + strlen(cmp_role) + 1) = '\0'; + } else + { + eRet = OMX_ErrorNoMore; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_aac_aenc::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_aac_aenc::allocate_done(void) +{ + OMX_BOOL bRet = OMX_FALSE; + if (pcm_input==1) + { + if ((m_inp_act_buf_count == m_inp_current_buf_count) + &&(m_out_act_buf_count == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + + } + if ((m_inp_act_buf_count == m_inp_current_buf_count) && m_inp_bEnabled ) + { + m_inp_bPopulated = OMX_TRUE; + } + + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + } else if (pcm_input==0) + { + if (m_out_act_buf_count == m_out_current_buf_count) + { + bRet=OMX_TRUE; + + } + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + + } + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_aac_aenc::ReleaseDone + +DESCRIPTION + Checks if IL client has released all the buffers. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_aac_aenc::release_done(OMX_U32 param1) +{ + DEBUG_PRINT("Inside omx_aac_aenc::release_done"); + OMX_BOOL bRet = OMX_FALSE; + + if (param1 == OMX_ALL) + { + + if ((0 == m_inp_current_buf_count)&&(0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_INPUT_PORT_INDEX ) + { + if ((0 == m_inp_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_OUTPUT_PORT_INDEX) + { + if ((0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } + return bRet; +} + +void omx_aac_aenc::audaac_rec_install_adif_header_variable (OMX_U16 byte_num, + OMX_U32 sample_index, + OMX_U8 channel_config) +{ + OMX_U8 buf8; + OMX_U32 value; + OMX_U32 dummy = 0; + OMX_U8 num_pfe, num_fce, num_sce, num_bce; + OMX_U8 num_lfe, num_ade, num_vce, num_com; + OMX_U8 pfe_index; + OMX_U8 i; + OMX_BOOL variable_bit_rate = OMX_FALSE; + + (void)byte_num; + (void)channel_config; + num_pfe = num_sce = num_bce = + num_lfe = num_ade = num_vce = num_com = 0; + audaac_hdr_bit_index = 32; + num_fce = 1; + /* Store Header Id "ADIF" first */ + memcpy(&audaac_header_adif[0], "ADIF", sizeof(unsigned int)); + + /* copyright_id_present field, 1 bit */ + value = 0; + audaac_rec_install_bits(audaac_header_adif, + AAC_COPYRIGHT_PRESENT_SIZE, + value, + &(audaac_hdr_bit_index)); + + if (value) { + /* Copyright present, 72 bits; skip it for now, + * just install dummy value */ + audaac_rec_install_bits(audaac_header_adif, + 72, + dummy, + &(audaac_hdr_bit_index)); + } + + /* original_copy field, 1 bit */ + value = 0; + audaac_rec_install_bits(audaac_header_adif, + AAC_ORIGINAL_COPY_SIZE, + 0, + &(audaac_hdr_bit_index)); + + /* home field, 1 bit */ + value = 0; + audaac_rec_install_bits(audaac_header_adif, + AAC_HOME_SIZE, + 0, + &(audaac_hdr_bit_index)); + + /* bitstream_type = 1, varibable bit rate, 1 bit */ + value = 0; + audaac_rec_install_bits(audaac_header_adif, + AAC_BITSTREAM_TYPE_SIZE, + value, + &(audaac_hdr_bit_index)); + + /* bit_rate field, 23 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_BITRATE_SIZE, + (OMX_U32)m_aac_param.nBitRate, + &(audaac_hdr_bit_index)); + + /* num_program_config_elements, 4 bits */ + num_pfe = 0; + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_PFE_SIZE, + (OMX_U32)num_pfe, + &(audaac_hdr_bit_index)); + + /* below is to install program_config_elements field, + * for now only one element is supported */ + for (pfe_index=0; pfe_index < num_pfe+1; pfe_index++) { + + + if (variable_bit_rate == OMX_FALSE) { + /* impossible, put dummy value for now */ + audaac_rec_install_bits(audaac_header_adif, + AAC_BUFFER_FULLNESS_SIZE, + 0, + &(audaac_hdr_bit_index)); + + } + + dummy = 0; + + /* element_instance_tag field, 4 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_ELEMENT_INSTANCE_TAG_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + /* object_type, 2 bits, AAC LC is supported */ + value = 1; + audaac_rec_install_bits(audaac_header_adif, + AAC_PROFILE_SIZE, /* object type */ + value, + &(audaac_hdr_bit_index)); + + /* sampling_frequency_index, 4 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_SAMPLING_FREQ_INDEX_SIZE, + (OMX_U32)sample_index, + &(audaac_hdr_bit_index)); + + /* num_front_channel_elements, 4 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_FRONT_CHANNEL_ELEMENTS_SIZE, + num_fce, + &(audaac_hdr_bit_index)); + + /* num_side_channel_elements, 4 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_SIDE_CHANNEL_ELEMENTS_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + /* num_back_channel_elements, 4 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_BACK_CHANNEL_ELEMENTS_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + /* num_lfe_channel_elements, 2 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_LFE_CHANNEL_ELEMENTS_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + /* num_assoc_data_elements, 3 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_ASSOC_DATA_ELEMENTS_SIZE, + num_ade, + &(audaac_hdr_bit_index)); + + /* num_valid_cc_elements, 4 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_NUM_VALID_CC_ELEMENTS_SIZE, + num_vce, + &(audaac_hdr_bit_index)); + + /* mono_mixdown_present, 1 bits */ + audaac_rec_install_bits(audaac_header_adif, + AAC_MONO_MIXDOWN_PRESENT_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + if (dummy) { + audaac_rec_install_bits(audaac_header_adif, + AAC_MONO_MIXDOWN_ELEMENT_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + /* stereo_mixdown_present */ + audaac_rec_install_bits(audaac_header_adif, + AAC_STEREO_MIXDOWN_PRESENT_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + if (dummy) { + audaac_rec_install_bits(audaac_header_adif, + AAC_STEREO_MIXDOWN_ELEMENT_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + /* matrix_mixdown_idx_present, 1 bit */ + audaac_rec_install_bits(audaac_header_adif, + AAC_MATRIX_MIXDOWN_PRESENT_SIZE, + dummy, + &(audaac_hdr_bit_index)); + + if (dummy) { + audaac_rec_install_bits(audaac_header_adif, + AAC_MATRIX_MIXDOWN_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + if(m_aac_param.nChannels == 2) + value = 16; + else + value = 0; + for (i=0; i<num_fce; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_FCE_SIZE, + value, + &(audaac_hdr_bit_index)); + } + + for (i=0; i<num_sce; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_SCE_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + for (i=0; i<num_bce; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_BCE_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + for (i=0; i<num_lfe; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_LFE_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + for (i=0; i<num_ade; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_ADE_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + for (i=0; i<num_vce; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_VCE_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + + /* byte_alignment() */ + buf8 = (OMX_U8)((audaac_hdr_bit_index) & (0x07)); + if (buf8) { + audaac_rec_install_bits(audaac_header_adif, + buf8, + dummy, + &(audaac_hdr_bit_index)); + } + + /* comment_field_bytes, 8 bits, + * skip the comment section */ + audaac_rec_install_bits(audaac_header_adif, + AAC_COMMENT_FIELD_BYTES_SIZE, + num_com, + &(audaac_hdr_bit_index)); + + for (i=0; i<num_com; i++) { + audaac_rec_install_bits(audaac_header_adif, + AAC_COMMENT_FIELD_DATA_SIZE, + dummy, + &(audaac_hdr_bit_index)); + } + } /* for (pfe_index=0; pfe_index < num_pfe+1; pfe_index++) */ + + /* byte_alignment() */ + buf8 = (OMX_U8)((audaac_hdr_bit_index) & (0x07)) ; + if (buf8) { + audaac_rec_install_bits(audaac_header_adif, + buf8, + dummy, + &(audaac_hdr_bit_index)); + } + +} + +void omx_aac_aenc::audaac_rec_install_bits(OMX_U8 *input, + OMX_U8 num_bits_reqd, + OMX_U32 value, + OMX_U16 *hdr_bit_index) +{ + OMX_U32 byte_index; + OMX_U8 bit_index; + OMX_U8 bits_avail_in_byte; + OMX_U8 num_to_copy; + OMX_U8 byte_to_copy; + + OMX_U8 num_remaining = num_bits_reqd; + OMX_U8 bit_mask; + + bit_mask = 0xFF; + + while (num_remaining) { + + byte_index = (*hdr_bit_index) >> 3; + bit_index = (*hdr_bit_index) & 0x07; + + bits_avail_in_byte = (OMX_U8)(8 - bit_index); + + num_to_copy = min(bits_avail_in_byte, num_remaining); + + byte_to_copy = (OMX_U8)((OMX_U8)((value >> (num_remaining - num_to_copy)) & 0xFF) << + (bits_avail_in_byte - num_to_copy)); + + input[byte_index] &= ((OMX_U8)(bit_mask << bits_avail_in_byte)); + input[byte_index] |= byte_to_copy; + + *hdr_bit_index = (OMX_U16)(*hdr_bit_index + num_to_copy); + + num_remaining = (OMX_U8)(num_remaining - num_to_copy); + } +} +void omx_aac_aenc::audaac_rec_install_mp4ff_header_variable (OMX_U16 byte_num, + OMX_U32 sample_index, + OMX_U8 channel_config) +{ + OMX_U16 audaac_hdr_bit_index; + (void)byte_num; + audaac_header_mp4ff[0] = 0; + audaac_header_mp4ff[1] = 0; + audaac_hdr_bit_index = 0; + + /* Audio object type, 5 bit */ + audaac_rec_install_bits(audaac_header_mp4ff, + AUDAAC_MP4FF_OBJ_TYPE, + 2, + &(audaac_hdr_bit_index)); + + /* Frequency index, 4 bit */ + audaac_rec_install_bits(audaac_header_mp4ff, + AUDAAC_MP4FF_FREQ_IDX, + (OMX_U32)sample_index, + &(audaac_hdr_bit_index)); + + /* Channel config filed, 4 bit */ + audaac_rec_install_bits(audaac_header_mp4ff, + AUDAAC_MP4FF_CH_CONFIG, + channel_config, + &(audaac_hdr_bit_index)); + +} + +int omx_aac_aenc::get_updated_bit_rate(int bitrate) +{ + int updated_rate, min_bitrate, max_bitrate; + + max_bitrate = m_aac_param.nSampleRate * + MAX_BITRATE_MULFACTOR; + switch(m_aac_param.eAACProfile) + { + case OMX_AUDIO_AACObjectLC: + min_bitrate = m_aac_param.nSampleRate; + if (m_aac_param.nChannels == 1) { + min_bitrate = min_bitrate/BITRATE_DIVFACTOR; + max_bitrate = max_bitrate/BITRATE_DIVFACTOR; + } + break; + case OMX_AUDIO_AACObjectHE: + min_bitrate = MIN_BITRATE; + if (m_aac_param.nChannels == 1) + max_bitrate = max_bitrate/BITRATE_DIVFACTOR; + break; + case OMX_AUDIO_AACObjectHE_PS: + min_bitrate = MIN_BITRATE; + break; + default: + return bitrate; + break; + } + /* Update MIN and MAX values*/ + if (min_bitrate > MIN_BITRATE) + min_bitrate = MIN_BITRATE; + if (max_bitrate > MAX_BITRATE) + max_bitrate = MAX_BITRATE; + /* Update the bitrate in the range */ + if (bitrate < min_bitrate) + updated_rate = min_bitrate; + else if(bitrate > max_bitrate) + updated_rate = max_bitrate; + else + updated_rate = bitrate; + return updated_rate; +} diff --git a/msm8909/mm-audio/aenc-aac/qdsp6/test/omx_aac_enc_test.c b/msm8909/mm-audio/aenc-aac/qdsp6/test/omx_aac_enc_test.c new file mode 100644 index 00000000..174cde6b --- /dev/null +++ b/msm8909/mm-audio/aenc-aac/qdsp6/test/omx_aac_enc_test.c @@ -0,0 +1,1293 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + + +/* + An Open max test application .... +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <time.h> +#include <sys/ioctl.h> +#include "OMX_Core.h" +#include "OMX_Component.h" +#include "pthread.h" +#include <signal.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdint.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include<unistd.h> +#include<string.h> +#include <pthread.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#ifdef AUDIOV2 +#include "control.h" +#endif +#include <linux/ioctl.h> + +typedef unsigned char uint8; +typedef unsigned char byte; +typedef unsigned int uint32; +typedef unsigned int uint16; +#define AUDAAC_MAX_ADIF_HEADER_LENGTH 64 +/* ADTS variable frame header, frame length field */ +#define AUDAAC_ADTS_FRAME_LENGTH_SIZE 13 +QOMX_AUDIO_STREAM_INFO_DATA streaminfoparam; +void audaac_rec_install_bits +( + uint8 *input, + byte num_bits_reqd, + uint32 value, + uint16 *hdr_bit_index +); + +/* maximum ADTS frame header length */ +#define AUDAAC_MAX_ADTS_HEADER_LENGTH 7 +void audaac_rec_install_adts_header_variable (uint16 byte_num); +void Release_Encoder(); + +#ifdef AUDIOV2 +unsigned short session_id; +int device_id; +int control = 0; +const char *device="handset_tx"; +#define DIR_TX 2 +#endif + +#define AACHDR_LAYER_SIZE 2 +#define AACHDR_CRC_SIZE 1 +#define AAC_PROFILE_SIZE 2 +#define AAC_SAMPLING_FREQ_INDEX_SIZE 4 +#define AAC_ORIGINAL_COPY_SIZE 1 +#define AAC_HOME_SIZE 1 + +#define MIN(A,B) (((A) < (B))?(A):(B)) + +uint8 audaac_header[AUDAAC_MAX_ADTS_HEADER_LENGTH]; +unsigned int audaac_hdr_bit_index; + + +FILE *F1 = NULL; + +uint32_t samplerate = 44100; +uint32_t channels = 2; +uint32_t bitrate = 128000; +uint32_t pcmplayback = 0; +uint32_t tunnel = 0; +uint32_t rectime = 0; +uint32_t format = 1; +uint32_t profile = OMX_AUDIO_AACObjectLC; +#define DEBUG_PRINT printf +unsigned to_idle_transition = 0; + +typedef enum adts_sample_index__ { + +ADTS_SAMPLE_INDEX_96000=0x0, +ADTS_SAMPLE_INDEX_88200, +ADTS_SAMPLE_INDEX_64000, +ADTS_SAMPLE_INDEX_48000, +ADTS_SAMPLE_INDEX_44100, +ADTS_SAMPLE_INDEX_32000, +ADTS_SAMPLE_INDEX_24000, +ADTS_SAMPLE_INDEX_22050, +ADTS_SAMPLE_INDEX_16000, +ADTS_SAMPLE_INDEX_12000, +ADTS_SAMPLE_INDEX_11025, +ADTS_SAMPLE_INDEX_8000, +ADTS_SAMPLE_INDEX_7350, +ADTS_SAMPLE_INDEX_MAX + +}adts_sample_index; +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ +#define false 0 +#define true 1 + +#define CONFIG_VERSION_SIZE(param) \ + param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ + param.nSize = sizeof(param); + +#define FAILED(result) (result != OMX_ErrorNone) + +#define SUCCEEDED(result) (result == OMX_ErrorNone) + +/************************************************************************/ +/* GLOBAL DECLARATIONS */ +/************************************************************************/ + +pthread_mutex_t lock; +pthread_cond_t cond; +pthread_mutex_t elock; +pthread_cond_t econd; +pthread_cond_t fcond; +pthread_mutex_t etb_lock; +pthread_mutex_t etb_lock1; +pthread_cond_t etb_cond; +FILE * inputBufferFile; +FILE * outputBufferFile; +OMX_PARAM_PORTDEFINITIONTYPE inputportFmt; +OMX_PARAM_PORTDEFINITIONTYPE outputportFmt; +OMX_AUDIO_PARAM_AACPROFILETYPE aacparam; +OMX_AUDIO_PARAM_PCMMODETYPE pcmparam; +OMX_PORT_PARAM_TYPE portParam; +OMX_ERRORTYPE error; + + + + +#define ID_RIFF 0x46464952 +#define ID_WAVE 0x45564157 +#define ID_FMT 0x20746d66 +#define ID_DATA 0x61746164 + +#define FORMAT_PCM 1 + +struct wav_header { + uint32_t riff_id; + uint32_t riff_sz; + uint32_t riff_fmt; + uint32_t fmt_id; + uint32_t fmt_sz; + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */ + uint16_t block_align; /* num_channels * bps / 8 */ + uint16_t bits_per_sample; + uint32_t data_id; + uint32_t data_sz; +}; +struct enc_meta_out{ + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; +} __attribute__ ((packed)); + +static int totaldatalen = 0; +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +unsigned int input_buf_cnt = 0; +unsigned int output_buf_cnt = 0; +int used_ip_buf_cnt = 0; +volatile int event_is_done = 0; +volatile int ebd_event_is_done = 0; +volatile int fbd_event_is_done = 0; +volatile int etb_event_is_done = 0; +int ebd_cnt; +int bInputEosReached = 0; +int bOutputEosReached = 0; +int bInputEosReached_tunnel = 0; +static int etb_done = 0; +int bFlushing = false; +int bPause = false; +const char *in_filename; +const char *out_filename; + +int timeStampLfile = 0; +int timestampInterval = 100; + +//* OMX Spec Version supported by the wrappers. Version = 1.1 */ +const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; +OMX_COMPONENTTYPE* aac_enc_handle = 0; + +OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; +OMX_BUFFERHEADERTYPE **pOutputBufHdrs = NULL; + +/************************************************************************/ +/* GLOBAL FUNC DECL */ +/************************************************************************/ +int Init_Encoder(char*); +int Play_Encoder(); +OMX_STRING aud_comp; +/**************************************************************************/ +/* STATIC DECLARATIONS */ +/**************************************************************************/ + +static int open_audio_file (); +static int Read_Buffer(OMX_BUFFERHEADERTYPE *pBufHdr ); +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *aac_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize); + + +static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); +static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + +static OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); +static OMX_ERRORTYPE parse_pcm_header(); +void wait_for_event(void) +{ + pthread_mutex_lock(&lock); + DEBUG_PRINT("%s: event_is_done=%d", __FUNCTION__, event_is_done); + while (event_is_done == 0) { + pthread_cond_wait(&cond, &lock); + } + event_is_done = 0; + pthread_mutex_unlock(&lock); +} + +void event_complete(void ) +{ + pthread_mutex_lock(&lock); + if (event_is_done == 0) { + event_is_done = 1; + pthread_cond_broadcast(&cond); + } + pthread_mutex_unlock(&lock); +} + +void etb_wait_for_event(void) +{ + pthread_mutex_lock(&etb_lock1); + DEBUG_PRINT("%s: etb_event_is_done=%d", __FUNCTION__, etb_event_is_done); + while (etb_event_is_done == 0) { + pthread_cond_wait(&etb_cond, &etb_lock1); + } + etb_event_is_done = 0; + pthread_mutex_unlock(&etb_lock1); +} + +void etb_event_complete(void ) +{ + pthread_mutex_lock(&etb_lock1); + if (etb_event_is_done == 0) { + etb_event_is_done = 1; + pthread_cond_broadcast(&etb_cond); + } + pthread_mutex_unlock(&etb_lock1); +} + + +OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ + DEBUG_PRINT("Function %s \n", __FUNCTION__); + /* To remove warning for unused variable to keep prototype same */ + (void)hComponent; + (void)pAppData; + (void)pEventData; + + switch(eEvent) { + case OMX_EventCmdComplete: + DEBUG_PRINT("\n OMX_EventCmdComplete event=%d data1=%u data2=%u\n",(OMX_EVENTTYPE)eEvent, + nData1,nData2); + event_complete(); + break; + case OMX_EventError: + DEBUG_PRINT("\n OMX_EventError \n"); + break; + case OMX_EventBufferFlag: + DEBUG_PRINT("\n OMX_EventBufferFlag \n"); + bOutputEosReached = true; + event_complete(); + break; + case OMX_EventPortSettingsChanged: + DEBUG_PRINT("\n OMX_EventPortSettingsChanged \n"); + break; + default: + DEBUG_PRINT("\n Unknown Event \n"); + break; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + size_t bytes_writen = 0; + size_t total_bytes_writen = 0; + size_t len = 0; + struct enc_meta_out *meta = NULL; + OMX_U8 *src = pBuffer->pBuffer; + unsigned int num_of_frames = 1; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + if(((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + DEBUG_PRINT("FBD::EOS on output port\n "); + bOutputEosReached = true; + return OMX_ErrorNone; + } + if(bInputEosReached_tunnel || bOutputEosReached) + { + DEBUG_PRINT("EOS REACHED NO MORE PROCESSING OF BUFFERS\n"); + return OMX_ErrorNone; + } + if(num_of_frames != src[0]){ + + printf("Data corrupt\n"); + return OMX_ErrorNone; + } + /* Skip the first bytes */ + + + + src += sizeof(unsigned char); + meta = (struct enc_meta_out *)src; + while (num_of_frames > 0) { + meta = (struct enc_meta_out *)src; + /*printf("offset=%d framesize=%d encoded_pcm[%d] msw_ts[%d]lsw_ts[%d] nflags[%d]\n", + meta->offset_to_frame, + meta->frame_size, + meta->encoded_pcm_samples, meta->msw_ts, meta->lsw_ts, meta->nflags);*/ + len = meta->frame_size; + + if(format == 6) + { + audaac_rec_install_adts_header_variable((uint16_t)(len + AUDAAC_MAX_ADTS_HEADER_LENGTH)); + bytes_writen = fwrite(audaac_header,1,AUDAAC_MAX_ADTS_HEADER_LENGTH,outputBufferFile); + if(bytes_writen < AUDAAC_MAX_ADTS_HEADER_LENGTH) + { + DEBUG_PRINT("error: invalid adts header length\n"); + return OMX_ErrorNone; + } + } + bytes_writen = fwrite(pBuffer->pBuffer + sizeof(unsigned char) + meta->offset_to_frame,1,len,outputBufferFile); + if(bytes_writen < len) + { + DEBUG_PRINT("error: invalid AAC encoded data \n"); + return OMX_ErrorNone; + } + src += sizeof(struct enc_meta_out); + num_of_frames--; + total_bytes_writen += len; + } + DEBUG_PRINT(" FillBufferDone size writen to file %zu\n",total_bytes_writen); + totaldatalen = totaldatalen + (int)total_bytes_writen; + + DEBUG_PRINT(" FBD calling FTB\n"); + OMX_FillThisBuffer(hComponent,pBuffer); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + int readBytes =0; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + ebd_cnt++; + used_ip_buf_cnt--; + pthread_mutex_lock(&etb_lock); + if(!etb_done) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT("Wait till first set of buffers are given to component\n"); + DEBUG_PRINT("\n*********************************************\n"); + etb_done++; + pthread_mutex_unlock(&etb_lock); + etb_wait_for_event(); + } + else + { + pthread_mutex_unlock(&etb_lock); + } + + + if(bInputEosReached) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT(" EBD::EOS on input port\n "); + DEBUG_PRINT("*********************************************\n"); + return OMX_ErrorNone; + }else if (bFlushing == true) { + DEBUG_PRINT("omx_aac_adec_test: bFlushing is set to TRUE used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + if (used_ip_buf_cnt == 0) { + bFlushing = false; + } else { + DEBUG_PRINT("omx_aac_adec_test: more buffer to come back used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + return OMX_ErrorNone; + } + } + + if((readBytes = Read_Buffer(pBuffer)) > 0) { + pBuffer->nFilledLen = (OMX_U32)readBytes; + used_ip_buf_cnt++; + OMX_EmptyThisBuffer(hComponent,pBuffer); + } + else{ + pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + used_ip_buf_cnt++; + bInputEosReached = true; + pBuffer->nFilledLen = 0; + OMX_EmptyThisBuffer(hComponent,pBuffer); + DEBUG_PRINT("EBD..Either EOS or Some Error while reading file\n"); + } + return OMX_ErrorNone; +} + +void signal_handler(int sig_id) { + + /* Flush */ + if (sig_id == SIGUSR1) { + DEBUG_PRINT("%s Initiate flushing\n", __FUNCTION__); + bFlushing = true; + OMX_SendCommand(aac_enc_handle, OMX_CommandFlush, OMX_ALL, NULL); + } else if (sig_id == SIGUSR2) { + if (bPause == true) { + DEBUG_PRINT("%s resume playback\n", __FUNCTION__); + bPause = false; + OMX_SendCommand(aac_enc_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); + } else { + DEBUG_PRINT("%s pause playback\n", __FUNCTION__); + bPause = true; + OMX_SendCommand(aac_enc_handle, OMX_CommandStateSet, OMX_StatePause, NULL); + } + } +} + +int main(int argc, char **argv) +{ + unsigned int bufCnt=0; + OMX_ERRORTYPE result; + + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = &signal_handler; + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGUSR2, &sa, NULL); + + (void) signal(SIGINT, Release_Encoder); + + pthread_cond_init(&cond, 0); + pthread_mutex_init(&lock, 0); + pthread_cond_init(&etb_cond, 0); + pthread_mutex_init(&etb_lock, 0); + pthread_mutex_init(&etb_lock1, 0); + + if (argc >= 9) { + in_filename = argv[1]; + out_filename = argv[2]; + samplerate = (uint32_t)atoi(argv[3]); + channels = (uint32_t)atoi(argv[4]); + tunnel = (uint32_t)atoi(argv[5]); + rectime = (uint32_t)atoi(argv[6]); + bitrate = (uint32_t)atoi(argv[7]); + format = (uint32_t)atoi(argv[8]); + profile = (uint32_t)atoi(argv[9]); + + DEBUG_PRINT("Input parameters: samplerate = %d, channels = %d, tunnel = %d," + " rectime = %d, bitrate = %d, format = %d, profile = %d\n", + samplerate, channels, tunnel, rectime, bitrate, format, profile); + + if (!((profile == 2) || (profile == 5) || (profile == 29))) { + DEBUG_PRINT("profile = %d, not supported. Supported " + "profile values are AAC_LC(2), AAC+(5), EAAC+(29)\n", profile); + return 0; + } + if (!((format == 1) || (format == 6))) { + DEBUG_PRINT("format = %d, not supported. Supported " + "formats are ADTS(1), RAW(6)\n", format); + return 0; + } + if ((channels > 2) || (channels <= 0)) { + DEBUG_PRINT("channels = %d, not supported. Supported " + "number of channels are 1 and 2\n", channels); + return 0; + } + if ((samplerate < 8000) && (samplerate > 48000)) { + DEBUG_PRINT("samplerate = %d, not supported, Supported " + "samplerates are 8000, 11025, 12000, 16000, 22050, " + "24000, 32000, 44100, 48000\n", samplerate); + return 0; + } else { + if ((profile == 5) || (profile == 29)) { + if (samplerate < 24000) { + DEBUG_PRINT("samplerate = %d, not supported for AAC+/EAAC+." + " Supported samplerates are 24000, 32000," + " 44100, 48000\n", samplerate); + return 0; + } + } + } + } else { + DEBUG_PRINT(" invalid format: \n"); + DEBUG_PRINT("ex: ./mm-aenc-omxaac INPUTFILE AAC_OUTPUTFILE SAMPFREQ CHANNEL TUNNEL RECORDTIME BITRATE FORMAT PROFILE\n"); + DEBUG_PRINT("FOR TUNNEL MOD PASS INPUT FILE AS ZERO\n"); + DEBUG_PRINT("RECORDTIME in seconds for AST Automation ...TUNNEL MODE ONLY\n"); + DEBUG_PRINT("FORMAT::ADTS(1), RAW(6)\n"); + DEBUG_PRINT("BITRATE in bits/sec \n"); + DEBUG_PRINT("PROFILE::AAC_LC(2), AAC+(5), EAAC+(29)\n"); + return 0; + } + if(tunnel == 0) + aud_comp = "OMX.qcom.audio.encoder.aac"; + else + aud_comp = "OMX.qcom.audio.encoder.tunneled.aac"; + if(Init_Encoder(aud_comp)!= 0x00) + { + DEBUG_PRINT("Decoder Init failed\n"); + return -1; + } + + fcntl(0, F_SETFL, O_NONBLOCK); + + if(Play_Encoder() != 0x00) + { + DEBUG_PRINT("Play_Decoder failed\n"); + return -1; + } + + // Wait till EOS is reached... + if(rectime && tunnel) + { + sleep(rectime); + rectime = 0; + bInputEosReached_tunnel = 1; + DEBUG_PRINT("\EOS ON INPUT PORT\n"); + } + else + { + wait_for_event(); + } + + if((bInputEosReached_tunnel) || ((bOutputEosReached) && !tunnel)) + { + + DEBUG_PRINT("\nMoving the decoder to idle state \n"); + OMX_SendCommand(aac_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + wait_for_event(); + DEBUG_PRINT("\nMoving the encoder to loaded state \n"); + OMX_SendCommand(aac_enc_handle, OMX_CommandStateSet, OMX_StateLoaded,0); + sleep(1); + if (!tunnel) + { + DEBUG_PRINT("\nFillBufferDone: Deallocating i/p buffers \n"); + for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(aac_enc_handle, 0, pInputBufHdrs[bufCnt]); + } + } + + DEBUG_PRINT ("\nFillBufferDone: Deallocating o/p buffers \n"); + for(bufCnt=0; bufCnt < output_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(aac_enc_handle, 1, pOutputBufHdrs[bufCnt]); + } + wait_for_event(); + + result = OMX_FreeHandle(aac_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + /* Deinit OpenMAX */ + if(tunnel) + { + #ifdef AUDIOV2 + if (msm_route_stream(DIR_TX,session_id,device_id, 0)) + { + DEBUG_PRINT("\ncould not set stream routing\n"); + return -1; + } + if (msm_en_device(device_id, 0)) + { + DEBUG_PRINT("\ncould not enable device\n"); + return -1; + } + msm_mixer_close(); + #endif + } + OMX_Deinit(); + ebd_cnt=0; + bOutputEosReached = false; + bInputEosReached_tunnel = false; + bInputEosReached = 0; + aac_enc_handle = NULL; + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + fclose(outputBufferFile); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...AAC ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + } + return 0; +} + +void Release_Encoder() +{ + static int cnt=0; + OMX_ERRORTYPE result; + + DEBUG_PRINT("END OF AAC ENCODING: EXITING PLEASE WAIT\n"); + bInputEosReached_tunnel = 1; + event_complete(); + cnt++; + if(cnt > 1) + { + /* FORCE RESET */ + aac_enc_handle = NULL; + ebd_cnt=0; + bInputEosReached_tunnel = false; + + result = OMX_FreeHandle(aac_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + + OMX_Deinit(); + + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...AAC ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + exit(0); + } +} + +int Init_Encoder(OMX_STRING audio_component) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE omxresult; + OMX_U32 total = 0; + typedef OMX_U8* OMX_U8_PTR; + char *role ="audio_encoder"; + + static OMX_CALLBACKTYPE call_back = { + &EventHandler,&EmptyBufferDone,&FillBufferDone + }; + + /* Init. the OpenMAX Core */ + DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); + omxresult = OMX_Init(); + + if(OMX_ErrorNone != omxresult) { + DEBUG_PRINT("\n Failed to Init OpenMAX core"); + return -1; + } + else { + DEBUG_PRINT("\nOpenMAX Core Init Done\n"); + } + + /* Query for audio decoders*/ + DEBUG_PRINT("Aac_test: Before entering OMX_GetComponentOfRole"); + OMX_GetComponentsOfRole(role, &total, 0); + DEBUG_PRINT ("\nTotal components of role=%s :%u", role, total); + + + omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&aac_enc_handle), + (OMX_STRING)audio_component, NULL, &call_back); + if (FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to Load the component:%s\n", audio_component); + return -1; + } + else + { + DEBUG_PRINT("\nComponent %s is in LOADED state\n", audio_component); + } + + /* Get the port information */ + CONFIG_VERSION_SIZE(portParam); + omxresult = OMX_GetParameter(aac_enc_handle, OMX_IndexParamAudioInit, + (OMX_PTR)&portParam); + + if(FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to get Port Param\n"); + return -1; + } + else + { + DEBUG_PRINT("\nportParam.nPorts:%u\n", portParam.nPorts); + DEBUG_PRINT("\nportParam.nStartPortNumber:%u\n", + portParam.nStartPortNumber); + } + return 0; +} + +int Play_Encoder() +{ + unsigned int i; + int Size=0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE ret; + OMX_INDEXTYPE index; +#ifdef __LP64__ + DEBUG_PRINT("sizeof[%ld]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#else + DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#endif + + /* open the i/p and o/p files based on the video file format passed */ + if(open_audio_file()) { + DEBUG_PRINT("\n Returning -1"); + return -1; + } + + /* Query the encoder input min buf requirements */ + CONFIG_VERSION_SIZE(inputportFmt); + + /* Port for which the Client needs to obtain info */ + inputportFmt.nPortIndex = portParam.nStartPortNumber; + + OMX_GetParameter(aac_enc_handle,OMX_IndexParamPortDefinition,&inputportFmt); + DEBUG_PRINT ("\nEnc Input Buffer Count %u\n", inputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Input Buffer Size %u\n", inputportFmt.nBufferSize); + + if(OMX_DirInput != inputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Input Port\n"); + return -1; + } + + pcmparam.nPortIndex = 0; + pcmparam.nChannels = channels; + pcmparam.nSamplingRate = samplerate; + OMX_SetParameter(aac_enc_handle,OMX_IndexParamAudioPcm,&pcmparam); + + + /* Query the encoder outport's min buf requirements */ + CONFIG_VERSION_SIZE(outputportFmt); + /* Port for which the Client needs to obtain info */ + outputportFmt.nPortIndex = portParam.nStartPortNumber + 1; + + OMX_GetParameter(aac_enc_handle,OMX_IndexParamPortDefinition,&outputportFmt); + DEBUG_PRINT ("\nEnc: Output Buffer Count %u\n", outputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Output Buffer Size %u\n", outputportFmt.nBufferSize); + + if(OMX_DirOutput != outputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Output Port\n"); + return -1; + } + + + CONFIG_VERSION_SIZE(aacparam); + + + aacparam.nPortIndex = 1; + aacparam.nChannels = channels; //2 ; /* 1-> mono 2-> stereo*/ + aacparam.nBitRate = bitrate; + aacparam.nSampleRate = samplerate; + aacparam.eChannelMode = OMX_AUDIO_ChannelModeStereo; + aacparam.eAACStreamFormat = (OMX_AUDIO_AACSTREAMFORMATTYPE)format; + aacparam.eAACProfile = (OMX_AUDIO_AACPROFILETYPE)profile; + OMX_SetParameter(aac_enc_handle,OMX_IndexParamAudioAac,&aacparam); + OMX_GetExtensionIndex(aac_enc_handle,"OMX.Qualcomm.index.audio.sessionId",&index); + OMX_GetParameter(aac_enc_handle,index,&streaminfoparam); + if(tunnel) + { + #ifdef AUDIOV2 + session_id = streaminfoparam.sessionId; + control = msm_mixer_open("/dev/snd/controlC0", 0); + if(control < 0) + printf("ERROR opening the device\n"); + device_id = msm_get_device(device); + DEBUG_PRINT ("\ndevice_id = %d\n",device_id); + DEBUG_PRINT("\nsession_id = %d\n",session_id); + if (msm_en_device(device_id, 1)) + { + perror("could not enable device\n"); + return -1; + } + + if (msm_route_stream(DIR_TX,session_id,device_id, 1)) + { + perror("could not set stream routing\n"); + return -1; + } + #endif + } + DEBUG_PRINT ("\nOMX_SendCommand Encoder -> IDLE\n"); + OMX_SendCommand(aac_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + /* wait_for_event(); should not wait here event complete status will + not come until enough buffer are allocated */ + if (tunnel == 0) + { + input_buf_cnt = inputportFmt.nBufferCountActual; // inputportFmt.nBufferCountMin + 5; + DEBUG_PRINT("Transition to Idle State succesful...\n"); + /* Allocate buffer on decoder's i/p port */ + error = Allocate_Buffer(aac_enc_handle, &pInputBufHdrs, inputportFmt.nPortIndex, + input_buf_cnt, inputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pInputBufHdrs == NULL) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer success\n"); + } + } + output_buf_cnt = outputportFmt.nBufferCountMin ; + + /* Allocate buffer on encoder's O/Pp port */ + error = Allocate_Buffer(aac_enc_handle, &pOutputBufHdrs, outputportFmt.nPortIndex, + output_buf_cnt, outputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pOutputBufHdrs == NULL) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer success\n"); + } + + wait_for_event(); + + + if (tunnel == 1) + { + DEBUG_PRINT ("\nOMX_SendCommand to enable TUNNEL MODE during IDLE\n"); + OMX_SendCommand(aac_enc_handle, OMX_CommandPortDisable,0,0); // disable input port + wait_for_event(); + } + + DEBUG_PRINT ("\nOMX_SendCommand encoder -> Executing\n"); + OMX_SendCommand(aac_enc_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + + DEBUG_PRINT(" Start sending OMX_FILLthisbuffer\n"); + + for(i=0; i < output_buf_cnt; i++) { + DEBUG_PRINT ("\nOMX_FillThisBuffer on output buf no.%d\n",i); + pOutputBufHdrs[i]->nOutputPortIndex = 1; + pOutputBufHdrs[i]->nFlags = pOutputBufHdrs[i]->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + ret = OMX_FillThisBuffer(aac_enc_handle, pOutputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_FillThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_FillThisBuffer success!\n"); + } + } + +if(tunnel == 0) +{ + DEBUG_PRINT(" Start sending OMX_emptythisbuffer\n"); + for (i = 0;i < input_buf_cnt;i++) { + DEBUG_PRINT ("\nOMX_EmptyThisBuffer on Input buf no.%d\n",i); + pInputBufHdrs[i]->nInputPortIndex = 0; + Size = Read_Buffer(pInputBufHdrs[i]); + if(Size <=0 ){ + DEBUG_PRINT("NO DATA READ\n"); + bInputEosReached = true; + pInputBufHdrs[i]->nFlags= OMX_BUFFERFLAG_EOS; + } + pInputBufHdrs[i]->nFilledLen = (OMX_U32)Size; + pInputBufHdrs[i]->nInputPortIndex = 0; + used_ip_buf_cnt++; + ret = OMX_EmptyThisBuffer(aac_enc_handle, pInputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_EmptyThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); + } + if(Size <=0 ){ + break;//eos reached + } + } + pthread_mutex_lock(&etb_lock); + if(etb_done) +{ + DEBUG_PRINT("Component is waiting for EBD to be released.\n"); + etb_event_complete(); + } + else + { + DEBUG_PRINT("\n****************************\n"); + DEBUG_PRINT("EBD not yet happened ...\n"); + DEBUG_PRINT("\n****************************\n"); + etb_done++; + } + pthread_mutex_unlock(&etb_lock); +} + + return 0; +} + + + +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *avc_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + unsigned int bufCnt=0; + /* To remove warning for unused variable to keep prototype same */ + (void)avc_enc_handle; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE*)*bufCntMin); + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + DEBUG_PRINT("\n OMX_AllocateBuffer No %d \n", bufCnt); + error = OMX_AllocateBuffer(aac_enc_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize); + } + + return error; +} + + + + +static int Read_Buffer (OMX_BUFFERHEADERTYPE *pBufHdr ) +{ + + size_t bytes_read=0; + + + pBufHdr->nFilledLen = 0; + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + + bytes_read = fread(pBufHdr->pBuffer, 1, pBufHdr->nAllocLen , inputBufferFile); + + pBufHdr->nFilledLen = (OMX_U32)bytes_read; + if(bytes_read == 0) + { + + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + DEBUG_PRINT ("\nBytes read zero\n"); + } + else + { + pBufHdr->nFlags = pBufHdr->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + } + + return (int)bytes_read; +} + + + +//In Encoder this Should Open a PCM or WAV file for input. + +static int open_audio_file () +{ + int error_code = 0; + + if (!tunnel) + { + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); + inputBufferFile = fopen (in_filename, "rb"); + if (inputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + in_filename); + error_code = -1; + } + if(parse_pcm_header() != 0x00) + { + DEBUG_PRINT("PCM parser failed \n"); + return -1; + } + } + + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, out_filename); + outputBufferFile = fopen (out_filename, "wb"); + if (outputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + out_filename); + error_code = -1; + } + return error_code; +} + + +void audaac_rec_install_bits +( + uint8 *input, + byte num_bits_reqd, + uint32 value, + uint16 *hdr_bit_index +) +{ + uint32 byte_index; + byte bit_index; + byte bits_avail_in_byte; + byte num_to_copy; + byte byte_to_copy; + + byte num_remaining = num_bits_reqd; + uint8 bit_mask; + + bit_mask = 0xFF; + + while (num_remaining) { + + byte_index = (*hdr_bit_index) >> 3; + bit_index = (*hdr_bit_index) & 0x07; + + bits_avail_in_byte = (uint8)(8 - bit_index); + + num_to_copy = MIN(bits_avail_in_byte, num_remaining); + + byte_to_copy = (uint8)(((value >> (num_remaining - num_to_copy)) & 0xFF) << + (bits_avail_in_byte - num_to_copy)); + + input[byte_index] &= ((uint8)(bit_mask << bits_avail_in_byte)); + input[byte_index] |= byte_to_copy; + + *hdr_bit_index += num_to_copy; + + num_remaining = (uint8)(num_remaining - num_to_copy); + } /* while (num_remaining) */ +} /* audaac_rec_install_bits */ + +adts_sample_index map_adts_sample_index(uint32 srate) +{ + adts_sample_index ret; + + switch(srate){ + + case 96000: + ret= ADTS_SAMPLE_INDEX_96000; + break; + case 88200: + ret= ADTS_SAMPLE_INDEX_88200; + break; + case 64000: + ret= ADTS_SAMPLE_INDEX_64000; + break; + case 48000: + ret=ADTS_SAMPLE_INDEX_48000; + break; + case 44100: + ret=ADTS_SAMPLE_INDEX_44100; + break; + case 32000: + ret=ADTS_SAMPLE_INDEX_32000; + break; + case 24000: + ret=ADTS_SAMPLE_INDEX_24000; + break; + case 22050: + ret=ADTS_SAMPLE_INDEX_22050; + break; + case 16000: + ret=ADTS_SAMPLE_INDEX_16000; + break; + case 12000: + ret=ADTS_SAMPLE_INDEX_12000; + break; + case 11025: + ret=ADTS_SAMPLE_INDEX_11025; + break; + case 8000: + ret=ADTS_SAMPLE_INDEX_8000; + break; + case 7350: + ret=ADTS_SAMPLE_INDEX_7350; + break; + default: + ret=ADTS_SAMPLE_INDEX_44100; + break; + } + return ret; +} + +void audaac_rec_install_adts_header_variable (uint16 byte_num) +{ + //uint16 bit_index=0; + + adts_sample_index srate_enum; + uint32 value; + + uint32 sample_index = samplerate; + uint8 channel_config = (uint8)channels; + + /* Store Sync word first */ + audaac_header[0] = 0xFF; + audaac_header[1] = 0xF0; + + audaac_hdr_bit_index = 12; + + if ((format == OMX_AUDIO_AACStreamFormatRAW) && + ((profile == OMX_AUDIO_AACObjectHE) || + (profile == OMX_AUDIO_AACObjectHE_PS))){ + if (samplerate >= 24000) + sample_index = samplerate/2; + } + + /* ID field, 1 bit */ + value = 1; + audaac_rec_install_bits(audaac_header, + 1, + value, + &(audaac_hdr_bit_index)); + + /* Layer field, 2 bits */ + value = 0; + audaac_rec_install_bits(audaac_header, + AACHDR_LAYER_SIZE, + value, + &(audaac_hdr_bit_index)); + + /* Protection_absent field, 1 bit */ + value = 1; + audaac_rec_install_bits(audaac_header, + AACHDR_CRC_SIZE, + value, + &(audaac_hdr_bit_index)); + + /* profile_ObjectType field, 2 bit */ + value = 1; + audaac_rec_install_bits(audaac_header, + AAC_PROFILE_SIZE, + value, + &(audaac_hdr_bit_index)); + + /* sampling_frequency_index field, 4 bits */ + srate_enum = map_adts_sample_index(sample_index); + audaac_rec_install_bits(audaac_header, + AAC_SAMPLING_FREQ_INDEX_SIZE, + (uint32)srate_enum, + &(audaac_hdr_bit_index)); + + DEBUG_PRINT("%s: sample_index=%d; srate_enum = %d \n", + __FUNCTION__, sample_index, srate_enum); + + /* pravate_bit field, 1 bits */ + audaac_rec_install_bits(audaac_header, + 1, + 0, + &(audaac_hdr_bit_index)); + + /* channel_configuration field, 3 bits */ + audaac_rec_install_bits(audaac_header, + 3, + channel_config, + &(audaac_hdr_bit_index)); + + + /* original/copy field, 1 bits */ + audaac_rec_install_bits(audaac_header, + AAC_ORIGINAL_COPY_SIZE, + 0, + &(audaac_hdr_bit_index)); + + + /* home field, 1 bits */ + audaac_rec_install_bits(audaac_header, + AAC_HOME_SIZE, + 0, + &(audaac_hdr_bit_index)); + + // bit_index = audaac_hdr_bit_index; + // bit_index += 2; + + /* copyr. id. bit, 1 bits */ + audaac_rec_install_bits(audaac_header, + 1, + 0, + &(audaac_hdr_bit_index)); + + /* copyr. id. start, 1 bits */ + audaac_rec_install_bits(audaac_header, + 1, + 0, + &(audaac_hdr_bit_index)); + + /* aac_frame_length field, 13 bits */ + audaac_rec_install_bits(audaac_header, + AUDAAC_ADTS_FRAME_LENGTH_SIZE, + byte_num, + &audaac_hdr_bit_index); + + /* adts_buffer_fullness field, 11 bits */ + audaac_rec_install_bits(audaac_header, + 11, + 0x660,/*0x660 = CBR,0x7FF = VBR*/ + &audaac_hdr_bit_index); + + /* number_of_raw_data_blocks_in_frame, 2 bits */ + audaac_rec_install_bits(audaac_header, + 2, + 0, + &audaac_hdr_bit_index); + +} /* audaac_rec_install_adts_header_variable */ + +static OMX_ERRORTYPE parse_pcm_header() +{ + struct wav_header hdr; + + DEBUG_PRINT("\n***************************************************************\n"); + if(fread(&hdr, 1, sizeof(hdr),inputBufferFile)!=sizeof(hdr)) + { + DEBUG_PRINT("Wav file cannot read header\n"); + return -1; + } + + if ((hdr.riff_id != ID_RIFF) || + (hdr.riff_fmt != ID_WAVE)|| + (hdr.fmt_id != ID_FMT)) + { + DEBUG_PRINT("Wav file is not a riff/wave file\n"); + return -1; + } + + if (hdr.audio_format != FORMAT_PCM) + { + DEBUG_PRINT("Wav file is not adpcm format %d and fmt size is %d\n", + hdr.audio_format, hdr.fmt_sz); + return -1; + } + + DEBUG_PRINT("Samplerate is %d\n", hdr.sample_rate); + DEBUG_PRINT("Channel Count is %d\n", hdr.num_channels); + DEBUG_PRINT("\n***************************************************************\n"); + + samplerate = hdr.sample_rate; + channels = hdr.num_channels; + + return OMX_ErrorNone; +} diff --git a/msm8909/mm-audio/aenc-amrnb/Android.mk b/msm8909/mm-audio/aenc-amrnb/Android.mk new file mode 100644 index 00000000..4834ad5c --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/Android.mk @@ -0,0 +1,8 @@ +ifneq ($(filter arm aarch64 arm64, $(TARGET_ARCH)),) + + +AENC_AMR_PATH:= $(call my-dir) + +include $(AENC_AMR_PATH)/qdsp6/Android.mk + +endif diff --git a/msm8909/mm-audio/aenc-amrnb/Makefile b/msm8909/mm-audio/aenc-amrnb/Makefile new file mode 100644 index 00000000..83d822bb --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/Makefile @@ -0,0 +1,6 @@ +all: + @echo "invoking omxaudio make" + $(MAKE) -C qdsp6 + +install: + $(MAKE) -C qdsp6 install diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/Android.mk b/msm8909/mm-audio/aenc-amrnb/qdsp6/Android.mk new file mode 100644 index 00000000..2bd71b95 --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/Android.mk @@ -0,0 +1,68 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libOmxAmrEnc-def := -g -O3 +libOmxAmrEnc-def += -DQC_MODIFIED +libOmxAmrEnc-def += -D_ANDROID_ +libOmxAmrEnc-def += -D_ENABLE_QC_MSG_LOG_ +libOmxAmrEnc-def += -DVERBOSE +libOmxAmrEnc-def += -D_DEBUG +libOmxAmrEnc-def += -Wconversion +libOmxAmrEnc-def += -DAUDIOV2 + +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxAmrEnc) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +libOmxAmrEnc-inc := $(LOCAL_PATH)/inc +libOmxAmrEnc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := libOmxAmrEnc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxAmrEnc-def) +LOCAL_C_INCLUDES := $(libOmxAmrEnc-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libutils liblog + +LOCAL_SRC_FILES := src/aenc_svr.c +LOCAL_SRC_FILES += src/omx_amr_aenc.cpp + +include $(BUILD_SHARED_LIBRARY) + +# --------------------------------------------------------------------------------- +# Make the apps-test (mm-aenc-omxamr-test) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +mm-amr-enc-test-inc := $(LOCAL_PATH)/inc +mm-amr-enc-test-inc += $(LOCAL_PATH)/test + +mm-amr-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore +mm-amr-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-audio/audio-alsa +LOCAL_MODULE := mm-aenc-omxamr-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxAmrEnc-def) +LOCAL_C_INCLUDES := $(mm-amr-enc-test-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libmm-omxcore +LOCAL_SHARED_LIBRARIES += libOmxAmrEnc +LOCAL_SHARED_LIBRARIES += libaudioalsa +LOCAL_SRC_FILES := test/omx_amr_enc_test.c + +include $(BUILD_EXECUTABLE) + +endif + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- + diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/Makefile b/msm8909/mm-audio/aenc-amrnb/qdsp6/Makefile new file mode 100644 index 00000000..0abd31cf --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/Makefile @@ -0,0 +1,81 @@ +# --------------------------------------------------------------------------------- +# MM-AUDIO-OSS-8K-AENC-AMR +# --------------------------------------------------------------------------------- + +# cross-compiler flags +CFLAGS += -Wall +CFLAGS += -Wundef +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs + +# cross-compile flags specific to shared objects +CFLAGS_SO += -fpic + +# required pre-processor flags +CPPFLAGS := -D__packed__= +CPPFLAGS += -DIMAGE_APPS_PROC +CPPFLAGS += -DFEATURE_Q_SINGLE_LINK +CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR +CPPFLAGS += -DFEATURE_LINUX +CPPFLAGS += -DFEATURE_NATIVELINUX +CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS + +CPPFLAGS += -g +CPPFALGS += -D_DEBUG +CPPFLAGS += -Iinc + +# linker flags +LDFLAGS += -L$(SYSROOT)/usr/lib + +# linker flags for shared objects +LDFLAGS_SO := -shared + +# defintions +LIBMAJOR := $(basename $(basename $(LIBVER))) +LIBINSTALLDIR := $(DESTDIR)usr/lib +INCINSTALLDIR := $(DESTDIR)usr/include +BININSTALLDIR := $(DESTDIR)usr/bin + +# --------------------------------------------------------------------------------- +# BUILD +# --------------------------------------------------------------------------------- +all: libOmxAmrEnc.so.$(LIBVER) mm-aenc-omxamr-test + +install: + echo "intalling aenc-amr in $(DESTDIR)" + if [ ! -d $(LIBINSTALLDIR) ]; then mkdir -p $(LIBINSTALLDIR); fi + if [ ! -d $(INCINSTALLDIR) ]; then mkdir -p $(INCINSTALLDIR); fi + if [ ! -d $(BININSTALLDIR) ]; then mkdir -p $(BININSTALLDIR); fi + install -m 555 libOmxAmrEnc.so.$(LIBVER) $(LIBINSTALLDIR) + cd $(LIBINSTALLDIR) && ln -s libOmxAmrEnc.so.$(LIBVER) libOmxAmrEnc.so.$(LIBMAJOR) + cd $(LIBINSTALLDIR) && ln -s libOmxAmrEnc.so.$(LIBMAJOR) libOmxAmrEnc.so + install -m 555 mm-aenc-omxamr-test $(BININSTALLDIR) + +# --------------------------------------------------------------------------------- +# COMPILE LIBRARY +# --------------------------------------------------------------------------------- +LDLIBS := -lpthread +LDLIBS += -lstdc++ +LDLIBS += -lOmxCore + +SRCS := src/omx_amr_aenc.cpp +SRCS += src/aenc_svr.c + +libOmxAmrEnc.so.$(LIBVER): $(SRCS) + $(CC) $(CPPFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxAmrEnc.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# --------------------------------------------------------------------------------- +# COMPILE TEST APP +# --------------------------------------------------------------------------------- +TEST_LDLIBS := -lpthread +TEST_LDLIBS += -ldl +TEST_LDLIBS += -lOmxCore + +TEST_SRCS := test/omx_amr_enc_test.c + +mm-aenc-omxamr-test: libOmxAmrEnc.so.$(LIBVER) $(TEST_SRCS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS) + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/Map.h b/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/Map.h new file mode 100644 index 00000000..aac96fd1 --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/Map.h @@ -0,0 +1,244 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include <stdio.h> +using namespace std; + +template <typename T,typename T2> +class Map +{ + struct node + { + T data; + T2 data2; + node* prev; + node* next; + node(T t, T2 t2,node* p, node* n) : + data(t), data2(t2), prev(p), next(n) {} + }; + node* head; + node* tail; + node* tmp; + unsigned size_of_list; + static Map<T,T2> *m_self; +public: + Map() : head( NULL ), tail ( NULL ),tmp(head),size_of_list(0) {} + bool empty() const { return ( !head || !tail ); } + operator bool() const { return !empty(); } + void insert(T,T2); + void show(); + int size(); + T2 find(T); // Return VALUE + T find_ele(T);// Check if the KEY is present or not + T2 begin(); //give the first ele + bool erase(T); + bool eraseall(); + bool isempty(); + ~Map() + { + while(head) + { + node* temp(head); + head=head->next; + size_of_list--; + delete temp; + } + } +}; + +template <typename T,typename T2> +T2 Map<T,T2>::find(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data2; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T Map<T,T2>::find_ele(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T2 Map<T,T2>::begin() +{ + tmp = head; + if(tmp) + { + return (tmp->data2); + } + return 0; +} + +template <typename T,typename T2> +void Map<T,T2>::show() +{ + tmp = head; + while(tmp) + { + printf("%d-->%d\n",tmp->data,tmp->data2); + tmp = tmp->next; + } +} + +template <typename T,typename T2> +int Map<T,T2>::size() +{ + int count =0; + tmp = head; + while(tmp) + { + tmp = tmp->next; + count++; + } + return count; +} + +template <typename T,typename T2> +void Map<T,T2>::insert(T data, T2 data2) +{ + tail = new node(data, data2,tail, NULL); + if( tail->prev ) + tail->prev->next = tail; + + if( empty() ) + { + head = tail; + tmp=head; + } + tmp = head; + size_of_list++; +} + +template <typename T,typename T2> +bool Map<T,T2>::erase(T d) +{ + bool found = false; + tmp = head; + node* prevnode = tmp; + node *tempnode; + + while(tmp) + { + if((head == tail) && (head->data == d)) + { + found = true; + tempnode = head; + head = tail = NULL; + delete tempnode; + break; + } + if((tmp ==head) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + tmp = tmp->next; + tmp->prev = NULL; + head = tmp; + tempnode->next = NULL; + delete tempnode; + break; + } + if((tmp == tail) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + prevnode->next = NULL; + tmp->prev = NULL; + tail = prevnode; + delete tempnode; + break; + } + if(tmp->data == d) + { + found = true; + prevnode->next = tmp->next; + tmp->next->prev = prevnode->next; + tempnode = tmp; + //tmp = tmp->next; + delete tempnode; + break; + } + prevnode = tmp; + tmp = tmp->next; + } + if(found)size_of_list--; + return found; +} + +template <typename T,typename T2> +bool Map<T,T2>::eraseall() +{ + // Be careful while using this method + // it not only removes the node but FREES(not delete) the allocated + // memory. + node *tempnode; + tmp = head; + while(head) + { + tempnode = head; + head = head->next; + tempnode->next = NULL; + if(tempnode->data) + free(tempnode->data); + if(tempnode->data2) + free(tempnode->data2); + delete tempnode; + } + tail = head = NULL; + return true; +} + + +template <typename T,typename T2> +bool Map<T,T2>::isempty() +{ + if(!size_of_list) return true; + else return false; +} + +#endif // _MAP_H_ diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/aenc_svr.h b/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/aenc_svr.h new file mode 100644 index 00000000..782641b5 --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/aenc_svr.h @@ -0,0 +1,120 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef AENC_SVR_H +#define AENC_SVR_H + +#ifdef __cplusplus +extern "C" { +#endif +#include <pthread.h> +#include <sched.h> +#include <utils/Log.h> + +#ifdef _ANDROID_ +#define LOG_TAG "QC_AMRENC" +#endif + +#ifndef LOGE +#define LOGE ALOGE +#endif + +#ifndef LOGW +#define LOGW ALOGW +#endif + +#ifndef LOGD +#define LOGD ALOGD +#endif + +#ifndef LOGV +#define LOGV ALOGV +#endif + +#ifndef LOGI +#define LOGI ALOGI +#endif + +#define DEBUG_PRINT_ERROR LOGE +#define DEBUG_PRINT LOGI +#define DEBUG_DETAIL LOGV + +typedef void (*message_func)(void* client_data, unsigned char id); + +/** + @brief audio encoder ipc info structure + + */ +struct amr_ipc_info +{ + pthread_t thr; + int pipe_in; + int pipe_out; + int dead; + message_func process_msg_cb; + void *client_data; + char thread_name[128]; +}; + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to command server + */ +struct amr_ipc_info *omx_amr_thread_create(message_func cb, + void* client_data, + char *th_name); + +struct amr_ipc_info *omx_amr_event_thread_create(message_func cb, + void* client_data, + char *th_name); +/** + @brief This function stop command server + + @param svr handle to command server + @return none + */ +void omx_amr_thread_stop(struct amr_ipc_info *amr_ipc); + + +/** + @brief This function post message in the command server + + @param svr handle to command server + @return none + */ +void omx_amr_post_msg(struct amr_ipc_info *amr_ipc, + unsigned char id); + +#ifdef __cplusplus +} +#endif + +#endif /* AENC_SVR */ diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h b/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h new file mode 100644 index 00000000..ed7f758e --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/inc/omx_amr_aenc.h @@ -0,0 +1,538 @@ +/*-------------------------------------------------------------------------- + +Copyright (c) 2010,2014 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _AMR_ENC_H_ +#define _AMR_ENC_H_ +/*============================================================================ + Audio Encoder + +@file omx_amr_aenc.h +This module contains the class definition for openMAX encoder component. + + + +============================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +/* Uncomment out below line #define LOG_NDEBUG 0 if we want to see + * all DEBUG_PRINT or LOGV messaging */ +#include<stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <time.h> +#include <inttypes.h> +#include <unistd.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#include "OMX_Core.h" +#include "OMX_Audio.h" +#include "aenc_svr.h" +#include "qc_omx_component.h" +#include "Map.h" +#include <semaphore.h> +#include <linux/msm_audio.h> +#include <linux/msm_audio_amrnb.h> +extern "C" { + void * get_omx_component_factory_fn(void); +} + + +////////////////////////////////////////////////////////////////////////////// +// Module specific globals +////////////////////////////////////////////////////////////////////////////// + + + +#define OMX_SPEC_VERSION 0x00000101 +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (x >= y?x:y) + +////////////////////////////////////////////////////////////////////////////// +// Macros +////////////////////////////////////////////////////////////////////////////// +// + + +#define PrintFrameHdr(i,bufHdr) \ + DEBUG_PRINT("i=%d OMX bufHdr[%p]buf[%p]size[%d]TS[%lld]nFlags[0x%x]\n",\ + i,\ + bufHdr, \ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFlags) + + +// BitMask Management logic +#define BITS_PER_BYTE 8 +#define BITMASK_SIZE(mIndex) \ + (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) +#define BITMASK_OFFSET(mIndex)\ + ((mIndex)/BITS_PER_BYTE) +#define BITMASK_FLAG(mIndex) \ + (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITMASK_CLEAR(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] &= ~(BITMASK_FLAG(mIndex)) +#define BITMASK_SET(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] |= BITMASK_FLAG(mIndex) +#define BITMASK_PRESENT(mArray,mIndex)\ + ((mArray)[BITMASK_OFFSET(mIndex)] & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex)\ + (((mArray)[BITMASK_OFFSET(mIndex)] & \ + BITMASK_FLAG(mIndex)) == 0x0) + +#define OMX_CORE_NUM_INPUT_BUFFERS 2 +#define OMX_CORE_NUM_OUTPUT_BUFFERS 16 + +#define OMX_CORE_INPUT_BUFFER_SIZE 8160 // Multiple of 160 +#define OMX_CORE_CONTROL_CMDQ_SIZE 100 +#define OMX_AENC_VOLUME_STEP 0x147 +#define OMX_AENC_MIN 0 +#define OMX_AENC_MAX 100 +#define NON_TUNNEL 1 +#define TUNNEL 0 +#define IP_PORT_BITMASK 0x02 +#define OP_PORT_BITMASK 0x01 +#define IP_OP_PORT_BITMASK 0x03 + +#define OMX_AMR_DEFAULT_SF 8000 +#define OMX_AMR_DEFAULT_CH_CFG 1 +#define OMX_AMR_DEFAULT_VOL 25 +// 14 bytes for input meta data +#define OMX_AENC_SIZEOF_META_BUF (OMX_CORE_INPUT_BUFFER_SIZE+14) + +#define TRUE 1 +#define FALSE 0 + +#define NUMOFFRAMES 1 +#define MAXFRAMELENGTH 32 +#define OMX_AMR_OUTPUT_BUFFER_SIZE ((NUMOFFRAMES * (sizeof(ENC_META_OUT) + MAXFRAMELENGTH) \ + + 1)) +#define FRAMEDURATION 20000 + +class omx_amr_aenc; + +// OMX AMR audio encoder class +class omx_amr_aenc: public qc_omx_component +{ +public: + omx_amr_aenc(); // constructor + virtual ~omx_amr_aenc(); // destructor + + OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + + OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp); + + OMX_ERRORTYPE component_init(OMX_STRING role); + + OMX_ERRORTYPE component_role_enum(OMX_HANDLETYPE hComp, + OMX_U8 *role, + OMX_U32 index); + + OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_HANDLETYPE peerComponent, + OMX_U32 peerPort, + OMX_TUNNELSETUPTYPE *tunnelSetup); + + OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE hComp, + OMX_STRING componentName, + OMX_VERSIONTYPE *componentVersion, + OMX_VERSIONTYPE * specVersion, + OMX_UUIDTYPE *componentUUID); + + OMX_ERRORTYPE get_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE hComp, + OMX_STRING paramName, + OMX_INDEXTYPE *indexType); + + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp, + OMX_STATETYPE *state); + + static void process_in_port_msg(void *client_data, + unsigned char id); + + static void process_out_port_msg(void *client_data, + unsigned char id); + + static void process_command_msg(void *client_data, + unsigned char id); + + static void process_event_cb(void *client_data, + unsigned char id); + + + OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp, + OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData); + + OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + void * eglImage); + + bool post_command(unsigned int p1, unsigned int p2, + unsigned char id); + + // Deferred callback identifiers + enum + { + //Event Callbacks from the component thread context + OMX_COMPONENT_GENERATE_EVENT = 0x1, + //Buffer Done callbacks from component thread context + OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2, + OMX_COMPONENT_GENERATE_ETB = 0x3, + //Command + OMX_COMPONENT_GENERATE_COMMAND = 0x4, + OMX_COMPONENT_GENERATE_FRAME_DONE = 0x05, + OMX_COMPONENT_GENERATE_FTB = 0x06, + OMX_COMPONENT_GENERATE_EOS = 0x07, + OMX_COMPONENT_PORTSETTINGS_CHANGED = 0x08, + OMX_COMPONENT_SUSPEND = 0x09, + OMX_COMPONENT_RESUME = 0x0a + }; +private: + + /////////////////////////////////////////////////////////// + // Type definitions + /////////////////////////////////////////////////////////// + // Bit Positions + enum flags_bit_positions + { + // Defer transition to IDLE + OMX_COMPONENT_IDLE_PENDING =0x1, + // Defer transition to LOADING + OMX_COMPONENT_LOADING_PENDING =0x2, + + OMX_COMPONENT_MUTED =0x3, + + // Defer transition to Enable + OMX_COMPONENT_INPUT_ENABLE_PENDING =0x4, + // Defer transition to Enable + OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x5, + // Defer transition to Disable + OMX_COMPONENT_INPUT_DISABLE_PENDING =0x6, + // Defer transition to Disable + OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x7 + }; + + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + input_buffer_map; + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + output_buffer_map; + + enum port_indexes + { + OMX_CORE_INPUT_PORT_INDEX =0, + OMX_CORE_OUTPUT_PORT_INDEX =1 + }; + + struct omx_event + { + unsigned long param1; + unsigned long param2; + unsigned char id; + }; + + struct omx_cmd_queue + { + omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE]; + unsigned m_read; + unsigned m_write; + unsigned m_size; + + omx_cmd_queue(); + ~omx_cmd_queue(); + bool insert_entry(unsigned long p1, unsigned long p2, unsigned char id); + bool pop_entry(unsigned long *p1,unsigned long *p2, unsigned char *id); + bool get_msg_id(unsigned char *id); + bool get_msg_with_id(unsigned *p1,unsigned *p2, unsigned id); + }; + + typedef struct TIMESTAMP + { + unsigned int LowPart; + unsigned int HighPart; + }__attribute__((packed)) TIMESTAMP; + + typedef struct metadata_input + { + unsigned short offsetVal; + TIMESTAMP nTimeStamp; + unsigned int nFlags; + }__attribute__((packed)) META_IN; + + typedef struct enc_meta_out + { + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; + } __attribute__ ((packed))ENC_META_OUT; + + typedef struct + { + OMX_U32 tot_in_buf_len; + OMX_U32 tot_out_buf_len; + OMX_TICKS tot_pb_time; + OMX_U32 fbd_cnt; + OMX_U32 ftb_cnt; + OMX_U32 etb_cnt; + OMX_U32 ebd_cnt; + }AMR_PB_STATS; + + /////////////////////////////////////////////////////////// + // Member variables + /////////////////////////////////////////////////////////// + OMX_U8 *m_tmp_meta_buf; + OMX_U8 *m_tmp_out_meta_buf; + OMX_U8 m_flush_cnt ; + OMX_U8 m_comp_deinit; + + // the below var doesnt hold good if combo of use and alloc bufs are used + OMX_S32 m_volume;//Unit to be determined + OMX_PTR m_app_data;// Application data + int nNumInputBuf; + int nNumOutputBuf; + int m_drv_fd; // Kernel device node file handle + bool bFlushinprogress; + bool is_in_th_sleep; + bool is_out_th_sleep; + unsigned int m_flags; //encapsulate the waiting states. + OMX_U64 nTimestamp; + OMX_U64 ts; + unsigned int pcm_input; //tunnel or non-tunnel + unsigned int m_inp_act_buf_count; // Num of Input Buffers + unsigned int m_out_act_buf_count; // Numb of Output Buffers + unsigned int m_inp_current_buf_count; // Num of Input Buffers + unsigned int m_out_current_buf_count; // Numb of Output Buffers + unsigned int output_buffer_size; + unsigned int input_buffer_size; + unsigned short m_session_id; + // store I/P PORT state + OMX_BOOL m_inp_bEnabled; + // store O/P PORT state + OMX_BOOL m_out_bEnabled; + //Input port Populated + OMX_BOOL m_inp_bPopulated; + //Output port Populated + OMX_BOOL m_out_bPopulated; + sem_t sem_States; + sem_t sem_read_msg; + sem_t sem_write_msg; + + volatile int m_is_event_done; + volatile int m_is_in_th_sleep; + volatile int m_is_out_th_sleep; + input_buffer_map m_input_buf_hdrs; + output_buffer_map m_output_buf_hdrs; + omx_cmd_queue m_input_q; + omx_cmd_queue m_input_ctrl_cmd_q; + omx_cmd_queue m_input_ctrl_ebd_q; + omx_cmd_queue m_command_q; + omx_cmd_queue m_output_q; + omx_cmd_queue m_output_ctrl_cmd_q; + omx_cmd_queue m_output_ctrl_fbd_q; + pthread_mutexattr_t m_outputlock_attr; + pthread_mutexattr_t m_commandlock_attr; + pthread_mutexattr_t m_lock_attr; + pthread_mutexattr_t m_state_attr; + pthread_mutexattr_t m_flush_attr; + pthread_mutexattr_t m_in_th_attr_1; + pthread_mutexattr_t m_out_th_attr_1; + pthread_mutexattr_t m_event_attr; + pthread_mutexattr_t m_in_th_attr; + pthread_mutexattr_t m_out_th_attr; + pthread_mutexattr_t out_buf_count_lock_attr; + pthread_mutexattr_t in_buf_count_lock_attr; + pthread_cond_t cond; + pthread_cond_t in_cond; + pthread_cond_t out_cond; + pthread_mutex_t m_lock; + pthread_mutex_t m_commandlock; + pthread_mutex_t m_outputlock; + // Mutexes for state change + pthread_mutex_t m_state_lock; + // Mutexes for flush acks from input and output threads + pthread_mutex_t m_flush_lock; + pthread_mutex_t m_event_lock; + pthread_mutex_t m_in_th_lock; + pthread_mutex_t m_out_th_lock; + pthread_mutex_t m_in_th_lock_1; + pthread_mutex_t m_out_th_lock_1; + pthread_mutex_t out_buf_count_lock; + pthread_mutex_t in_buf_count_lock; + + OMX_STATETYPE m_state; // OMX State + OMX_STATETYPE nState; + OMX_CALLBACKTYPE m_cb; // Application callbacks + AMR_PB_STATS m_amr_pb_stats; + struct amr_ipc_info *m_ipc_to_in_th; // for input thread + struct amr_ipc_info *m_ipc_to_out_th; // for output thread + struct amr_ipc_info *m_ipc_to_cmd_th; // for command thread + OMX_PRIORITYMGMTTYPE m_priority_mgm ; + OMX_AUDIO_PARAM_AMRTYPE m_amr_param; // Cache AMR encoder parameter + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_param; // Cache pcm parameter + OMX_PARAM_COMPONENTROLETYPE component_Role; + OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier; + + /////////////////////////////////////////////////////////// + // Private methods + /////////////////////////////////////////////////////////// + OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port,OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE use_input_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE use_output_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + bool allocate_done(void); + + bool release_done(OMX_U32 param1); + + bool execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl=true); + + bool execute_input_omx_flush(void); + + bool execute_output_omx_flush(void); + + bool search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool post_input(unsigned long p1, unsigned long p2, + unsigned char id); + + bool post_output(unsigned long p1, unsigned long p2, + unsigned char id); + + void process_events(omx_amr_aenc *client_data); + + void buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void wait_for_event(); + + void event_complete(); + + void in_th_goto_sleep(); + + void in_th_wakeup(); + + void out_th_goto_sleep(); + + void out_th_wakeup(); + + void flush_ack(); + void deinit_encoder(); + +}; +#endif diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/src/aenc_svr.c b/msm8909/mm-audio/aenc-amrnb/qdsp6/src/aenc_svr.c new file mode 100644 index 00000000..dea7c7f2 --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/src/aenc_svr.c @@ -0,0 +1,205 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> +#include <errno.h> + +#include <aenc_svr.h> + +/** + @brief This function processes posted messages + + Once thread is being spawned, this function is run to + start processing commands posted by client + + @param info pointer to context + + */ +void *omx_amr_msg(void *info) +{ + struct amr_ipc_info *amr_info = (struct amr_ipc_info*)info; + unsigned char id; + ssize_t n; + + DEBUG_DETAIL("\n%s: message thread start\n", __FUNCTION__); + while (!amr_info->dead) + { + n = read(amr_info->pipe_in, &id, 1); + if (0 == n) break; + if (1 == n) + { + DEBUG_DETAIL("\n%s-->pipe_in=%d pipe_out=%d\n", + amr_info->thread_name, + amr_info->pipe_in, + amr_info->pipe_out); + + amr_info->process_msg_cb(amr_info->client_data, id); + } + if ((n < 0) && (errno != EINTR)) break; + } + DEBUG_DETAIL("%s: message thread stop\n", __FUNCTION__); + + return 0; +} + +void *omx_amr_events(void *info) +{ + struct amr_ipc_info *amr_info = (struct amr_ipc_info*)info; + unsigned char id = 0; + + DEBUG_DETAIL("%s: message thread start\n", amr_info->thread_name); + amr_info->process_msg_cb(amr_info->client_data, id); + DEBUG_DETAIL("%s: message thread stop\n", amr_info->thread_name); + return 0; +} + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to msging thread + */ +struct amr_ipc_info *omx_amr_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct amr_ipc_info *amr_info; + + amr_info = calloc(1, sizeof(struct amr_ipc_info)); + if (!amr_info) + { + return 0; + } + + amr_info->client_data = client_data; + amr_info->process_msg_cb = cb; + strlcpy(amr_info->thread_name, th_name, sizeof(amr_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT_ERROR("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + amr_info->pipe_in = fds[0]; + amr_info->pipe_out = fds[1]; + + r = pthread_create(&amr_info->thr, 0, omx_amr_msg, amr_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", amr_info->thread_name); + return amr_info; + + +fail_thread: + close(amr_info->pipe_in); + close(amr_info->pipe_out); + +fail_pipe: + free(amr_info); + + return 0; +} + +/** + * @brief This function starts command server + * + * @param cb pointer to callback function from the client + * @param client_data reference client wants to get back + * through callback + * @return handle to msging thread + * */ +struct amr_ipc_info *omx_amr_event_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct amr_ipc_info *amr_info; + + amr_info = calloc(1, sizeof(struct amr_ipc_info)); + if (!amr_info) + { + return 0; + } + + amr_info->client_data = client_data; + amr_info->process_msg_cb = cb; + strlcpy(amr_info->thread_name, th_name, sizeof(amr_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + amr_info->pipe_in = fds[0]; + amr_info->pipe_out = fds[1]; + + r = pthread_create(&amr_info->thr, 0, omx_amr_events, amr_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", amr_info->thread_name); + return amr_info; + + +fail_thread: + close(amr_info->pipe_in); + close(amr_info->pipe_out); + +fail_pipe: + free(amr_info); + + return 0; +} + +void omx_amr_thread_stop(struct amr_ipc_info *amr_info) { + DEBUG_DETAIL("%s stop server\n", __FUNCTION__); + close(amr_info->pipe_in); + close(amr_info->pipe_out); + pthread_join(amr_info->thr,NULL); + amr_info->pipe_out = -1; + amr_info->pipe_in = -1; + DEBUG_DETAIL("%s: message thread close fds%d %d\n", amr_info->thread_name, + amr_info->pipe_in,amr_info->pipe_out); + free(amr_info); +} + +void omx_amr_post_msg(struct amr_ipc_info *amr_info, unsigned char id) { + DEBUG_DETAIL("\n%s id=%d\n", __FUNCTION__,id); + write(amr_info->pipe_out, &id, 1); +} diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/src/omx_amr_aenc.cpp b/msm8909/mm-audio/aenc-amrnb/qdsp6/src/omx_amr_aenc.cpp new file mode 100644 index 00000000..5e9ee4e7 --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/src/omx_amr_aenc.cpp @@ -0,0 +1,4532 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ +@file omx_aenc_amr.c + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + + +#include<string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include "omx_amr_aenc.h" +#include <errno.h> + +using namespace std; +#define SLEEP_MS 100 + +// omx_cmd_queue destructor +omx_amr_aenc::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_amr_aenc::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q, 0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_amr_aenc::omx_cmd_queue::insert_entry(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool ret = true; + if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full"); + } + return ret; +} + +bool omx_amr_aenc::omx_cmd_queue::pop_entry(unsigned long *p1, + unsigned long *p2, unsigned char *id) +{ + bool ret = true; + if (m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR Delete!!! Command Queue Empty"); + } + return ret; +} + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return(new omx_amr_aenc); +} +bool omx_amr_aenc::omx_cmd_queue::get_msg_id(unsigned char *id) +{ + if(m_size > 0) + { + *id = m_q[m_read].id; + DEBUG_PRINT("get_msg_id=%d\n",*id); + } + else{ + return false; + } + return true; +} +/*============================================================================= +FUNCTION: + wait_for_event + +DESCRIPTION: + waits for a particular event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_amr_aenc::wait_for_event() +{ + int rc; + struct timespec ts; + pthread_mutex_lock(&m_event_lock); + while (0 == m_is_event_done) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += (SLEEP_MS/1000); + ts.tv_nsec += ((SLEEP_MS%1000) * 1000000); + rc = pthread_cond_timedwait(&cond, &m_event_lock, &ts); + if (rc == ETIMEDOUT && !m_is_event_done) { + DEBUG_PRINT("Timed out waiting for flush"); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + } + } + m_is_event_done = 0; + pthread_mutex_unlock(&m_event_lock); +} + +/*============================================================================= +FUNCTION: + event_complete + +DESCRIPTION: + informs about the occurance of an event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_amr_aenc::event_complete() +{ + pthread_mutex_lock(&m_event_lock); + if (0 == m_is_event_done) + { + m_is_event_done = 1; + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&m_event_lock); +} + +// All this non-sense because of a single amr object +void omx_amr_aenc::in_th_goto_sleep() +{ + pthread_mutex_lock(&m_in_th_lock); + while (0 == m_is_in_th_sleep) + { + pthread_cond_wait(&in_cond, &m_in_th_lock); + } + m_is_in_th_sleep = 0; + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_amr_aenc::in_th_wakeup() +{ + pthread_mutex_lock(&m_in_th_lock); + if (0 == m_is_in_th_sleep) + { + m_is_in_th_sleep = 1; + pthread_cond_signal(&in_cond); + } + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_amr_aenc::out_th_goto_sleep() +{ + + pthread_mutex_lock(&m_out_th_lock); + while (0 == m_is_out_th_sleep) + { + pthread_cond_wait(&out_cond, &m_out_th_lock); + } + m_is_out_th_sleep = 0; + pthread_mutex_unlock(&m_out_th_lock); +} + +void omx_amr_aenc::out_th_wakeup() +{ + pthread_mutex_lock(&m_out_th_lock); + if (0 == m_is_out_th_sleep) + { + m_is_out_th_sleep = 1; + pthread_cond_signal(&out_cond); + } + pthread_mutex_unlock(&m_out_th_lock); +} +/* ====================================================================== +FUNCTION + omx_amr_aenc::omx_amr_aenc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_amr_aenc::omx_amr_aenc(): m_tmp_meta_buf(NULL), + m_tmp_out_meta_buf(NULL), + m_flush_cnt(255), + m_comp_deinit(0), + m_volume(25), + m_app_data(NULL), + nNumInputBuf(0), + nNumOutputBuf(0), + m_drv_fd(-1), + bFlushinprogress(0), + is_in_th_sleep(false), + is_out_th_sleep(false), + m_flags(0), + nTimestamp(0), + ts(0), + pcm_input(0), + m_inp_act_buf_count (OMX_CORE_NUM_INPUT_BUFFERS), + m_out_act_buf_count (OMX_CORE_NUM_OUTPUT_BUFFERS), + m_inp_current_buf_count(0), + m_out_current_buf_count(0), + output_buffer_size((OMX_U32)OMX_AMR_OUTPUT_BUFFER_SIZE), + input_buffer_size(OMX_CORE_INPUT_BUFFER_SIZE), + m_session_id(0), + m_inp_bEnabled(OMX_TRUE), + m_out_bEnabled(OMX_TRUE), + m_inp_bPopulated(OMX_FALSE), + m_out_bPopulated(OMX_FALSE), + m_is_event_done(0), + m_state(OMX_StateInvalid), + m_ipc_to_in_th(NULL), + m_ipc_to_out_th(NULL), + m_ipc_to_cmd_th(NULL) +{ + int cond_ret = 0; + component_Role.nSize = 0; + memset(&m_cmp, 0, sizeof(m_cmp)); + memset(&m_cb, 0, sizeof(m_cb)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + memset(&m_amr_param, 0, sizeof(m_amr_param)); + memset(&m_amr_pb_stats, 0, sizeof(m_amr_pb_stats)); + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + + pthread_mutexattr_init(&m_lock_attr); + pthread_mutex_init(&m_lock, &m_lock_attr); + pthread_mutexattr_init(&m_commandlock_attr); + pthread_mutex_init(&m_commandlock, &m_commandlock_attr); + + pthread_mutexattr_init(&m_outputlock_attr); + pthread_mutex_init(&m_outputlock, &m_outputlock_attr); + + pthread_mutexattr_init(&m_state_attr); + pthread_mutex_init(&m_state_lock, &m_state_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_flush_attr); + pthread_mutex_init(&m_flush_lock, &m_flush_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_in_th_attr); + pthread_mutex_init(&m_in_th_lock, &m_in_th_attr); + + pthread_mutexattr_init(&m_out_th_attr); + pthread_mutex_init(&m_out_th_lock, &m_out_th_attr); + + pthread_mutexattr_init(&m_in_th_attr_1); + pthread_mutex_init(&m_in_th_lock_1, &m_in_th_attr_1); + + pthread_mutexattr_init(&m_out_th_attr_1); + pthread_mutex_init(&m_out_th_lock_1, &m_out_th_attr_1); + + pthread_mutexattr_init(&out_buf_count_lock_attr); + pthread_mutex_init(&out_buf_count_lock, &out_buf_count_lock_attr); + + pthread_mutexattr_init(&in_buf_count_lock_attr); + pthread_mutex_init(&in_buf_count_lock, &in_buf_count_lock_attr); + if ((cond_ret = pthread_cond_init (&cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&in_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for in_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&out_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for out_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + + sem_init(&sem_read_msg,0, 0); + sem_init(&sem_write_msg,0, 0); + sem_init(&sem_States,0, 0); + return; +} + + +/* ====================================================================== +FUNCTION + omx_amr_aenc::~omx_amr_aenc + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_amr_aenc::~omx_amr_aenc() +{ + DEBUG_PRINT_ERROR("AMR Object getting destroyed comp-deinit=%d\n", + m_comp_deinit); + if ( !m_comp_deinit ) + { + deinit_encoder(); + } + pthread_mutexattr_destroy(&m_lock_attr); + pthread_mutex_destroy(&m_lock); + + pthread_mutexattr_destroy(&m_commandlock_attr); + pthread_mutex_destroy(&m_commandlock); + + pthread_mutexattr_destroy(&m_outputlock_attr); + pthread_mutex_destroy(&m_outputlock); + + pthread_mutexattr_destroy(&m_state_attr); + pthread_mutex_destroy(&m_state_lock); + + pthread_mutexattr_destroy(&m_event_attr); + pthread_mutex_destroy(&m_event_lock); + + pthread_mutexattr_destroy(&m_flush_attr); + pthread_mutex_destroy(&m_flush_lock); + + pthread_mutexattr_destroy(&m_in_th_attr); + pthread_mutex_destroy(&m_in_th_lock); + + pthread_mutexattr_destroy(&m_out_th_attr); + pthread_mutex_destroy(&m_out_th_lock); + + pthread_mutexattr_destroy(&out_buf_count_lock_attr); + pthread_mutex_destroy(&out_buf_count_lock); + + pthread_mutexattr_destroy(&in_buf_count_lock_attr); + pthread_mutex_destroy(&in_buf_count_lock); + + pthread_mutexattr_destroy(&m_in_th_attr_1); + pthread_mutex_destroy(&m_in_th_lock_1); + + pthread_mutexattr_destroy(&m_out_th_attr_1); + pthread_mutex_destroy(&m_out_th_lock_1); + pthread_mutex_destroy(&out_buf_count_lock); + pthread_mutex_destroy(&in_buf_count_lock); + pthread_cond_destroy(&cond); + pthread_cond_destroy(&in_cond); + pthread_cond_destroy(&out_cond); + sem_destroy (&sem_read_msg); + sem_destroy (&sem_write_msg); + sem_destroy (&sem_States); + DEBUG_PRINT_ERROR("OMX AMR component destroyed\n"); + return; +} + +/** + @brief memory function for sending EmptyBufferDone event + back to IL client + + @param bufHdr OMX buffer header to be passed back to IL client + @return none + */ +void omx_amr_aenc::buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.EmptyBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_BUFFER_DONE,bufHdr); + bufHdr->nFilledLen = 0; + + m_cb.EmptyBufferDone(&m_cmp, m_app_data, bufHdr); + pthread_mutex_lock(&in_buf_count_lock); + m_amr_pb_stats.ebd_cnt++; + nNumInputBuf--; + DEBUG_DETAIL("EBD CB:: in_buf_len=%d nNumInputBuf=%d ebd_cnt=%d\n",\ + m_amr_pb_stats.tot_in_buf_len, + nNumInputBuf, m_amr_pb_stats.ebd_cnt); + pthread_mutex_unlock(&in_buf_count_lock); + } + + return; +} + +/*============================================================================= +FUNCTION: + flush_ack + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_amr_aenc::flush_ack() +{ + // Decrement the FLUSH ACK count and notify the waiting recepients + pthread_mutex_lock(&m_flush_lock); + --m_flush_cnt; + if (0 == m_flush_cnt) + { + event_complete(); + } + DEBUG_PRINT("Rxed FLUSH ACK cnt=%d\n",m_flush_cnt); + pthread_mutex_unlock(&m_flush_lock); +} +void omx_amr_aenc::frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.FillBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_FRAME_DONE,bufHdr); + m_amr_pb_stats.fbd_cnt++; + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf--; + DEBUG_PRINT("FBD CB:: nNumOutputBuf=%d out_buf_len=%u fbd_cnt=%u\n",\ + nNumOutputBuf, + m_amr_pb_stats.tot_out_buf_len, + m_amr_pb_stats.fbd_cnt); + m_amr_pb_stats.tot_out_buf_len += bufHdr->nFilledLen; + m_amr_pb_stats.tot_pb_time = bufHdr->nTimeStamp; + DEBUG_PRINT("FBD:in_buf_len=%u out_buf_len=%u\n", + m_amr_pb_stats.tot_in_buf_len, + m_amr_pb_stats.tot_out_buf_len); + + pthread_mutex_unlock(&out_buf_count_lock); + m_cb.FillBufferDone(&m_cmp, m_app_data, bufHdr); + } + return; +} + +/*============================================================================= +FUNCTION: + process_out_port_msg + +DESCRIPTION: + Function for handling all commands from IL client +IL client commands are processed and callbacks are generated through +this routine Audio Command Server provides the thread context for this routine + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_amr_aenc::process_out_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; // qsize + unsigned tot_qsize = 0; + omx_amr_aenc *pThis = (omx_amr_aenc *) client_data; + OMX_STATETYPE state; + +loopback_out: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" OUT: IN LOADED STATE RETURN\n"); + return; + } + pthread_mutex_lock(&pThis->m_outputlock); + + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + + if ( 0 == tot_qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_DETAIL("OUT-->BREAK FROM LOOP...%d\n",tot_qsize); + return; + } + if ( (state != OMX_StateExecuting) && !qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + DEBUG_DETAIL("OUT:1.SLEEPING OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + + if ( ((!pThis->m_output_ctrl_cmd_q.m_size) && !pThis->m_out_bEnabled) ) + { + // case where no port reconfig and nothing in the flush q + DEBUG_DETAIL("No flush/port reconfig qsize=%d tot_qsize=%d",\ + qsize,tot_qsize); + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + if(pThis->m_output_ctrl_cmd_q.m_size || !(pThis->bFlushinprogress)) + { + DEBUG_PRINT("OUT:2. SLEEPING OUT THREAD \n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + } + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_DETAIL("OUT-->QSIZE-flush=%d,fbd=%d QSIZE=%d state=%d\n",\ + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size,state); + + + if (qsize) + { + // process FLUSH message + pThis->m_output_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_ctrl_fbd_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_output_ctrl_fbd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // if no FLUSH and FBD's then process FTB's + pThis->m_output_q.pop_entry(&p1,&p2,&ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("OUT--> Empty Queue state=%d %d %d %d\n",state, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("OUT: SLEEPING AGAIN OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pthread_mutex_unlock(&pThis->m_outputlock); + pThis->out_th_goto_sleep(); + goto loopback_out; + } + } + pthread_mutex_unlock(&pThis->m_outputlock); + + if ( qsize > 0 ) + { + id = ident; + ident = 0; + DEBUG_DETAIL("OUT->state[%d]ident[%d]flushq[%d]fbd[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if ( OMX_COMPONENT_GENERATE_FRAME_DONE == id ) + { + pThis->frame_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_FTB == id ) + { + pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_EOS == id ) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + + } + else if(id == OMX_COMPONENT_RESUME) + { + DEBUG_PRINT("RESUMED...\n"); + } + else if(id == OMX_COMPONENT_GENERATE_COMMAND) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL("Executing FLUSH command on Output port\n"); + pThis->execute_output_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:OUT-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR: OUT--> Empty OUTPUTQ\n"); + } + + return; +} + +/*============================================================================= +FUNCTION: + process_command_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_amr_aenc::process_command_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + omx_amr_aenc *pThis = (omx_amr_aenc*)client_data; + pthread_mutex_lock(&pThis->m_commandlock); + + qsize = pThis->m_command_q.m_size; + DEBUG_DETAIL("CMD-->QSIZE=%d state=%d\n",pThis->m_command_q.m_size, + pThis->m_state); + + if (!qsize) + { + DEBUG_DETAIL("CMD-->BREAKING FROM LOOP\n"); + pthread_mutex_unlock(&pThis->m_commandlock); + return; + } else + { + pThis->m_command_q.pop_entry(&p1,&p2,&ident); + } + pthread_mutex_unlock(&pThis->m_commandlock); + + id = ident; + DEBUG_DETAIL("CMD->state[%d]id[%d]cmdq[%d]n",\ + pThis->m_state,ident, \ + pThis->m_command_q.m_size); + + if (OMX_COMPONENT_GENERATE_EVENT == id) + { + if (pThis->m_cb.EventHandler) + { + if (OMX_CommandStateSet == p1) + { + pthread_mutex_lock(&pThis->m_state_lock); + pThis->m_state = (OMX_STATETYPE) p2; + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_PRINT("CMD:Process->state set to %d \n", \ + pThis->m_state); + + if (pThis->m_state == OMX_StateExecuting || + pThis->m_state == OMX_StateLoaded) + { + + pthread_mutex_lock(&pThis->m_in_th_lock_1); + if (pThis->is_in_th_sleep) + { + pThis->is_in_th_sleep = false; + DEBUG_DETAIL("CMD:WAKING UP IN THREADS\n"); + pThis->in_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + + pthread_mutex_lock(&pThis->m_out_th_lock_1); + if (pThis->is_out_th_sleep) + { + DEBUG_DETAIL("CMD:WAKING UP OUT THREADS\n"); + pThis->is_out_th_sleep = false; + pThis->out_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + } + } + if (OMX_StateInvalid == pThis->m_state) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + } else if ((signed)p2 == OMX_ErrorPortUnpopulated) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + (OMX_U32)p2, + 0, + 0 ); + } else + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventCmdComplete, + (OMX_U32)p1, (OMX_U32)p2, NULL ); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:CMD-->EventHandler NULL \n"); + } + } else if (OMX_COMPONENT_GENERATE_COMMAND == id) + { + pThis->send_command_proxy(&pThis->m_cmp, + (OMX_COMMANDTYPE)p1, + (OMX_U32)p2,(OMX_PTR)NULL); + } else if (OMX_COMPONENT_PORTSETTINGS_CHANGED == id) + { + DEBUG_DETAIL("CMD-->RXED PORTSETTINGS_CHANGED"); + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventPortSettingsChanged, + 1, 1, NULL ); + } + else + { + DEBUG_PRINT_ERROR("CMD->state[%d]id[%d]\n",pThis->m_state,ident); + } + return; +} + +/*============================================================================= +FUNCTION: + process_in_port_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_amr_aenc::process_in_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + unsigned tot_qsize = 0; + omx_amr_aenc *pThis = (omx_amr_aenc *) client_data; + OMX_STATETYPE state; + + if (!pThis) + { + DEBUG_PRINT_ERROR("ERROR:IN--> Invalid Obj \n"); + return; + } +loopback_in: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" IN: IN LOADED STATE RETURN\n"); + return; + } + // Protect the shared queue data structure + pthread_mutex_lock(&pThis->m_lock); + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + if ( 0 == tot_qsize ) + { + DEBUG_DETAIL("IN-->BREAKING FROM IN LOOP"); + pthread_mutex_unlock(&pThis->m_lock); + return; + } + + if ( (state != OMX_StateExecuting) && ! (pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_DETAIL("SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + else if ((state == OMX_StatePause)) + { + if(!(pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + + DEBUG_DETAIL("IN: SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + } + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + DEBUG_DETAIL("Input-->QSIZE-flush=%d,ebd=%d QSIZE=%d state=%d\n",\ + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size, state); + + + if ( qsize ) + { + // process FLUSH message + pThis->m_input_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_input_ctrl_ebd_q.m_size) && + (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_input_ctrl_ebd_q.pop_entry(&p1,&p2,&ident); + } else if ((qsize = pThis->m_input_q.m_size) && + (state == OMX_StateExecuting)) + { + // if no FLUSH and EBD's then process ETB's + pThis->m_input_q.pop_entry(&p1, &p2, &ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("IN-->state[%d]cmdq[%d]ebdq[%d]in[%d]\n",\ + state,pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("IN: SLEEPING AGAIN IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pthread_mutex_unlock(&pThis->m_lock); + pThis->in_th_goto_sleep(); + goto loopback_in; + } + } + pthread_mutex_unlock(&pThis->m_lock); + + if ( qsize > 0 ) + { + id = ident; + DEBUG_DETAIL("Input->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + if ( OMX_COMPONENT_GENERATE_BUFFER_DONE == id ) + { + pThis->buffer_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } + else if(id == OMX_COMPONENT_GENERATE_EOS) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventBufferFlag, 0, 1, NULL ); + } else if ( OMX_COMPONENT_GENERATE_ETB == id ) + { + pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_COMMAND == id ) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL(" Executing FLUSH command on Input port\n"); + pThis->execute_input_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } + else + { + DEBUG_PRINT_ERROR("ERROR:IN-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR:IN-->Empty INPUT Q\n"); + } + return; +} + +/** + @brief member function for performing component initialization + + @param role C string mandating role of this component + @return Error status + */ +OMX_ERRORTYPE omx_amr_aenc::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + m_state = OMX_StateLoaded; + + /* DSP does not give information about the bitstream + randomly assign the value right now. Query will result in + incorrect param */ + memset(&m_amr_param, 0, sizeof(m_amr_param)); + m_amr_param.nSize = (OMX_U32)sizeof(m_amr_param); + m_amr_param.nChannels = OMX_AMR_DEFAULT_CH_CFG; + m_volume = OMX_AMR_DEFAULT_VOL; /* Close to unity gain */ + memset(&m_amr_pb_stats,0,sizeof(AMR_PB_STATS)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + m_pcm_param.nSize = (OMX_U32)sizeof(m_pcm_param); + m_pcm_param.nChannels = OMX_AMR_DEFAULT_CH_CFG; + m_pcm_param.nSamplingRate = OMX_AMR_DEFAULT_SF; + nTimestamp = 0; + ts = 0; + + nNumInputBuf = 0; + nNumOutputBuf = 0; + m_ipc_to_in_th = NULL; // Command server instance + m_ipc_to_out_th = NULL; // Client server instance + m_ipc_to_cmd_th = NULL; // command instance + m_is_out_th_sleep = 0; + m_is_in_th_sleep = 0; + is_out_th_sleep= false; + + is_in_th_sleep=false; + + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + m_priority_mgm.nGroupID =0; + m_priority_mgm.nGroupPriority=0; + + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + m_buffer_supplier.nPortIndex=OMX_BufferSupplyUnspecified; + + DEBUG_PRINT_ERROR(" component init: role = %s\n",role); + + DEBUG_PRINT(" component init: role = %s\n",role); + component_Role.nVersion.nVersion = OMX_SPEC_VERSION; + if (!strcmp(role,"OMX.qcom.audio.encoder.amrnb")) + { + pcm_input = 1; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.amrnb")) + { + pcm_input = 0; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else + { + component_Role.nSize = (OMX_U32)sizeof("\0"); + strlcpy((char *)component_Role.cRole, (const char*)"\0", + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED is invalid\n", role); + } + if(pcm_input) + { + m_tmp_meta_buf = (OMX_U8*) malloc(sizeof(OMX_U8) * + (OMX_CORE_INPUT_BUFFER_SIZE + sizeof(META_IN))); + + if (m_tmp_meta_buf == NULL){ + DEBUG_PRINT_ERROR("Mem alloc failed for tmp meta buf\n"); + return OMX_ErrorInsufficientResources; + } + } + m_tmp_out_meta_buf = + (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_AMR_OUTPUT_BUFFER_SIZE); + if ( m_tmp_out_meta_buf == NULL ){ + DEBUG_PRINT_ERROR("Mem alloc failed for out meta buf\n"); + return OMX_ErrorInsufficientResources; + } + + if(0 == pcm_input) + { + m_drv_fd = open("/dev/msm_amrnb_in",O_RDONLY); + DEBUG_PRINT("Driver in Tunnel mode open\n"); + } + else + { + m_drv_fd = open("/dev/msm_amrnb_in",O_RDWR); + DEBUG_PRINT("Driver in Non Tunnel mode open\n"); + } + if (m_drv_fd < 0) + { + DEBUG_PRINT_ERROR("Component_init Open Failed[%d] errno[%d]",\ + m_drv_fd,errno); + + return OMX_ErrorInsufficientResources; + } + if(ioctl(m_drv_fd, AUDIO_GET_SESSION_ID,&m_session_id) == -1) + { + DEBUG_PRINT_ERROR("AUDIO_GET_SESSION_ID FAILED\n"); + } + if(pcm_input) + { + if (!m_ipc_to_in_th) + { + m_ipc_to_in_th = omx_amr_thread_create(process_in_port_msg, + this, (char *)"INPUT_THREAD"); + if (!m_ipc_to_in_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start \ + Input port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + } + + if (!m_ipc_to_cmd_th) + { + m_ipc_to_cmd_th = omx_amr_thread_create(process_command_msg, + this, (char *)"CMD_THREAD"); + if (!m_ipc_to_cmd_th) + { + DEBUG_PRINT_ERROR("ERROR!!!Failed to start " + "command message thread\n"); + return OMX_ErrorInsufficientResources; + } + } + + if (!m_ipc_to_out_th) + { + m_ipc_to_out_th = omx_amr_thread_create(process_out_port_msg, + this, (char *)"OUTPUT_THREAD"); + if (!m_ipc_to_out_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start output " + "port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + return eRet; +} + +/** + + @brief member function to retrieve version of component + + + + @param hComp handle to this component instance + @param componentName name of component + @param componentVersion pointer to memory space which stores the + version number + @param specVersion pointer to memory sapce which stores version of + openMax specification + @param componentUUID + @return Error status + */ +OMX_ERRORTYPE omx_amr_aenc::get_component_version +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID) +{ + if((hComp == NULL) || (componentName == NULL) || + (specVersion == NULL) || (componentUUID == NULL)) + { + componentVersion = NULL; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + componentVersion->nVersion = OMX_SPEC_VERSION; + specVersion->nVersion = OMX_SPEC_VERSION; + return OMX_ErrorNone; +} +/** + @brief member function handles command from IL client + + This function simply queue up commands from IL client. + Commands will be processed in command server thread context later + + @param hComp handle to component instance + @param cmd type of command + @param param1 parameters associated with the command type + @param cmdData + @return Error status +*/ +OMX_ERRORTYPE omx_amr_aenc::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + int portIndex = (int)param1; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateInvalid == m_state) + { + return OMX_ErrorInvalidState; + } + if ( (cmd == OMX_CommandFlush) && (portIndex > 1) ) + { + return OMX_ErrorBadPortIndex; + } + post_command((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + DEBUG_PRINT("Send Command : returns with OMX_ErrorNone \n"); + DEBUG_PRINT("send_command : recieved state before semwait= %u\n",param1); + sem_wait (&sem_States); + DEBUG_PRINT("send_command : recieved state after semwait\n"); + return OMX_ErrorNone; +} + +/** + @brief member function performs actual processing of commands excluding + empty buffer call + + @param hComp handle to component + @param cmd command type + @param param1 parameter associated with the command + @param cmdData + + @return error status +*/ +OMX_ERRORTYPE omx_amr_aenc::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + // Handle only IDLE and executing + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1; + nState = eState; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_CommandStateSet == cmd) + { + /***************************/ + /* Current State is Loaded */ + /***************************/ + if (OMX_StateLoaded == m_state) + { + if (OMX_StateIdle == eState) + { + + if (allocate_done() || + (m_inp_bEnabled == OMX_FALSE + && m_out_bEnabled == OMX_FALSE)) + { + DEBUG_PRINT("SCP-->Allocate Done Complete\n"); + } + else + { + DEBUG_PRINT("SCP-->Loaded to Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + bFlag = 0; + } + + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Loaded\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } + + else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->WaitForResources\n"); + eRet = OMX_ErrorNone; + } + + else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Executing\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Pause\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Invalid\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + m_state = OMX_StateInvalid; + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP-->Loaded to Invalid(%d))\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if (OMX_StateIdle == m_state) + { + if (OMX_StateLoaded == eState) + { + if (release_done(-1)) + { + if (ioctl(m_drv_fd, AUDIO_STOP, 0) == -1) + { + DEBUG_PRINT_ERROR("SCP:Idle->Loaded,\ + ioctl stop failed %d\n", errno); + } + + nTimestamp=0; + ts = 0; + DEBUG_PRINT("SCP-->Idle to Loaded\n"); + } else + { + DEBUG_PRINT("SCP--> Idle to Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + else if (OMX_StateExecuting == eState) + { + + struct msm_audio_amrnb_enc_config_v2 drv_amr_enc_config; + struct msm_audio_stream_config drv_stream_config; + struct msm_audio_buf_cfg buf_cfg; + struct msm_audio_config pcm_cfg; + + if(ioctl(m_drv_fd, AUDIO_GET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + if(ioctl(m_drv_fd, AUDIO_SET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + + if(ioctl(m_drv_fd, AUDIO_GET_AMRNB_ENC_CONFIG_V2, + &drv_amr_enc_config) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_AMRNB_ENC_CONFIG_V2 \ + failed, errno[%d]\n", errno); + } + drv_amr_enc_config.band_mode = m_amr_param.eAMRBandMode; + drv_amr_enc_config.dtx_enable = m_amr_param.eAMRDTXMode; + drv_amr_enc_config.frame_format = m_amr_param.eAMRFrameFormat; + if(ioctl(m_drv_fd, AUDIO_SET_AMRNB_ENC_CONFIG_V2, &drv_amr_enc_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_AMRNB_ENC_CONFIG_V2 \ + failed, errno[%d]\n", errno); + } + if (ioctl(m_drv_fd, AUDIO_GET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_BUF_CFG, errno[%d]\n", + errno); + } + buf_cfg.meta_info_enable = 1; + buf_cfg.frames_per_buf = NUMOFFRAMES; + if (ioctl(m_drv_fd, AUDIO_SET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_BUF_CFG, errno[%d]\n", + errno); + } + if(pcm_input) + { + if (ioctl(m_drv_fd, AUDIO_GET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_CONFIG, errno[%d]\n", + errno); + } + pcm_cfg.channel_count = m_pcm_param.nChannels; + pcm_cfg.sample_rate = m_pcm_param.nSamplingRate; + DEBUG_PRINT("pcm config %u %u\n",m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + + if (ioctl(m_drv_fd, AUDIO_SET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_CONFIG, errno[%d]\n", + errno); + } + } + if(ioctl(m_drv_fd, AUDIO_START, 0) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_START failed, errno[%d]\n", + errno); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } + DEBUG_PRINT("SCP-->Idle to Executing\n"); + nState = eState; + } else if (eState == OMX_StateIdle) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Idle\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Pause\n"); + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Idle to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if (OMX_StateExecuting == m_state) + { + if (OMX_StateIdle == eState) + { + DEBUG_PRINT("SCP-->Executing to Idle \n"); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + + } else if (OMX_StatePause == eState) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED PAUSE STATE\n"); + DEBUG_DETAIL("*************************\n"); + //ioctl(m_drv_fd, AUDIO_PAUSE, 0); + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Executing \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Executing to %d Not Handled\n", + eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if (OMX_StatePause == m_state) + { + if( (eState == OMX_StateExecuting || eState == OMX_StateIdle) ) + { + pthread_mutex_lock(&m_out_th_lock_1); + if(is_out_th_sleep) + { + DEBUG_DETAIL("PE: WAKING UP OUT THREAD\n"); + is_out_th_sleep = false; + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } + if ( OMX_StateExecuting == eState ) + { + nState = eState; + } else if ( OMX_StateIdle == eState ) + { + DEBUG_PRINT("SCP-->Paused to Idle \n"); + DEBUG_PRINT ("\n Internal flush issued"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + } else if ( eState == OMX_StateLoaded ) + { + DEBUG_PRINT("\n Pause --> loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n Pause --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("\n Pause --> Pause \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n Pause --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT("SCP-->Paused to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /**************************************/ + /* Current State is WaitForResources */ + /**************************************/ + else if (m_state == OMX_StateWaitForResources) + { + if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Loaded\n"); + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: \ + WaitForResources-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Executing\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Pause\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> %d to %d(Not Handled)\n", + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /****************************/ + /* Current State is Invalid */ + /****************************/ + else if (m_state == OMX_StateInvalid) + { + if (OMX_StateLoaded == eState || OMX_StateWaitForResources == eState + || OMX_StateIdle == eState || OMX_StateExecuting == eState + || OMX_StatePause == eState || OMX_StateInvalid == eState) + { + DEBUG_PRINT("OMXCORE-SM: Invalid-->Loaded/Idle/Executing" + "/Pause/Invalid/WaitForResources\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } + } else + { + DEBUG_PRINT_ERROR("OMXCORE-SM: %d --> %d(Not Handled)\n",\ + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } else if (OMX_CommandFlush == cmd) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED FLUSH COMMAND port=%u\n",param1); + DEBUG_DETAIL("*************************\n"); + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || + param1 == OMX_CORE_OUTPUT_PORT_INDEX || + (signed)param1 == -1 ) + { + execute_omx_flush(param1); + } else + { + eRet = OMX_ErrorBadPortIndex; + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError, + OMX_CommandFlush, OMX_ErrorBadPortIndex, NULL ); + } + } else if ( cmd == OMX_CommandPortDisable ) + { + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL ) + { + DEBUG_PRINT("SCP: Disabling Input port Indx\n"); + m_inp_bEnabled = OMX_FALSE; + if ( (m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(0) ) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_inp_bEnabled=%d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + + else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable in "\ + " param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + // Skip the event notification + + } + + } + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + + DEBUG_PRINT("SCP: Disabling Output port Indx\n"); + m_out_bEnabled = OMX_FALSE; + if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(1)) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_out_bEnabled=%d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable out "\ + "param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + // Skip the event notification + + } + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortDisable: disable wrong port ID"); + } + + } else if (cmd == OMX_CommandPortEnable) + { + bFlag = 0; + if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_TRUE; + DEBUG_PRINT("SCP: Enabling Input port Indx\n"); + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_inp_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + + } else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + + } + } + + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + DEBUG_PRINT("SCP: Enabling Output port Indx\n"); + m_out_bEnabled = OMX_TRUE; + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_out_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortEnable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + + } + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_PRINT("SCP:WAKING OUT THR, OMX_CommandPortEnable\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortEnable: disable wrong port ID"); + } + + } else + { + DEBUG_PRINT_ERROR("SCP-->ERROR: Invali Command [%d]\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + DEBUG_PRINT("posting sem_States\n"); + sem_post (&sem_States); + if (eRet == OMX_ErrorNone && bFlag) + { + post_command(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + return eRet; +} + +/*============================================================================= +FUNCTION: + execute_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + [IN] param1 + [IN] cmd_cmpl + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_amr_aenc::execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl) +{ + bool bRet = true; + + DEBUG_PRINT("Execute_omx_flush Port[%u]", param1); + struct timespec abs_timeout; + abs_timeout.tv_sec = 1; + abs_timeout.tv_nsec = 0; + + if ((signed)param1 == -1) + { + bFlushinprogress = true; + DEBUG_PRINT("Execute flush for both I/p O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + + // Send Flush commands to input and output threads + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + // Send Flush to the kernel so that the in and out buffers are released + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("FLush:ioctl flush failed errno=%d\n",errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + + + // sleep till the FLUSH ACK are done by both the input and + // output threads + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + + DEBUG_PRINT("RECIEVED BOTH FLUSH ACK's param1=%u cmd_cmpl=%d",\ + param1,cmd_cmpl); + + // If not going to idle state, Send FLUSH complete message + // to the Client, now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + DEBUG_PRINT("Inside FLUSH.. sending FLUSH CMPL\n"); + } + bFlushinprogress = false; + } + else if (param1 == OMX_CORE_INPUT_PORT_INDEX) + { + DEBUG_PRINT("Execute FLUSH for I/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + //sleep till the FLUSH ACK are done by both the input and output threads + DEBUG_DETAIL("Executing FLUSH for I/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + DEBUG_DETAIL(" RECIEVED FLUSH ACK FOR I/P PORT param1=%d",param1); + + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == param1) + { + DEBUG_PRINT("Executing FLUSH for O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + DEBUG_DETAIL("Executing FLUSH for O/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) ==-1) + DEBUG_PRINT_ERROR("Flush:Output port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + // sleep till the FLUSH ACK are done by both the input and + // output threads + wait_for_event(); + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + } + DEBUG_DETAIL("RECIEVED FLUSH ACK FOR O/P PORT param1=%d",param1); + } else + { + DEBUG_PRINT("Invalid Port ID[%u]",param1); + } + return bRet; +} + +/*============================================================================= +FUNCTION: + execute_input_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_amr_aenc::execute_input_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on input port"); + + pthread_mutex_lock(&m_lock); + do + { + qsize = m_input_q.m_size; + tot_qsize = qsize; + tot_qsize += m_input_ctrl_ebd_q.m_size; + + DEBUG_DETAIL("Input FLUSH-->flushq[%d] ebd[%d]dataq[%d]",\ + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size,qsize); + if (!tot_qsize) + { + DEBUG_DETAIL("Input-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_lock); + break; + } + if (qsize) + { + m_input_q.pop_entry(&p1, &p2, &ident); + if ((ident == OMX_COMPONENT_GENERATE_ETB) || + (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Flush:Input dataq=%p \n", omx_buf); + omx_buf->nFilledLen = 0; + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else if (m_input_ctrl_ebd_q.m_size) + { + m_input_ctrl_ebd_q.pop_entry(&p1, &p2, &ident); + if (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + omx_buf->nFilledLen = 0; + DEBUG_DETAIL("Flush:ctrl dataq=%p \n", omx_buf); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else + { + } + }while (tot_qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("IN-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_lock); + return true; +} + +/*============================================================================= +FUNCTION: + execute_output_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_amr_aenc::execute_output_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on output port"); + + pthread_mutex_lock(&m_outputlock); + do + { + qsize = m_output_q.m_size; + DEBUG_DETAIL("OUT FLUSH-->flushq[%d] fbd[%d]dataq[%d]",\ + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size,qsize); + tot_qsize = qsize; + tot_qsize += m_output_ctrl_fbd_q.m_size; + if (!tot_qsize) + { + DEBUG_DETAIL("OUT-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_outputlock); + break; + } + if (qsize) + { + m_output_q.pop_entry(&p1,&p2,&ident); + if ( (OMX_COMPONENT_GENERATE_FTB == ident) || + (OMX_COMPONENT_GENERATE_FRAME_DONE == ident)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n",\ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FBD FROM FLUSH"); + } + } else if ((qsize = m_output_ctrl_fbd_q.m_size)) + { + m_output_ctrl_fbd_q.pop_entry(&p1, &p2, &ident); + if (OMX_COMPONENT_GENERATE_FRAME_DONE == ident) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n", \ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FROM CTRL-FBDQ FROM FLUSH"); + } + } + }while (qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("OUT-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_outputlock); + return true; +} + +/*============================================================================= +FUNCTION: + post_input + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_amr_aenc::post_input(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + pthread_mutex_lock(&m_lock); + + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND)) + { + // insert flush message and ebd + m_input_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ((OMX_COMPONENT_GENERATE_BUFFER_DONE == id)) + { + // insert ebd + m_input_ctrl_ebd_q.insert_entry(p1,p2,id); + } else + { + // ETBS in this queue + m_input_q.insert_entry(p1,p2,id); + } + + if (m_ipc_to_in_th) + { + bRet = true; + omx_amr_post_msg(m_ipc_to_in_th, id); + } + + DEBUG_DETAIL("PostInput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d] \n",\ + m_state, + id, + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size, + m_input_q.m_size); + + pthread_mutex_unlock(&m_lock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_command + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_amr_aenc::post_command(unsigned int p1, + unsigned int p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_commandlock); + + m_command_q.insert_entry(p1,p2,id); + + if (m_ipc_to_cmd_th) + { + bRet = true; + omx_amr_post_msg(m_ipc_to_cmd_th, id); + } + + DEBUG_DETAIL("PostCmd-->state[%d]id[%d]cmdq[%d]flags[%x]\n",\ + m_state, + id, + m_command_q.m_size, + m_flags >> 3); + + pthread_mutex_unlock(&m_commandlock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_output + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_amr_aenc::post_output(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_outputlock); + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND) + || (id == OMX_COMPONENT_RESUME)) + { + // insert flush message and fbd + m_output_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ( (OMX_COMPONENT_GENERATE_FRAME_DONE == id) ) + { + // insert flush message and fbd + m_output_ctrl_fbd_q.insert_entry(p1,p2,id); + } else + { + m_output_q.insert_entry(p1,p2,id); + } + if ( m_ipc_to_out_th ) + { + bRet = true; + omx_amr_post_msg(m_ipc_to_out_th, id); + } + DEBUG_DETAIL("PostOutput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + m_state, + id, + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size, + m_output_q.m_size); + + pthread_mutex_unlock(&m_outputlock); + return bRet; +} +/** + @brief member function that return parameters to IL client + + @param hComp handle to component instance + @param paramIndex Parameter type + @param paramData pointer to memory space which would hold the + paramter + @return error status +*/ +OMX_ERRORTYPE omx_amr_aenc::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (paramData == NULL) + { + DEBUG_PRINT("get_parameter: paramData is NULL\n"); + return OMX_ErrorBadParameter; + } + + switch ((int)paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + DEBUG_PRINT("OMX_IndexParamPortDefinition " \ + "portDefn->nPortIndex = %u\n", + portDefn->nPortIndex); + + portDefn->nVersion.nVersion = OMX_SPEC_VERSION; + portDefn->nSize = (OMX_U32)sizeof(portDefn); + portDefn->eDomain = OMX_PortDomainAudio; + + if (0 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirInput; + portDefn->bEnabled = m_inp_bEnabled; + portDefn->bPopulated = m_inp_bPopulated; + portDefn->nBufferCountActual = m_inp_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_INPUT_BUFFERS; + portDefn->nBufferSize = input_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingPCM; + portDefn->format.audio.pNativeRender = 0; + } else if (1 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirOutput; + portDefn->bEnabled = m_out_bEnabled; + portDefn->bPopulated = m_out_bPopulated; + portDefn->nBufferCountActual = m_out_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_OUTPUT_BUFFERS; + portDefn->nBufferSize = output_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingAMR; + portDefn->format.audio.pNativeRender = 0; + } else + { + portDefn->eDir = OMX_DirMax; + DEBUG_PRINT_ERROR("Bad Port idx %d\n",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioInit\n"); + + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 2; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioPortFormat\n"); + portFormatType->nVersion.nVersion = OMX_SPEC_VERSION; + portFormatType->nSize = (OMX_U32)sizeof(portFormatType); + + if (OMX_CORE_INPUT_PORT_INDEX == portFormatType->nPortIndex) + { + + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX== + portFormatType->nPortIndex) + { + DEBUG_PRINT("get_parameter: OMX_IndexParamAudioFormat: "\ + "%u\n", portFormatType->nIndex); + + portFormatType->eEncoding = OMX_AUDIO_CodingAMR; + } else + { + DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioAmr: + { + OMX_AUDIO_PARAM_AMRTYPE *amrParam = + (OMX_AUDIO_PARAM_AMRTYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioAmr\n"); + if (OMX_CORE_OUTPUT_PORT_INDEX== amrParam->nPortIndex) + { + memcpy(amrParam,&m_amr_param, + sizeof(OMX_AUDIO_PARAM_AMRTYPE)); + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioAmr "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)amrParam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case QOMX_IndexParamAudioSessionId: + { + QOMX_AUDIO_STREAM_INFO_DATA *streaminfoparam = + (QOMX_AUDIO_STREAM_INFO_DATA *) paramData; + streaminfoparam->sessionId = (OMX_U8)m_session_id; + break; + } + + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam = + (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(pcmparam,&m_pcm_param,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + DEBUG_PRINT("get_parameter: Sampling rate %u",\ + pcmparam->nSamplingRate); + DEBUG_PRINT("get_parameter: Number of channels %u",\ + pcmparam->nChannels); + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioPcm "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamComponentSuspended: + { + OMX_PARAM_SUSPENSIONTYPE *suspend= + (OMX_PARAM_SUSPENSIONTYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamComponentSuspended %p\n", + suspend); + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamVideoInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *priorityMgmtType = + (OMX_PRIORITYMGMTTYPE*)paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamPriorityMgmt\n"); + priorityMgmtType->nSize = (OMX_U32)sizeof(priorityMgmtType); + priorityMgmtType->nVersion.nVersion = OMX_SPEC_VERSION; + priorityMgmtType->nGroupID = m_priority_mgm.nGroupID; + priorityMgmtType->nGroupPriority = + m_priority_mgm.nGroupPriority; + break; + } + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamImageInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + + bufferSupplierType->nSize = (OMX_U32)sizeof(bufferSupplierType); + bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; + if (OMX_CORE_INPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else + { + DEBUG_PRINT_ERROR("get_parameter:"\ + "OMX_IndexParamCompBufferSupplier eRet"\ + "%08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamOtherInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + componentRole->nSize = component_Role.nSize; + componentRole->nVersion = component_Role.nVersion; + strlcpy((char *)componentRole->cRole, + (const char*)component_Role.cRole, + sizeof(componentRole->cRole)); + DEBUG_PRINT_ERROR("nSize = %d , nVersion = %d, cRole = %s\n", + component_Role.nSize, + component_Role.nVersion, + component_Role.cRole); + break; + + } + default: + { + DEBUG_PRINT_ERROR("unknown param %08x\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; + +} + +/** + @brief member function that set paramter from IL client + + @param hComp handle to component instance + @param paramIndex parameter type + @param paramData pointer to memory space which holds the paramter + @return error status + */ +OMX_ERRORTYPE omx_amr_aenc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("set_parameter is not in proper state\n"); + return OMX_ErrorIncorrectStateOperation; + } + if (paramData == NULL) + { + DEBUG_PRINT("param data is NULL"); + return OMX_ErrorBadParameter; + } + + switch (paramIndex) + { + case OMX_IndexParamAudioAmr: + { + DEBUG_PRINT("OMX_IndexParamAudioAmr"); + OMX_AUDIO_PARAM_AMRTYPE *amrparam + = (OMX_AUDIO_PARAM_AMRTYPE *) paramData; + memcpy(&m_amr_param,amrparam, + sizeof(OMX_AUDIO_PARAM_AMRTYPE)); + break; + } + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + if (((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources && + ((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == true)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == true))) + ||(((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == false)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == false)) && + (m_state != OMX_StateWaitForResources))) + { + DEBUG_PRINT("Set Parameter called in valid state\n"); + } else + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + DEBUG_PRINT("OMX_IndexParamPortDefinition portDefn->nPortIndex " + "= %u\n",portDefn->nPortIndex); + if (OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_INPUT_BUFFERS ) + { + m_inp_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_inp_act_buf_count =OMX_CORE_NUM_INPUT_BUFFERS; + } + input_buffer_size = portDefn->nBufferSize; + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_OUTPUT_BUFFERS ) + { + m_out_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_out_act_buf_count =OMX_CORE_NUM_OUTPUT_BUFFERS; + } + output_buffer_size = portDefn->nBufferSize; + } else + { + DEBUG_PRINT(" set_parameter: Bad Port idx %d",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamPriorityMgmt: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt\n"); + + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype + = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt %u\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT("set_parameter: priorityMgmtype %u\n", + priorityMgmtype->nGroupPriority); + + m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; + m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + case OMX_IndexParamAudioPortFormat: + { + + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPortFormat\n"); + + if (OMX_CORE_INPUT_PORT_INDEX== portFormatType->nPortIndex) + { + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + portFormatType->nPortIndex) + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioFormat:"\ + " %u\n", portFormatType->nIndex); + portFormatType->eEncoding = OMX_AUDIO_CodingAMR; + } else + { + DEBUG_PRINT_ERROR("set_parameter: Bad port index %d\n", \ + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("set_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("set_param: OMX_IndexParamCompBufferSupplier %d",\ + bufferSupplierType->eBufferSupplier); + + if (bufferSupplierType->nPortIndex == OMX_CORE_INPUT_PORT_INDEX + || bufferSupplierType->nPortIndex == + OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT("set_parameter:\ + OMX_IndexParamCompBufferSupplier\n"); + m_buffer_supplier.eBufferSupplier = + bufferSupplierType->eBufferSupplier; + } else + { + DEBUG_PRINT_ERROR("set_param:\ + IndexParamCompBufferSup %08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + + break; } + + case OMX_IndexParamAudioPcm: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPcm\n"); + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam + = (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(&m_pcm_param,pcmparam,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + DEBUG_PRINT("set_pcm_parameter: %u %u",\ + m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + } else + { + DEBUG_PRINT_ERROR("Set_parameter:OMX_IndexParamAudioPcm " + "OMX_ErrorBadPortIndex %d\n", + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamSuspensionPolicy: + { + eRet = OMX_ErrorNotImplemented; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + component_Role.nSize = componentRole->nSize; + component_Role.nVersion = componentRole->nVersion; + strlcpy((char *)component_Role.cRole, + (const char*)componentRole->cRole, + sizeof(component_Role.cRole)); + break; + } + + default: + { + DEBUG_PRINT_ERROR("unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *volume = + (OMX_AUDIO_CONFIG_VOLUMETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == volume->nPortIndex) + { + volume->nSize = (OMX_U32)sizeof(volume); + volume->nVersion.nVersion = OMX_SPEC_VERSION; + volume->bLinear = OMX_TRUE; + volume->sVolume.nValue = m_volume; + volume->sVolume.nMax = OMX_AENC_MAX; + volume->sVolume.nMin = OMX_AENC_MIN; + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = + (OMX_AUDIO_CONFIG_MUTETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == mute->nPortIndex) + { + mute->nSize = (OMX_U32)sizeof(mute); + mute->nVersion.nVersion = OMX_SPEC_VERSION; + mute->bMute = (BITMASK_PRESENT(&m_flags, + OMX_COMPONENT_MUTED)?OMX_TRUE:OMX_FALSE); + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Set Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if ( m_state == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *vol = + (OMX_AUDIO_CONFIG_VOLUMETYPE*)configData; + if (vol->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if ((vol->sVolume.nValue <= OMX_AENC_MAX) && + (vol->sVolume.nValue >= OMX_AENC_MIN)) + { + m_volume = vol->sVolume.nValue; + if (BITMASK_ABSENT(&m_flags, OMX_COMPONENT_MUTED)) + { + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + + } else + { + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = (OMX_AUDIO_CONFIG_MUTETYPE*) + configData; + if (mute->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if (mute->bMute == OMX_TRUE) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, 0); */ + } else + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. <TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::get_extension_index( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if((hComp == NULL) || (paramName == NULL) || (indexType == NULL)) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(strncmp(paramName,"OMX.Qualcomm.index.audio.sessionId", + strlen("OMX.Qualcomm.index.audio.sessionId")) == 0) + { + *indexType =(OMX_INDEXTYPE)QOMX_IndexParamAudioSessionId; + DEBUG_PRINT("Extension index type - %d\n", *indexType); + + } + else + { + return OMX_ErrorBadParameter; + + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::GetState + +DESCRIPTION + Returns the state information back to the caller.<TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + *state = m_state; + DEBUG_PRINT("Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. <TBD> + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::component_tunnel_request +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n"); + + if((hComp == NULL) || (peerComponent == NULL) || (tunnelSetup == NULL)) + { + port = port; + peerPort = peerPort; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::allocate_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + if(m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc((nBufSize + \ + sizeof(OMX_BUFFERHEADERTYPE)+sizeof(META_IN)) , 1); + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + free(buf_ptr); + return OMX_ErrorBadParameter; + } + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + sizeof(META_IN)+ + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + m_input_buf_hdrs.insert(bufHdr, NULL); + + m_inp_current_buf_count++; + DEBUG_PRINT("AIB:bufHdr %p bufHdr->pBuffer %p m_inp_buf_cnt=%d \ + bytes=%u", bufHdr, bufHdr->pBuffer,m_inp_current_buf_count, + bytes); + + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT("Input buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +OMX_ERRORTYPE omx_amr_aenc::allocate_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_out_current_buf_count < m_out_act_buf_count) + { + buf_ptr = (char *) calloc( (nBufSize + sizeof(OMX_BUFFERHEADERTYPE)),1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + DEBUG_PRINT("AOB::bufHdr %p bufHdr->pBuffer %p m_out_buf_cnt=%d"\ + "bytes=%u",bufHdr, bufHdr->pBuffer,\ + m_out_current_buf_count, bytes); + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_amr_aenc::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::allocate_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + // What if the client calls again. + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n", + (int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("allocate_buffer: before allocate_done \n"); + if (allocate_done()) + { + DEBUG_PRINT("allocate_buffer: after allocate_done \n"); + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("allocate_buffer: post idle transition event \n"); + } + DEBUG_PRINT("allocate_buffer: complete \n"); + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + m_out_bEnabled = OMX_TRUE; + + DEBUG_PRINT("AllocBuf-->is_out_th_sleep=%d\n",is_out_th_sleep); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("AllocBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("AB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + } + DEBUG_PRINT("Allocate Buffer exit with ret Code %d\n", eRet); + return eRet; +} + +/*============================================================================= +FUNCTION: + use_buffer + +DESCRIPTION: + OMX Use Buffer method implementation. + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_amr_aenc::use_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("Checking for Output Allocate buffer Done"); + if (allocate_done()) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("UseBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("UB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + } + } + DEBUG_PRINT("Use Buffer for port[%u] eRet[%d]\n", port,eRet); + return eRet; +} +/*============================================================================= +FUNCTION: + use_input_buffer + +DESCRIPTION: + Helper function for Use buffer in the input pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_amr_aenc::use_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if(bytes < input_buffer_size) + { + /* return if i\p buffer size provided by client + is less than min i\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + if (m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_input_buffer:bufHdr %p bufHdr->pBuffer %p \ + bytes=%u", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + input_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_input_buf_hdrs.insert(bufHdr, NULL); + m_inp_current_buf_count++; + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Input buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +/*============================================================================= +FUNCTION: + use_output_buffer + +DESCRIPTION: + Helper function for Use buffer in the output pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_amr_aenc::use_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (bytes < output_buffer_size) + { + /* return if o\p buffer size provided by client + is less than min o\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT("Inside omx_amr_aenc::use_output_buffer"); + if (m_out_current_buf_count < m_out_act_buf_count) + { + + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + DEBUG_PRINT("BufHdr=%p buffer=%p\n",bufHdr,buffer); + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_output_buffer:bufHdr %p bufHdr->pBuffer %p \ + len=%u", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + output_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_amr_aenc::search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_input_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_input_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_amr_aenc::search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_output_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_output_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +// Free Buffer - API call +/** + @brief member function that handles free buffer command from IL client + + This function is a block-call function that handles IL client request to + freeing the buffer + + @param hComp handle to component instance + @param port id of port which holds the buffer + @param buffer buffer header + @return Error status +*/ +OMX_ERRORTYPE omx_amr_aenc::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("Free_Buffer buf %p\n", buffer); + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT(" free buffer while Component in Loading pending\n"); + } else if ((m_inp_bEnabled == OMX_FALSE && + port == OMX_CORE_INPUT_PORT_INDEX)|| + (m_out_bEnabled == OMX_FALSE && + port == OMX_CORE_OUTPUT_PORT_INDEX)) + { + DEBUG_PRINT("Free Buffer while port %u disabled\n", port); + } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT("Invalid state to free buffer,ports need to be disabled:\ + OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return eRet; + } else + { + DEBUG_PRINT("free_buffer: Invalid state to free buffer,ports need to be\ + disabled:OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + if (m_inp_current_buf_count != 0) + { + m_inp_bPopulated = OMX_FALSE; + if (true == search_input_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:in_buffer[%p]\n",buffer); + m_input_buf_hdrs.erase(buffer); + free(buffer); + m_inp_current_buf_count--; + } else + { + DEBUG_PRINT_ERROR("Free_Buf:Error-->free_buffer, \ + Invalid Input buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + DEBUG_PRINT_ERROR("Error: free_buffer,Port Index calculation \ + came out Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_done(0)) + { + DEBUG_PRINT("INPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + if (m_out_current_buf_count != 0) + { + m_out_bPopulated = OMX_FALSE; + if (true == search_output_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:out_buffer[%p]\n",buffer); + m_output_buf_hdrs.erase(buffer); + free(buffer); + m_out_current_buf_count--; + } else + { + DEBUG_PRINT("Free_Buf:Error-->free_buffer , \ + Invalid Output buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_done(1)) + { + DEBUG_PRINT("OUTPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + if ((OMX_ErrorNone == eRet) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if (release_done(-1)) + { + if(ioctl(m_drv_fd, AUDIO_STOP, 0) < 0) + DEBUG_PRINT_ERROR("AUDIO STOP in free buffer failed\n"); + else + DEBUG_PRINT("AUDIO STOP in free buffer passed\n"); + + + DEBUG_PRINT("Free_Buf: Free buffer\n"); + + + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + DEBUG_PRINT("Before OMX_StateLoaded \ + OMX_COMPONENT_GENERATE_EVENT\n"); + post_command(OMX_CommandStateSet, + OMX_StateLoaded,OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("After OMX_StateLoaded OMX_COMPONENT_GENERATE_EVENT\n"); + + } + } + return eRet; +} + + +/** + @brief member function that that handles empty this buffer command + + This function meremly queue up the command and data would be consumed + in command server thread context + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_amr_aenc::empty_this_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("ETB:Buf:%p Len %u TS %lld numInBuf=%d\n", \ + buffer, buffer->nFilledLen, buffer->nTimeStamp, (nNumInputBuf)); + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (!m_inp_bEnabled) + { + DEBUG_PRINT("empty_this_buffer OMX_ErrorIncorrectStateOperation "\ + "Port Status %d \n", m_inp_bEnabled); + return OMX_ErrorIncorrectStateOperation; + } + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_amr_aenc::etb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_amr_aenc::etb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + if ((m_state != OMX_StateExecuting) && + (m_state != OMX_StatePause)) + { + DEBUG_PRINT_ERROR("Invalid state\n"); + eRet = OMX_ErrorInvalidState; + } + if (OMX_ErrorNone == eRet) + { + if (search_input_bufhdr(buffer) == true) + { + post_input((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_ETB); + } else + { + DEBUG_PRINT_ERROR("Bad header %p \n", buffer); + eRet = OMX_ErrorBadParameter; + } + } + pthread_mutex_lock(&in_buf_count_lock); + nNumInputBuf++; + m_amr_pb_stats.etb_cnt++; + pthread_mutex_unlock(&in_buf_count_lock); + return eRet; +} +/** + @brief member function that writes data to kernel driver + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_amr_aenc::empty_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + META_IN meta_in; + //Pointer to the starting location of the data to be transcoded + OMX_U8 *srcStart; + //The total length of the data to be transcoded + srcStart = buffer->pBuffer; + OMX_U8 *data = NULL; + PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer); + memset(&meta_in,0,sizeof(meta_in)); + if ( search_input_bufhdr(buffer) == false ) + { + DEBUG_PRINT("ETBP: INVALID BUF HDR\n"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorBadParameter; + } + if (m_tmp_meta_buf) + { + data = m_tmp_meta_buf; + + // copy the metadata info from the BufHdr and insert to payload + meta_in.offsetVal = (OMX_U16)sizeof(META_IN); + meta_in.nTimeStamp.LowPart = + (unsigned int)((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp)& 0xFFFFFFFF); + meta_in.nTimeStamp.HighPart = + (unsigned int) (((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) >> 32) & 0xFFFFFFFF); + meta_in.nFlags &= ~OMX_BUFFERFLAG_EOS; + if(buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + DEBUG_PRINT("EOS OCCURED \n"); + meta_in.nFlags |= OMX_BUFFERFLAG_EOS; + } + memcpy(data,&meta_in, meta_in.offsetVal); + DEBUG_PRINT("meta_in.nFlags = %d\n",meta_in.nFlags); + } + + memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen); + write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN)); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (OMX_StateExecuting == state) + { + DEBUG_DETAIL("In Exe state, EBD CB"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + } else + { + /* Assume empty this buffer function has already checked + validity of buffer */ + DEBUG_PRINT("Empty buffer %p to kernel driver\n", buffer); + post_input((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_BUFFER_DONE); + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_amr_aenc::fill_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + ENC_META_OUT *meta_out = NULL; + ssize_t nReadbytes = 0; + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (true == search_output_bufhdr(buffer)) + { + DEBUG_PRINT("\nBefore Read..m_drv_fd = %d,\n",m_drv_fd); + nReadbytes = read(m_drv_fd,buffer->pBuffer,output_buffer_size ); + DEBUG_DETAIL("FTBP->Al_len[%lu]buf[%p]size[%d]numOutBuf[%d]\n",\ + buffer->nAllocLen,buffer->pBuffer, + nReadbytes,nNumOutputBuf); + if (nReadbytes <= 0) { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorNone; + } else + DEBUG_PRINT("Read bytes %d\n",nReadbytes); + // Buffer from Driver will have + // 1 byte => Nr of frame field + // (sizeof(ENC_META_OUT) * Nr of frame) bytes => meta_out->offset_to_frame + // Frame Size * Nr of frame => + + meta_out = (ENC_META_OUT *)(buffer->pBuffer + sizeof(unsigned char)); + buffer->nTimeStamp = (((OMX_TICKS)meta_out->msw_ts << 32)+ + meta_out->lsw_ts); + buffer->nFlags |= meta_out->nflags; + buffer->nOffset = (OMX_U32)(meta_out->offset_to_frame + + sizeof(unsigned char)); + buffer->nFilledLen = (OMX_U32)(nReadbytes - buffer->nOffset); + ts += FRAMEDURATION; + buffer->nTimeStamp = ts; + nTimestamp = buffer->nTimeStamp; + DEBUG_PRINT("nflags %d frame_size %d offset_to_frame %d \ + timestamp %lld\n", meta_out->nflags, meta_out->frame_size, + meta_out->offset_to_frame, buffer->nTimeStamp); + + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + DEBUG_PRINT("FTBP: Now, Send EOS flag to Client \n"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + } + + return OMX_ErrorNone; + } + DEBUG_PRINT("nState %d \n",nState ); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (state == OMX_StatePause) + { + DEBUG_PRINT("FTBP:Post the FBD to event thread currstate=%d\n",\ + state); + post_output((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_FRAME_DONE); + } + else + { + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + + } + + } + else + DEBUG_PRINT("\n FTBP-->Invalid buffer in FTB \n"); + + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + + + +PARAMETERS + + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::fill_this_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_amr_aenc::ftb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (m_out_bEnabled == OMX_FALSE) + { + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_amr_aenc::ftb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf++; + m_amr_pb_stats.ftb_cnt++; + DEBUG_DETAIL("FTB:nNumOutputBuf is %d", nNumOutputBuf); + pthread_mutex_unlock(&out_buf_count_lock); + post_output((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_FTB); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + m_cb = *callbacks; + m_app_data = appData; + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateLoaded != m_state && OMX_StateInvalid != m_state) + { + DEBUG_PRINT_ERROR("Warning: Rxed DeInit when not in LOADED state %d\n", + m_state); + } + deinit_encoder(); + +DEBUG_PRINT_ERROR("%s:COMPONENT DEINIT...\n", __FUNCTION__); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::deinit_encoder + +DESCRIPTION + Closes all the threads and release memory allocated to the heap. + +PARAMETERS + None. + +RETURN VALUE + None. + +========================================================================== */ +void omx_amr_aenc::deinit_encoder() +{ + DEBUG_PRINT("Component-deinit being processed\n"); + DEBUG_PRINT("********************************\n"); + DEBUG_PRINT("STATS: in-buf-len[%u]out-buf-len[%u] tot-pb-time[%lld]",\ + m_amr_pb_stats.tot_in_buf_len, + m_amr_pb_stats.tot_out_buf_len, + m_amr_pb_stats.tot_pb_time); + DEBUG_PRINT("STATS: fbd-cnt[%u]ftb-cnt[%u]etb-cnt[%u]ebd-cnt[%u]",\ + m_amr_pb_stats.fbd_cnt,m_amr_pb_stats.ftb_cnt, + m_amr_pb_stats.etb_cnt, + m_amr_pb_stats.ebd_cnt); + memset(&m_amr_pb_stats,0,sizeof(AMR_PB_STATS)); + + if((OMX_StateLoaded != m_state) && (OMX_StateInvalid != m_state)) + { + DEBUG_PRINT_ERROR("%s,Deinit called in state[%d]\n",__FUNCTION__,\ + m_state); + // Get back any buffers from driver + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + // force state change to loaded so that all threads can be exited + pthread_mutex_lock(&m_state_lock); + m_state = OMX_StateLoaded; + pthread_mutex_unlock(&m_state_lock); + DEBUG_PRINT_ERROR("Freeing Buf:inp_current_buf_count[%d][%d]\n",\ + m_inp_current_buf_count, + m_input_buf_hdrs.size()); + m_input_buf_hdrs.eraseall(); + DEBUG_PRINT_ERROR("Freeing Buf:out_current_buf_count[%d][%d]\n",\ + m_out_current_buf_count, + m_output_buf_hdrs.size()); + m_output_buf_hdrs.eraseall(); + + } + if(pcm_input) + { + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("Deinit:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + if(pcm_input) + { + if (m_ipc_to_in_th != NULL) + { + omx_amr_thread_stop(m_ipc_to_in_th); + m_ipc_to_in_th = NULL; + } + } + + if (m_ipc_to_cmd_th != NULL) + { + omx_amr_thread_stop(m_ipc_to_cmd_th); + m_ipc_to_cmd_th = NULL; + } + if (m_ipc_to_out_th != NULL) + { + DEBUG_DETAIL("Inside omx_amr_thread_stop\n"); + omx_amr_thread_stop(m_ipc_to_out_th); + m_ipc_to_out_th = NULL; + } + + + if(ioctl(m_drv_fd, AUDIO_STOP, 0) <0) + DEBUG_PRINT_ERROR("De-init: AUDIO_STOP FAILED\n"); + + if(pcm_input && m_tmp_meta_buf ) + { + free(m_tmp_meta_buf); + } + + if(m_tmp_out_meta_buf) + { + free(m_tmp_out_meta_buf); + } + nNumInputBuf = 0; + nNumOutputBuf = 0; + bFlushinprogress = 0; + + m_inp_current_buf_count=0; + m_out_current_buf_count=0; + m_out_act_buf_count = 0; + m_inp_act_buf_count = 0; + m_inp_bEnabled = OMX_FALSE; + m_out_bEnabled = OMX_FALSE; + m_inp_bPopulated = OMX_FALSE; + m_out_bPopulated = OMX_FALSE; + nTimestamp = 0; + ts = 0; + + if ( m_drv_fd >= 0 ) + { + if(close(m_drv_fd) < 0) + DEBUG_PRINT("De-init: Driver Close Failed \n"); + m_drv_fd = -1; + } + else + { + DEBUG_PRINT_ERROR(" AMR device already closed\n"); + } + m_comp_deinit=1; + m_is_out_th_sleep = 1; + m_is_in_th_sleep = 1; + DEBUG_PRINT("************************************\n"); + DEBUG_PRINT(" DEINIT COMPLETED"); + DEBUG_PRINT("************************************\n"); + +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation <TBD>. + +PARAMETERS + <TBD>. + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::use_EGL_image +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + DEBUG_PRINT_ERROR("Error : use_EGL_image: Not Implemented \n"); + + if((hComp == NULL) || (appData == NULL) || (eglImage == NULL)) + { + bufferHdr = bufferHdr; + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_amr_aenc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_amr_aenc::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + const char *cmp_role = "audio_encoder.amr"; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (index == 0 && role) + { + memcpy(role, cmp_role, strlen(cmp_role)); + *(((char *) role) + strlen(cmp_role) +1) = '\0'; + } else + { + eRet = OMX_ErrorNoMore; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_amr_aenc::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_amr_aenc::allocate_done(void) +{ + OMX_BOOL bRet = OMX_FALSE; + if (pcm_input==1) + { + if ((m_inp_act_buf_count == m_inp_current_buf_count) + &&(m_out_act_buf_count == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + + } + if ((m_inp_act_buf_count == m_inp_current_buf_count) && m_inp_bEnabled ) + { + m_inp_bPopulated = OMX_TRUE; + } + + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + } else if (pcm_input==0) + { + if (m_out_act_buf_count == m_out_current_buf_count) + { + bRet=OMX_TRUE; + + } + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + + } + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_amr_aenc::ReleaseDone + +DESCRIPTION + Checks if IL client has released all the buffers. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_amr_aenc::release_done(OMX_U32 param1) +{ + DEBUG_PRINT("Inside omx_amr_aenc::release_done"); + OMX_BOOL bRet = OMX_FALSE; + + if (param1 == OMX_ALL) + { + if ((0 == m_inp_current_buf_count)&&(0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_INPUT_PORT_INDEX ) + { + if ((0 == m_inp_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_OUTPUT_PORT_INDEX) + { + if ((0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } + return bRet; +} diff --git a/msm8909/mm-audio/aenc-amrnb/qdsp6/test/omx_amr_enc_test.c b/msm8909/mm-audio/aenc-amrnb/qdsp6/test/omx_amr_enc_test.c new file mode 100644 index 00000000..e5097484 --- /dev/null +++ b/msm8909/mm-audio/aenc-amrnb/qdsp6/test/omx_amr_enc_test.c @@ -0,0 +1,1055 @@ + +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + + +/* + An Open max test application .... +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <time.h> +#include <sys/ioctl.h> +#include "OMX_Core.h" +#include "OMX_Component.h" +#include "pthread.h" +#include <signal.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdint.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include<unistd.h> +#include<string.h> +#include <pthread.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#ifdef AUDIOV2 +#include "control.h" +#endif + + +#include <linux/ioctl.h> + +typedef unsigned char uint8; +typedef unsigned char byte; +typedef unsigned int uint32; +typedef unsigned int uint16; +QOMX_AUDIO_STREAM_INFO_DATA streaminfoparam; +/* maximum ADTS frame header length */ +void Release_Encoder(); + +#ifdef AUDIOV2 +unsigned short session_id; +int device_id; +int control = 0; +const char *device="handset_tx"; +#define DIR_TX 2 +#endif + +uint32_t samplerate = 8000; +uint32_t channels = 1; +uint32_t bandmode = 7; +uint32_t dtxenable = 0; +uint32_t rectime = 0; +uint32_t recpath = 0; +uint32_t pcmplayback = 0; +uint32_t tunnel = 0; +uint32_t format = 1; +#define DEBUG_PRINT printf +unsigned to_idle_transition = 0; +unsigned long total_pcm_bytes; + +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ +#define false 0 +#define true 1 + +#define CONFIG_VERSION_SIZE(param) \ + param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ + param.nSize = sizeof(param); + +#define MIN_BITRATE 4 /* Bit rate 1 - 13.6 , 2 - 6.2 , 3 - 2.7 , 4 - 1.0 kbps*/ +#define MAX_BITRATE 4 +#define AMR_HEADER_SIZE 6 +#define FAILED(result) (result != OMX_ErrorNone) + +#define SUCCEEDED(result) (result == OMX_ErrorNone) + +/************************************************************************/ +/* GLOBAL DECLARATIONS */ +/************************************************************************/ + +pthread_mutex_t lock; +pthread_cond_t cond; +pthread_mutex_t elock; +pthread_cond_t econd; +pthread_cond_t fcond; +pthread_mutex_t etb_lock; +pthread_mutex_t etb_lock1; +pthread_cond_t etb_cond; +FILE * inputBufferFile; +FILE * outputBufferFile; +OMX_PARAM_PORTDEFINITIONTYPE inputportFmt; +OMX_PARAM_PORTDEFINITIONTYPE outputportFmt; +OMX_AUDIO_PARAM_AMRTYPE amrparam; +OMX_AUDIO_PARAM_PCMMODETYPE pcmparam; +OMX_PORT_PARAM_TYPE portParam; +OMX_PORT_PARAM_TYPE portFmt; +OMX_ERRORTYPE error; + + + + +#define ID_RIFF 0x46464952 +#define ID_WAVE 0x45564157 +#define ID_FMT 0x20746d66 +#define ID_DATA 0x61746164 + +#define FORMAT_PCM 1 + +struct wav_header { + uint32_t riff_id; + uint32_t riff_sz; + uint32_t riff_fmt; + uint32_t fmt_id; + uint32_t fmt_sz; + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */ + uint16_t block_align; /* num_channels * bps / 8 */ + uint16_t bits_per_sample; + uint32_t data_id; + uint32_t data_sz; +}; +struct enc_meta_out{ + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; +} __attribute__ ((packed)); + +struct qcp_header { + /* RIFF Section */ + char riff[4]; + unsigned int s_riff; + char qlcm[4]; + + /* Format chunk */ + char fmt[4]; + unsigned int s_fmt; + char mjr; + char mnr; + unsigned int data1; /* UNIQUE ID of the codec */ + unsigned short data2; + unsigned short data3; + char data4[8]; + unsigned short ver; /* Codec Info */ + char name[80]; + unsigned short abps; /* average bits per sec of the codec */ + unsigned short bytes_per_pkt; + unsigned short samp_per_block; + unsigned short samp_per_sec; + unsigned short bits_per_samp; + unsigned char vr_num_of_rates; /* Rate Header fmt info */ + unsigned char rvd1[3]; + unsigned short vr_bytes_per_pkt[8]; + unsigned int rvd2[5]; + + /* Vrat chunk */ + unsigned char vrat[4]; + unsigned int s_vrat; + unsigned int v_rate; + unsigned int size_in_pkts; + + /* Data chunk */ + unsigned char data[4]; + unsigned int s_data; +} __attribute__ ((packed)); + +static int totaldatalen = 0; +static int framecnt = 0; +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +unsigned int input_buf_cnt = 0; +unsigned int output_buf_cnt = 0; +int used_ip_buf_cnt = 0; +volatile int event_is_done = 0; +volatile int ebd_event_is_done = 0; +volatile int fbd_event_is_done = 0; +volatile int etb_event_is_done = 0; +int ebd_cnt; +int bInputEosReached = 0; +int bOutputEosReached = 0; +int bInputEosReached_tunnel = 0; +static int etb_done = 0; +int bFlushing = false; +int bPause = false; +const char *in_filename; +const char *out_filename; + +int timeStampLfile = 0; +int timestampInterval = 100; + +//* OMX Spec Version supported by the wrappers. Version = 1.1 */ +const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; +OMX_COMPONENTTYPE* amr_enc_handle = 0; + +OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; +OMX_BUFFERHEADERTYPE **pOutputBufHdrs = NULL; + +/************************************************************************/ +/* GLOBAL FUNC DECL */ +/************************************************************************/ +int Init_Encoder(char*); +int Play_Encoder(); +OMX_STRING aud_comp; +/**************************************************************************/ +/* STATIC DECLARATIONS */ +/**************************************************************************/ + +static int open_audio_file (); +static int Read_Buffer(OMX_BUFFERHEADERTYPE *pBufHdr ); +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *amr_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize); + + +static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); +static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + +static OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); +static OMX_ERRORTYPE parse_pcm_header(); +void wait_for_event(void) +{ + pthread_mutex_lock(&lock); + DEBUG_PRINT("%s: event_is_done=%d", __FUNCTION__, event_is_done); + while (event_is_done == 0) { + pthread_cond_wait(&cond, &lock); + } + event_is_done = 0; + pthread_mutex_unlock(&lock); +} + +void event_complete(void ) +{ + pthread_mutex_lock(&lock); + if (event_is_done == 0) { + event_is_done = 1; + pthread_cond_broadcast(&cond); + } + pthread_mutex_unlock(&lock); +} + +void etb_wait_for_event(void) +{ + pthread_mutex_lock(&etb_lock1); + DEBUG_PRINT("%s: etb_event_is_done=%d", __FUNCTION__, etb_event_is_done); + while (etb_event_is_done == 0) { + pthread_cond_wait(&etb_cond, &etb_lock1); + } + etb_event_is_done = 0; + pthread_mutex_unlock(&etb_lock1); +} + +void etb_event_complete(void ) +{ + pthread_mutex_lock(&etb_lock1); + if (etb_event_is_done == 0) { + etb_event_is_done = 1; + pthread_cond_broadcast(&etb_cond); + } + pthread_mutex_unlock(&etb_lock1); +} + + +OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ + DEBUG_PRINT("Function %s \n", __FUNCTION__); + + /* To remove warning for unused variable to keep prototype same */ + (void)hComponent; + (void)pAppData; + (void)pEventData; + switch(eEvent) { + case OMX_EventCmdComplete: + DEBUG_PRINT("\n OMX_EventCmdComplete event=%d data1=%u data2=%u\n",(OMX_EVENTTYPE)eEvent, + nData1,nData2); + event_complete(); + break; + case OMX_EventError: + DEBUG_PRINT("\n OMX_EventError \n"); + break; + case OMX_EventBufferFlag: + DEBUG_PRINT("\n OMX_EventBufferFlag \n"); + bOutputEosReached = true; + event_complete(); + break; + case OMX_EventPortSettingsChanged: + DEBUG_PRINT("\n OMX_EventPortSettingsChanged \n"); + break; + default: + DEBUG_PRINT("\n Unknown Event \n"); + break; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + size_t bytes_writen = 0; + size_t total_bytes_writen = 0; + size_t len = 0; + struct enc_meta_out *meta = NULL; + OMX_U8 *src = pBuffer->pBuffer; + unsigned int num_of_frames = 1; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + if(((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + DEBUG_PRINT("FBD::EOS on output port\n "); + bOutputEosReached = true; + return OMX_ErrorNone; + } + if(bInputEosReached_tunnel || bOutputEosReached) + { + DEBUG_PRINT("EOS REACHED NO MORE PROCESSING OF BUFFERS\n"); + return OMX_ErrorNone; + } + if(num_of_frames != src[0]){ + + printf("Data corrupt\n"); + return OMX_ErrorNone; + } + /* Skip the first bytes */ + + + + src += sizeof(unsigned char); + meta = (struct enc_meta_out *)src; + while (num_of_frames > 0) { + meta = (struct enc_meta_out *)src; + /*printf("offset=%d framesize=%d encoded_pcm[%d] msw_ts[%d]lsw_ts[%d] nflags[%d]\n", + meta->offset_to_frame, + meta->frame_size, + meta->encoded_pcm_samples, meta->msw_ts, meta->lsw_ts, meta->nflags);*/ + len = meta->frame_size; + + bytes_writen = fwrite(pBuffer->pBuffer + sizeof(unsigned char) + meta->offset_to_frame,1,len,outputBufferFile); + if(bytes_writen < len) + { + DEBUG_PRINT("error: invalid AMR encoded data \n"); + return OMX_ErrorNone; + } + src += sizeof(struct enc_meta_out); + num_of_frames--; + total_bytes_writen += len; + } + DEBUG_PRINT(" FillBufferDone size writen to file %zu count %d\n",total_bytes_writen, framecnt); + totaldatalen = totaldatalen + (int)total_bytes_writen; + framecnt++; + + DEBUG_PRINT(" FBD calling FTB\n"); + OMX_FillThisBuffer(hComponent,pBuffer); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + int readBytes =0; + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + ebd_cnt++; + used_ip_buf_cnt--; + pthread_mutex_lock(&etb_lock); + if(!etb_done) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT("Wait till first set of buffers are given to component\n"); + DEBUG_PRINT("\n*********************************************\n"); + etb_done++; + pthread_mutex_unlock(&etb_lock); + etb_wait_for_event(); + } + else + { + pthread_mutex_unlock(&etb_lock); + } + + + if(bInputEosReached) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT(" EBD::EOS on input port\n "); + DEBUG_PRINT("*********************************************\n"); + return OMX_ErrorNone; + }else if (bFlushing == true) { + DEBUG_PRINT("omx_amr_adec_test: bFlushing is set to TRUE used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + if (used_ip_buf_cnt == 0) { + bFlushing = false; + } else { + DEBUG_PRINT("omx_amr_adec_test: more buffer to come back used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + return OMX_ErrorNone; + } + } + + if((readBytes = Read_Buffer(pBuffer)) > 0) { + pBuffer->nFilledLen = (OMX_U32)readBytes; + used_ip_buf_cnt++; + OMX_EmptyThisBuffer(hComponent,pBuffer); + } + else{ + pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + used_ip_buf_cnt++; + bInputEosReached = true; + pBuffer->nFilledLen = 0; + OMX_EmptyThisBuffer(hComponent,pBuffer); + DEBUG_PRINT("EBD..Either EOS or Some Error while reading file\n"); + } + return OMX_ErrorNone; +} + +void signal_handler(int sig_id) { + + /* Flush */ + if (sig_id == SIGUSR1) { + DEBUG_PRINT("%s Initiate flushing\n", __FUNCTION__); + bFlushing = true; + OMX_SendCommand(amr_enc_handle, OMX_CommandFlush, OMX_ALL, NULL); + } else if (sig_id == SIGUSR2) { + if (bPause == true) { + DEBUG_PRINT("%s resume record\n", __FUNCTION__); + bPause = false; + OMX_SendCommand(amr_enc_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); + } else { + DEBUG_PRINT("%s pause record\n", __FUNCTION__); + bPause = true; + OMX_SendCommand(amr_enc_handle, OMX_CommandStateSet, OMX_StatePause, NULL); + } + } +} + +int main(int argc, char **argv) +{ + unsigned int bufCnt=0; + OMX_ERRORTYPE result; + + struct sigaction sa; + char amr_header[6] = {0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A}; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = &signal_handler; + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGUSR2, &sa, NULL); + + (void) signal(SIGINT, Release_Encoder); + + pthread_cond_init(&cond, 0); + pthread_mutex_init(&lock, 0); + pthread_cond_init(&etb_cond, 0); + pthread_mutex_init(&etb_lock, 0); + pthread_mutex_init(&etb_lock1, 0); + + if (argc >= 8) { + in_filename = argv[1]; + out_filename = argv[2]; + tunnel = (uint32_t)atoi(argv[3]); + bandmode = (uint32_t)atoi(argv[4]); + dtxenable = (uint32_t)atoi(argv[5]); + recpath = (uint32_t)atoi(argv[6]); // No configuration support yet.. + rectime = (uint32_t)atoi(argv[7]); + + } else { + DEBUG_PRINT(" invalid format: \n"); + DEBUG_PRINT("ex: ./mm-aenc-omxamr-test INPUTFILE OUTPUTFILE Tunnel BANDMODE DTXENABLE RECORDPATH RECORDTIME\n"); + DEBUG_PRINT("Bandmode 1-7, dtxenable 0-1\n"); + DEBUG_PRINT("RECORDPATH 0(TX),1(RX),2(BOTH),3(MIC)\n"); + DEBUG_PRINT("RECORDTIME in seconds for AST Automation\n"); + return 0; + } + if(recpath != 3) { + DEBUG_PRINT("For RECORDPATH Only MIC supported\n"); + return 0; + } + if(tunnel == 0) + aud_comp = "OMX.qcom.audio.encoder.amrnb"; + else + aud_comp = "OMX.qcom.audio.encoder.tunneled.amrnb"; + if(Init_Encoder(aud_comp)!= 0x00) + { + DEBUG_PRINT("Decoder Init failed\n"); + return -1; + } + + fcntl(0, F_SETFL, O_NONBLOCK); + + if(Play_Encoder() != 0x00) + { + DEBUG_PRINT("Play_Decoder failed\n"); + return -1; + } + + // Wait till EOS is reached... + if(rectime && tunnel) + { + sleep(rectime); + rectime = 0; + bInputEosReached_tunnel = 1; + DEBUG_PRINT("\EOS ON INPUT PORT\n"); + } + else + { + wait_for_event(); + } + + if((bInputEosReached_tunnel) || ((bOutputEosReached) && !tunnel)) + { + + DEBUG_PRINT("\nMoving the decoder to idle state \n"); + OMX_SendCommand(amr_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + wait_for_event(); + + DEBUG_PRINT("\nMoving the encoder to loaded state \n"); + OMX_SendCommand(amr_enc_handle, OMX_CommandStateSet, OMX_StateLoaded,0); + sleep(1); + if (!tunnel) + { + DEBUG_PRINT("\nFillBufferDone: Deallocating i/p buffers \n"); + for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(amr_enc_handle, 0, pInputBufHdrs[bufCnt]); + } + } + + DEBUG_PRINT ("\nFillBufferDone: Deallocating o/p buffers \n"); + for(bufCnt=0; bufCnt < output_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(amr_enc_handle, 1, pOutputBufHdrs[bufCnt]); + } + wait_for_event(); + fseek(outputBufferFile, 0,SEEK_SET); + fwrite(amr_header,1,AMR_HEADER_SIZE,outputBufferFile); + + result = OMX_FreeHandle(amr_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + if(tunnel) + { + #ifdef AUDIOV2 + if (msm_route_stream(DIR_TX,session_id,device_id, 0)) + { + DEBUG_PRINT("\ncould not set stream routing\n"); + return -1; + } + if (msm_en_device(device_id, 0)) + { + DEBUG_PRINT("\ncould not enable device\n"); + return -1; + } + msm_mixer_close(); + #endif + } + OMX_Deinit(); + ebd_cnt=0; + bOutputEosReached = false; + bInputEosReached_tunnel = false; + bInputEosReached = 0; + amr_enc_handle = NULL; + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + fclose(outputBufferFile); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...AMR ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + } + return 0; +} + +void Release_Encoder() +{ + static int cnt=0; + OMX_ERRORTYPE result; + + DEBUG_PRINT("END OF AMR ENCODING: EXITING PLEASE WAIT\n"); + bInputEosReached_tunnel = 1; + event_complete(); + cnt++; + if(cnt > 1) + { + /* FORCE RESET */ + amr_enc_handle = NULL; + ebd_cnt=0; + bInputEosReached_tunnel = false; + + result = OMX_FreeHandle(amr_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + + OMX_Deinit(); + + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...AMR ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + exit(0); + } +} + +int Init_Encoder(OMX_STRING audio_component) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE omxresult; + OMX_U32 total = 0; + typedef OMX_U8* OMX_U8_PTR; + char *role ="audio_encoder"; + + static OMX_CALLBACKTYPE call_back = { + &EventHandler,&EmptyBufferDone,&FillBufferDone + }; + + /* Init. the OpenMAX Core */ + DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); + omxresult = OMX_Init(); + + if(OMX_ErrorNone != omxresult) { + DEBUG_PRINT("\n Failed to Init OpenMAX core"); + return -1; + } + else { + DEBUG_PRINT("\nOpenMAX Core Init Done\n"); + } + + /* Query for audio decoders*/ + DEBUG_PRINT("Amr_test: Before entering OMX_GetComponentOfRole"); + OMX_GetComponentsOfRole(role, &total, 0); + DEBUG_PRINT ("\nTotal components of role=%s :%u", role, total); + + + omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&amr_enc_handle), + (OMX_STRING)audio_component, NULL, &call_back); + if (FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to Load the component:%s\n", audio_component); + return -1; + } + else + { + DEBUG_PRINT("\nComponent %s is in LOADED state\n", audio_component); + } + + /* Get the port information */ + CONFIG_VERSION_SIZE(portParam); + omxresult = OMX_GetParameter(amr_enc_handle, OMX_IndexParamAudioInit, + (OMX_PTR)&portParam); + + if(FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to get Port Param\n"); + return -1; + } + else + { + DEBUG_PRINT("\nportParam.nPorts:%u\n", portParam.nPorts); + DEBUG_PRINT("\nportParam.nStartPortNumber:%u\n", + portParam.nStartPortNumber); + } + + if(OMX_ErrorNone != omxresult) + { + DEBUG_PRINT("Set parameter failed"); + } + + return 0; +} + +int Play_Encoder() +{ + unsigned int i; + int Size=0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE ret; + OMX_INDEXTYPE index; +#ifdef __LP64__ + DEBUG_PRINT("sizeof[%ld]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#else + DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#endif + + /* open the i/p and o/p files based on the video file format passed */ + if(open_audio_file()) { + DEBUG_PRINT("\n Returning -1"); + return -1; + } + + /* Query the encoder input min buf requirements */ + CONFIG_VERSION_SIZE(inputportFmt); + + /* Port for which the Client needs to obtain info */ + inputportFmt.nPortIndex = portParam.nStartPortNumber; + + OMX_GetParameter(amr_enc_handle,OMX_IndexParamPortDefinition,&inputportFmt); + DEBUG_PRINT ("\nEnc Input Buffer Count %u\n", inputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Input Buffer Size %u\n", inputportFmt.nBufferSize); + + if(OMX_DirInput != inputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Input Port\n"); + return -1; + } + + pcmparam.nPortIndex = 0; + pcmparam.nChannels = channels; + pcmparam.nSamplingRate = samplerate; + OMX_SetParameter(amr_enc_handle,OMX_IndexParamAudioPcm,&pcmparam); + + + /* Query the encoder outport's min buf requirements */ + CONFIG_VERSION_SIZE(outputportFmt); + /* Port for which the Client needs to obtain info */ + outputportFmt.nPortIndex = portParam.nStartPortNumber + 1; + + OMX_GetParameter(amr_enc_handle,OMX_IndexParamPortDefinition,&outputportFmt); + DEBUG_PRINT ("\nEnc: Output Buffer Count %u\n", outputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Output Buffer Size %u\n", outputportFmt.nBufferSize); + + if(OMX_DirOutput != outputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Output Port\n"); + return -1; + } + + + CONFIG_VERSION_SIZE(amrparam); + + amrparam.nPortIndex = 1; + amrparam.nChannels = channels; //2 ; /* 1-> mono 2-> stereo*/ + amrparam.eAMRBandMode = bandmode; + amrparam.eAMRDTXMode = dtxenable; + OMX_SetParameter(amr_enc_handle,OMX_IndexParamAudioAmr,&amrparam); + OMX_GetExtensionIndex(amr_enc_handle,"OMX.Qualcomm.index.audio.sessionId",&index); + OMX_GetParameter(amr_enc_handle,index,&streaminfoparam); + if(tunnel) { + #ifdef AUDIOV2 + session_id = streaminfoparam.sessionId; + control = msm_mixer_open("/dev/snd/controlC0", 0); + if(control < 0) + printf("ERROR opening the device\n"); + device_id = msm_get_device(device); + DEBUG_PRINT ("\ndevice_id = %d\n",device_id); + DEBUG_PRINT("\nsession_id = %d\n",session_id); + if (msm_en_device(device_id, 1)) + { + perror("could not enable device\n"); + return -1; + } + if (msm_route_stream(DIR_TX,session_id,device_id, 1)) + { + perror("could not set stream routing\n"); + return -1; + } + #endif + } + + DEBUG_PRINT ("\nOMX_SendCommand Encoder -> IDLE\n"); + OMX_SendCommand(amr_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + /* wait_for_event(); should not wait here event complete status will + not come until enough buffer are allocated */ + if (tunnel == 0) + { + input_buf_cnt = inputportFmt.nBufferCountActual; // inputportFmt.nBufferCountMin + 5; + DEBUG_PRINT("Transition to Idle State succesful...\n"); + /* Allocate buffer on decoder's i/p port */ + error = Allocate_Buffer(amr_enc_handle, &pInputBufHdrs, inputportFmt.nPortIndex, + input_buf_cnt, inputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pInputBufHdrs == NULL ) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer success\n"); + } + } + output_buf_cnt = outputportFmt.nBufferCountMin ; + + /* Allocate buffer on encoder's O/Pp port */ + error = Allocate_Buffer(amr_enc_handle, &pOutputBufHdrs, outputportFmt.nPortIndex, + output_buf_cnt, outputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pOutputBufHdrs == NULL ) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer success\n"); + } + + wait_for_event(); + + + if (tunnel == 1) + { + DEBUG_PRINT ("\nOMX_SendCommand to enable TUNNEL MODE during IDLE\n"); + OMX_SendCommand(amr_enc_handle, OMX_CommandPortDisable,0,0); // disable input port + wait_for_event(); + } + + DEBUG_PRINT ("\nOMX_SendCommand encoder -> Executing\n"); + OMX_SendCommand(amr_enc_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + + DEBUG_PRINT(" Start sending OMX_FILLthisbuffer\n"); + + for(i=0; i < output_buf_cnt; i++) { + DEBUG_PRINT ("\nOMX_FillThisBuffer on output buf no.%d\n",i); + pOutputBufHdrs[i]->nOutputPortIndex = 1; + pOutputBufHdrs[i]->nFlags = pOutputBufHdrs[i]->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + ret = OMX_FillThisBuffer(amr_enc_handle, pOutputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_FillThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_FillThisBuffer success!\n"); + } + } + +if(tunnel == 0) +{ + DEBUG_PRINT(" Start sending OMX_emptythisbuffer\n"); + for (i = 0;i < input_buf_cnt;i++) { + DEBUG_PRINT ("\nOMX_EmptyThisBuffer on Input buf no.%d\n",i); + pInputBufHdrs[i]->nInputPortIndex = 0; + Size = Read_Buffer(pInputBufHdrs[i]); + if(Size <=0 ){ + DEBUG_PRINT("NO DATA READ\n"); + bInputEosReached = true; + pInputBufHdrs[i]->nFlags= OMX_BUFFERFLAG_EOS; + } + pInputBufHdrs[i]->nFilledLen = (OMX_U32)Size; + pInputBufHdrs[i]->nInputPortIndex = 0; + used_ip_buf_cnt++; + ret = OMX_EmptyThisBuffer(amr_enc_handle, pInputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_EmptyThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); + } + if(Size <=0 ){ + break;//eos reached + } + } + pthread_mutex_lock(&etb_lock); + if(etb_done) +{ + DEBUG_PRINT("Component is waiting for EBD to be released.\n"); + etb_event_complete(); + } + else + { + DEBUG_PRINT("\n****************************\n"); + DEBUG_PRINT("EBD not yet happened ...\n"); + DEBUG_PRINT("\n****************************\n"); + etb_done++; + } + pthread_mutex_unlock(&etb_lock); +} + + return 0; +} + + + +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *avc_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + unsigned int bufCnt=0; + + /* To remove warning for unused variable to keep prototype same */ + (void)avc_enc_handle; + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE*)*bufCntMin); + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + DEBUG_PRINT("\n OMX_AllocateBuffer No %d \n", bufCnt); + error = OMX_AllocateBuffer(amr_enc_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize); + } + + return error; +} + + + + +static int Read_Buffer (OMX_BUFFERHEADERTYPE *pBufHdr ) +{ + + size_t bytes_read=0; + + + pBufHdr->nFilledLen = 0; + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + + bytes_read = fread(pBufHdr->pBuffer, 1, pBufHdr->nAllocLen , inputBufferFile); + + pBufHdr->nFilledLen = (OMX_U32)bytes_read; + // Time stamp logic + ((OMX_BUFFERHEADERTYPE *)pBufHdr)->nTimeStamp = \ + + (OMX_TICKS) ((total_pcm_bytes * 1000)/(samplerate * channels *2)); + + DEBUG_PRINT ("\n--time stamp -- %ld\n", (unsigned long)((OMX_BUFFERHEADERTYPE *)pBufHdr)->nTimeStamp); + if(bytes_read == 0) + { + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + DEBUG_PRINT ("\nBytes read zero\n"); + } + else + { + pBufHdr->nFlags = pBufHdr->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + + total_pcm_bytes = (unsigned)(total_pcm_bytes + bytes_read); + } + + return (int)bytes_read;; +} + + + +//In Encoder this Should Open a PCM or WAV file for input. + +static int open_audio_file () +{ + int error_code = 0; + + if (!tunnel) + { + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); + inputBufferFile = fopen (in_filename, "rb"); + if (inputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + in_filename); + error_code = -1; + } + if(parse_pcm_header() != 0x00) + { + DEBUG_PRINT("PCM parser failed \n"); + return -1; + } + } + + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, out_filename); + outputBufferFile = fopen (out_filename, "wb"); + if (outputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + out_filename); + error_code = -1; + return error_code; + } + fseek(outputBufferFile, AMR_HEADER_SIZE, SEEK_SET); + return error_code; +} + +static OMX_ERRORTYPE parse_pcm_header() +{ + struct wav_header hdr; + + DEBUG_PRINT("\n***************************************************************\n"); + if(fread(&hdr, 1, sizeof(hdr),inputBufferFile)!=sizeof(hdr)) + { + DEBUG_PRINT("Wav file cannot read header\n"); + return -1; + } + + if ((hdr.riff_id != ID_RIFF) || + (hdr.riff_fmt != ID_WAVE)|| + (hdr.fmt_id != ID_FMT)) + { + DEBUG_PRINT("Wav file is not a riff/wave file\n"); + return -1; + } + + if (hdr.audio_format != FORMAT_PCM) + { + DEBUG_PRINT("Wav file is not adpcm format %d and fmt size is %d\n", + hdr.audio_format, hdr.fmt_sz); + return -1; + } + + DEBUG_PRINT("Samplerate is %d\n", hdr.sample_rate); + DEBUG_PRINT("Channel Count is %d\n", hdr.num_channels); + DEBUG_PRINT("\n***************************************************************\n"); + + samplerate = hdr.sample_rate; + channels = hdr.num_channels; + total_pcm_bytes = 0; + + return OMX_ErrorNone; +} diff --git a/msm8909/mm-audio/aenc-evrc/Android.mk b/msm8909/mm-audio/aenc-evrc/Android.mk new file mode 100644 index 00000000..d8d0818b --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/Android.mk @@ -0,0 +1,7 @@ +ifneq ($(filter arm aarch64 arm64, $(TARGET_ARCH)),) + +AENC_EVRC_PATH:= $(call my-dir) + +include $(AENC_EVRC_PATH)/qdsp6/Android.mk + +endif diff --git a/msm8909/mm-audio/aenc-evrc/Makefile b/msm8909/mm-audio/aenc-evrc/Makefile new file mode 100644 index 00000000..83d822bb --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/Makefile @@ -0,0 +1,6 @@ +all: + @echo "invoking omxaudio make" + $(MAKE) -C qdsp6 + +install: + $(MAKE) -C qdsp6 install diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/Android.mk b/msm8909/mm-audio/aenc-evrc/qdsp6/Android.mk new file mode 100644 index 00000000..a9f556dc --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/Android.mk @@ -0,0 +1,67 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libOmxEvrcEnc-def := -g -O3 +libOmxEvrcEnc-def += -DQC_MODIFIED +libOmxEvrcEnc-def += -D_ANDROID_ +libOmxEvrcEnc-def += -D_ENABLE_QC_MSG_LOG_ +libOmxEvrcEnc-def += -DVERBOSE +libOmxEvrcEnc-def += -D_DEBUG +libOmxEvrcEnc-def += -Wconversion +libOmxEvrcEnc-def += -DAUDIOV2 + +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxEvrcEnc) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +libOmxEvrcEnc-inc := $(LOCAL_PATH)/inc +libOmxEvrcEnc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := libOmxEvrcEnc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxEvrcEnc-def) +LOCAL_C_INCLUDES := $(libOmxEvrcEnc-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libutils liblog + +LOCAL_SRC_FILES := src/aenc_svr.c +LOCAL_SRC_FILES += src/omx_evrc_aenc.cpp + +include $(BUILD_SHARED_LIBRARY) + +# --------------------------------------------------------------------------------- +# Make the apps-test (mm-aenc-omxevrc-test) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +mm-evrc-enc-test-inc := $(LOCAL_PATH)/inc +mm-evrc-enc-test-inc += $(LOCAL_PATH)/test +mm-evrc-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore +mm-evrc-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-audio/audio-alsa +LOCAL_MODULE := mm-aenc-omxevrc-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxEvrcEnc-def) +LOCAL_C_INCLUDES := $(mm-evrc-enc-test-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libmm-omxcore +LOCAL_SHARED_LIBRARIES += libOmxEvrcEnc +LOCAL_SHARED_LIBRARIES += libaudioalsa +LOCAL_SRC_FILES := test/omx_evrc_enc_test.c + +include $(BUILD_EXECUTABLE) + +endif + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- + diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/Makefile b/msm8909/mm-audio/aenc-evrc/qdsp6/Makefile new file mode 100644 index 00000000..d0871dea --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/Makefile @@ -0,0 +1,81 @@ +# --------------------------------------------------------------------------------- +# MM-AUDIO-OSS-8K-AENC-EVRC +# --------------------------------------------------------------------------------- + +# cross-compiler flags +CFLAGS += -Wall +CFLAGS += -Wundef +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs + +# cross-compile flags specific to shared objects +CFLAGS_SO += -fpic + +# required pre-processor flags +CPPFLAGS := -D__packed__= +CPPFLAGS += -DIMAGE_APPS_PROC +CPPFLAGS += -DFEATURE_Q_SINGLE_LINK +CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR +CPPFLAGS += -DFEATURE_LINUX +CPPFLAGS += -DFEATURE_NATIVELINUX +CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS + +CPPFLAGS += -g +CPPFALGS += -D_DEBUG +CPPFLAGS += -Iinc + +# linker flags +LDFLAGS += -L$(SYSROOT)/usr/lib + +# linker flags for shared objects +LDFLAGS_SO := -shared + +# defintions +LIBMAJOR := $(basename $(basename $(LIBVER))) +LIBINSTALLDIR := $(DESTDIR)usr/lib +INCINSTALLDIR := $(DESTDIR)usr/include +BININSTALLDIR := $(DESTDIR)usr/bin + +# --------------------------------------------------------------------------------- +# BUILD +# --------------------------------------------------------------------------------- +all: libOmxEvrcEnc.so.$(LIBVER) mm-aenc-omxevrc-test + +install: + echo "intalling aenc-evrc in $(DESTDIR)" + if [ ! -d $(LIBINSTALLDIR) ]; then mkdir -p $(LIBINSTALLDIR); fi + if [ ! -d $(INCINSTALLDIR) ]; then mkdir -p $(INCINSTALLDIR); fi + if [ ! -d $(BININSTALLDIR) ]; then mkdir -p $(BININSTALLDIR); fi + install -m 555 libOmxEvrcEnc.so.$(LIBVER) $(LIBINSTALLDIR) + cd $(LIBINSTALLDIR) && ln -s libOmxEvrcEnc.so.$(LIBVER) libOmxEvrcEnc.so.$(LIBMAJOR) + cd $(LIBINSTALLDIR) && ln -s libOmxEvrcEnc.so.$(LIBMAJOR) libOmxEvrcEnc.so + install -m 555 mm-aenc-omxevrc-test $(BININSTALLDIR) + +# --------------------------------------------------------------------------------- +# COMPILE LIBRARY +# --------------------------------------------------------------------------------- +LDLIBS := -lpthread +LDLIBS += -lstdc++ +LDLIBS += -lOmxCore + +SRCS := src/omx_evrc_aenc.cpp +SRCS += src/aenc_svr.c + +libOmxEvrcEnc.so.$(LIBVER): $(SRCS) + $(CC) $(CPPFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxEvrcEnc.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# --------------------------------------------------------------------------------- +# COMPILE TEST APP +# --------------------------------------------------------------------------------- +TEST_LDLIBS := -lpthread +TEST_LDLIBS += -ldl +TEST_LDLIBS += -lOmxCore + +TEST_SRCS := test/omx_evrc_enc_test.c + +mm-aenc-omxevrc-test: libOmxEvrcEnc.so.$(LIBVER) $(TEST_SRCS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS) + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/inc/Map.h b/msm8909/mm-audio/aenc-evrc/qdsp6/inc/Map.h new file mode 100644 index 00000000..aac96fd1 --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/inc/Map.h @@ -0,0 +1,244 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include <stdio.h> +using namespace std; + +template <typename T,typename T2> +class Map +{ + struct node + { + T data; + T2 data2; + node* prev; + node* next; + node(T t, T2 t2,node* p, node* n) : + data(t), data2(t2), prev(p), next(n) {} + }; + node* head; + node* tail; + node* tmp; + unsigned size_of_list; + static Map<T,T2> *m_self; +public: + Map() : head( NULL ), tail ( NULL ),tmp(head),size_of_list(0) {} + bool empty() const { return ( !head || !tail ); } + operator bool() const { return !empty(); } + void insert(T,T2); + void show(); + int size(); + T2 find(T); // Return VALUE + T find_ele(T);// Check if the KEY is present or not + T2 begin(); //give the first ele + bool erase(T); + bool eraseall(); + bool isempty(); + ~Map() + { + while(head) + { + node* temp(head); + head=head->next; + size_of_list--; + delete temp; + } + } +}; + +template <typename T,typename T2> +T2 Map<T,T2>::find(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data2; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T Map<T,T2>::find_ele(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T2 Map<T,T2>::begin() +{ + tmp = head; + if(tmp) + { + return (tmp->data2); + } + return 0; +} + +template <typename T,typename T2> +void Map<T,T2>::show() +{ + tmp = head; + while(tmp) + { + printf("%d-->%d\n",tmp->data,tmp->data2); + tmp = tmp->next; + } +} + +template <typename T,typename T2> +int Map<T,T2>::size() +{ + int count =0; + tmp = head; + while(tmp) + { + tmp = tmp->next; + count++; + } + return count; +} + +template <typename T,typename T2> +void Map<T,T2>::insert(T data, T2 data2) +{ + tail = new node(data, data2,tail, NULL); + if( tail->prev ) + tail->prev->next = tail; + + if( empty() ) + { + head = tail; + tmp=head; + } + tmp = head; + size_of_list++; +} + +template <typename T,typename T2> +bool Map<T,T2>::erase(T d) +{ + bool found = false; + tmp = head; + node* prevnode = tmp; + node *tempnode; + + while(tmp) + { + if((head == tail) && (head->data == d)) + { + found = true; + tempnode = head; + head = tail = NULL; + delete tempnode; + break; + } + if((tmp ==head) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + tmp = tmp->next; + tmp->prev = NULL; + head = tmp; + tempnode->next = NULL; + delete tempnode; + break; + } + if((tmp == tail) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + prevnode->next = NULL; + tmp->prev = NULL; + tail = prevnode; + delete tempnode; + break; + } + if(tmp->data == d) + { + found = true; + prevnode->next = tmp->next; + tmp->next->prev = prevnode->next; + tempnode = tmp; + //tmp = tmp->next; + delete tempnode; + break; + } + prevnode = tmp; + tmp = tmp->next; + } + if(found)size_of_list--; + return found; +} + +template <typename T,typename T2> +bool Map<T,T2>::eraseall() +{ + // Be careful while using this method + // it not only removes the node but FREES(not delete) the allocated + // memory. + node *tempnode; + tmp = head; + while(head) + { + tempnode = head; + head = head->next; + tempnode->next = NULL; + if(tempnode->data) + free(tempnode->data); + if(tempnode->data2) + free(tempnode->data2); + delete tempnode; + } + tail = head = NULL; + return true; +} + + +template <typename T,typename T2> +bool Map<T,T2>::isempty() +{ + if(!size_of_list) return true; + else return false; +} + +#endif // _MAP_H_ diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/inc/aenc_svr.h b/msm8909/mm-audio/aenc-evrc/qdsp6/inc/aenc_svr.h new file mode 100644 index 00000000..46f40ee3 --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/inc/aenc_svr.h @@ -0,0 +1,122 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef AENC_SVR_H +#define AENC_SVR_H + +#ifdef __cplusplus +extern "C" { +#endif +#include <pthread.h> +#include <sched.h> +#include <utils/Log.h> + +#ifdef _ANDROID_ +#define LOG_TAG "QC_EVRCENC" +#endif + +#ifndef LOGE +#define LOGE ALOGE +#endif + +#ifndef LOGW +#define LOGW ALOGW +#endif + +#ifndef LOGD +#define LOGD ALOGD +#endif + +#ifndef LOGV +#define LOGV ALOGV +#endif + +#ifndef LOGI +#define LOGI ALOGI +#endif + +#define DEBUG_PRINT_ERROR LOGE +#define DEBUG_PRINT LOGI +#define DEBUG_DETAIL LOGV + +typedef void (*message_func)(void* client_data, unsigned char id); + +/** + @brief audio encoder ipc info structure + + */ +struct evrc_ipc_info +{ + pthread_t thr; + int pipe_in; + int pipe_out; + int dead; + message_func process_msg_cb; + void *client_data; + char thread_name[128]; +}; + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to command server + */ +struct evrc_ipc_info *omx_evrc_thread_create(message_func cb, + void* client_data, + char *th_name); + +struct evrc_ipc_info *omx_evrc_event_thread_create(message_func cb, + void* client_data, + char *th_name); +/** + @brief This function stop command server + + @param svr handle to command server + @return none + */ +void omx_evrc_thread_stop(struct evrc_ipc_info *evrc_ipc); + + +/** + @brief This function post message in the command server + + @param svr handle to command server + @return none + */ +void omx_evrc_post_msg(struct evrc_ipc_info *evrc_ipc, + unsigned char id); + +void* omx_evrc_comp_timer_handler(void *); + +#ifdef __cplusplus +} +#endif + +#endif /* AENC_SVR */ diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h b/msm8909/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h new file mode 100644 index 00000000..09ffb2d7 --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/inc/omx_evrc_aenc.h @@ -0,0 +1,539 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010,2014 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _EVRC_ENC_H_ +#define _EVRC_ENC_H_ +/*============================================================================ + Audio Encoder + +@file omx_evrc_aenc.h +This module contains the class definition for openMAX encoder component. + + + +============================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +/* Uncomment out below line #define LOG_NDEBUG 0 if we want to see + * all DEBUG_PRINT or LOGV messaging */ +#include<stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <time.h> +#include <inttypes.h> +#include <unistd.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#include "OMX_Core.h" +#include "OMX_Audio.h" +#include "aenc_svr.h" +#include "qc_omx_component.h" +#include "Map.h" +#include <semaphore.h> +#include <linux/msm_audio.h> +#include <linux/msm_audio_qcp.h> +extern "C" { + void * get_omx_component_factory_fn(void); +} + + +////////////////////////////////////////////////////////////////////////////// +// Module specific globals +////////////////////////////////////////////////////////////////////////////// + + + +#define OMX_SPEC_VERSION 0x00000101 +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (x >= y?x:y) + +////////////////////////////////////////////////////////////////////////////// +// Macros +////////////////////////////////////////////////////////////////////////////// +// + + +#define PrintFrameHdr(i,bufHdr) \ + DEBUG_PRINT("i=%d OMX bufHdr[%p]buf[%p]size[%d]TS[%lld]nFlags[0x%x]\n",\ + i,\ + bufHdr, \ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFlags) + + +// BitMask Management logic +#define BITS_PER_BYTE 8 +#define BITMASK_SIZE(mIndex) \ + (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) +#define BITMASK_OFFSET(mIndex)\ + ((mIndex)/BITS_PER_BYTE) +#define BITMASK_FLAG(mIndex) \ + (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITMASK_CLEAR(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] &= ~(BITMASK_FLAG(mIndex)) +#define BITMASK_SET(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] |= BITMASK_FLAG(mIndex) +#define BITMASK_PRESENT(mArray,mIndex)\ + ((mArray)[BITMASK_OFFSET(mIndex)] & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex)\ + (((mArray)[BITMASK_OFFSET(mIndex)] & \ + BITMASK_FLAG(mIndex)) == 0x0) + +#define OMX_CORE_NUM_INPUT_BUFFERS 2 +#define OMX_CORE_NUM_OUTPUT_BUFFERS 16 + +#define OMX_CORE_INPUT_BUFFER_SIZE 8160 // Multiple of 160 +#define OMX_CORE_CONTROL_CMDQ_SIZE 100 +#define OMX_AENC_VOLUME_STEP 0x147 +#define OMX_AENC_MIN 0 +#define OMX_AENC_MAX 100 +#define NON_TUNNEL 1 +#define TUNNEL 0 +#define IP_PORT_BITMASK 0x02 +#define OP_PORT_BITMASK 0x01 +#define IP_OP_PORT_BITMASK 0x03 + +#define OMX_EVRC_DEFAULT_SF 8000 +#define OMX_EVRC_DEFAULT_CH_CFG 1 +#define OMX_EVRC_DEFAULT_VOL 25 +// 14 bytes for input meta data +#define OMX_AENC_SIZEOF_META_BUF (OMX_CORE_INPUT_BUFFER_SIZE+14) + +#define TRUE 1 +#define FALSE 0 + +#define NUMOFFRAMES 1 +#define MAXFRAMELENGTH 25 +#define OMX_EVRC_OUTPUT_BUFFER_SIZE ((NUMOFFRAMES * (sizeof(ENC_META_OUT) + MAXFRAMELENGTH) \ + + 1)) + +#define OMX_EVRC_DEFAULT_MINRATE 4 +#define OMX_EVRC_DEFAULT_MAXRATE 4 + +class omx_evrc_aenc; + +// OMX EVRC audio encoder class +class omx_evrc_aenc: public qc_omx_component +{ +public: + omx_evrc_aenc(); // constructor + virtual ~omx_evrc_aenc(); // destructor + + OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + + OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp); + + OMX_ERRORTYPE component_init(OMX_STRING role); + + OMX_ERRORTYPE component_role_enum(OMX_HANDLETYPE hComp, + OMX_U8 *role, + OMX_U32 index); + + OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_HANDLETYPE peerComponent, + OMX_U32 peerPort, + OMX_TUNNELSETUPTYPE *tunnelSetup); + + OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE hComp, + OMX_STRING componentName, + OMX_VERSIONTYPE *componentVersion, + OMX_VERSIONTYPE * specVersion, + OMX_UUIDTYPE *componentUUID); + + OMX_ERRORTYPE get_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE hComp, + OMX_STRING paramName, + OMX_INDEXTYPE *indexType); + + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp, + OMX_STATETYPE *state); + + static void process_in_port_msg(void *client_data, + unsigned char id); + + static void process_out_port_msg(void *client_data, + unsigned char id); + + static void process_command_msg(void *client_data, + unsigned char id); + + static void process_event_cb(void *client_data, + unsigned char id); + + + OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp, + OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData); + + OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + void * eglImage); + + bool post_command(unsigned int p1, unsigned int p2, + unsigned char id); + + // Deferred callback identifiers + enum + { + //Event Callbacks from the component thread context + OMX_COMPONENT_GENERATE_EVENT = 0x1, + //Buffer Done callbacks from component thread context + OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2, + OMX_COMPONENT_GENERATE_ETB = 0x3, + //Command + OMX_COMPONENT_GENERATE_COMMAND = 0x4, + OMX_COMPONENT_GENERATE_FRAME_DONE = 0x05, + OMX_COMPONENT_GENERATE_FTB = 0x06, + OMX_COMPONENT_GENERATE_EOS = 0x07, + OMX_COMPONENT_PORTSETTINGS_CHANGED = 0x08, + OMX_COMPONENT_SUSPEND = 0x09, + OMX_COMPONENT_RESUME = 0x0a + }; +private: + + /////////////////////////////////////////////////////////// + // Type definitions + /////////////////////////////////////////////////////////// + // Bit Positions + enum flags_bit_positions + { + // Defer transition to IDLE + OMX_COMPONENT_IDLE_PENDING =0x1, + // Defer transition to LOADING + OMX_COMPONENT_LOADING_PENDING =0x2, + + OMX_COMPONENT_MUTED =0x3, + + // Defer transition to Enable + OMX_COMPONENT_INPUT_ENABLE_PENDING =0x4, + // Defer transition to Enable + OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x5, + // Defer transition to Disable + OMX_COMPONENT_INPUT_DISABLE_PENDING =0x6, + // Defer transition to Disable + OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x7 + }; + + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + input_buffer_map; + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + output_buffer_map; + + enum port_indexes + { + OMX_CORE_INPUT_PORT_INDEX =0, + OMX_CORE_OUTPUT_PORT_INDEX =1 + }; + + struct omx_event + { + unsigned long param1; + unsigned long param2; + unsigned char id; + }; + + struct omx_cmd_queue + { + omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE]; + unsigned m_read; + unsigned m_write; + unsigned m_size; + + omx_cmd_queue(); + ~omx_cmd_queue(); + bool insert_entry(unsigned long p1, unsigned long p2, unsigned char id); + bool pop_entry(unsigned long *p1,unsigned long *p2, unsigned char *id); + bool get_msg_id(unsigned char *id); + bool get_msg_with_id(unsigned *p1,unsigned *p2, unsigned char id); + }; + + typedef struct TIMESTAMP + { + unsigned int LowPart; + unsigned int HighPart; + }__attribute__((packed)) TIMESTAMP; + + typedef struct metadata_input + { + unsigned short offsetVal; + TIMESTAMP nTimeStamp; + unsigned int nFlags; + }__attribute__((packed)) META_IN; + + typedef struct enc_meta_out + { + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; + } __attribute__ ((packed))ENC_META_OUT; + + typedef struct + { + OMX_U32 tot_in_buf_len; + OMX_U32 tot_out_buf_len; + OMX_TICKS tot_pb_time; + OMX_U32 fbd_cnt; + OMX_U32 ftb_cnt; + OMX_U32 etb_cnt; + OMX_U32 ebd_cnt; + }EVRC_PB_STATS; + + /////////////////////////////////////////////////////////// + // Member variables + /////////////////////////////////////////////////////////// + OMX_U8 *m_tmp_meta_buf; + OMX_U8 *m_tmp_out_meta_buf; + OMX_U8 m_flush_cnt ; + OMX_U8 m_comp_deinit; + + // the below var doesnt hold good if combo of use and alloc bufs are used + OMX_S32 m_volume;//Unit to be determined + OMX_PTR m_app_data;// Application data + int nNumInputBuf; + int nNumOutputBuf; + int m_drv_fd; // Kernel device node file handle + bool bFlushinprogress; + bool is_in_th_sleep; + bool is_out_th_sleep; + unsigned int m_flags; //encapsulate the waiting states. + OMX_TICKS nTimestamp; + unsigned int pcm_input; //tunnel or non-tunnel + unsigned int m_inp_act_buf_count; // Num of Input Buffers + unsigned int m_out_act_buf_count; // Numb of Output Buffers + unsigned int m_inp_current_buf_count; // Num of Input Buffers + unsigned int m_out_current_buf_count; // Numb of Output Buffers + unsigned int output_buffer_size; + unsigned int input_buffer_size; + unsigned short m_session_id; + // store I/P PORT state + OMX_BOOL m_inp_bEnabled; + // store O/P PORT state + OMX_BOOL m_out_bEnabled; + //Input port Populated + OMX_BOOL m_inp_bPopulated; + //Output port Populated + OMX_BOOL m_out_bPopulated; + sem_t sem_States; + sem_t sem_read_msg; + sem_t sem_write_msg; + + volatile int m_is_event_done; + volatile int m_is_in_th_sleep; + volatile int m_is_out_th_sleep; + input_buffer_map m_input_buf_hdrs; + output_buffer_map m_output_buf_hdrs; + omx_cmd_queue m_input_q; + omx_cmd_queue m_input_ctrl_cmd_q; + omx_cmd_queue m_input_ctrl_ebd_q; + omx_cmd_queue m_command_q; + omx_cmd_queue m_output_q; + omx_cmd_queue m_output_ctrl_cmd_q; + omx_cmd_queue m_output_ctrl_fbd_q; + pthread_mutexattr_t m_outputlock_attr; + pthread_mutexattr_t m_commandlock_attr; + pthread_mutexattr_t m_lock_attr; + pthread_mutexattr_t m_state_attr; + pthread_mutexattr_t m_flush_attr; + pthread_mutexattr_t m_in_th_attr_1; + pthread_mutexattr_t m_out_th_attr_1; + pthread_mutexattr_t m_event_attr; + pthread_mutexattr_t m_in_th_attr; + pthread_mutexattr_t m_out_th_attr; + pthread_mutexattr_t out_buf_count_lock_attr; + pthread_mutexattr_t in_buf_count_lock_attr; + pthread_cond_t cond; + pthread_cond_t in_cond; + pthread_cond_t out_cond; + pthread_mutex_t m_lock; + pthread_mutex_t m_commandlock; + pthread_mutex_t m_outputlock; + // Mutexes for state change + pthread_mutex_t m_state_lock; + // Mutexes for flush acks from input and output threads + pthread_mutex_t m_flush_lock; + pthread_mutex_t m_event_lock; + pthread_mutex_t m_in_th_lock; + pthread_mutex_t m_out_th_lock; + pthread_mutex_t m_in_th_lock_1; + pthread_mutex_t m_out_th_lock_1; + pthread_mutex_t out_buf_count_lock; + pthread_mutex_t in_buf_count_lock; + + OMX_STATETYPE m_state; // OMX State + OMX_STATETYPE nState; + OMX_CALLBACKTYPE m_cb; // Application callbacks + EVRC_PB_STATS m_evrc_pb_stats; + struct evrc_ipc_info *m_ipc_to_in_th; // for input thread + struct evrc_ipc_info *m_ipc_to_out_th; // for output thread + struct evrc_ipc_info *m_ipc_to_cmd_th; // for command thread + struct evrc_ipc_info *m_ipc_to_event_th; //for txco event thread + OMX_PRIORITYMGMTTYPE m_priority_mgm ; + OMX_AUDIO_PARAM_EVRCTYPE m_evrc_param; // Cache EVRC encoder parameter + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_param; // Cache pcm parameter + OMX_PARAM_COMPONENTROLETYPE component_Role; + OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier; + + /////////////////////////////////////////////////////////// + // Private methods + /////////////////////////////////////////////////////////// + OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port,OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE use_input_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE use_output_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + bool allocate_done(void); + + bool release_done(OMX_U32 param1); + + bool execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl=true); + + bool execute_input_omx_flush(void); + + bool execute_output_omx_flush(void); + + bool search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool post_input(unsigned long p1, unsigned long p2, + unsigned char id); + + bool post_output(unsigned long p1, unsigned long p2, + unsigned char id); + + void process_events(omx_evrc_aenc *client_data); + + void buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void wait_for_event(); + + void event_complete(); + + void in_th_goto_sleep(); + + void in_th_wakeup(); + + void out_th_goto_sleep(); + + void out_th_wakeup(); + + void flush_ack(); + void deinit_encoder(); + +}; +#endif diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/src/aenc_svr.c b/msm8909/mm-audio/aenc-evrc/qdsp6/src/aenc_svr.c new file mode 100644 index 00000000..4f828fcf --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/src/aenc_svr.c @@ -0,0 +1,205 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> +#include <errno.h> + +#include <aenc_svr.h> + +/** + @brief This function processes posted messages + + Once thread is being spawned, this function is run to + start processing commands posted by client + + @param info pointer to context + + */ +void *omx_evrc_msg(void *info) +{ + struct evrc_ipc_info *evrc_info = (struct evrc_ipc_info*)info; + unsigned char id; + ssize_t n; + + DEBUG_DETAIL("\n%s: message thread start\n", __FUNCTION__); + while (!evrc_info->dead) + { + n = read(evrc_info->pipe_in, &id, 1); + if (0 == n) break; + if (1 == n) + { + DEBUG_DETAIL("\n%s-->pipe_in=%d pipe_out=%d\n", + evrc_info->thread_name, + evrc_info->pipe_in, + evrc_info->pipe_out); + + evrc_info->process_msg_cb(evrc_info->client_data, id); + } + if ((n < 0) && (errno != EINTR)) break; + } + DEBUG_DETAIL("%s: message thread stop\n", __FUNCTION__); + + return 0; +} + +void *omx_evrc_events(void *info) +{ + struct evrc_ipc_info *evrc_info = (struct evrc_ipc_info*)info; + unsigned char id = 0; + + DEBUG_DETAIL("%s: message thread start\n", evrc_info->thread_name); + evrc_info->process_msg_cb(evrc_info->client_data, id); + DEBUG_DETAIL("%s: message thread stop\n", evrc_info->thread_name); + return 0; +} + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to msging thread + */ +struct evrc_ipc_info *omx_evrc_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct evrc_ipc_info *evrc_info; + + evrc_info = calloc(1, sizeof(struct evrc_ipc_info)); + if (!evrc_info) + { + return 0; + } + + evrc_info->client_data = client_data; + evrc_info->process_msg_cb = cb; + strlcpy(evrc_info->thread_name, th_name, sizeof(evrc_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT_ERROR("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + evrc_info->pipe_in = fds[0]; + evrc_info->pipe_out = fds[1]; + + r = pthread_create(&evrc_info->thr, 0, omx_evrc_msg, evrc_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", evrc_info->thread_name); + return evrc_info; + + +fail_thread: + close(evrc_info->pipe_in); + close(evrc_info->pipe_out); + +fail_pipe: + free(evrc_info); + + return 0; +} + +/** + * @brief This function starts command server + * + * @param cb pointer to callback function from the client + * @param client_data reference client wants to get back + * through callback + * @return handle to msging thread + * */ +struct evrc_ipc_info *omx_evrc_event_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct evrc_ipc_info *evrc_info; + + evrc_info = calloc(1, sizeof(struct evrc_ipc_info)); + if (!evrc_info) + { + return 0; + } + + evrc_info->client_data = client_data; + evrc_info->process_msg_cb = cb; + strlcpy(evrc_info->thread_name, th_name, sizeof(evrc_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + evrc_info->pipe_in = fds[0]; + evrc_info->pipe_out = fds[1]; + + r = pthread_create(&evrc_info->thr, 0, omx_evrc_events, evrc_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", evrc_info->thread_name); + return evrc_info; + + +fail_thread: + close(evrc_info->pipe_in); + close(evrc_info->pipe_out); + +fail_pipe: + free(evrc_info); + + return 0; +} + +void omx_evrc_thread_stop(struct evrc_ipc_info *evrc_info) { + DEBUG_DETAIL("%s stop server\n", __FUNCTION__); + close(evrc_info->pipe_in); + close(evrc_info->pipe_out); + pthread_join(evrc_info->thr,NULL); + evrc_info->pipe_out = -1; + evrc_info->pipe_in = -1; + DEBUG_DETAIL("%s: message thread close fds%d %d\n", evrc_info->thread_name, + evrc_info->pipe_in,evrc_info->pipe_out); + free(evrc_info); +} + +void omx_evrc_post_msg(struct evrc_ipc_info *evrc_info, unsigned char id) { + DEBUG_DETAIL("\n%s id=%d\n", __FUNCTION__,id); + write(evrc_info->pipe_out, &id, 1); +} diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp b/msm8909/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp new file mode 100644 index 00000000..8200365f --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/src/omx_evrc_aenc.cpp @@ -0,0 +1,4531 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ +@file omx_aenc_evrc.c + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + + +#include<string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include "omx_evrc_aenc.h" +#include <errno.h> + +using namespace std; +#define SLEEP_MS 100 + +// omx_cmd_queue destructor +omx_evrc_aenc::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_evrc_aenc::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q, 0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_evrc_aenc::omx_cmd_queue::insert_entry(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool ret = true; + if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full"); + } + return ret; +} + +bool omx_evrc_aenc::omx_cmd_queue::pop_entry(unsigned long *p1, + unsigned long *p2, unsigned char *id) +{ + bool ret = true; + if (m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR Delete!!! Command Queue Empty"); + } + return ret; +} + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return(new omx_evrc_aenc); +} +bool omx_evrc_aenc::omx_cmd_queue::get_msg_id(unsigned char *id) +{ + if(m_size > 0) + { + *id = m_q[m_read].id; + DEBUG_PRINT("get_msg_id=%d\n",*id); + } + else{ + return false; + } + return true; +} +/*============================================================================= +FUNCTION: + wait_for_event + +DESCRIPTION: + waits for a particular event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_evrc_aenc::wait_for_event() +{ + int rc; + struct timespec ts; + pthread_mutex_lock(&m_event_lock); + while (0 == m_is_event_done) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += (SLEEP_MS/1000); + ts.tv_nsec += ((SLEEP_MS%1000) * 1000000); + rc = pthread_cond_timedwait(&cond, &m_event_lock, &ts); + if (rc == ETIMEDOUT && !m_is_event_done) { + DEBUG_PRINT("Timed out waiting for flush"); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + } + } + m_is_event_done = 0; + pthread_mutex_unlock(&m_event_lock); +} + +/*============================================================================= +FUNCTION: + event_complete + +DESCRIPTION: + informs about the occurance of an event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_evrc_aenc::event_complete() +{ + pthread_mutex_lock(&m_event_lock); + if (0 == m_is_event_done) + { + m_is_event_done = 1; + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&m_event_lock); +} + +// All this non-sense because of a single evrc object +void omx_evrc_aenc::in_th_goto_sleep() +{ + pthread_mutex_lock(&m_in_th_lock); + while (0 == m_is_in_th_sleep) + { + pthread_cond_wait(&in_cond, &m_in_th_lock); + } + m_is_in_th_sleep = 0; + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_evrc_aenc::in_th_wakeup() +{ + pthread_mutex_lock(&m_in_th_lock); + if (0 == m_is_in_th_sleep) + { + m_is_in_th_sleep = 1; + pthread_cond_signal(&in_cond); + } + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_evrc_aenc::out_th_goto_sleep() +{ + + pthread_mutex_lock(&m_out_th_lock); + while (0 == m_is_out_th_sleep) + { + pthread_cond_wait(&out_cond, &m_out_th_lock); + } + m_is_out_th_sleep = 0; + pthread_mutex_unlock(&m_out_th_lock); +} + +void omx_evrc_aenc::out_th_wakeup() +{ + pthread_mutex_lock(&m_out_th_lock); + if (0 == m_is_out_th_sleep) + { + m_is_out_th_sleep = 1; + pthread_cond_signal(&out_cond); + } + pthread_mutex_unlock(&m_out_th_lock); +} +/* ====================================================================== +FUNCTION + omx_evrc_aenc::omx_evrc_aenc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_evrc_aenc::omx_evrc_aenc(): m_tmp_meta_buf(NULL), + m_tmp_out_meta_buf(NULL), + m_flush_cnt(255), + m_comp_deinit(0), + m_volume(25), + m_app_data(NULL), + nNumInputBuf(0), + nNumOutputBuf(0), + m_drv_fd(-1), + bFlushinprogress(0), + is_in_th_sleep(false), + is_out_th_sleep(false), + m_flags(0), + nTimestamp(0), + m_inp_act_buf_count (OMX_CORE_NUM_INPUT_BUFFERS), + m_out_act_buf_count (OMX_CORE_NUM_OUTPUT_BUFFERS), + m_inp_current_buf_count(0), + m_out_current_buf_count(0), + output_buffer_size((OMX_U32)OMX_EVRC_OUTPUT_BUFFER_SIZE), + input_buffer_size(OMX_CORE_INPUT_BUFFER_SIZE), + m_inp_bEnabled(OMX_TRUE), + m_out_bEnabled(OMX_TRUE), + m_inp_bPopulated(OMX_FALSE), + m_out_bPopulated(OMX_FALSE), + m_is_event_done(0), + m_state(OMX_StateInvalid), + m_ipc_to_in_th(NULL), + m_ipc_to_out_th(NULL), + m_ipc_to_cmd_th(NULL) +{ + int cond_ret = 0; + memset(&m_cmp, 0, sizeof(m_cmp)); + memset(&m_cb, 0, sizeof(m_cb)); + memset(&m_evrc_param, 0, sizeof(m_evrc_param)); + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + memset(&m_evrc_pb_stats, 0, sizeof(m_evrc_pb_stats)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + + pthread_mutexattr_init(&m_lock_attr); + pthread_mutex_init(&m_lock, &m_lock_attr); + pthread_mutexattr_init(&m_commandlock_attr); + pthread_mutex_init(&m_commandlock, &m_commandlock_attr); + + pthread_mutexattr_init(&m_outputlock_attr); + pthread_mutex_init(&m_outputlock, &m_outputlock_attr); + + pthread_mutexattr_init(&m_state_attr); + pthread_mutex_init(&m_state_lock, &m_state_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_flush_attr); + pthread_mutex_init(&m_flush_lock, &m_flush_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_in_th_attr); + pthread_mutex_init(&m_in_th_lock, &m_in_th_attr); + + pthread_mutexattr_init(&m_out_th_attr); + pthread_mutex_init(&m_out_th_lock, &m_out_th_attr); + + pthread_mutexattr_init(&m_in_th_attr_1); + pthread_mutex_init(&m_in_th_lock_1, &m_in_th_attr_1); + + pthread_mutexattr_init(&m_out_th_attr_1); + pthread_mutex_init(&m_out_th_lock_1, &m_out_th_attr_1); + + pthread_mutexattr_init(&out_buf_count_lock_attr); + pthread_mutex_init(&out_buf_count_lock, &out_buf_count_lock_attr); + + pthread_mutexattr_init(&in_buf_count_lock_attr); + pthread_mutex_init(&in_buf_count_lock, &in_buf_count_lock_attr); + if ((cond_ret = pthread_cond_init (&cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&in_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for in_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&out_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for out_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + + sem_init(&sem_read_msg,0, 0); + sem_init(&sem_write_msg,0, 0); + sem_init(&sem_States,0, 0); + return; +} + + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::~omx_evrc_aenc + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_evrc_aenc::~omx_evrc_aenc() +{ + DEBUG_PRINT_ERROR("EVRC Object getting destroyed comp-deinit=%d\n", + m_comp_deinit); + if ( !m_comp_deinit ) + { + deinit_encoder(); + } + pthread_mutexattr_destroy(&m_lock_attr); + pthread_mutex_destroy(&m_lock); + + pthread_mutexattr_destroy(&m_commandlock_attr); + pthread_mutex_destroy(&m_commandlock); + + pthread_mutexattr_destroy(&m_outputlock_attr); + pthread_mutex_destroy(&m_outputlock); + + pthread_mutexattr_destroy(&m_state_attr); + pthread_mutex_destroy(&m_state_lock); + + pthread_mutexattr_destroy(&m_event_attr); + pthread_mutex_destroy(&m_event_lock); + + pthread_mutexattr_destroy(&m_flush_attr); + pthread_mutex_destroy(&m_flush_lock); + + pthread_mutexattr_destroy(&m_in_th_attr); + pthread_mutex_destroy(&m_in_th_lock); + + pthread_mutexattr_destroy(&m_out_th_attr); + pthread_mutex_destroy(&m_out_th_lock); + + pthread_mutexattr_destroy(&out_buf_count_lock_attr); + pthread_mutex_destroy(&out_buf_count_lock); + + pthread_mutexattr_destroy(&in_buf_count_lock_attr); + pthread_mutex_destroy(&in_buf_count_lock); + + pthread_mutexattr_destroy(&m_in_th_attr_1); + pthread_mutex_destroy(&m_in_th_lock_1); + + pthread_mutexattr_destroy(&m_out_th_attr_1); + pthread_mutex_destroy(&m_out_th_lock_1); + pthread_mutex_destroy(&out_buf_count_lock); + pthread_mutex_destroy(&in_buf_count_lock); + pthread_cond_destroy(&cond); + pthread_cond_destroy(&in_cond); + pthread_cond_destroy(&out_cond); + sem_destroy (&sem_read_msg); + sem_destroy (&sem_write_msg); + sem_destroy (&sem_States); + DEBUG_PRINT_ERROR("OMX EVRC component destroyed\n"); + return; +} + +/** + @brief memory function for sending EmptyBufferDone event + back to IL client + + @param bufHdr OMX buffer header to be passed back to IL client + @return none + */ +void omx_evrc_aenc::buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.EmptyBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_BUFFER_DONE,bufHdr); + bufHdr->nFilledLen = 0; + + m_cb.EmptyBufferDone(&m_cmp, m_app_data, bufHdr); + pthread_mutex_lock(&in_buf_count_lock); + m_evrc_pb_stats.ebd_cnt++; + nNumInputBuf--; + DEBUG_DETAIL("EBD CB:: in_buf_len=%d nNumInputBuf=%d %d ebd_cnt %d \n",\ + m_evrc_pb_stats.tot_in_buf_len, + nNumInputBuf, m_evrc_pb_stats.ebd_cnt); + pthread_mutex_unlock(&in_buf_count_lock); + } + + return; +} + +/*============================================================================= +FUNCTION: + flush_ack + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_evrc_aenc::flush_ack() +{ + // Decrement the FLUSH ACK count and notify the waiting recepients + pthread_mutex_lock(&m_flush_lock); + --m_flush_cnt; + if (0 == m_flush_cnt) + { + event_complete(); + } + DEBUG_PRINT("Rxed FLUSH ACK cnt=%d\n",m_flush_cnt); + pthread_mutex_unlock(&m_flush_lock); +} +void omx_evrc_aenc::frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.FillBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_FRAME_DONE,bufHdr); + m_evrc_pb_stats.fbd_cnt++; + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf--; + DEBUG_PRINT("FBD CB:: nNumOutputBuf=%d out_buf_len=%u fbd_cnt=%u\n",\ + nNumOutputBuf, + m_evrc_pb_stats.tot_out_buf_len, + m_evrc_pb_stats.fbd_cnt); + m_evrc_pb_stats.tot_out_buf_len += bufHdr->nFilledLen; + m_evrc_pb_stats.tot_pb_time = bufHdr->nTimeStamp; + DEBUG_PRINT("FBD:in_buf_len=%u out_buf_len=%u\n", + m_evrc_pb_stats.tot_in_buf_len, + m_evrc_pb_stats.tot_out_buf_len); + + pthread_mutex_unlock(&out_buf_count_lock); + m_cb.FillBufferDone(&m_cmp, m_app_data, bufHdr); + } + return; +} + +/*============================================================================= +FUNCTION: + process_out_port_msg + +DESCRIPTION: + Function for handling all commands from IL client +IL client commands are processed and callbacks are generated through +this routine Audio Command Server provides the thread context for this routine + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_evrc_aenc::process_out_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; // qsize + unsigned tot_qsize = 0; + omx_evrc_aenc *pThis = (omx_evrc_aenc *) client_data; + OMX_STATETYPE state; + +loopback_out: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" OUT: IN LOADED STATE RETURN\n"); + return; + } + pthread_mutex_lock(&pThis->m_outputlock); + + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + + if ( 0 == tot_qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_DETAIL("OUT-->BREAK FROM LOOP...%d\n",tot_qsize); + return; + } + if ( (state != OMX_StateExecuting) && !qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + DEBUG_DETAIL("OUT:1.SLEEPING OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + + if ( ((!pThis->m_output_ctrl_cmd_q.m_size) && !pThis->m_out_bEnabled) ) + { + // case where no port reconfig and nothing in the flush q + DEBUG_DETAIL("No flush/port reconfig qsize=%d tot_qsize=%d",\ + qsize,tot_qsize); + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + if(pThis->m_output_ctrl_cmd_q.m_size || !(pThis->bFlushinprogress)) + { + DEBUG_PRINT("OUT:2. SLEEPING OUT THREAD \n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + } + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_DETAIL("OUT-->QSIZE-flush=%d,fbd=%d QSIZE=%d state=%d\n",\ + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size,state); + + + if (qsize) + { + // process FLUSH message + pThis->m_output_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_ctrl_fbd_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_output_ctrl_fbd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // if no FLUSH and FBD's then process FTB's + pThis->m_output_q.pop_entry(&p1,&p2,&ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("OUT--> Empty Queue state=%d %d %d %d\n",state, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("OUT: SLEEPING AGAIN OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pthread_mutex_unlock(&pThis->m_outputlock); + pThis->out_th_goto_sleep(); + goto loopback_out; + } + } + pthread_mutex_unlock(&pThis->m_outputlock); + + if ( qsize > 0 ) + { + id = ident; + ident = 0; + DEBUG_DETAIL("OUT->state[%d]ident[%d]flushq[%d]fbd[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if ( OMX_COMPONENT_GENERATE_FRAME_DONE == id ) + { + pThis->frame_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_FTB == id ) + { + pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_EOS == id ) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + + } + else if(id == OMX_COMPONENT_RESUME) + { + DEBUG_PRINT("RESUMED...\n"); + } + else if(id == OMX_COMPONENT_GENERATE_COMMAND) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL("Executing FLUSH command on Output port\n"); + pThis->execute_output_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:OUT-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR: OUT--> Empty OUTPUTQ\n"); + } + + return; +} + +/*============================================================================= +FUNCTION: + process_command_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_evrc_aenc::process_command_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + omx_evrc_aenc *pThis = (omx_evrc_aenc*)client_data; + pthread_mutex_lock(&pThis->m_commandlock); + + qsize = pThis->m_command_q.m_size; + DEBUG_DETAIL("CMD-->QSIZE=%d state=%d\n",pThis->m_command_q.m_size, + pThis->m_state); + + if (!qsize) + { + DEBUG_DETAIL("CMD-->BREAKING FROM LOOP\n"); + pthread_mutex_unlock(&pThis->m_commandlock); + return; + } else + { + pThis->m_command_q.pop_entry(&p1,&p2,&ident); + } + pthread_mutex_unlock(&pThis->m_commandlock); + + id = ident; + DEBUG_DETAIL("CMD->state[%d]id[%d]cmdq[%d]n",\ + pThis->m_state,ident, \ + pThis->m_command_q.m_size); + + if (OMX_COMPONENT_GENERATE_EVENT == id) + { + if (pThis->m_cb.EventHandler) + { + if (OMX_CommandStateSet == p1) + { + pthread_mutex_lock(&pThis->m_state_lock); + pThis->m_state = (OMX_STATETYPE) p2; + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_PRINT("CMD:Process->state set to %d \n", \ + pThis->m_state); + + if (pThis->m_state == OMX_StateExecuting || + pThis->m_state == OMX_StateLoaded) + { + + pthread_mutex_lock(&pThis->m_in_th_lock_1); + if (pThis->is_in_th_sleep) + { + pThis->is_in_th_sleep = false; + DEBUG_DETAIL("CMD:WAKING UP IN THREADS\n"); + pThis->in_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + + pthread_mutex_lock(&pThis->m_out_th_lock_1); + if (pThis->is_out_th_sleep) + { + DEBUG_DETAIL("CMD:WAKING UP OUT THREADS\n"); + pThis->is_out_th_sleep = false; + pThis->out_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + } + } + if (OMX_StateInvalid == pThis->m_state) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + } else if ((signed)p2 == OMX_ErrorPortUnpopulated) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + (OMX_U32)p2, + 0, + 0 ); + } else + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventCmdComplete, + (OMX_U32)p1, (OMX_U32)p2, NULL ); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:CMD-->EventHandler NULL \n"); + } + } else if (OMX_COMPONENT_GENERATE_COMMAND == id) + { + pThis->send_command_proxy(&pThis->m_cmp, + (OMX_COMMANDTYPE)p1, + (OMX_U32)p2,(OMX_PTR)NULL); + } else if (OMX_COMPONENT_PORTSETTINGS_CHANGED == id) + { + DEBUG_DETAIL("CMD-->RXED PORTSETTINGS_CHANGED"); + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventPortSettingsChanged, + 1, 1, NULL ); + } + else + { + DEBUG_PRINT_ERROR("CMD->state[%d]id[%d]\n",pThis->m_state,ident); + } + return; +} + +/*============================================================================= +FUNCTION: + process_in_port_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_evrc_aenc::process_in_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + unsigned tot_qsize = 0; + omx_evrc_aenc *pThis = (omx_evrc_aenc *) client_data; + OMX_STATETYPE state; + + if (!pThis) + { + DEBUG_PRINT_ERROR("ERROR:IN--> Invalid Obj \n"); + return; + } +loopback_in: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" IN: IN LOADED STATE RETURN\n"); + return; + } + // Protect the shared queue data structure + pthread_mutex_lock(&pThis->m_lock); + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + if ( 0 == tot_qsize ) + { + DEBUG_DETAIL("IN-->BREAKING FROM IN LOOP"); + pthread_mutex_unlock(&pThis->m_lock); + return; + } + + if ( (state != OMX_StateExecuting) && ! (pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_DETAIL("SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + else if ((state == OMX_StatePause)) + { + if(!(pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + + DEBUG_DETAIL("IN: SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + } + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + DEBUG_DETAIL("Input-->QSIZE-flush=%d,ebd=%d QSIZE=%d state=%d\n",\ + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size, state); + + + if ( qsize ) + { + // process FLUSH message + pThis->m_input_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_input_ctrl_ebd_q.m_size) && + (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_input_ctrl_ebd_q.pop_entry(&p1,&p2,&ident); + } else if ((qsize = pThis->m_input_q.m_size) && + (state == OMX_StateExecuting)) + { + // if no FLUSH and EBD's then process ETB's + pThis->m_input_q.pop_entry(&p1, &p2, &ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("IN-->state[%d]cmdq[%d]ebdq[%d]in[%d]\n",\ + state,pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("IN: SLEEPING AGAIN IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pthread_mutex_unlock(&pThis->m_lock); + pThis->in_th_goto_sleep(); + goto loopback_in; + } + } + pthread_mutex_unlock(&pThis->m_lock); + + if ( qsize > 0 ) + { + id = ident; + DEBUG_DETAIL("Input->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + if ( OMX_COMPONENT_GENERATE_BUFFER_DONE == id ) + { + pThis->buffer_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } + else if(id == OMX_COMPONENT_GENERATE_EOS) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventBufferFlag, 0, 1, NULL ); + } else if ( OMX_COMPONENT_GENERATE_ETB == id ) + { + pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_COMMAND == id ) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL(" Executing FLUSH command on Input port\n"); + pThis->execute_input_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } + else + { + DEBUG_PRINT_ERROR("ERROR:IN-->Invalid Id[%u]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR:IN-->Empty INPUT Q\n"); + } + return; +} + +/** + @brief member function for performing component initialization + + @param role C string mandating role of this component + @return Error status + */ +OMX_ERRORTYPE omx_evrc_aenc::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + m_state = OMX_StateLoaded; + + /* DSP does not give information about the bitstream + randomly assign the value right now. Query will result in + incorrect param */ + memset(&m_evrc_param, 0, sizeof(m_evrc_param)); + m_evrc_param.nSize = (OMX_U32)sizeof(m_evrc_param); + m_evrc_param.nChannels = OMX_EVRC_DEFAULT_CH_CFG; + //Current DSP does not have config + m_evrc_param.eCDMARate = OMX_AUDIO_CDMARateFull; + m_evrc_param.nMinBitRate = OMX_EVRC_DEFAULT_MINRATE; + m_evrc_param.nMaxBitRate = OMX_EVRC_DEFAULT_MAXRATE; + m_volume = OMX_EVRC_DEFAULT_VOL; /* Close to unity gain */ + memset(&m_evrc_pb_stats,0,sizeof(EVRC_PB_STATS)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + m_pcm_param.nSize = (OMX_U32)sizeof(m_pcm_param); + m_pcm_param.nChannels = OMX_EVRC_DEFAULT_CH_CFG; + m_pcm_param.nSamplingRate = OMX_EVRC_DEFAULT_SF; + nTimestamp = 0; + + + nNumInputBuf = 0; + nNumOutputBuf = 0; + m_ipc_to_in_th = NULL; // Command server instance + m_ipc_to_out_th = NULL; // Client server instance + m_ipc_to_cmd_th = NULL; // command instance + m_is_out_th_sleep = 0; + m_is_in_th_sleep = 0; + is_out_th_sleep= false; + + is_in_th_sleep=false; + + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + m_priority_mgm.nGroupID =0; + m_priority_mgm.nGroupPriority=0; + + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + m_buffer_supplier.nPortIndex=OMX_BufferSupplyUnspecified; + + DEBUG_PRINT_ERROR(" component init: role = %s\n",role); + + DEBUG_PRINT(" component init: role = %s\n",role); + component_Role.nVersion.nVersion = OMX_SPEC_VERSION; + if (!strcmp(role,"OMX.qcom.audio.encoder.evrc")) + { + pcm_input = 1; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, + (const char*)role, sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.evrc")) + { + pcm_input = 0; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, + (const char*)role, sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else + { + component_Role.nSize = (OMX_U32)sizeof("\0"); + strlcpy((char *)component_Role.cRole, + (const char*)"\0",sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED is invalid\n", role); + } + if(pcm_input) + { + + + m_tmp_meta_buf = (OMX_U8*) malloc(sizeof(OMX_U8) * + (OMX_CORE_INPUT_BUFFER_SIZE + sizeof(META_IN))); + + if (m_tmp_meta_buf == NULL){ + DEBUG_PRINT_ERROR("Mem alloc failed for in meta buf\n"); + return OMX_ErrorInsufficientResources; + } + } + m_tmp_out_meta_buf = + (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_EVRC_OUTPUT_BUFFER_SIZE); + if ( m_tmp_out_meta_buf == NULL ) { + DEBUG_PRINT_ERROR("Mem alloc failed for out meta buf\n"); + return OMX_ErrorInsufficientResources; + } + + if(0 == pcm_input) + { + m_drv_fd = open("/dev/msm_evrc_in",O_RDONLY); + DEBUG_PRINT("Driver in Tunnel mode open\n"); + } + else + { + m_drv_fd = open("/dev/msm_evrc_in",O_RDWR); + DEBUG_PRINT("Driver in Non Tunnel mode open\n"); + } + if (m_drv_fd < 0) + { + DEBUG_PRINT_ERROR("Component_init Open Failed[%d] errno[%d]",\ + m_drv_fd,errno); + + return OMX_ErrorInsufficientResources; + } + if(ioctl(m_drv_fd, AUDIO_GET_SESSION_ID,&m_session_id) == -1) + { + DEBUG_PRINT_ERROR("AUDIO_GET_SESSION_ID FAILED\n"); + } + if(pcm_input) + { + if (!m_ipc_to_in_th) + { + m_ipc_to_in_th = omx_evrc_thread_create(process_in_port_msg, + this, (char *)"INPUT_THREAD"); + if (!m_ipc_to_in_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start \ + Input port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + } + + if (!m_ipc_to_cmd_th) + { + m_ipc_to_cmd_th = omx_evrc_thread_create(process_command_msg, + this, (char *)"CMD_THREAD"); + if (!m_ipc_to_cmd_th) + { + DEBUG_PRINT_ERROR("ERROR!!!Failed to start " + "command message thread\n"); + return OMX_ErrorInsufficientResources; + } + } + + if (!m_ipc_to_out_th) + { + m_ipc_to_out_th = omx_evrc_thread_create(process_out_port_msg, + this, (char *)"OUTPUT_THREAD"); + if (!m_ipc_to_out_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start output " + "port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + return eRet; +} + +/** + + @brief member function to retrieve version of component + + + + @param hComp handle to this component instance + @param componentName name of component + @param componentVersion pointer to memory space which stores the + version number + @param specVersion pointer to memory sapce which stores version of + openMax specification + @param componentUUID + @return Error status + */ +OMX_ERRORTYPE omx_evrc_aenc::get_component_version +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID) +{ + if((hComp == NULL) || (componentName == NULL) || + (specVersion == NULL) || (componentUUID == NULL)) + { + componentVersion = NULL; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + componentVersion->nVersion = OMX_SPEC_VERSION; + specVersion->nVersion = OMX_SPEC_VERSION; + return OMX_ErrorNone; +} +/** + @brief member function handles command from IL client + + This function simply queue up commands from IL client. + Commands will be processed in command server thread context later + + @param hComp handle to component instance + @param cmd type of command + @param param1 parameters associated with the command type + @param cmdData + @return Error status +*/ +OMX_ERRORTYPE omx_evrc_aenc::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + int portIndex = (int)param1; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateInvalid == m_state) + { + return OMX_ErrorInvalidState; + } + if ( (cmd == OMX_CommandFlush) && (portIndex > 1) ) + { + return OMX_ErrorBadPortIndex; + } + post_command((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + DEBUG_PRINT("Send Command : returns with OMX_ErrorNone \n"); + DEBUG_PRINT("send_command : recieved state before semwait= %u\n",param1); + sem_wait (&sem_States); + DEBUG_PRINT("send_command : recieved state after semwait\n"); + return OMX_ErrorNone; +} + +/** + @brief member function performs actual processing of commands excluding + empty buffer call + + @param hComp handle to component + @param cmd command type + @param param1 parameter associated with the command + @param cmdData + + @return error status +*/ +OMX_ERRORTYPE omx_evrc_aenc::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + // Handle only IDLE and executing + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1; + nState = eState; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_CommandStateSet == cmd) + { + /***************************/ + /* Current State is Loaded */ + /***************************/ + if (OMX_StateLoaded == m_state) + { + if (OMX_StateIdle == eState) + { + + if (allocate_done() || + (m_inp_bEnabled == OMX_FALSE + && m_out_bEnabled == OMX_FALSE)) + { + DEBUG_PRINT("SCP-->Allocate Done Complete\n"); + } + else + { + DEBUG_PRINT("SCP-->Loaded to Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + bFlag = 0; + } + + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Loaded\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } + + else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->WaitForResources\n"); + eRet = OMX_ErrorNone; + } + + else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Executing\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Pause\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Invalid\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + m_state = OMX_StateInvalid; + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP-->Loaded to Invalid(%d))\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if (OMX_StateIdle == m_state) + { + if (OMX_StateLoaded == eState) + { + if (release_done(-1)) + { + if (ioctl(m_drv_fd, AUDIO_STOP, 0) == -1) + { + DEBUG_PRINT_ERROR("SCP:Idle->Loaded,\ + ioctl stop failed %d\n", errno); + } + + nTimestamp=0; + + DEBUG_PRINT("SCP-->Idle to Loaded\n"); + } else + { + DEBUG_PRINT("SCP--> Idle to Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + else if (OMX_StateExecuting == eState) + { + + struct msm_audio_evrc_enc_config drv_evrc_enc_config; + struct msm_audio_stream_config drv_stream_config; + struct msm_audio_buf_cfg buf_cfg; + struct msm_audio_config pcm_cfg; + + if(ioctl(m_drv_fd, AUDIO_GET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + if(ioctl(m_drv_fd, AUDIO_SET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + + if(ioctl(m_drv_fd, AUDIO_GET_EVRC_ENC_CONFIG, + &drv_evrc_enc_config) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_EVRC_ENC_CONFIG failed,\ + errno[%d]\n", errno); + } + drv_evrc_enc_config.min_bit_rate = m_evrc_param.nMinBitRate; + drv_evrc_enc_config.max_bit_rate = m_evrc_param.nMaxBitRate; + if(ioctl(m_drv_fd, AUDIO_SET_EVRC_ENC_CONFIG, &drv_evrc_enc_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_EVRC_ENC_CONFIG failed,\ + errno[%d]\n", errno); + } + if (ioctl(m_drv_fd, AUDIO_GET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_BUF_CFG, errno[%d]\n", + errno); + } + buf_cfg.meta_info_enable = 1; + buf_cfg.frames_per_buf = NUMOFFRAMES; + if (ioctl(m_drv_fd, AUDIO_SET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_BUF_CFG, errno[%d]\n", + errno); + } + if(pcm_input) + { + if (ioctl(m_drv_fd, AUDIO_GET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_CONFIG, errno[%d]\n", + errno); + } + pcm_cfg.channel_count = m_pcm_param.nChannels; + pcm_cfg.sample_rate = m_pcm_param.nSamplingRate; + DEBUG_PRINT("pcm config %u %u\n",m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + + if (ioctl(m_drv_fd, AUDIO_SET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_CONFIG, errno[%d]\n", + errno); + } + } + if(ioctl(m_drv_fd, AUDIO_START, 0) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_START failed, errno[%d]\n", + errno); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + + } + DEBUG_PRINT("SCP-->Idle to Executing\n"); + nState = eState; + } else if (eState == OMX_StateIdle) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Idle\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Pause\n"); + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Idle to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if (OMX_StateExecuting == m_state) + { + if (OMX_StateIdle == eState) + { + DEBUG_PRINT("SCP-->Executing to Idle \n"); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + + } else if (OMX_StatePause == eState) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED PAUSE STATE\n"); + DEBUG_DETAIL("*************************\n"); + //ioctl(m_drv_fd, AUDIO_PAUSE, 0); + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Executing \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Executing to %d Not Handled\n", + eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if (OMX_StatePause == m_state) + { + if( (eState == OMX_StateExecuting || eState == OMX_StateIdle) ) + { + pthread_mutex_lock(&m_out_th_lock_1); + if(is_out_th_sleep) + { + DEBUG_DETAIL("PE: WAKING UP OUT THREAD\n"); + is_out_th_sleep = false; + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } + if ( OMX_StateExecuting == eState ) + { + nState = eState; + } else if ( OMX_StateIdle == eState ) + { + DEBUG_PRINT("SCP-->Paused to Idle \n"); + DEBUG_PRINT ("\n Internal flush issued"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + } else if ( eState == OMX_StateLoaded ) + { + DEBUG_PRINT("\n Pause --> loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n Pause --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("\n Pause --> Pause \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n Pause --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT("SCP-->Paused to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /**************************************/ + /* Current State is WaitForResources */ + /**************************************/ + else if (m_state == OMX_StateWaitForResources) + { + if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Loaded\n"); + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: \ + WaitForResources-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Executing\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Pause\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> %d to %d(Not Handled)\n", + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /****************************/ + /* Current State is Invalid */ + /****************************/ + else if (m_state == OMX_StateInvalid) + { + if (OMX_StateLoaded == eState || OMX_StateWaitForResources == eState + || OMX_StateIdle == eState || OMX_StateExecuting == eState + || OMX_StatePause == eState || OMX_StateInvalid == eState) + { + DEBUG_PRINT("OMXCORE-SM: Invalid-->Loaded/Idle/Executing" + "/Pause/Invalid/WaitForResources\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } + } else + { + DEBUG_PRINT_ERROR("OMXCORE-SM: %d --> %d(Not Handled)\n",\ + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } else if (OMX_CommandFlush == cmd) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED FLUSH COMMAND port=%u\n",param1); + DEBUG_DETAIL("*************************\n"); + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || + param1 == OMX_CORE_OUTPUT_PORT_INDEX || + (signed)param1 == -1 ) + { + execute_omx_flush(param1); + } else + { + eRet = OMX_ErrorBadPortIndex; + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError, + OMX_CommandFlush, OMX_ErrorBadPortIndex, NULL ); + } + } else if ( cmd == OMX_CommandPortDisable ) + { + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL ) + { + DEBUG_PRINT("SCP: Disabling Input port Indx\n"); + m_inp_bEnabled = OMX_FALSE; + if ( (m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(0) ) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_inp_bEnabled = %d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + + else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable in "\ + " param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + // Skip the event notification + + } + + } + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + + DEBUG_PRINT("SCP: Disabling Output port Indx\n"); + m_out_bEnabled = OMX_FALSE; + if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(1)) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_out_bEnabled = %d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable out "\ + "param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + // Skip the event notification + + } + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortDisable: disable wrong port ID"); + } + + } else if (cmd == OMX_CommandPortEnable) + { + bFlag = 0; + if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_TRUE; + DEBUG_PRINT("SCP: Enabling Input port Indx\n"); + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_inp_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + + } else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + + } + } + + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + DEBUG_PRINT("SCP: Enabling Output port Indx\n"); + m_out_bEnabled = OMX_TRUE; + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_out_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortEnable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + + } + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_PRINT("SCP:WAKING OUT THR, OMX_CommandPortEnable\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortEnable: disable wrong port ID"); + } + + } else + { + DEBUG_PRINT_ERROR("SCP-->ERROR: Invali Command [%d]\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + DEBUG_PRINT("posting sem_States\n"); + sem_post (&sem_States); + if (eRet == OMX_ErrorNone && bFlag) + { + post_command(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + return eRet; +} + +/*============================================================================= +FUNCTION: + execute_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + [IN] param1 + [IN] cmd_cmpl + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_evrc_aenc::execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl) +{ + bool bRet = true; + + DEBUG_PRINT("Execute_omx_flush Port[%u]", param1); + struct timespec abs_timeout; + abs_timeout.tv_sec = 1; + abs_timeout.tv_nsec = 0; + + if ((signed)param1 == -1) + { + bFlushinprogress = true; + DEBUG_PRINT("Execute flush for both I/p O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + + // Send Flush commands to input and output threads + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + // Send Flush to the kernel so that the in and out buffers are released + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("FLush:ioctl flush failed errno=%d\n",errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + + + // sleep till the FLUSH ACK are done by both the input and + // output threads + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + + DEBUG_PRINT("RECIEVED BOTH FLUSH ACK's param1=%u cmd_cmpl=%d",\ + param1,cmd_cmpl); + + // If not going to idle state, Send FLUSH complete message + // to the Client, now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + DEBUG_PRINT("Inside FLUSH.. sending FLUSH CMPL\n"); + } + bFlushinprogress = false; + } + else if (param1 == OMX_CORE_INPUT_PORT_INDEX) + { + DEBUG_PRINT("Execute FLUSH for I/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + //sleep till the FLUSH ACK are done by both the input and output threads + DEBUG_DETAIL("Executing FLUSH for I/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + DEBUG_DETAIL(" RECIEVED FLUSH ACK FOR I/P PORT param1=%d",param1); + + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == param1) + { + DEBUG_PRINT("Executing FLUSH for O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + DEBUG_DETAIL("Executing FLUSH for O/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) ==-1) + DEBUG_PRINT_ERROR("Flush:Output port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + // sleep till the FLUSH ACK are done by both the input and + // output threads + wait_for_event(); + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + } + DEBUG_DETAIL("RECIEVED FLUSH ACK FOR O/P PORT param1=%d",param1); + } else + { + DEBUG_PRINT("Invalid Port ID[%u]",param1); + } + return bRet; +} + +/*============================================================================= +FUNCTION: + execute_input_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_evrc_aenc::execute_input_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on input port"); + + pthread_mutex_lock(&m_lock); + do + { + qsize = m_input_q.m_size; + tot_qsize = qsize; + tot_qsize += m_input_ctrl_ebd_q.m_size; + + DEBUG_DETAIL("Input FLUSH-->flushq[%d] ebd[%d]dataq[%d]",\ + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size,qsize); + if (!tot_qsize) + { + DEBUG_DETAIL("Input-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_lock); + break; + } + if (qsize) + { + m_input_q.pop_entry(&p1, &p2, &ident); + if ((ident == OMX_COMPONENT_GENERATE_ETB) || + (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Flush:Input dataq=%p \n", omx_buf); + omx_buf->nFilledLen = 0; + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else if (m_input_ctrl_ebd_q.m_size) + { + m_input_ctrl_ebd_q.pop_entry(&p1, &p2, &ident); + if (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + omx_buf->nFilledLen = 0; + DEBUG_DETAIL("Flush:ctrl dataq=%p \n", omx_buf); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else + { + } + }while (tot_qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("IN-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_lock); + return true; +} + +/*============================================================================= +FUNCTION: + execute_output_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_evrc_aenc::execute_output_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1; // Parameter - 1 + unsigned long p2; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on output port"); + + pthread_mutex_lock(&m_outputlock); + do + { + qsize = m_output_q.m_size; + DEBUG_DETAIL("OUT FLUSH-->flushq[%d] fbd[%d]dataq[%d]",\ + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size,qsize); + tot_qsize = qsize; + tot_qsize += m_output_ctrl_fbd_q.m_size; + if (!tot_qsize) + { + DEBUG_DETAIL("OUT-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_outputlock); + break; + } + if (qsize) + { + m_output_q.pop_entry(&p1,&p2,&ident); + if ( (OMX_COMPONENT_GENERATE_FTB == ident) || + (OMX_COMPONENT_GENERATE_FRAME_DONE == ident)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n",\ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FBD FROM FLUSH"); + } + } else if ((qsize = m_output_ctrl_fbd_q.m_size)) + { + m_output_ctrl_fbd_q.pop_entry(&p1, &p2, &ident); + if (OMX_COMPONENT_GENERATE_FRAME_DONE == ident) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n", \ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FROM CTRL-FBDQ FROM FLUSH"); + } + } + }while (qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("OUT-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_outputlock); + return true; +} + +/*============================================================================= +FUNCTION: + post_input + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_evrc_aenc::post_input(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + pthread_mutex_lock(&m_lock); + + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND)) + { + // insert flush message and ebd + m_input_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ((OMX_COMPONENT_GENERATE_BUFFER_DONE == id)) + { + // insert ebd + m_input_ctrl_ebd_q.insert_entry(p1,p2,id); + } else + { + // ETBS in this queue + m_input_q.insert_entry(p1,p2,id); + } + + if (m_ipc_to_in_th) + { + bRet = true; + omx_evrc_post_msg(m_ipc_to_in_th, id); + } + + DEBUG_DETAIL("PostInput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d] \n",\ + m_state, + id, + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size, + m_input_q.m_size); + + pthread_mutex_unlock(&m_lock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_command + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_evrc_aenc::post_command(unsigned int p1, + unsigned int p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_commandlock); + + m_command_q.insert_entry(p1,p2,id); + + if (m_ipc_to_cmd_th) + { + bRet = true; + omx_evrc_post_msg(m_ipc_to_cmd_th, id); + } + + DEBUG_DETAIL("PostCmd-->state[%d]id[%d]cmdq[%d]flags[%x]\n",\ + m_state, + id, + m_command_q.m_size, + m_flags >> 3); + + pthread_mutex_unlock(&m_commandlock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_output + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_evrc_aenc::post_output(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_outputlock); + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND) + || (id == OMX_COMPONENT_RESUME)) + { + // insert flush message and fbd + m_output_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ( (OMX_COMPONENT_GENERATE_FRAME_DONE == id) ) + { + // insert flush message and fbd + m_output_ctrl_fbd_q.insert_entry(p1,p2,id); + } else + { + m_output_q.insert_entry(p1,p2,id); + } + if ( m_ipc_to_out_th ) + { + bRet = true; + omx_evrc_post_msg(m_ipc_to_out_th, id); + } + DEBUG_DETAIL("PostOutput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + m_state, + id, + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size, + m_output_q.m_size); + + pthread_mutex_unlock(&m_outputlock); + return bRet; +} +/** + @brief member function that return parameters to IL client + + @param hComp handle to component instance + @param paramIndex Parameter type + @param paramData pointer to memory space which would hold the + paramter + @return error status +*/ +OMX_ERRORTYPE omx_evrc_aenc::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (paramData == NULL) + { + DEBUG_PRINT("get_parameter: paramData is NULL\n"); + return OMX_ErrorBadParameter; + } + + switch ((int)paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + DEBUG_PRINT("OMX_IndexParamPortDefinition " \ + "portDefn->nPortIndex = %u\n", + portDefn->nPortIndex); + + portDefn->nVersion.nVersion = OMX_SPEC_VERSION; + portDefn->nSize = (OMX_U32)sizeof(portDefn); + portDefn->eDomain = OMX_PortDomainAudio; + + if (0 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirInput; + portDefn->bEnabled = m_inp_bEnabled; + portDefn->bPopulated = m_inp_bPopulated; + portDefn->nBufferCountActual = m_inp_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_INPUT_BUFFERS; + portDefn->nBufferSize = input_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingPCM; + portDefn->format.audio.pNativeRender = 0; + } else if (1 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirOutput; + portDefn->bEnabled = m_out_bEnabled; + portDefn->bPopulated = m_out_bPopulated; + portDefn->nBufferCountActual = m_out_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_OUTPUT_BUFFERS; + portDefn->nBufferSize = output_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingEVRC; + portDefn->format.audio.pNativeRender = 0; + } else + { + portDefn->eDir = OMX_DirMax; + DEBUG_PRINT_ERROR("Bad Port idx %d\n",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioInit\n"); + + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 2; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioPortFormat\n"); + portFormatType->nVersion.nVersion = OMX_SPEC_VERSION; + portFormatType->nSize = (OMX_U32)sizeof(portFormatType); + + if (OMX_CORE_INPUT_PORT_INDEX == portFormatType->nPortIndex) + { + + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX== + portFormatType->nPortIndex) + { + DEBUG_PRINT("get_parameter: OMX_IndexParamAudioFormat: "\ + "%u\n", portFormatType->nIndex); + + portFormatType->eEncoding = OMX_AUDIO_CodingEVRC; + } else + { + DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioEvrc: + { + OMX_AUDIO_PARAM_EVRCTYPE *evrcParam = + (OMX_AUDIO_PARAM_EVRCTYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioEvrc\n"); + if (OMX_CORE_OUTPUT_PORT_INDEX== evrcParam->nPortIndex) + { + memcpy(evrcParam,&m_evrc_param, + sizeof(OMX_AUDIO_PARAM_EVRCTYPE)); + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioEvrc "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)evrcParam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case QOMX_IndexParamAudioSessionId: + { + QOMX_AUDIO_STREAM_INFO_DATA *streaminfoparam = + (QOMX_AUDIO_STREAM_INFO_DATA *) paramData; + streaminfoparam->sessionId = (OMX_U8)m_session_id; + break; + } + + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam = + (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(pcmparam,&m_pcm_param,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + DEBUG_PRINT("get_parameter: Sampling rate %u",\ + pcmparam->nSamplingRate); + DEBUG_PRINT("get_parameter: Number of channels %u",\ + pcmparam->nChannels); + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioPcm "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamComponentSuspended: + { + OMX_PARAM_SUSPENSIONTYPE *suspend = + (OMX_PARAM_SUSPENSIONTYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamComponentSuspended %p\n", + suspend); + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamVideoInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *priorityMgmtType = + (OMX_PRIORITYMGMTTYPE*)paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamPriorityMgmt\n"); + priorityMgmtType->nSize = (OMX_U32)sizeof(priorityMgmtType); + priorityMgmtType->nVersion.nVersion = OMX_SPEC_VERSION; + priorityMgmtType->nGroupID = m_priority_mgm.nGroupID; + priorityMgmtType->nGroupPriority = + m_priority_mgm.nGroupPriority; + break; + } + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamImageInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + + bufferSupplierType->nSize = (OMX_U32)sizeof(bufferSupplierType); + bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; + if (OMX_CORE_INPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else + { + DEBUG_PRINT_ERROR("get_parameter:"\ + "OMX_IndexParamCompBufferSupplier eRet"\ + "%08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamOtherInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + componentRole->nSize = component_Role.nSize; + componentRole->nVersion = component_Role.nVersion; + strlcpy((char *)componentRole->cRole, + (const char*)component_Role.cRole, + sizeof(componentRole->cRole)); + DEBUG_PRINT_ERROR("nSize = %d , nVersion = %d, cRole = %s\n", + component_Role.nSize, + component_Role.nVersion, + component_Role.cRole); + break; + + } + default: + { + DEBUG_PRINT_ERROR("unknown param %08x\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; + +} + +/** + @brief member function that set paramter from IL client + + @param hComp handle to component instance + @param paramIndex parameter type + @param paramData pointer to memory space which holds the paramter + @return error status + */ +OMX_ERRORTYPE omx_evrc_aenc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("set_parameter is not in proper state\n"); + return OMX_ErrorIncorrectStateOperation; + } + if (paramData == NULL) + { + DEBUG_PRINT("param data is NULL"); + return OMX_ErrorBadParameter; + } + + switch (paramIndex) + { + case OMX_IndexParamAudioEvrc: + { + DEBUG_PRINT("OMX_IndexParamAudioEvrc"); + OMX_AUDIO_PARAM_AMRTYPE *evrcparam + = (OMX_AUDIO_PARAM_AMRTYPE *) paramData; + memcpy(&m_evrc_param,evrcparam, + sizeof(OMX_AUDIO_PARAM_EVRCTYPE)); + break; + } + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + if (((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources && + ((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == true)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == true))) + ||(((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == false)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == false)) && + (m_state != OMX_StateWaitForResources))) + { + DEBUG_PRINT("Set Parameter called in valid state\n"); + } else + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + DEBUG_PRINT("OMX_IndexParamPortDefinition portDefn->nPortIndex " + "= %u\n",portDefn->nPortIndex); + if (OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_INPUT_BUFFERS ) + { + m_inp_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_inp_act_buf_count =OMX_CORE_NUM_INPUT_BUFFERS; + } + input_buffer_size = portDefn->nBufferSize; + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_OUTPUT_BUFFERS ) + { + m_out_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_out_act_buf_count =OMX_CORE_NUM_OUTPUT_BUFFERS; + } + output_buffer_size = portDefn->nBufferSize; + } else + { + DEBUG_PRINT(" set_parameter: Bad Port idx %d",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamPriorityMgmt: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt\n"); + + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype + = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt %u\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT("set_parameter: priorityMgmtype %u\n", + priorityMgmtype->nGroupPriority); + + m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; + m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + case OMX_IndexParamAudioPortFormat: + { + + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPortFormat\n"); + + if (OMX_CORE_INPUT_PORT_INDEX== portFormatType->nPortIndex) + { + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + portFormatType->nPortIndex) + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioFormat:"\ + " %u\n", portFormatType->nIndex); + portFormatType->eEncoding = OMX_AUDIO_CodingEVRC; + } else + { + DEBUG_PRINT_ERROR("set_parameter: Bad port index %d\n", \ + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("set_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("set_param: OMX_IndexParamCompBufferSupplier %d",\ + bufferSupplierType->eBufferSupplier); + + if (bufferSupplierType->nPortIndex == OMX_CORE_INPUT_PORT_INDEX + || bufferSupplierType->nPortIndex == + OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT("set_parameter:\ + OMX_IndexParamCompBufferSupplier\n"); + m_buffer_supplier.eBufferSupplier = + bufferSupplierType->eBufferSupplier; + } else + { + DEBUG_PRINT_ERROR("set_param:\ + IndexParamCompBufferSup %08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + + break; } + + case OMX_IndexParamAudioPcm: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPcm\n"); + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam + = (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(&m_pcm_param,pcmparam,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + DEBUG_PRINT("set_pcm_parameter: %u %u",\ + m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + } else + { + DEBUG_PRINT_ERROR("Set_parameter:OMX_IndexParamAudioPcm " + "OMX_ErrorBadPortIndex %d\n", + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamSuspensionPolicy: + { + eRet = OMX_ErrorNotImplemented; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + component_Role.nSize = componentRole->nSize; + component_Role.nVersion = componentRole->nVersion; + strlcpy((char *)component_Role.cRole, + (const char*)componentRole->cRole, + sizeof(component_Role.cRole)); + break; + } + + default: + { + DEBUG_PRINT_ERROR("unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *volume = + (OMX_AUDIO_CONFIG_VOLUMETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == volume->nPortIndex) + { + volume->nSize = (OMX_U32)sizeof(volume); + volume->nVersion.nVersion = OMX_SPEC_VERSION; + volume->bLinear = OMX_TRUE; + volume->sVolume.nValue = m_volume; + volume->sVolume.nMax = OMX_AENC_MAX; + volume->sVolume.nMin = OMX_AENC_MIN; + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = + (OMX_AUDIO_CONFIG_MUTETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == mute->nPortIndex) + { + mute->nSize = (OMX_U32)sizeof(mute); + mute->nVersion.nVersion = OMX_SPEC_VERSION; + mute->bMute = (BITMASK_PRESENT(&m_flags, + OMX_COMPONENT_MUTED)?OMX_TRUE:OMX_FALSE); + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Set Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if ( m_state == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *vol = + (OMX_AUDIO_CONFIG_VOLUMETYPE*)configData; + if (vol->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if ((vol->sVolume.nValue <= OMX_AENC_MAX) && + (vol->sVolume.nValue >= OMX_AENC_MIN)) + { + m_volume = vol->sVolume.nValue; + if (BITMASK_ABSENT(&m_flags, OMX_COMPONENT_MUTED)) + { + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + + } else + { + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = (OMX_AUDIO_CONFIG_MUTETYPE*) + configData; + if (mute->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if (mute->bMute == OMX_TRUE) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, 0); */ + } else + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. <TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::get_extension_index( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if((hComp == NULL) || (paramName == NULL) || (indexType == NULL)) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(strncmp(paramName,"OMX.Qualcomm.index.audio.sessionId", + strlen("OMX.Qualcomm.index.audio.sessionId")) == 0) + { + *indexType =(OMX_INDEXTYPE)QOMX_IndexParamAudioSessionId; + DEBUG_PRINT("Extension index type - %d\n", *indexType); + + } + else + { + return OMX_ErrorBadParameter; + + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::GetState + +DESCRIPTION + Returns the state information back to the caller.<TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + *state = m_state; + DEBUG_PRINT("Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. <TBD> + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::component_tunnel_request +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n"); + + if((hComp == NULL) || (peerComponent == NULL) || (tunnelSetup == NULL)) + { + port = port; + peerPort = peerPort; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::allocate_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + if(m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc((nBufSize + \ + sizeof(OMX_BUFFERHEADERTYPE)+sizeof(META_IN)) , 1); + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + free(buf_ptr); + return OMX_ErrorBadParameter; + } + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + sizeof(META_IN)+ + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + m_input_buf_hdrs.insert(bufHdr, NULL); + + m_inp_current_buf_count++; + DEBUG_PRINT("AIB:bufHdr %p bufHdr->pBuffer %p m_inp_buf_cnt=%u \ + bytes=%u", bufHdr, bufHdr->pBuffer, + m_inp_current_buf_count, bytes); + + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT("Input buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +OMX_ERRORTYPE omx_evrc_aenc::allocate_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_out_current_buf_count < m_out_act_buf_count) + { + buf_ptr = (char *) calloc( (nBufSize + sizeof(OMX_BUFFERHEADERTYPE)),1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + DEBUG_PRINT("AOB::bufHdr %p bufHdr->pBuffer %p m_out_buf_cnt=%d "\ + "bytes=%u",bufHdr, bufHdr->pBuffer,\ + m_out_current_buf_count, bytes); + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_evrc_aenc::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::allocate_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + // What if the client calls again. + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n", + (int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("allocate_buffer: before allocate_done \n"); + if (allocate_done()) + { + DEBUG_PRINT("allocate_buffer: after allocate_done \n"); + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("allocate_buffer: post idle transition event \n"); + } + DEBUG_PRINT("allocate_buffer: complete \n"); + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + m_out_bEnabled = OMX_TRUE; + + DEBUG_PRINT("AllocBuf-->is_out_th_sleep=%d\n",is_out_th_sleep); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("AllocBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("AB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + } + DEBUG_PRINT("Allocate Buffer exit with ret Code %d\n", eRet); + return eRet; +} + +/*============================================================================= +FUNCTION: + use_buffer + +DESCRIPTION: + OMX Use Buffer method implementation. + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_evrc_aenc::use_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("Checking for Output Allocate buffer Done"); + if (allocate_done()) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("UseBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("UB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + } + } + DEBUG_PRINT("Use Buffer for port[%u] eRet[%d]\n", port,eRet); + return eRet; +} +/*============================================================================= +FUNCTION: + use_input_buffer + +DESCRIPTION: + Helper function for Use buffer in the input pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_evrc_aenc::use_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if(bytes < input_buffer_size) + { + /* return if i\p buffer size provided by client + is less than min i\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + if (m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_input_buffer:bufHdr %p bufHdr->pBuffer %p \ + bytes=%u", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + input_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_input_buf_hdrs.insert(bufHdr, NULL); + m_inp_current_buf_count++; + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Input buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +/*============================================================================= +FUNCTION: + use_output_buffer + +DESCRIPTION: + Helper function for Use buffer in the output pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_evrc_aenc::use_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (bytes < output_buffer_size) + { + /* return if o\p buffer size provided by client + is less than min o\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT("Inside omx_evrc_aenc::use_output_buffer"); + if (m_out_current_buf_count < m_out_act_buf_count) + { + + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + DEBUG_PRINT("BufHdr=%p buffer=%p\n",bufHdr,buffer); + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_output_buffer:bufHdr %p bufHdr->pBuffer %p \ + len=%u\n", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + output_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_evrc_aenc::search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_input_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_input_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_evrc_aenc::search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_output_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_output_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +// Free Buffer - API call +/** + @brief member function that handles free buffer command from IL client + + This function is a block-call function that handles IL client request to + freeing the buffer + + @param hComp handle to component instance + @param port id of port which holds the buffer + @param buffer buffer header + @return Error status +*/ +OMX_ERRORTYPE omx_evrc_aenc::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("Free_Buffer buf %p\n", buffer); + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT(" free buffer while Component in Loading pending\n"); + } else if ((m_inp_bEnabled == OMX_FALSE && + port == OMX_CORE_INPUT_PORT_INDEX)|| + (m_out_bEnabled == OMX_FALSE && + port == OMX_CORE_OUTPUT_PORT_INDEX)) + { + DEBUG_PRINT("Free Buffer while port %u disabled\n", port); + } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT("Invalid state to free buffer,ports need to be disabled:\ + OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return eRet; + } else + { + DEBUG_PRINT("free_buffer: Invalid state to free buffer,ports need to be\ + disabled:OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + if (m_inp_current_buf_count != 0) + { + m_inp_bPopulated = OMX_FALSE; + if (true == search_input_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:in_buffer[%p]\n",buffer); + m_input_buf_hdrs.erase(buffer); + free(buffer); + m_inp_current_buf_count--; + } else + { + DEBUG_PRINT_ERROR("Free_Buf:Error-->free_buffer, \ + Invalid Input buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + DEBUG_PRINT_ERROR("Error: free_buffer,Port Index calculation \ + came out Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_done(0)) + { + DEBUG_PRINT("INPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + if (m_out_current_buf_count != 0) + { + m_out_bPopulated = OMX_FALSE; + if (true == search_output_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:out_buffer[%p]\n",buffer); + m_output_buf_hdrs.erase(buffer); + free(buffer); + m_out_current_buf_count--; + } else + { + DEBUG_PRINT("Free_Buf:Error-->free_buffer , \ + Invalid Output buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_done(1)) + { + DEBUG_PRINT("OUTPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + if ((OMX_ErrorNone == eRet) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if (release_done(-1)) + { + if(ioctl(m_drv_fd, AUDIO_STOP, 0) < 0) + DEBUG_PRINT_ERROR("AUDIO STOP in free buffer failed\n"); + else + DEBUG_PRINT("AUDIO STOP in free buffer passed\n"); + + + DEBUG_PRINT("Free_Buf: Free buffer\n"); + + + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + DEBUG_PRINT("Before OMX_StateLoaded \ + OMX_COMPONENT_GENERATE_EVENT\n"); + post_command(OMX_CommandStateSet, + OMX_StateLoaded,OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("After OMX_StateLoaded OMX_COMPONENT_GENERATE_EVENT\n"); + + } + } + return eRet; +} + + +/** + @brief member function that that handles empty this buffer command + + This function meremly queue up the command and data would be consumed + in command server thread context + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_evrc_aenc::empty_this_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("ETB:Buf:%p Len %u TS %lld numInBuf=%d\n", \ + buffer, buffer->nFilledLen, buffer->nTimeStamp, (nNumInputBuf)); + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (!m_inp_bEnabled) + { + DEBUG_PRINT("empty_this_buffer OMX_ErrorIncorrectStateOperation "\ + "Port Status %d \n", m_inp_bEnabled); + return OMX_ErrorIncorrectStateOperation; + } + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_evrc_aenc::etb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_evrc_aenc::etb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + if ((m_state != OMX_StateExecuting) && + (m_state != OMX_StatePause)) + { + DEBUG_PRINT_ERROR("Invalid state\n"); + eRet = OMX_ErrorInvalidState; + } + if (OMX_ErrorNone == eRet) + { + if (search_input_bufhdr(buffer) == true) + { + post_input((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_ETB); + } else + { + DEBUG_PRINT_ERROR("Bad header %p \n", buffer); + eRet = OMX_ErrorBadParameter; + } + } + pthread_mutex_lock(&in_buf_count_lock); + nNumInputBuf++; + m_evrc_pb_stats.etb_cnt++; + pthread_mutex_unlock(&in_buf_count_lock); + return eRet; +} +/** + @brief member function that writes data to kernel driver + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_evrc_aenc::empty_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + META_IN meta_in; + //Pointer to the starting location of the data to be transcoded + OMX_U8 *srcStart; + //The total length of the data to be transcoded + srcStart = buffer->pBuffer; + OMX_U8 *data = NULL; + PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer); + memset(&meta_in,0,sizeof(meta_in)); + if ( search_input_bufhdr(buffer) == false ) + { + DEBUG_PRINT("ETBP: INVALID BUF HDR\n"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorBadParameter; + } + if (m_tmp_meta_buf) + { + data = m_tmp_meta_buf; + + // copy the metadata info from the BufHdr and insert to payload + meta_in.offsetVal = (OMX_U16)sizeof(META_IN); + meta_in.nTimeStamp.LowPart = + (unsigned int) ((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) & 0xFFFFFFFF); + meta_in.nTimeStamp.HighPart = + (unsigned int) (((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) >> 32) & 0xFFFFFFFF); + meta_in.nFlags &= ~OMX_BUFFERFLAG_EOS; + if(buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + DEBUG_PRINT("EOS OCCURED \n"); + meta_in.nFlags |= OMX_BUFFERFLAG_EOS; + } + memcpy(data,&meta_in, meta_in.offsetVal); + DEBUG_PRINT("meta_in.nFlags = %d\n",meta_in.nFlags); + } + + memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen); + write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN)); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (OMX_StateExecuting == state) + { + DEBUG_DETAIL("In Exe state, EBD CB"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + } else + { + /* Assume empty this buffer function has already checked + validity of buffer */ + DEBUG_PRINT("Empty buffer %p to kernel driver\n", buffer); + post_input((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_BUFFER_DONE); + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_evrc_aenc::fill_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + ENC_META_OUT *meta_out = NULL; + ssize_t nReadbytes = 0; + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (true == search_output_bufhdr(buffer)) + { + DEBUG_PRINT("\nBefore Read..m_drv_fd = %d,\n",m_drv_fd); + nReadbytes = read(m_drv_fd,buffer->pBuffer,output_buffer_size ); + DEBUG_DETAIL("FTBP->Al_len[%lu]buf[%p]size[%d]numOutBuf[%d]\n",\ + buffer->nAllocLen,buffer->pBuffer, + nReadbytes,nNumOutputBuf); + if (nReadbytes <= 0) { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorNone; + } else + DEBUG_PRINT("Read bytes %d\n",nReadbytes); + // Buffer from Driver will have + // 1 byte => Nr of frame field + // (sizeof(ENC_META_OUT) * Nr of frame) bytes => meta_out->offset_to_frame + // Frame Size * Nr of frame => + + meta_out = (ENC_META_OUT *)(buffer->pBuffer + sizeof(unsigned char)); + buffer->nTimeStamp = (((OMX_TICKS) meta_out->msw_ts << 32)+ + meta_out->lsw_ts); + buffer->nFlags |= meta_out->nflags; + buffer->nOffset = (OMX_U32)(meta_out->offset_to_frame + + sizeof(unsigned char)); + buffer->nFilledLen = (OMX_U32)(nReadbytes - buffer->nOffset); + nTimestamp = buffer->nTimeStamp; + DEBUG_PRINT("nflags %d frame_size %d offset_to_frame %d \ + timestamp %lld\n", meta_out->nflags, + meta_out->frame_size, meta_out->offset_to_frame, + buffer->nTimeStamp); + + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + DEBUG_PRINT("FTBP: Now, Send EOS flag to Client \n"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + } + + return OMX_ErrorNone; + } + DEBUG_PRINT("nState %d \n",nState ); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (state == OMX_StatePause) + { + DEBUG_PRINT("FTBP:Post the FBD to event thread currstate=%d\n",\ + state); + post_output((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_FRAME_DONE); + } + else + { + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + + } + + } + else + DEBUG_PRINT("\n FTBP-->Invalid buffer in FTB \n"); + + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + + + +PARAMETERS + + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::fill_this_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_evrc_aenc::ftb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (m_out_bEnabled == OMX_FALSE) + { + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_evrc_aenc::ftb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf++; + m_evrc_pb_stats.ftb_cnt++; + DEBUG_DETAIL("FTB:nNumOutputBuf is %d", nNumOutputBuf); + pthread_mutex_unlock(&out_buf_count_lock); + post_output((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_FTB); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + m_cb = *callbacks; + m_app_data = appData; + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateLoaded != m_state && OMX_StateInvalid != m_state) + { + DEBUG_PRINT_ERROR("Warning: Rxed DeInit when not in LOADED state %d\n", + m_state); + } + deinit_encoder(); + +DEBUG_PRINT_ERROR("%s:COMPONENT DEINIT...\n", __FUNCTION__); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::deinit_encoder + +DESCRIPTION + Closes all the threads and release memory allocated to the heap. + +PARAMETERS + None. + +RETURN VALUE + None. + +========================================================================== */ +void omx_evrc_aenc::deinit_encoder() +{ + DEBUG_PRINT("Component-deinit being processed\n"); + DEBUG_PRINT("********************************\n"); + DEBUG_PRINT("STATS: in-buf-len[%u]out-buf-len[%u] tot-pb-time[%lld]",\ + m_evrc_pb_stats.tot_in_buf_len, + m_evrc_pb_stats.tot_out_buf_len, + m_evrc_pb_stats.tot_pb_time); + DEBUG_PRINT("STATS: fbd-cnt[%u]ftb-cnt[%u]etb-cnt[%u]ebd-cnt[%u]",\ + m_evrc_pb_stats.fbd_cnt,m_evrc_pb_stats.ftb_cnt, + m_evrc_pb_stats.etb_cnt, + m_evrc_pb_stats.ebd_cnt); + memset(&m_evrc_pb_stats,0,sizeof(EVRC_PB_STATS)); + + if((OMX_StateLoaded != m_state) && (OMX_StateInvalid != m_state)) + { + DEBUG_PRINT_ERROR("%s,Deinit called in state[%d]\n",__FUNCTION__,\ + m_state); + // Get back any buffers from driver + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + // force state change to loaded so that all threads can be exited + pthread_mutex_lock(&m_state_lock); + m_state = OMX_StateLoaded; + pthread_mutex_unlock(&m_state_lock); + DEBUG_PRINT_ERROR("Freeing Buf:inp_current_buf_count[%d][%d]\n",\ + m_inp_current_buf_count, + m_input_buf_hdrs.size()); + m_input_buf_hdrs.eraseall(); + DEBUG_PRINT_ERROR("Freeing Buf:out_current_buf_count[%d][%d]\n",\ + m_out_current_buf_count, + m_output_buf_hdrs.size()); + m_output_buf_hdrs.eraseall(); + + } + if(pcm_input) + { + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("Deinit:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + if(pcm_input) + { + if (m_ipc_to_in_th != NULL) + { + omx_evrc_thread_stop(m_ipc_to_in_th); + m_ipc_to_in_th = NULL; + } + } + + if (m_ipc_to_cmd_th != NULL) + { + omx_evrc_thread_stop(m_ipc_to_cmd_th); + m_ipc_to_cmd_th = NULL; + } + if (m_ipc_to_out_th != NULL) + { + DEBUG_DETAIL("Inside omx_evrc_thread_stop\n"); + omx_evrc_thread_stop(m_ipc_to_out_th); + m_ipc_to_out_th = NULL; + } + + + if(ioctl(m_drv_fd, AUDIO_STOP, 0) <0) + DEBUG_PRINT_ERROR("De-init: AUDIO_STOP FAILED\n"); + + if(pcm_input && m_tmp_meta_buf ) + { + free(m_tmp_meta_buf); + } + + if(m_tmp_out_meta_buf) + { + free(m_tmp_out_meta_buf); + } + nNumInputBuf = 0; + nNumOutputBuf = 0; + bFlushinprogress = 0; + + m_inp_current_buf_count=0; + m_out_current_buf_count=0; + m_out_act_buf_count = 0; + m_inp_act_buf_count = 0; + m_inp_bEnabled = OMX_FALSE; + m_out_bEnabled = OMX_FALSE; + m_inp_bPopulated = OMX_FALSE; + m_out_bPopulated = OMX_FALSE; + + if ( m_drv_fd >= 0 ) + { + if(close(m_drv_fd) < 0) + DEBUG_PRINT("De-init: Driver Close Failed \n"); + m_drv_fd = -1; + } + else + { + DEBUG_PRINT_ERROR(" EVRC device already closed\n"); + } + m_comp_deinit=1; + m_is_out_th_sleep = 1; + m_is_in_th_sleep = 1; + DEBUG_PRINT("************************************\n"); + DEBUG_PRINT(" DEINIT COMPLETED"); + DEBUG_PRINT("************************************\n"); + +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation <TBD>. + +PARAMETERS + <TBD>. + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::use_EGL_image +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + DEBUG_PRINT_ERROR("Error : use_EGL_image: Not Implemented \n"); + + if((hComp == NULL) || (appData == NULL) || (eglImage == NULL)) + { + bufferHdr = bufferHdr; + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_evrc_aenc::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + const char *cmp_role = "audio_encoder.evrc"; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (index == 0 && role) + { + memcpy(role, cmp_role, strlen(cmp_role)); + *(((char *) role) + strlen(cmp_role) + 1) = '\0'; + } else + { + eRet = OMX_ErrorNoMore; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_evrc_aenc::allocate_done(void) +{ + OMX_BOOL bRet = OMX_FALSE; + if (pcm_input==1) + { + if ((m_inp_act_buf_count == m_inp_current_buf_count) + &&(m_out_act_buf_count == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + + } + if ((m_inp_act_buf_count == m_inp_current_buf_count) && m_inp_bEnabled ) + { + m_inp_bPopulated = OMX_TRUE; + } + + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + } else if (pcm_input==0) + { + if (m_out_act_buf_count == m_out_current_buf_count) + { + bRet=OMX_TRUE; + + } + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + + } + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_evrc_aenc::ReleaseDone + +DESCRIPTION + Checks if IL client has released all the buffers. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_evrc_aenc::release_done(OMX_U32 param1) +{ + DEBUG_PRINT("Inside omx_evrc_aenc::release_done"); + OMX_BOOL bRet = OMX_FALSE; + + if (param1 == OMX_ALL) + { + if ((0 == m_inp_current_buf_count)&&(0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_INPUT_PORT_INDEX ) + { + if ((0 == m_inp_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_OUTPUT_PORT_INDEX) + { + if ((0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } + return bRet; +} diff --git a/msm8909/mm-audio/aenc-evrc/qdsp6/test/omx_evrc_enc_test.c b/msm8909/mm-audio/aenc-evrc/qdsp6/test/omx_evrc_enc_test.c new file mode 100644 index 00000000..63d953bd --- /dev/null +++ b/msm8909/mm-audio/aenc-evrc/qdsp6/test/omx_evrc_enc_test.c @@ -0,0 +1,1098 @@ + +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + + +/* + An Open max test application .... +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <time.h> +#include <sys/ioctl.h> +#include "OMX_Core.h" +#include "OMX_Component.h" +#include "pthread.h" +#include <signal.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdint.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include<unistd.h> +#include<string.h> +#include <pthread.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#ifdef AUDIOV2 +#include "control.h" +#endif + + +#include <linux/ioctl.h> + +typedef unsigned char uint8; +typedef unsigned char byte; +typedef unsigned int uint32; +typedef unsigned int uint16; +QOMX_AUDIO_STREAM_INFO_DATA streaminfoparam; +/* maximum ADTS frame header length */ +void Release_Encoder(); + +#ifdef AUDIOV2 +unsigned short session_id; +int device_id; +int control = 0; +const char *device="handset_tx"; +#define DIR_TX 2 +#endif + +uint32_t samplerate = 8000; +uint32_t channels = 1; +uint32_t min_bitrate = 0; +uint32_t max_bitrate = 0; +uint32_t cdmarate = 0; +uint32_t rectime = 0; +uint32_t recpath = 0; +int32_t pcmplayback = 0; +uint32_t tunnel = 0; +uint32_t format = 1; +#define DEBUG_PRINT printf +unsigned to_idle_transition = 0; +unsigned long total_pcm_bytes; + +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ +#define false 0 +#define true 1 + +#define CONFIG_VERSION_SIZE(param) \ + param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ + param.nSize = sizeof(param); + +#define QCP_HEADER_SIZE sizeof(struct qcp_header) +#define MIN_BITRATE 4 /* Bit rate 1 - 13.6 , 2 - 6.2 , 3 - 2.7 , 4 - 1.0 kbps*/ +#define MAX_BITRATE 4 + +#define FAILED(result) (result != OMX_ErrorNone) + +#define SUCCEEDED(result) (result == OMX_ErrorNone) + +/************************************************************************/ +/* GLOBAL DECLARATIONS */ +/************************************************************************/ + +pthread_mutex_t lock; +pthread_cond_t cond; +pthread_mutex_t elock; +pthread_cond_t econd; +pthread_cond_t fcond; +pthread_mutex_t etb_lock; +pthread_mutex_t etb_lock1; +pthread_cond_t etb_cond; +FILE * inputBufferFile; +FILE * outputBufferFile; +OMX_PARAM_PORTDEFINITIONTYPE inputportFmt; +OMX_PARAM_PORTDEFINITIONTYPE outputportFmt; +OMX_AUDIO_PARAM_EVRCTYPE evrcparam; +OMX_AUDIO_PARAM_PCMMODETYPE pcmparam; +OMX_PORT_PARAM_TYPE portParam; +OMX_PORT_PARAM_TYPE portFmt; +OMX_ERRORTYPE error; + + + + +#define ID_RIFF 0x46464952 +#define ID_WAVE 0x45564157 +#define ID_FMT 0x20746d66 +#define ID_DATA 0x61746164 + +#define FORMAT_PCM 1 + +struct wav_header { + uint32_t riff_id; + uint32_t riff_sz; + uint32_t riff_fmt; + uint32_t fmt_id; + uint32_t fmt_sz; + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */ + uint16_t block_align; /* num_channels * bps / 8 */ + uint16_t bits_per_sample; + uint32_t data_id; + uint32_t data_sz; +}; +struct enc_meta_out{ + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; +} __attribute__ ((packed)); + +struct qcp_header { + /* RIFF Section */ + char riff[4]; + unsigned int s_riff; + char qlcm[4]; + + /* Format chunk */ + char fmt[4]; + unsigned int s_fmt; + char mjr; + char mnr; + unsigned int data1; /* UNIQUE ID of the codec */ + unsigned short data2; + unsigned short data3; + char data4[8]; + unsigned short ver; /* Codec Info */ + char name[80]; + unsigned short abps; /* average bits per sec of the codec */ + unsigned short bytes_per_pkt; + unsigned short samp_per_block; + unsigned short samp_per_sec; + unsigned short bits_per_samp; + unsigned char vr_num_of_rates; /* Rate Header fmt info */ + unsigned char rvd1[3]; + unsigned short vr_bytes_per_pkt[8]; + unsigned int rvd2[5]; + + /* Vrat chunk */ + unsigned char vrat[4]; + unsigned int s_vrat; + unsigned int v_rate; + unsigned int size_in_pkts; + + /* Data chunk */ + unsigned char data[4]; + unsigned int s_data; +} __attribute__ ((packed)); + + /* Common part */ + static struct qcp_header append_header = { + {'R', 'I', 'F', 'F'}, 0, {'Q', 'L', 'C', 'M'}, + {'f', 'm', 't', ' '}, 150, 1, 0, 0, 0, 0,{0}, 0, {0},0,0,160,8000,16,0,{0},{0},{0}, + {'v','r','a','t'},0, 0, 0,{'d','a','t','a'},0 + }; + +static int totaldatalen = 0; +static int framecnt = 0; +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +unsigned int input_buf_cnt = 0; +unsigned int output_buf_cnt = 0; +int used_ip_buf_cnt = 0; +volatile int event_is_done = 0; +volatile int ebd_event_is_done = 0; +volatile int fbd_event_is_done = 0; +volatile int etb_event_is_done = 0; +int ebd_cnt; +int bInputEosReached = 0; +int bOutputEosReached = 0; +int bInputEosReached_tunnel = 0; +static int etb_done = 0; +int bFlushing = false; +int bPause = false; +const char *in_filename; +const char *out_filename; + +int timeStampLfile = 0; +int timestampInterval = 100; + +//* OMX Spec Version supported by the wrappers. Version = 1.1 */ +const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; +OMX_COMPONENTTYPE* evrc_enc_handle = 0; + +OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; +OMX_BUFFERHEADERTYPE **pOutputBufHdrs = NULL; + +/************************************************************************/ +/* GLOBAL FUNC DECL */ +/************************************************************************/ +int Init_Encoder(char*); +int Play_Encoder(); +OMX_STRING aud_comp; +/**************************************************************************/ +/* STATIC DECLARATIONS */ +/**************************************************************************/ + +static int open_audio_file (); +static int Read_Buffer(OMX_BUFFERHEADERTYPE *pBufHdr ); +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *evrc_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize); + + +static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); +static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + +static OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); +static OMX_ERRORTYPE parse_pcm_header(); +void wait_for_event(void) +{ + pthread_mutex_lock(&lock); + DEBUG_PRINT("%s: event_is_done=%d", __FUNCTION__, event_is_done); + while (event_is_done == 0) { + pthread_cond_wait(&cond, &lock); + } + event_is_done = 0; + pthread_mutex_unlock(&lock); +} + +void event_complete(void ) +{ + pthread_mutex_lock(&lock); + if (event_is_done == 0) { + event_is_done = 1; + pthread_cond_broadcast(&cond); + } + pthread_mutex_unlock(&lock); +} + +void etb_wait_for_event(void) +{ + pthread_mutex_lock(&etb_lock1); + DEBUG_PRINT("%s: etb_event_is_done=%d", __FUNCTION__, etb_event_is_done); + while (etb_event_is_done == 0) { + pthread_cond_wait(&etb_cond, &etb_lock1); + } + etb_event_is_done = 0; + pthread_mutex_unlock(&etb_lock1); +} + +void etb_event_complete(void ) +{ + pthread_mutex_lock(&etb_lock1); + if (etb_event_is_done == 0) { + etb_event_is_done = 1; + pthread_cond_broadcast(&etb_cond); + } + pthread_mutex_unlock(&etb_lock1); +} + +static void create_qcp_header(int Datasize, int Frames) +{ + append_header.s_riff = (unsigned)(Datasize + (int)QCP_HEADER_SIZE - 8); + /* exclude riff id and size field */ + append_header.data1 = 0xe689d48d; + append_header.data2 = 0x9076; + append_header.data3 = 0x46b5; + append_header.data4[0] = 0x91; + append_header.data4[1] = 0xef; + append_header.data4[2] = 0x73; + append_header.data4[3] = 0x6a; + append_header.data4[4] = 0x51; + append_header.data4[5] = 0x00; + append_header.data4[6] = 0xce; + append_header.data4[7] = 0xb4; + append_header.ver = 0x0001; + memcpy(append_header.name, "TIA IS-127 Enhanced Variable Rate Codec, Speech Service Option 3", 64); + append_header.abps = 9600; + append_header.bytes_per_pkt = 23; + append_header.vr_num_of_rates = 4; + append_header.vr_bytes_per_pkt[0] = 0x0416; + append_header.vr_bytes_per_pkt[1] = 0x030a; + append_header.vr_bytes_per_pkt[2] = 0x0200; + append_header.vr_bytes_per_pkt[3] = 0x0102; + append_header.s_vrat = 0x00000008; + append_header.v_rate = 0x00000001; + append_header.size_in_pkts = (unsigned)Frames; + append_header.s_data = (unsigned)Datasize; + return; +} + +OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ + DEBUG_PRINT("Function %s \n", __FUNCTION__); + + /* To remove warning for unused variable to keep prototype same */ + (void)hComponent; + (void)pAppData; + (void)pEventData; + switch(eEvent) { + case OMX_EventCmdComplete: + DEBUG_PRINT("\n OMX_EventCmdComplete event=%d data1=%u data2=%u\n",(OMX_EVENTTYPE)eEvent, + nData1,nData2); + event_complete(); + break; + case OMX_EventError: + DEBUG_PRINT("\n OMX_EventError \n"); + break; + case OMX_EventBufferFlag: + DEBUG_PRINT("\n OMX_EventBufferFlag \n"); + bOutputEosReached = true; + event_complete(); + break; + case OMX_EventPortSettingsChanged: + DEBUG_PRINT("\n OMX_EventPortSettingsChanged \n"); + break; + default: + DEBUG_PRINT("\n Unknown Event \n"); + break; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + size_t bytes_writen = 0; + size_t total_bytes_writen = 0; + size_t len = 0; + struct enc_meta_out *meta = NULL; + OMX_U8 *src = pBuffer->pBuffer; + unsigned int num_of_frames = 1; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + if(((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + DEBUG_PRINT("FBD::EOS on output port\n "); + bOutputEosReached = true; + return OMX_ErrorNone; + } + if(bInputEosReached_tunnel || bOutputEosReached) + { + DEBUG_PRINT("EOS REACHED NO MORE PROCESSING OF BUFFERS\n"); + return OMX_ErrorNone; + } + if(num_of_frames != src[0]){ + + printf("Data corrupt\n"); + return OMX_ErrorNone; + } + /* Skip the first bytes */ + + + + src += sizeof(unsigned char); + meta = (struct enc_meta_out *)src; + while (num_of_frames > 0) { + meta = (struct enc_meta_out *)src; + /*printf("offset=%d framesize=%d encoded_pcm[%d] msw_ts[%d]lsw_ts[%d] nflags[%d]\n", + meta->offset_to_frame, + meta->frame_size, + meta->encoded_pcm_samples, meta->msw_ts, meta->lsw_ts, meta->nflags);*/ + len = meta->frame_size; + + bytes_writen = fwrite(pBuffer->pBuffer + sizeof(unsigned char) + meta->offset_to_frame,1,len,outputBufferFile); + if(bytes_writen < len) + { + DEBUG_PRINT("error: invalid EVRC encoded data \n"); + return OMX_ErrorNone; + } + src += sizeof(struct enc_meta_out); + num_of_frames--; + total_bytes_writen += len; + } + DEBUG_PRINT(" FillBufferDone size writen to file %zu count %d\n",total_bytes_writen, framecnt); + totaldatalen = totaldatalen + (int)total_bytes_writen; + framecnt++; + + DEBUG_PRINT(" FBD calling FTB\n"); + OMX_FillThisBuffer(hComponent,pBuffer); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + int readBytes =0; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + ebd_cnt++; + used_ip_buf_cnt--; + pthread_mutex_lock(&etb_lock); + if(!etb_done) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT("Wait till first set of buffers are given to component\n"); + DEBUG_PRINT("\n*********************************************\n"); + etb_done++; + pthread_mutex_unlock(&etb_lock); + etb_wait_for_event(); + } + else + { + pthread_mutex_unlock(&etb_lock); + } + + + if(bInputEosReached) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT(" EBD::EOS on input port\n "); + DEBUG_PRINT("*********************************************\n"); + return OMX_ErrorNone; + }else if (bFlushing == true) { + DEBUG_PRINT("omx_evrc13_adec_test: bFlushing is set to TRUE used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + if (used_ip_buf_cnt == 0) { + bFlushing = false; + } else { + DEBUG_PRINT("omx_evrc13_adec_test: more buffer to come back used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + return OMX_ErrorNone; + } + } + + if((readBytes = Read_Buffer(pBuffer)) > 0) { + pBuffer->nFilledLen = (OMX_U32)readBytes; + used_ip_buf_cnt++; + OMX_EmptyThisBuffer(hComponent,pBuffer); + } + else{ + pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + used_ip_buf_cnt++; + bInputEosReached = true; + pBuffer->nFilledLen = 0; + OMX_EmptyThisBuffer(hComponent,pBuffer); + DEBUG_PRINT("EBD..Either EOS or Some Error while reading file\n"); + } + return OMX_ErrorNone; +} + +void signal_handler(int sig_id) { + + /* Flush */ + if (sig_id == SIGUSR1) { + DEBUG_PRINT("%s Initiate flushing\n", __FUNCTION__); + bFlushing = true; + OMX_SendCommand(evrc_enc_handle, OMX_CommandFlush, OMX_ALL, NULL); + } else if (sig_id == SIGUSR2) { + if (bPause == true) { + DEBUG_PRINT("%s resume record\n", __FUNCTION__); + bPause = false; + OMX_SendCommand(evrc_enc_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); + } else { + DEBUG_PRINT("%s pause record\n", __FUNCTION__); + bPause = true; + OMX_SendCommand(evrc_enc_handle, OMX_CommandStateSet, OMX_StatePause, NULL); + } + } +} + +int main(int argc, char **argv) +{ + unsigned int bufCnt=0; + OMX_ERRORTYPE result; + + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = &signal_handler; + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGUSR2, &sa, NULL); + + (void) signal(SIGINT, Release_Encoder); + + pthread_cond_init(&cond, 0); + pthread_mutex_init(&lock, 0); + pthread_cond_init(&etb_cond, 0); + pthread_mutex_init(&etb_lock, 0); + pthread_mutex_init(&etb_lock1, 0); + + if (argc >= 9) { + in_filename = argv[1]; + out_filename = argv[2]; + tunnel = (uint32_t)atoi(argv[3]); + min_bitrate = (uint32_t)atoi(argv[4]); + max_bitrate = (uint32_t)atoi(argv[5]); + cdmarate = (uint32_t)atoi(argv[6]); + recpath = (uint32_t)atoi(argv[7]); // No configuration support yet.. + rectime = (uint32_t)atoi(argv[8]); + + } else { + DEBUG_PRINT(" invalid format: \n"); + DEBUG_PRINT("ex: ./mm-aenc-omxevrc-test INPUTFILE OUTPUTFILE Tunnel MINRATE MAXRATE CDMARATE RECORDPATH RECORDTIME\n"); + DEBUG_PRINT("MINRATE MAXRATE and CDMARATE 1 to 4\n"); + DEBUG_PRINT("RECORDPATH 0(TX),1(RX),2(BOTH),3(MIC)\n"); + DEBUG_PRINT("RECORDTIME in seconds for AST Automation\n"); + return 0; + } + if(recpath != 3) { + DEBUG_PRINT("For RECORDPATH Only MIC supported\n"); + return 0; + } + if(tunnel == 0) + aud_comp = "OMX.qcom.audio.encoder.evrc"; + else + aud_comp = "OMX.qcom.audio.encoder.tunneled.evrc"; + if(Init_Encoder(aud_comp)!= 0x00) + { + DEBUG_PRINT("Decoder Init failed\n"); + return -1; + } + + fcntl(0, F_SETFL, O_NONBLOCK); + + if(Play_Encoder() != 0x00) + { + DEBUG_PRINT("Play_Decoder failed\n"); + return -1; + } + + // Wait till EOS is reached... + if(rectime && tunnel) + { + sleep(rectime); + rectime = 0; + bInputEosReached_tunnel = 1; + DEBUG_PRINT("\EOS ON INPUT PORT\n"); + } + else + { + wait_for_event(); + } + + if((bInputEosReached_tunnel) || ((bOutputEosReached) && !tunnel)) + { + + DEBUG_PRINT("\nMoving the decoder to idle state \n"); + OMX_SendCommand(evrc_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + wait_for_event(); + + DEBUG_PRINT("\nMoving the encoder to loaded state \n"); + OMX_SendCommand(evrc_enc_handle, OMX_CommandStateSet, OMX_StateLoaded,0); + sleep(1); + if (!tunnel) + { + DEBUG_PRINT("\nFillBufferDone: Deallocating i/p buffers \n"); + for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(evrc_enc_handle, 0, pInputBufHdrs[bufCnt]); + } + } + + DEBUG_PRINT ("\nFillBufferDone: Deallocating o/p buffers \n"); + for(bufCnt=0; bufCnt < output_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(evrc_enc_handle, 1, pOutputBufHdrs[bufCnt]); + } + wait_for_event(); + create_qcp_header(totaldatalen, framecnt); + fseek(outputBufferFile, 0,SEEK_SET); + fwrite(&append_header,1,QCP_HEADER_SIZE,outputBufferFile); + + + result = OMX_FreeHandle(evrc_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + if(tunnel) + { + #ifdef AUDIOV2 + if (msm_route_stream(DIR_TX,session_id,device_id, 0)) + { + DEBUG_PRINT("\ncould not set stream routing\n"); + return -1; + } + if (msm_en_device(device_id, 0)) + { + DEBUG_PRINT("\ncould not enable device\n"); + return -1; + } + msm_mixer_close(); + #endif + } + OMX_Deinit(); + ebd_cnt=0; + bOutputEosReached = false; + bInputEosReached_tunnel = false; + bInputEosReached = 0; + evrc_enc_handle = NULL; + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + fclose(outputBufferFile); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...EVRC ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + } + return 0; +} + +void Release_Encoder() +{ + static int cnt=0; + OMX_ERRORTYPE result; + + DEBUG_PRINT("END OF EVRC ENCODING: EXITING PLEASE WAIT\n"); + bInputEosReached_tunnel = 1; + event_complete(); + cnt++; + if(cnt > 1) + { + /* FORCE RESET */ + evrc_enc_handle = NULL; + ebd_cnt=0; + bInputEosReached_tunnel = false; + + result = OMX_FreeHandle(evrc_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + + OMX_Deinit(); + + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...EVRC ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + exit(0); + } +} + +int Init_Encoder(OMX_STRING audio_component) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE omxresult; + OMX_U32 total = 0; + typedef OMX_U8* OMX_U8_PTR; + char *role ="audio_encoder"; + + static OMX_CALLBACKTYPE call_back = { + &EventHandler,&EmptyBufferDone,&FillBufferDone + }; + + /* Init. the OpenMAX Core */ + DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); + omxresult = OMX_Init(); + + if(OMX_ErrorNone != omxresult) { + DEBUG_PRINT("\n Failed to Init OpenMAX core"); + return -1; + } + else { + DEBUG_PRINT("\nOpenMAX Core Init Done\n"); + } + + /* Query for audio decoders*/ + DEBUG_PRINT("Evrc_test: Before entering OMX_GetComponentOfRole"); + OMX_GetComponentsOfRole(role, &total, 0); + DEBUG_PRINT ("\nTotal components of role=%s :%u", role, total); + + + omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&evrc_enc_handle), + (OMX_STRING)audio_component, NULL, &call_back); + if (FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to Load the component:%s\n", audio_component); + return -1; + } + else + { + DEBUG_PRINT("\nComponent %s is in LOADED state\n", audio_component); + } + + /* Get the port information */ + CONFIG_VERSION_SIZE(portParam); + omxresult = OMX_GetParameter(evrc_enc_handle, OMX_IndexParamAudioInit, + (OMX_PTR)&portParam); + + if(FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to get Port Param\n"); + return -1; + } + else + { + DEBUG_PRINT("\nportParam.nPorts:%u\n", portParam.nPorts); + DEBUG_PRINT("\nportParam.nStartPortNumber:%u\n", + portParam.nStartPortNumber); + } + + if(OMX_ErrorNone != omxresult) + { + DEBUG_PRINT("Set parameter failed"); + } + + return 0; +} + +int Play_Encoder() +{ + unsigned int i; + int Size=0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE ret; + OMX_INDEXTYPE index; +#ifdef __LP64__ + DEBUG_PRINT("sizeof[%ld]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#else + DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#endif + + /* open the i/p and o/p files based on the video file format passed */ + if(open_audio_file()) { + DEBUG_PRINT("\n Returning -1"); + return -1; + } + + /* Query the encoder input min buf requirements */ + CONFIG_VERSION_SIZE(inputportFmt); + + /* Port for which the Client needs to obtain info */ + inputportFmt.nPortIndex = portParam.nStartPortNumber; + + OMX_GetParameter(evrc_enc_handle,OMX_IndexParamPortDefinition,&inputportFmt); + DEBUG_PRINT ("\nEnc Input Buffer Count %u\n", inputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Input Buffer Size %u\n", inputportFmt.nBufferSize); + + if(OMX_DirInput != inputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Input Port\n"); + return -1; + } + + pcmparam.nPortIndex = 0; + pcmparam.nChannels = channels; + pcmparam.nSamplingRate = samplerate; + OMX_SetParameter(evrc_enc_handle,OMX_IndexParamAudioPcm,&pcmparam); + + + /* Query the encoder outport's min buf requirements */ + CONFIG_VERSION_SIZE(outputportFmt); + /* Port for which the Client needs to obtain info */ + outputportFmt.nPortIndex = portParam.nStartPortNumber + 1; + + OMX_GetParameter(evrc_enc_handle,OMX_IndexParamPortDefinition,&outputportFmt); + DEBUG_PRINT ("\nEnc: Output Buffer Count %u\n", outputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Output Buffer Size %u\n", outputportFmt.nBufferSize); + + if(OMX_DirOutput != outputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Output Port\n"); + return -1; + } + + + CONFIG_VERSION_SIZE(evrcparam); + + evrcparam.nPortIndex = 1; + evrcparam.nChannels = channels; //2 ; /* 1-> mono 2-> stereo*/ + evrcparam.nMinBitRate = min_bitrate; + evrcparam.nMaxBitRate = max_bitrate; + OMX_SetParameter(evrc_enc_handle,OMX_IndexParamAudioEvrc,&evrcparam); + OMX_GetExtensionIndex(evrc_enc_handle,"OMX.Qualcomm.index.audio.sessionId",&index); + OMX_GetParameter(evrc_enc_handle,index,&streaminfoparam); + if(tunnel) { + #ifdef AUDIOV2 + session_id = streaminfoparam.sessionId; + control = msm_mixer_open("/dev/snd/controlC0", 0); + if(control < 0) + printf("ERROR opening the device\n"); + device_id = msm_get_device(device); + DEBUG_PRINT ("\ndevice_id = %d\n",device_id); + DEBUG_PRINT("\nsession_id = %d\n",session_id); + if (msm_en_device(device_id, 1)) + { + perror("could not enable device\n"); + return -1; + } + if (msm_route_stream(DIR_TX,session_id,device_id, 1)) + { + perror("could not set stream routing\n"); + return -1; + } + #endif + } + + DEBUG_PRINT ("\nOMX_SendCommand Encoder -> IDLE\n"); + OMX_SendCommand(evrc_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + /* wait_for_event(); should not wait here event complete status will + not come until enough buffer are allocated */ + if (tunnel == 0) + { + input_buf_cnt = inputportFmt.nBufferCountActual; // inputportFmt.nBufferCountMin + 5; + DEBUG_PRINT("Transition to Idle State succesful...\n"); + /* Allocate buffer on decoder's i/p port */ + error = Allocate_Buffer(evrc_enc_handle, &pInputBufHdrs, inputportFmt.nPortIndex, + input_buf_cnt, inputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pInputBufHdrs == NULL) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer success\n"); + } + } + output_buf_cnt = outputportFmt.nBufferCountMin ; + + /* Allocate buffer on encoder's O/Pp port */ + error = Allocate_Buffer(evrc_enc_handle, &pOutputBufHdrs, outputportFmt.nPortIndex, + output_buf_cnt, outputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pOutputBufHdrs == NULL) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer success\n"); + } + + wait_for_event(); + + + if (tunnel == 1) + { + DEBUG_PRINT ("\nOMX_SendCommand to enable TUNNEL MODE during IDLE\n"); + OMX_SendCommand(evrc_enc_handle, OMX_CommandPortDisable,0,0); // disable input port + wait_for_event(); + } + + DEBUG_PRINT ("\nOMX_SendCommand encoder -> Executing\n"); + OMX_SendCommand(evrc_enc_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + + DEBUG_PRINT(" Start sending OMX_FILLthisbuffer\n"); + + for(i=0; i < output_buf_cnt; i++) { + DEBUG_PRINT ("\nOMX_FillThisBuffer on output buf no.%d\n",i); + pOutputBufHdrs[i]->nOutputPortIndex = 1; + pOutputBufHdrs[i]->nFlags = pOutputBufHdrs[i]->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + ret = OMX_FillThisBuffer(evrc_enc_handle, pOutputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_FillThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_FillThisBuffer success!\n"); + } + } + +if(tunnel == 0) +{ + DEBUG_PRINT(" Start sending OMX_emptythisbuffer\n"); + for (i = 0;i < input_buf_cnt;i++) { + DEBUG_PRINT ("\nOMX_EmptyThisBuffer on Input buf no.%d\n",i); + pInputBufHdrs[i]->nInputPortIndex = 0; + Size = Read_Buffer(pInputBufHdrs[i]); + if(Size <=0 ){ + DEBUG_PRINT("NO DATA READ\n"); + bInputEosReached = true; + pInputBufHdrs[i]->nFlags= OMX_BUFFERFLAG_EOS; + } + pInputBufHdrs[i]->nFilledLen = (OMX_U32)Size; + pInputBufHdrs[i]->nInputPortIndex = 0; + used_ip_buf_cnt++; + ret = OMX_EmptyThisBuffer(evrc_enc_handle, pInputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_EmptyThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); + } + if(Size <=0 ){ + break;//eos reached + } + } + pthread_mutex_lock(&etb_lock); + if(etb_done) +{ + DEBUG_PRINT("Component is waiting for EBD to be released.\n"); + etb_event_complete(); + } + else + { + DEBUG_PRINT("\n****************************\n"); + DEBUG_PRINT("EBD not yet happened ...\n"); + DEBUG_PRINT("\n****************************\n"); + etb_done++; + } + pthread_mutex_unlock(&etb_lock); +} + + return 0; +} + + + +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *avc_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + unsigned int bufCnt=0; + + /* To remove warning for unused variable to keep prototype same */ + (void)avc_enc_handle; + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE*)*bufCntMin); + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + DEBUG_PRINT("\n OMX_AllocateBuffer No %d \n", bufCnt); + error = OMX_AllocateBuffer(evrc_enc_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize); + } + + return error; +} + + + + +static int Read_Buffer (OMX_BUFFERHEADERTYPE *pBufHdr ) +{ + + size_t bytes_read=0; + + + pBufHdr->nFilledLen = 0; + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + + bytes_read = fread(pBufHdr->pBuffer, 1, pBufHdr->nAllocLen , inputBufferFile); + + pBufHdr->nFilledLen = (OMX_U32)bytes_read; + // Time stamp logic + ((OMX_BUFFERHEADERTYPE *)pBufHdr)->nTimeStamp = \ + + (OMX_TICKS) ((total_pcm_bytes * 1000)/(samplerate * channels *2)); + + DEBUG_PRINT ("\n--time stamp -- %ld\n", (unsigned long)((OMX_BUFFERHEADERTYPE *)pBufHdr)->nTimeStamp); + if(bytes_read == 0) + { + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + DEBUG_PRINT ("\nBytes read zero\n"); + } + else + { + pBufHdr->nFlags = pBufHdr->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + + total_pcm_bytes = (unsigned)(total_pcm_bytes + bytes_read); + } + + return (int)bytes_read;; +} + + + +//In Encoder this Should Open a PCM or WAV file for input. + +static int open_audio_file () +{ + int error_code = 0; + + if (!tunnel) + { + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); + inputBufferFile = fopen (in_filename, "rb"); + if (inputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + in_filename); + error_code = -1; + } + if(parse_pcm_header() != 0x00) + { + DEBUG_PRINT("PCM parser failed \n"); + return -1; + } + } + + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, out_filename); + outputBufferFile = fopen (out_filename, "wb"); + if (outputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + out_filename); + error_code = -1; + return error_code; + } + fseek(outputBufferFile, QCP_HEADER_SIZE, SEEK_SET); + return error_code; +} + +static OMX_ERRORTYPE parse_pcm_header() +{ + struct wav_header hdr; + + DEBUG_PRINT("\n***************************************************************\n"); + if(fread(&hdr, 1, sizeof(hdr),inputBufferFile)!=sizeof(hdr)) + { + DEBUG_PRINT("Wav file cannot read header\n"); + return -1; + } + + if ((hdr.riff_id != ID_RIFF) || + (hdr.riff_fmt != ID_WAVE)|| + (hdr.fmt_id != ID_FMT)) + { + DEBUG_PRINT("Wav file is not a riff/wave file\n"); + return -1; + } + + if (hdr.audio_format != FORMAT_PCM) + { + DEBUG_PRINT("Wav file is not adpcm format %d and fmt size is %d\n", + hdr.audio_format, hdr.fmt_sz); + return -1; + } + + DEBUG_PRINT("Samplerate is %d\n", hdr.sample_rate); + DEBUG_PRINT("Channel Count is %d\n", hdr.num_channels); + DEBUG_PRINT("\n***************************************************************\n"); + + samplerate = hdr.sample_rate; + channels = hdr.num_channels; + total_pcm_bytes = 0; + + return OMX_ErrorNone; +} diff --git a/msm8909/mm-audio/aenc-qcelp13/Android.mk b/msm8909/mm-audio/aenc-qcelp13/Android.mk new file mode 100644 index 00000000..58d0456b --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/Android.mk @@ -0,0 +1,7 @@ +ifneq ($(filter arm aarch64 arm64, $(TARGET_ARCH)),) + +AENC_QCELP13_PATH:= $(call my-dir) + +include $(AENC_QCELP13_PATH)/qdsp6/Android.mk + +endif diff --git a/msm8909/mm-audio/aenc-qcelp13/Makefile b/msm8909/mm-audio/aenc-qcelp13/Makefile new file mode 100644 index 00000000..83d822bb --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/Makefile @@ -0,0 +1,6 @@ +all: + @echo "invoking omxaudio make" + $(MAKE) -C qdsp6 + +install: + $(MAKE) -C qdsp6 install diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/Android.mk b/msm8909/mm-audio/aenc-qcelp13/qdsp6/Android.mk new file mode 100644 index 00000000..006a2754 --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/Android.mk @@ -0,0 +1,69 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libOmxQcelp13Enc-def := -g -O3 +libOmxQcelp13Enc-def += -DQC_MODIFIED +libOmxQcelp13Enc-def += -D_ANDROID_ +libOmxQcelp13Enc-def += -D_ENABLE_QC_MSG_LOG_ +libOmxQcelp13Enc-def += -DVERBOSE +libOmxQcelp13Enc-def += -D_DEBUG +libOmxQcelp13Enc-def += -Wconversion +libOmxQcelp13Enc-def += -DAUDIOV2 + +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxQcelp13Enc) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +libOmxQcelp13Enc-inc := $(LOCAL_PATH)/inc +libOmxQcelp13Enc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := libOmxQcelp13Enc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxQcelp13Enc-def) +LOCAL_C_INCLUDES := $(libOmxQcelp13Enc-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libutils liblog + +LOCAL_SRC_FILES := src/aenc_svr.c +LOCAL_SRC_FILES += src/omx_qcelp13_aenc.cpp + +include $(BUILD_SHARED_LIBRARY) + + +# --------------------------------------------------------------------------------- +# Make the apps-test (mm-aenc-omxqcelp13-test) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +mm-qcelp13-enc-test-inc := $(LOCAL_PATH)/inc +mm-qcelp13-enc-test-inc += $(LOCAL_PATH)/test + +mm-qcelp13-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore +mm-qcelp13-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-audio/audio-alsa +LOCAL_MODULE := mm-aenc-omxqcelp13-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxQcelp13Enc-def) +LOCAL_C_INCLUDES := $(mm-qcelp13-enc-test-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libmm-omxcore +LOCAL_SHARED_LIBRARIES += libOmxQcelp13Enc +LOCAL_SHARED_LIBRARIES += libaudioalsa +LOCAL_SRC_FILES := test/omx_qcelp13_enc_test.c + +include $(BUILD_EXECUTABLE) + +endif + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- + diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/Makefile b/msm8909/mm-audio/aenc-qcelp13/qdsp6/Makefile new file mode 100644 index 00000000..b14655bd --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/Makefile @@ -0,0 +1,81 @@ +# --------------------------------------------------------------------------------- +# MM-AUDIO-OSS-8K-AENC-QCELP13 +# --------------------------------------------------------------------------------- + +# cross-compiler flags +CFLAGS += -Wall +CFLAGS += -Wundef +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs + +# cross-compile flags specific to shared objects +CFLAGS_SO += -fpic + +# required pre-processor flags +CPPFLAGS := -D__packed__= +CPPFLAGS += -DIMAGE_APPS_PROC +CPPFLAGS += -DFEATURE_Q_SINGLE_LINK +CPPFLAGS += -DFEATURE_Q_NO_SELF_QPTR +CPPFLAGS += -DFEATURE_LINUX +CPPFLAGS += -DFEATURE_NATIVELINUX +CPPFLAGS += -DFEATURE_DSM_DUP_ITEMS + +CPPFLAGS += -g +CPPFALGS += -D_DEBUG +CPPFLAGS += -Iinc + +# linker flags +LDFLAGS += -L$(SYSROOT)/usr/lib + +# linker flags for shared objects +LDFLAGS_SO := -shared + +# defintions +LIBMAJOR := $(basename $(basename $(LIBVER))) +LIBINSTALLDIR := $(DESTDIR)usr/lib +INCINSTALLDIR := $(DESTDIR)usr/include +BININSTALLDIR := $(DESTDIR)usr/bin + +# --------------------------------------------------------------------------------- +# BUILD +# --------------------------------------------------------------------------------- +all: libOmxQcelp13Enc.so.$(LIBVER) mm-aenc-omxqcelp13-test + +install: + echo "intalling aenc-qcelp13 in $(DESTDIR)" + if [ ! -d $(LIBINSTALLDIR) ]; then mkdir -p $(LIBINSTALLDIR); fi + if [ ! -d $(INCINSTALLDIR) ]; then mkdir -p $(INCINSTALLDIR); fi + if [ ! -d $(BININSTALLDIR) ]; then mkdir -p $(BININSTALLDIR); fi + install -m 555 libOmxQcelp13Enc.so.$(LIBVER) $(LIBINSTALLDIR) + cd $(LIBINSTALLDIR) && ln -s libOmxQcelp13Enc.so.$(LIBVER) libOmxQcelp13Enc.so.$(LIBMAJOR) + cd $(LIBINSTALLDIR) && ln -s libOmxQcelp13Enc.so.$(LIBMAJOR) libOmxQcelp13Enc.so + install -m 555 mm-aenc-omxqcelp13-test $(BININSTALLDIR) + +# --------------------------------------------------------------------------------- +# COMPILE LIBRARY +# --------------------------------------------------------------------------------- +LDLIBS := -lpthread +LDLIBS += -lstdc++ +LDLIBS += -lOmxCore + +SRCS := src/omx_qcelp13_aenc.cpp +SRCS += src/aenc_svr.c + +libOmxQcelp13Enc.so.$(LIBVER): $(SRCS) + $(CC) $(CPPFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxQcelp13Enc.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# --------------------------------------------------------------------------------- +# COMPILE TEST APP +# --------------------------------------------------------------------------------- +TEST_LDLIBS := -lpthread +TEST_LDLIBS += -ldl +TEST_LDLIBS += -lOmxCore + +TEST_SRCS := test/omx_qcelp13_enc_test.c + +mm-aenc-omxqcelp13-test: libOmxQcelp13Enc.so.$(LIBVER) $(TEST_SRCS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS) + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/Map.h b/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/Map.h new file mode 100644 index 00000000..aac96fd1 --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/Map.h @@ -0,0 +1,244 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include <stdio.h> +using namespace std; + +template <typename T,typename T2> +class Map +{ + struct node + { + T data; + T2 data2; + node* prev; + node* next; + node(T t, T2 t2,node* p, node* n) : + data(t), data2(t2), prev(p), next(n) {} + }; + node* head; + node* tail; + node* tmp; + unsigned size_of_list; + static Map<T,T2> *m_self; +public: + Map() : head( NULL ), tail ( NULL ),tmp(head),size_of_list(0) {} + bool empty() const { return ( !head || !tail ); } + operator bool() const { return !empty(); } + void insert(T,T2); + void show(); + int size(); + T2 find(T); // Return VALUE + T find_ele(T);// Check if the KEY is present or not + T2 begin(); //give the first ele + bool erase(T); + bool eraseall(); + bool isempty(); + ~Map() + { + while(head) + { + node* temp(head); + head=head->next; + size_of_list--; + delete temp; + } + } +}; + +template <typename T,typename T2> +T2 Map<T,T2>::find(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data2; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T Map<T,T2>::find_ele(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data; + } + tmp = tmp->next; + } + return 0; +} + +template <typename T,typename T2> +T2 Map<T,T2>::begin() +{ + tmp = head; + if(tmp) + { + return (tmp->data2); + } + return 0; +} + +template <typename T,typename T2> +void Map<T,T2>::show() +{ + tmp = head; + while(tmp) + { + printf("%d-->%d\n",tmp->data,tmp->data2); + tmp = tmp->next; + } +} + +template <typename T,typename T2> +int Map<T,T2>::size() +{ + int count =0; + tmp = head; + while(tmp) + { + tmp = tmp->next; + count++; + } + return count; +} + +template <typename T,typename T2> +void Map<T,T2>::insert(T data, T2 data2) +{ + tail = new node(data, data2,tail, NULL); + if( tail->prev ) + tail->prev->next = tail; + + if( empty() ) + { + head = tail; + tmp=head; + } + tmp = head; + size_of_list++; +} + +template <typename T,typename T2> +bool Map<T,T2>::erase(T d) +{ + bool found = false; + tmp = head; + node* prevnode = tmp; + node *tempnode; + + while(tmp) + { + if((head == tail) && (head->data == d)) + { + found = true; + tempnode = head; + head = tail = NULL; + delete tempnode; + break; + } + if((tmp ==head) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + tmp = tmp->next; + tmp->prev = NULL; + head = tmp; + tempnode->next = NULL; + delete tempnode; + break; + } + if((tmp == tail) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + prevnode->next = NULL; + tmp->prev = NULL; + tail = prevnode; + delete tempnode; + break; + } + if(tmp->data == d) + { + found = true; + prevnode->next = tmp->next; + tmp->next->prev = prevnode->next; + tempnode = tmp; + //tmp = tmp->next; + delete tempnode; + break; + } + prevnode = tmp; + tmp = tmp->next; + } + if(found)size_of_list--; + return found; +} + +template <typename T,typename T2> +bool Map<T,T2>::eraseall() +{ + // Be careful while using this method + // it not only removes the node but FREES(not delete) the allocated + // memory. + node *tempnode; + tmp = head; + while(head) + { + tempnode = head; + head = head->next; + tempnode->next = NULL; + if(tempnode->data) + free(tempnode->data); + if(tempnode->data2) + free(tempnode->data2); + delete tempnode; + } + tail = head = NULL; + return true; +} + + +template <typename T,typename T2> +bool Map<T,T2>::isempty() +{ + if(!size_of_list) return true; + else return false; +} + +#endif // _MAP_H_ diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/aenc_svr.h b/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/aenc_svr.h new file mode 100644 index 00000000..940d863a --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/aenc_svr.h @@ -0,0 +1,120 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef AENC_SVR_H +#define AENC_SVR_H + +#ifdef __cplusplus +extern "C" { +#endif +#include <pthread.h> +#include <sched.h> +#include <utils/Log.h> + +#ifdef _ANDROID_ +#define LOG_TAG "QC_QCELP13ENC" +#endif + +#ifndef LOGE +#define LOGE ALOGE +#endif + +#ifndef LOGW +#define LOGW ALOGW +#endif + +#ifndef LOGD +#define LOGD ALOGD +#endif + +#ifndef LOGV +#define LOGV ALOGV +#endif + +#ifndef LOGI +#define LOGI ALOGI +#endif + +#define DEBUG_PRINT_ERROR LOGE +#define DEBUG_PRINT LOGI +#define DEBUG_DETAIL LOGV + +typedef void (*message_func)(void* client_data, unsigned char id); + +/** + @brief audio encoder ipc info structure + + */ +struct qcelp13_ipc_info +{ + pthread_t thr; + int pipe_in; + int pipe_out; + int dead; + message_func process_msg_cb; + void *client_data; + char thread_name[128]; +}; + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to command server + */ +struct qcelp13_ipc_info *omx_qcelp13_thread_create(message_func cb, + void* client_data, + char *th_name); + +struct qcelp13_ipc_info *omx_qcelp13_event_thread_create(message_func cb, + void* client_data, + char *th_name); +/** + @brief This function stop command server + + @param svr handle to command server + @return none + */ +void omx_qcelp13_thread_stop(struct qcelp13_ipc_info *qcelp13_ipc); + + +/** + @brief This function post message in the command server + + @param svr handle to command server + @return none + */ +void omx_qcelp13_post_msg(struct qcelp13_ipc_info *qcelp13_ipc, + unsigned char id); + +#ifdef __cplusplus +} +#endif + +#endif /* AENC_SVR */ diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h b/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h new file mode 100644 index 00000000..22cc9ed4 --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/inc/omx_qcelp13_aenc.h @@ -0,0 +1,539 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _QCELP13_ENC_H_ +#define _QCELP13_ENC_H_ +/*============================================================================ + Audio Encoder + +@file omx_qcelp13_aenc.h +This module contains the class definition for openMAX encoder component. + + + +============================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +/* Uncomment out below line #define LOG_NDEBUG 0 if we want to see + * all DEBUG_PRINT or LOGV messaging */ +#include<stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <time.h> +#include <inttypes.h> +#include <unistd.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#include "OMX_Core.h" +#include "OMX_Audio.h" +#include "aenc_svr.h" +#include "qc_omx_component.h" +#include "Map.h" +#include <semaphore.h> +#include <linux/msm_audio.h> +#include <linux/msm_audio_qcp.h> +extern "C" { + void * get_omx_component_factory_fn(void); +} + + +////////////////////////////////////////////////////////////////////////////// +// Module specific globals +////////////////////////////////////////////////////////////////////////////// + + + +#define OMX_SPEC_VERSION 0x00000101 +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (x >= y?x:y) + +////////////////////////////////////////////////////////////////////////////// +// Macros +////////////////////////////////////////////////////////////////////////////// +// + + +#define PrintFrameHdr(i,bufHdr) \ + DEBUG_PRINT("i=%d OMX bufHdr[%p]buf[%p]size[%d]TS[%lld]nFlags[0x%x]\n",\ + i,\ + bufHdr, \ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\ + ((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp, \ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFlags) + + +// BitMask Management logic +#define BITS_PER_BYTE 8 +#define BITMASK_SIZE(mIndex) \ + (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) +#define BITMASK_OFFSET(mIndex)\ + ((mIndex)/BITS_PER_BYTE) +#define BITMASK_FLAG(mIndex) \ + (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITMASK_CLEAR(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] &= ~(BITMASK_FLAG(mIndex)) +#define BITMASK_SET(mArray,mIndex)\ + (mArray)[BITMASK_OFFSET(mIndex)] |= BITMASK_FLAG(mIndex) +#define BITMASK_PRESENT(mArray,mIndex)\ + ((mArray)[BITMASK_OFFSET(mIndex)] & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex)\ + (((mArray)[BITMASK_OFFSET(mIndex)] & \ + BITMASK_FLAG(mIndex)) == 0x0) + +#define OMX_CORE_NUM_INPUT_BUFFERS 2 +#define OMX_CORE_NUM_OUTPUT_BUFFERS 16 + +#define OMX_CORE_INPUT_BUFFER_SIZE 8160 // Multiple of 160 +#define OMX_CORE_CONTROL_CMDQ_SIZE 100 +#define OMX_AENC_VOLUME_STEP 0x147 +#define OMX_AENC_MIN 0 +#define OMX_AENC_MAX 100 +#define NON_TUNNEL 1 +#define TUNNEL 0 +#define IP_PORT_BITMASK 0x02 +#define OP_PORT_BITMASK 0x01 +#define IP_OP_PORT_BITMASK 0x03 + +#define OMX_QCELP13_DEFAULT_SF 8000 +#define OMX_QCELP13_DEFAULT_CH_CFG 1 +#define OMX_QCELP13_DEFAULT_VOL 25 +// 14 bytes for input meta data +#define OMX_AENC_SIZEOF_META_BUF (OMX_CORE_INPUT_BUFFER_SIZE+14) + +#define TRUE 1 +#define FALSE 0 + +#define NUMOFFRAMES 1 +#define MAXFRAMELENGTH 35 +#define OMX_QCELP13_OUTPUT_BUFFER_SIZE ((NUMOFFRAMES * (sizeof(ENC_META_OUT) + MAXFRAMELENGTH) \ + + 1)) + +#define OMX_QCELP13_DEFAULT_MINRATE 4 +#define OMX_QCELP13_DEFAULT_MAXRATE 4 + +class omx_qcelp13_aenc; + +// OMX mo3 audio encoder class +class omx_qcelp13_aenc: public qc_omx_component +{ +public: + omx_qcelp13_aenc(); // constructor + virtual ~omx_qcelp13_aenc(); // destructor + + OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + + OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp); + + OMX_ERRORTYPE component_init(OMX_STRING role); + + OMX_ERRORTYPE component_role_enum(OMX_HANDLETYPE hComp, + OMX_U8 *role, + OMX_U32 index); + + OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_HANDLETYPE peerComponent, + OMX_U32 peerPort, + OMX_TUNNELSETUPTYPE *tunnelSetup); + + OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + + OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE hComp, + OMX_STRING componentName, + OMX_VERSIONTYPE *componentVersion, + OMX_VERSIONTYPE * specVersion, + OMX_UUIDTYPE *componentUUID); + + OMX_ERRORTYPE get_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE hComp, + OMX_STRING paramName, + OMX_INDEXTYPE *indexType); + + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp, + OMX_STATETYPE *state); + + static void process_in_port_msg(void *client_data, + unsigned char id); + + static void process_out_port_msg(void *client_data, + unsigned char id); + + static void process_command_msg(void *client_data, + unsigned char id); + + static void process_event_cb(void *client_data, + unsigned char id); + + + OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp, + OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData); + + OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + void * eglImage); + + bool post_command(unsigned int p1, unsigned int p2, + unsigned char id); + + // Deferred callback identifiers + enum + { + //Event Callbacks from the component thread context + OMX_COMPONENT_GENERATE_EVENT = 0x1, + //Buffer Done callbacks from component thread context + OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2, + OMX_COMPONENT_GENERATE_ETB = 0x3, + //Command + OMX_COMPONENT_GENERATE_COMMAND = 0x4, + OMX_COMPONENT_GENERATE_FRAME_DONE = 0x05, + OMX_COMPONENT_GENERATE_FTB = 0x06, + OMX_COMPONENT_GENERATE_EOS = 0x07, + OMX_COMPONENT_PORTSETTINGS_CHANGED = 0x08, + OMX_COMPONENT_SUSPEND = 0x09, + OMX_COMPONENT_RESUME = 0x0a + }; +private: + + /////////////////////////////////////////////////////////// + // Type definitions + /////////////////////////////////////////////////////////// + // Bit Positions + enum flags_bit_positions + { + // Defer transition to IDLE + OMX_COMPONENT_IDLE_PENDING =0x1, + // Defer transition to LOADING + OMX_COMPONENT_LOADING_PENDING =0x2, + + OMX_COMPONENT_MUTED =0x3, + + // Defer transition to Enable + OMX_COMPONENT_INPUT_ENABLE_PENDING =0x4, + // Defer transition to Enable + OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x5, + // Defer transition to Disable + OMX_COMPONENT_INPUT_DISABLE_PENDING =0x6, + // Defer transition to Disable + OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x7 + }; + + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + input_buffer_map; + + typedef Map<OMX_BUFFERHEADERTYPE*, OMX_BUFFERHEADERTYPE*> + output_buffer_map; + + enum port_indexes + { + OMX_CORE_INPUT_PORT_INDEX =0, + OMX_CORE_OUTPUT_PORT_INDEX =1 + }; + + struct omx_event + { + unsigned long param1; + unsigned long param2; + unsigned char id; + }; + + struct omx_cmd_queue + { + omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE]; + unsigned m_read; + unsigned m_write; + unsigned m_size; + + omx_cmd_queue(); + ~omx_cmd_queue(); + bool insert_entry(unsigned long p1, unsigned long p2, unsigned char id); + bool pop_entry(unsigned long *p1,unsigned long *p2, unsigned char *id); + bool get_msg_id(unsigned char *id); + bool get_msg_with_id(unsigned *p1,unsigned *p2, unsigned id); + }; + + typedef struct TIMESTAMP + { + unsigned int LowPart; + unsigned int HighPart; + }__attribute__((packed)) TIMESTAMP; + + typedef struct metadata_input + { + unsigned short offsetVal; + TIMESTAMP nTimeStamp; + unsigned int nFlags; + }__attribute__((packed)) META_IN; + + typedef struct enc_meta_out + { + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; + } __attribute__ ((packed))ENC_META_OUT; + + typedef struct + { + OMX_U32 tot_in_buf_len; + OMX_U32 tot_out_buf_len; + OMX_TICKS tot_pb_time; + OMX_U32 fbd_cnt; + OMX_U32 ftb_cnt; + OMX_U32 etb_cnt; + OMX_U32 ebd_cnt; + }QCELP13_PB_STATS; + + /////////////////////////////////////////////////////////// + // Member variables + /////////////////////////////////////////////////////////// + OMX_U8 *m_tmp_meta_buf; + OMX_U8 *m_tmp_out_meta_buf; + OMX_U8 m_flush_cnt ; + OMX_U8 m_comp_deinit; + + // the below var doesnt hold good if combo of use and alloc bufs are used + OMX_S32 m_volume;//Unit to be determined + OMX_PTR m_app_data;// Application data + int nNumInputBuf; + int nNumOutputBuf; + int m_drv_fd; // Kernel device node file handle + bool bFlushinprogress; + bool is_in_th_sleep; + bool is_out_th_sleep; + unsigned int m_flags; //encapsulate the waiting states. + OMX_TICKS nTimestamp; + unsigned int pcm_input; //tunnel or non-tunnel + unsigned int m_inp_act_buf_count; // Num of Input Buffers + unsigned int m_out_act_buf_count; // Numb of Output Buffers + unsigned int m_inp_current_buf_count; // Num of Input Buffers + unsigned int m_out_current_buf_count; // Numb of Output Buffers + unsigned int output_buffer_size; + unsigned int input_buffer_size; + unsigned short m_session_id; + // store I/P PORT state + OMX_BOOL m_inp_bEnabled; + // store O/P PORT state + OMX_BOOL m_out_bEnabled; + //Input port Populated + OMX_BOOL m_inp_bPopulated; + //Output port Populated + OMX_BOOL m_out_bPopulated; + sem_t sem_States; + sem_t sem_read_msg; + sem_t sem_write_msg; + + volatile int m_is_event_done; + volatile int m_is_in_th_sleep; + volatile int m_is_out_th_sleep; + input_buffer_map m_input_buf_hdrs; + output_buffer_map m_output_buf_hdrs; + omx_cmd_queue m_input_q; + omx_cmd_queue m_input_ctrl_cmd_q; + omx_cmd_queue m_input_ctrl_ebd_q; + omx_cmd_queue m_command_q; + omx_cmd_queue m_output_q; + omx_cmd_queue m_output_ctrl_cmd_q; + omx_cmd_queue m_output_ctrl_fbd_q; + pthread_mutexattr_t m_outputlock_attr; + pthread_mutexattr_t m_commandlock_attr; + pthread_mutexattr_t m_lock_attr; + pthread_mutexattr_t m_state_attr; + pthread_mutexattr_t m_flush_attr; + pthread_mutexattr_t m_in_th_attr_1; + pthread_mutexattr_t m_out_th_attr_1; + pthread_mutexattr_t m_event_attr; + pthread_mutexattr_t m_in_th_attr; + pthread_mutexattr_t m_out_th_attr; + pthread_mutexattr_t out_buf_count_lock_attr; + pthread_mutexattr_t in_buf_count_lock_attr; + pthread_cond_t cond; + pthread_cond_t in_cond; + pthread_cond_t out_cond; + pthread_mutex_t m_lock; + pthread_mutex_t m_commandlock; + pthread_mutex_t m_outputlock; + // Mutexes for state change + pthread_mutex_t m_state_lock; + // Mutexes for flush acks from input and output threads + pthread_mutex_t m_flush_lock; + pthread_mutex_t m_event_lock; + pthread_mutex_t m_in_th_lock; + pthread_mutex_t m_out_th_lock; + pthread_mutex_t m_in_th_lock_1; + pthread_mutex_t m_out_th_lock_1; + pthread_mutex_t out_buf_count_lock; + pthread_mutex_t in_buf_count_lock; + + OMX_STATETYPE m_state; // OMX State + OMX_STATETYPE nState; + OMX_CALLBACKTYPE m_cb; // Application callbacks + QCELP13_PB_STATS m_qcelp13_pb_stats; + struct qcelp13_ipc_info *m_ipc_to_in_th; // for input thread + struct qcelp13_ipc_info *m_ipc_to_out_th; // for output thread + struct qcelp13_ipc_info *m_ipc_to_cmd_th; // for command thread + struct qcelp13_ipc_info *m_ipc_to_event_th; //for txco event thread + OMX_PRIORITYMGMTTYPE m_priority_mgm ; + OMX_AUDIO_PARAM_QCELP13TYPE m_qcelp13_param; // Cache QCELP13 encoder parameter + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_param; // Cache pcm parameter + OMX_PARAM_COMPONENTROLETYPE component_Role; + OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier; + + /////////////////////////////////////////////////////////// + // Private methods + /////////////////////////////////////////////////////////// + OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port,OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE use_input_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE use_output_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE **bufHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + bool allocate_done(void); + + bool release_done(OMX_U32 param1); + + bool execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl=true); + + bool execute_input_omx_flush(void); + + bool execute_output_omx_flush(void); + + bool search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer); + + bool post_input(unsigned long p1, unsigned long p2, + unsigned char id); + + bool post_output(unsigned long p1, unsigned long p2, + unsigned char id); + + void process_events(omx_qcelp13_aenc *client_data); + + void buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr); + + void wait_for_event(); + + void event_complete(); + + void in_th_goto_sleep(); + + void in_th_wakeup(); + + void out_th_goto_sleep(); + + void out_th_wakeup(); + + void flush_ack(); + void deinit_encoder(); + +}; +#endif diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/src/aenc_svr.c b/msm8909/mm-audio/aenc-qcelp13/qdsp6/src/aenc_svr.c new file mode 100644 index 00000000..bdc96acf --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/src/aenc_svr.c @@ -0,0 +1,208 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> +#include <errno.h> + +#include <aenc_svr.h> + +/** + @brief This function processes posted messages + + Once thread is being spawned, this function is run to + start processing commands posted by client + + @param info pointer to context + + */ +void *omx_qcelp13_msg(void *info) +{ + struct qcelp13_ipc_info *qcelp13_info = (struct qcelp13_ipc_info*)info; + unsigned char id; + ssize_t n; + + DEBUG_DETAIL("\n%s: message thread start\n", __FUNCTION__); + while (!qcelp13_info->dead) + { + n = read(qcelp13_info->pipe_in, &id, 1); + if (0 == n) break; + if (1 == n) + { + DEBUG_DETAIL("\n%s-->pipe_in=%d pipe_out=%d\n", + qcelp13_info->thread_name, + qcelp13_info->pipe_in, + qcelp13_info->pipe_out); + + qcelp13_info->process_msg_cb(qcelp13_info->client_data, id); + } + if ((n < 0) && (errno != EINTR)) break; + } + DEBUG_DETAIL("%s: message thread stop\n", __FUNCTION__); + + return 0; +} + +void *omx_qcelp13_events(void *info) +{ + struct qcelp13_ipc_info *qcelp13_info = (struct qcelp13_ipc_info*)info; + unsigned char id = 0; + + DEBUG_DETAIL("%s: message thread start\n", qcelp13_info->thread_name); + qcelp13_info->process_msg_cb(qcelp13_info->client_data, id); + DEBUG_DETAIL("%s: message thread stop\n", qcelp13_info->thread_name); + return 0; +} + +/** + @brief This function starts command server + + @param cb pointer to callback function from the client + @param client_data reference client wants to get back + through callback + @return handle to msging thread + */ +struct qcelp13_ipc_info *omx_qcelp13_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct qcelp13_ipc_info *qcelp13_info; + + qcelp13_info = calloc(1, sizeof(struct qcelp13_ipc_info)); + if (!qcelp13_info) + { + return 0; + } + + qcelp13_info->client_data = client_data; + qcelp13_info->process_msg_cb = cb; + strlcpy(qcelp13_info->thread_name, th_name, + sizeof(qcelp13_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT_ERROR("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + qcelp13_info->pipe_in = fds[0]; + qcelp13_info->pipe_out = fds[1]; + + r = pthread_create(&qcelp13_info->thr, 0, omx_qcelp13_msg, qcelp13_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", qcelp13_info->thread_name); + return qcelp13_info; + + +fail_thread: + close(qcelp13_info->pipe_in); + close(qcelp13_info->pipe_out); + +fail_pipe: + free(qcelp13_info); + + return 0; +} + +/** + * @brief This function starts command server + * + * @param cb pointer to callback function from the client + * @param client_data reference client wants to get back + * through callback + * @return handle to msging thread + * */ +struct qcelp13_ipc_info *omx_qcelp13_event_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct qcelp13_ipc_info *qcelp13_info; + + qcelp13_info = calloc(1, sizeof(struct qcelp13_ipc_info)); + if (!qcelp13_info) + { + return 0; + } + + qcelp13_info->client_data = client_data; + qcelp13_info->process_msg_cb = cb; + strlcpy(qcelp13_info->thread_name, th_name, + sizeof(qcelp13_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + qcelp13_info->pipe_in = fds[0]; + qcelp13_info->pipe_out = fds[1]; + + r = pthread_create(&qcelp13_info->thr, 0, omx_qcelp13_events, qcelp13_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", qcelp13_info->thread_name); + return qcelp13_info; + + +fail_thread: + close(qcelp13_info->pipe_in); + close(qcelp13_info->pipe_out); + +fail_pipe: + free(qcelp13_info); + + return 0; +} + +void omx_qcelp13_thread_stop(struct qcelp13_ipc_info *qcelp13_info) { + DEBUG_DETAIL("%s stop server\n", __FUNCTION__); + close(qcelp13_info->pipe_in); + close(qcelp13_info->pipe_out); + pthread_join(qcelp13_info->thr,NULL); + qcelp13_info->pipe_out = -1; + qcelp13_info->pipe_in = -1; + DEBUG_DETAIL("%s: message thread close fds%d %d\n", qcelp13_info->thread_name, + qcelp13_info->pipe_in,qcelp13_info->pipe_out); + free(qcelp13_info); +} + +void omx_qcelp13_post_msg(struct qcelp13_ipc_info *qcelp13_info, unsigned char id) { + DEBUG_DETAIL("\n%s id=%d\n", __FUNCTION__,id); + + write(qcelp13_info->pipe_out, &id, 1); +} diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp b/msm8909/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp new file mode 100644 index 00000000..399b8cf9 --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/src/omx_qcelp13_aenc.cpp @@ -0,0 +1,4532 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ +@file omx_aenc_qcelp13.c + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + + +#include<string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include "omx_qcelp13_aenc.h" +#include <errno.h> + +using namespace std; +#define SLEEP_MS 100 + +// omx_cmd_queue destructor +omx_qcelp13_aenc::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_qcelp13_aenc::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q, 0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_qcelp13_aenc::omx_cmd_queue::insert_entry(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool ret = true; + if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full"); + } + return ret; +} + +bool omx_qcelp13_aenc::omx_cmd_queue::pop_entry(unsigned long *p1, + unsigned long *p2, unsigned char *id) +{ + bool ret = true; + if (m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + + } + } else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR Delete!!! Command Queue Empty"); + } + return ret; +} + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return(new omx_qcelp13_aenc); +} +bool omx_qcelp13_aenc::omx_cmd_queue::get_msg_id(unsigned char *id) +{ + if(m_size > 0) + { + *id = m_q[m_read].id; + DEBUG_PRINT("get_msg_id=%d\n",*id); + } + else{ + return false; + } + return true; +} +/*============================================================================= +FUNCTION: + wait_for_event + +DESCRIPTION: + waits for a particular event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_qcelp13_aenc::wait_for_event() +{ + int rc; + struct timespec ts; + pthread_mutex_lock(&m_event_lock); + while (0 == m_is_event_done) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += (SLEEP_MS/1000); + ts.tv_nsec += ((SLEEP_MS%1000) * 1000000); + rc = pthread_cond_timedwait(&cond, &m_event_lock, &ts); + if (rc == ETIMEDOUT && !m_is_event_done) { + DEBUG_PRINT("Timed out waiting for flush"); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + } + } + m_is_event_done = 0; + pthread_mutex_unlock(&m_event_lock); +} + +/*============================================================================= +FUNCTION: + event_complete + +DESCRIPTION: + informs about the occurance of an event + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_qcelp13_aenc::event_complete() +{ + pthread_mutex_lock(&m_event_lock); + if (0 == m_is_event_done) + { + m_is_event_done = 1; + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&m_event_lock); +} + +// All this non-sense because of a single qcelp13 object +void omx_qcelp13_aenc::in_th_goto_sleep() +{ + pthread_mutex_lock(&m_in_th_lock); + while (0 == m_is_in_th_sleep) + { + pthread_cond_wait(&in_cond, &m_in_th_lock); + } + m_is_in_th_sleep = 0; + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_qcelp13_aenc::in_th_wakeup() +{ + pthread_mutex_lock(&m_in_th_lock); + if (0 == m_is_in_th_sleep) + { + m_is_in_th_sleep = 1; + pthread_cond_signal(&in_cond); + } + pthread_mutex_unlock(&m_in_th_lock); +} + +void omx_qcelp13_aenc::out_th_goto_sleep() +{ + + pthread_mutex_lock(&m_out_th_lock); + while (0 == m_is_out_th_sleep) + { + pthread_cond_wait(&out_cond, &m_out_th_lock); + } + m_is_out_th_sleep = 0; + pthread_mutex_unlock(&m_out_th_lock); +} + +void omx_qcelp13_aenc::out_th_wakeup() +{ + pthread_mutex_lock(&m_out_th_lock); + if (0 == m_is_out_th_sleep) + { + m_is_out_th_sleep = 1; + pthread_cond_signal(&out_cond); + } + pthread_mutex_unlock(&m_out_th_lock); +} +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::omx_qcelp13_aenc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_qcelp13_aenc::omx_qcelp13_aenc(): m_tmp_meta_buf(NULL), + m_tmp_out_meta_buf(NULL), + m_flush_cnt(255), + m_comp_deinit(0), + m_volume(25), + m_app_data(NULL), + nNumInputBuf(0), + nNumOutputBuf(0), + m_drv_fd(-1), + bFlushinprogress(0), + is_in_th_sleep(false), + is_out_th_sleep(false), + m_flags(0), + nTimestamp(0), + pcm_input(0), + m_inp_act_buf_count (OMX_CORE_NUM_INPUT_BUFFERS), + m_out_act_buf_count (OMX_CORE_NUM_OUTPUT_BUFFERS), + m_inp_current_buf_count(0), + m_out_current_buf_count(0), + output_buffer_size((OMX_U32)OMX_QCELP13_OUTPUT_BUFFER_SIZE), + input_buffer_size(OMX_CORE_INPUT_BUFFER_SIZE), + m_session_id(0), + m_inp_bEnabled(OMX_TRUE), + m_out_bEnabled(OMX_TRUE), + m_inp_bPopulated(OMX_FALSE), + m_out_bPopulated(OMX_FALSE), + m_is_event_done(0), + m_state(OMX_StateInvalid), + m_ipc_to_in_th(NULL), + m_ipc_to_out_th(NULL), + m_ipc_to_cmd_th(NULL), + m_ipc_to_event_th(NULL) +{ + int cond_ret = 0; + component_Role.nSize = 0; + memset(&m_cmp, 0, sizeof(m_cmp)); + memset(&m_cb, 0, sizeof(m_cb)); + memset(&m_qcelp13_pb_stats, 0, sizeof(m_qcelp13_pb_stats)); + memset(&m_qcelp13_param, 0, sizeof(m_qcelp13_param)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + + pthread_mutexattr_init(&m_lock_attr); + pthread_mutex_init(&m_lock, &m_lock_attr); + pthread_mutexattr_init(&m_commandlock_attr); + pthread_mutex_init(&m_commandlock, &m_commandlock_attr); + + pthread_mutexattr_init(&m_outputlock_attr); + pthread_mutex_init(&m_outputlock, &m_outputlock_attr); + + pthread_mutexattr_init(&m_state_attr); + pthread_mutex_init(&m_state_lock, &m_state_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_flush_attr); + pthread_mutex_init(&m_flush_lock, &m_flush_attr); + + pthread_mutexattr_init(&m_event_attr); + pthread_mutex_init(&m_event_lock, &m_event_attr); + + pthread_mutexattr_init(&m_in_th_attr); + pthread_mutex_init(&m_in_th_lock, &m_in_th_attr); + + pthread_mutexattr_init(&m_out_th_attr); + pthread_mutex_init(&m_out_th_lock, &m_out_th_attr); + + pthread_mutexattr_init(&m_in_th_attr_1); + pthread_mutex_init(&m_in_th_lock_1, &m_in_th_attr_1); + + pthread_mutexattr_init(&m_out_th_attr_1); + pthread_mutex_init(&m_out_th_lock_1, &m_out_th_attr_1); + + pthread_mutexattr_init(&out_buf_count_lock_attr); + pthread_mutex_init(&out_buf_count_lock, &out_buf_count_lock_attr); + + pthread_mutexattr_init(&in_buf_count_lock_attr); + pthread_mutex_init(&in_buf_count_lock, &in_buf_count_lock_attr); + if ((cond_ret = pthread_cond_init (&cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&in_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for in_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&out_cond, NULL)) != 0) + { + DEBUG_PRINT_ERROR("pthread_cond_init returns non zero for out_cond\n"); + if (cond_ret == EAGAIN) + DEBUG_PRINT_ERROR("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + DEBUG_PRINT_ERROR("Insufficient memory to initialise \ + condition variable\n"); + } + + sem_init(&sem_read_msg,0, 0); + sem_init(&sem_write_msg,0, 0); + sem_init(&sem_States,0, 0); + return; +} + + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::~omx_qcelp13_aenc + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_qcelp13_aenc::~omx_qcelp13_aenc() +{ + DEBUG_PRINT_ERROR("QCELP13 Object getting destroyed comp-deinit=%d\n", + m_comp_deinit); + if ( !m_comp_deinit ) + { + deinit_encoder(); + } + pthread_mutexattr_destroy(&m_lock_attr); + pthread_mutex_destroy(&m_lock); + + pthread_mutexattr_destroy(&m_commandlock_attr); + pthread_mutex_destroy(&m_commandlock); + + pthread_mutexattr_destroy(&m_outputlock_attr); + pthread_mutex_destroy(&m_outputlock); + + pthread_mutexattr_destroy(&m_state_attr); + pthread_mutex_destroy(&m_state_lock); + + pthread_mutexattr_destroy(&m_event_attr); + pthread_mutex_destroy(&m_event_lock); + + pthread_mutexattr_destroy(&m_flush_attr); + pthread_mutex_destroy(&m_flush_lock); + + pthread_mutexattr_destroy(&m_in_th_attr); + pthread_mutex_destroy(&m_in_th_lock); + + pthread_mutexattr_destroy(&m_out_th_attr); + pthread_mutex_destroy(&m_out_th_lock); + + pthread_mutexattr_destroy(&out_buf_count_lock_attr); + pthread_mutex_destroy(&out_buf_count_lock); + + pthread_mutexattr_destroy(&in_buf_count_lock_attr); + pthread_mutex_destroy(&in_buf_count_lock); + + pthread_mutexattr_destroy(&m_in_th_attr_1); + pthread_mutex_destroy(&m_in_th_lock_1); + + pthread_mutexattr_destroy(&m_out_th_attr_1); + pthread_mutex_destroy(&m_out_th_lock_1); + pthread_cond_destroy(&cond); + pthread_cond_destroy(&in_cond); + pthread_cond_destroy(&out_cond); + sem_destroy (&sem_read_msg); + sem_destroy (&sem_write_msg); + sem_destroy (&sem_States); + DEBUG_PRINT_ERROR("OMX QCELP13 component destroyed\n"); + return; +} + +/** + @brief memory function for sending EmptyBufferDone event + back to IL client + + @param bufHdr OMX buffer header to be passed back to IL client + @return none + */ +void omx_qcelp13_aenc::buffer_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.EmptyBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_BUFFER_DONE,bufHdr); + bufHdr->nFilledLen = 0; + + m_cb.EmptyBufferDone(&m_cmp, m_app_data, bufHdr); + pthread_mutex_lock(&in_buf_count_lock); + m_qcelp13_pb_stats.ebd_cnt++; + nNumInputBuf--; + DEBUG_DETAIL("EBD CB:: in_buf_len=%d nNumInputBuf=%d\n ebd_cnt=%d",\ + m_qcelp13_pb_stats.tot_in_buf_len, + nNumInputBuf, m_qcelp13_pb_stats.ebd_cnt); + pthread_mutex_unlock(&in_buf_count_lock); + } + + return; +} + +/*============================================================================= +FUNCTION: + flush_ack + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_qcelp13_aenc::flush_ack() +{ + // Decrement the FLUSH ACK count and notify the waiting recepients + pthread_mutex_lock(&m_flush_lock); + --m_flush_cnt; + if (0 == m_flush_cnt) + { + event_complete(); + } + DEBUG_PRINT("Rxed FLUSH ACK cnt=%d\n",m_flush_cnt); + pthread_mutex_unlock(&m_flush_lock); +} +void omx_qcelp13_aenc::frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.FillBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_FRAME_DONE,bufHdr); + m_qcelp13_pb_stats.fbd_cnt++; + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf--; + DEBUG_PRINT("FBD CB:: nNumOutputBuf=%d out_buf_len=%u fbd_cnt=%u\n",\ + nNumOutputBuf, + m_qcelp13_pb_stats.tot_out_buf_len, + m_qcelp13_pb_stats.fbd_cnt); + m_qcelp13_pb_stats.tot_out_buf_len += bufHdr->nFilledLen; + m_qcelp13_pb_stats.tot_pb_time = bufHdr->nTimeStamp; + DEBUG_PRINT("FBD:in_buf_len=%u out_buf_len=%u\n", + m_qcelp13_pb_stats.tot_in_buf_len, + m_qcelp13_pb_stats.tot_out_buf_len); + + pthread_mutex_unlock(&out_buf_count_lock); + m_cb.FillBufferDone(&m_cmp, m_app_data, bufHdr); + } + return; +} + +/*============================================================================= +FUNCTION: + process_out_port_msg + +DESCRIPTION: + Function for handling all commands from IL client +IL client commands are processed and callbacks are generated through +this routine Audio Command Server provides the thread context for this routine + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_qcelp13_aenc::process_out_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; // qsize + unsigned tot_qsize = 0; + omx_qcelp13_aenc *pThis = (omx_qcelp13_aenc *) client_data; + OMX_STATETYPE state; + +loopback_out: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" OUT: IN LOADED STATE RETURN\n"); + return; + } + pthread_mutex_lock(&pThis->m_outputlock); + + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + + if ( 0 == tot_qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_DETAIL("OUT-->BREAK FROM LOOP...%d\n",tot_qsize); + return; + } + if ( (state != OMX_StateExecuting) && !qsize ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + DEBUG_DETAIL("OUT:1.SLEEPING OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + + if ( ((!pThis->m_output_ctrl_cmd_q.m_size) && !pThis->m_out_bEnabled) ) + { + // case where no port reconfig and nothing in the flush q + DEBUG_DETAIL("No flush/port reconfig qsize=%d tot_qsize=%d",\ + qsize,tot_qsize); + pthread_mutex_unlock(&pThis->m_outputlock); + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + return; + + if(pThis->m_output_ctrl_cmd_q.m_size || !(pThis->bFlushinprogress)) + { + DEBUG_PRINT("OUT:2. SLEEPING OUT THREAD \n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pThis->out_th_goto_sleep(); + } + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize = pThis->m_output_ctrl_cmd_q.m_size; + tot_qsize += pThis->m_output_ctrl_fbd_q.m_size; + tot_qsize += pThis->m_output_q.m_size; + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_DETAIL("OUT-->QSIZE-flush=%d,fbd=%d QSIZE=%d state=%d\n",\ + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size,state); + + + if (qsize) + { + // process FLUSH message + pThis->m_output_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_ctrl_fbd_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_output_ctrl_fbd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_output_q.m_size) && + (pThis->m_out_bEnabled) && (state == OMX_StateExecuting) ) + { + // if no FLUSH and FBD's then process FTB's + pThis->m_output_q.pop_entry(&p1,&p2,&ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_outputlock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("OUT--> Empty Queue state=%d %d %d %d\n",state, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("OUT: SLEEPING AGAIN OUT THREAD\n"); + pthread_mutex_lock(&pThis->m_out_th_lock_1); + pThis->is_out_th_sleep = true; + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + pthread_mutex_unlock(&pThis->m_outputlock); + pThis->out_th_goto_sleep(); + goto loopback_out; + } + } + pthread_mutex_unlock(&pThis->m_outputlock); + + if ( qsize > 0 ) + { + id = ident; + ident = 0; + DEBUG_DETAIL("OUT->state[%d]ident[%d]flushq[%d]fbd[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_output_ctrl_cmd_q.m_size, + pThis->m_output_ctrl_fbd_q.m_size, + pThis->m_output_q.m_size); + + if ( OMX_COMPONENT_GENERATE_FRAME_DONE == id ) + { + pThis->frame_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_FTB == id ) + { + pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_EOS == id ) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + + } + else if(id == OMX_COMPONENT_RESUME) + { + DEBUG_PRINT("RESUMED...\n"); + } + else if(id == OMX_COMPONENT_GENERATE_COMMAND) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL("Executing FLUSH command on Output port\n"); + pThis->execute_output_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:OUT-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR: OUT--> Empty OUTPUTQ\n"); + } + + return; +} + +/*============================================================================= +FUNCTION: + process_command_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_qcelp13_aenc::process_command_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + omx_qcelp13_aenc *pThis = (omx_qcelp13_aenc*)client_data; + pthread_mutex_lock(&pThis->m_commandlock); + + qsize = pThis->m_command_q.m_size; + DEBUG_DETAIL("CMD-->QSIZE=%d state=%d\n",pThis->m_command_q.m_size, + pThis->m_state); + + if (!qsize) + { + DEBUG_DETAIL("CMD-->BREAKING FROM LOOP\n"); + pthread_mutex_unlock(&pThis->m_commandlock); + return; + } else + { + pThis->m_command_q.pop_entry(&p1,&p2,&ident); + } + pthread_mutex_unlock(&pThis->m_commandlock); + + id = ident; + DEBUG_DETAIL("CMD->state[%d]id[%d]cmdq[%d]n",\ + pThis->m_state,ident, \ + pThis->m_command_q.m_size); + + if (OMX_COMPONENT_GENERATE_EVENT == id) + { + if (pThis->m_cb.EventHandler) + { + if (OMX_CommandStateSet == p1) + { + pthread_mutex_lock(&pThis->m_state_lock); + pThis->m_state = (OMX_STATETYPE) p2; + pthread_mutex_unlock(&pThis->m_state_lock); + DEBUG_PRINT("CMD:Process->state set to %d \n", \ + pThis->m_state); + + if (pThis->m_state == OMX_StateExecuting || + pThis->m_state == OMX_StateLoaded) + { + + pthread_mutex_lock(&pThis->m_in_th_lock_1); + if (pThis->is_in_th_sleep) + { + pThis->is_in_th_sleep = false; + DEBUG_DETAIL("CMD:WAKING UP IN THREADS\n"); + pThis->in_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + + pthread_mutex_lock(&pThis->m_out_th_lock_1); + if (pThis->is_out_th_sleep) + { + DEBUG_DETAIL("CMD:WAKING UP OUT THREADS\n"); + pThis->is_out_th_sleep = false; + pThis->out_th_wakeup(); + } + pthread_mutex_unlock(&pThis->m_out_th_lock_1); + } + } + if (OMX_StateInvalid == pThis->m_state) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + } else if ((signed)p2 == OMX_ErrorPortUnpopulated) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventError, + (OMX_U32)p2, + 0, + 0 ); + } else + { + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventCmdComplete, + (OMX_U32)p1, (OMX_U32)p2, NULL ); + } + } else + { + DEBUG_PRINT_ERROR("ERROR:CMD-->EventHandler NULL \n"); + } + } else if (OMX_COMPONENT_GENERATE_COMMAND == id) + { + pThis->send_command_proxy(&pThis->m_cmp, + (OMX_COMMANDTYPE)p1, + (OMX_U32)p2,(OMX_PTR)NULL); + } else if (OMX_COMPONENT_PORTSETTINGS_CHANGED == id) + { + DEBUG_DETAIL("CMD-->RXED PORTSETTINGS_CHANGED"); + pThis->m_cb.EventHandler(&pThis->m_cmp, + pThis->m_app_data, + OMX_EventPortSettingsChanged, + 1, 1, NULL ); + } + else + { + DEBUG_PRINT_ERROR("CMD->state[%d]id[%d]\n",pThis->m_state,ident); + } + return; +} + +/*============================================================================= +FUNCTION: + process_in_port_msg + +DESCRIPTION: + + +INPUT/OUTPUT PARAMETERS: + [INOUT] client_data + [IN] id + +RETURN VALUE: + None + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +void omx_qcelp13_aenc::process_in_port_msg(void *client_data, unsigned char id) +{ + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize = 0; + unsigned tot_qsize = 0; + omx_qcelp13_aenc *pThis = (omx_qcelp13_aenc *) client_data; + OMX_STATETYPE state; + + if (!pThis) + { + DEBUG_PRINT_ERROR("ERROR:IN--> Invalid Obj \n"); + return; + } +loopback_in: + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + if ( state == OMX_StateLoaded ) + { + DEBUG_PRINT(" IN: IN LOADED STATE RETURN\n"); + return; + } + // Protect the shared queue data structure + pthread_mutex_lock(&pThis->m_lock); + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + if ( 0 == tot_qsize ) + { + DEBUG_DETAIL("IN-->BREAKING FROM IN LOOP"); + pthread_mutex_unlock(&pThis->m_lock); + return; + } + + if ( (state != OMX_StateExecuting) && ! (pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_DETAIL("SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + /* Get the updated state */ + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + else if ((state == OMX_StatePause)) + { + if(!(pThis->m_input_ctrl_cmd_q.m_size)) + { + pthread_mutex_unlock(&pThis->m_lock); + + DEBUG_DETAIL("IN: SLEEPING IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pThis->in_th_goto_sleep(); + + pthread_mutex_lock(&pThis->m_state_lock); + pThis->get_state(&pThis->m_cmp, &state); + pthread_mutex_unlock(&pThis->m_state_lock); + } + } + + qsize = pThis->m_input_ctrl_cmd_q.m_size; + tot_qsize = qsize; + tot_qsize += pThis->m_input_ctrl_ebd_q.m_size; + tot_qsize += pThis->m_input_q.m_size; + + DEBUG_DETAIL("Input-->QSIZE-flush=%d,ebd=%d QSIZE=%d state=%d\n",\ + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size, state); + + + if ( qsize ) + { + // process FLUSH message + pThis->m_input_ctrl_cmd_q.pop_entry(&p1,&p2,&ident); + } else if ( (qsize = pThis->m_input_ctrl_ebd_q.m_size) && + (state == OMX_StateExecuting) ) + { + // then process EBD's + pThis->m_input_ctrl_ebd_q.pop_entry(&p1,&p2,&ident); + } else if ((qsize = pThis->m_input_q.m_size) && + (state == OMX_StateExecuting)) + { + // if no FLUSH and EBD's then process ETB's + pThis->m_input_q.pop_entry(&p1, &p2, &ident); + } else if ( state == OMX_StateLoaded ) + { + pthread_mutex_unlock(&pThis->m_lock); + DEBUG_PRINT("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + DEBUG_PRINT("IN-->state[%d]cmdq[%d]ebdq[%d]in[%d]\n",\ + state,pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + + if(state == OMX_StatePause) + { + DEBUG_DETAIL("IN: SLEEPING AGAIN IN THREAD\n"); + pthread_mutex_lock(&pThis->m_in_th_lock_1); + pThis->is_in_th_sleep = true; + pthread_mutex_unlock(&pThis->m_in_th_lock_1); + pthread_mutex_unlock(&pThis->m_lock); + pThis->in_th_goto_sleep(); + goto loopback_in; + } + } + pthread_mutex_unlock(&pThis->m_lock); + + if ( qsize > 0 ) + { + id = ident; + DEBUG_DETAIL("Input->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + pThis->m_state, + ident, + pThis->m_input_ctrl_cmd_q.m_size, + pThis->m_input_ctrl_ebd_q.m_size, + pThis->m_input_q.m_size); + if ( OMX_COMPONENT_GENERATE_BUFFER_DONE == id ) + { + pThis->buffer_done_cb((OMX_BUFFERHEADERTYPE *)p2); + } + else if(id == OMX_COMPONENT_GENERATE_EOS) + { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventBufferFlag, 0, 1, NULL ); + } else if ( OMX_COMPONENT_GENERATE_ETB == id ) + { + pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, + (OMX_BUFFERHEADERTYPE *)p2); + } else if ( OMX_COMPONENT_GENERATE_COMMAND == id ) + { + // Execute FLUSH command + if ( OMX_CommandFlush == p1 ) + { + DEBUG_DETAIL(" Executing FLUSH command on Input port\n"); + pThis->execute_input_omx_flush(); + } else + { + DEBUG_DETAIL("Invalid command[%lu]\n",p1); + } + } + else + { + DEBUG_PRINT_ERROR("ERROR:IN-->Invalid Id[%d]\n",id); + } + } else + { + DEBUG_DETAIL("ERROR:IN-->Empty INPUT Q\n"); + } + return; +} + +/** + @brief member function for performing component initialization + + @param role C string mandating role of this component + @return Error status + */ +OMX_ERRORTYPE omx_qcelp13_aenc::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + m_state = OMX_StateLoaded; + + /* DSP does not give information about the bitstream + randomly assign the value right now. Query will result in + incorrect param */ + memset(&m_qcelp13_param, 0, sizeof(m_qcelp13_param)); + m_qcelp13_param.nSize = (OMX_U32)sizeof(m_qcelp13_param); + m_qcelp13_param.nChannels = OMX_QCELP13_DEFAULT_CH_CFG; + //Current DSP does not have config + m_qcelp13_param.eCDMARate = OMX_AUDIO_CDMARateFull; + m_qcelp13_param.nMinBitRate = OMX_QCELP13_DEFAULT_MINRATE; + m_qcelp13_param.nMaxBitRate = OMX_QCELP13_DEFAULT_MAXRATE; + m_volume = OMX_QCELP13_DEFAULT_VOL; /* Close to unity gain */ + memset(&m_qcelp13_pb_stats,0,sizeof(QCELP13_PB_STATS)); + memset(&m_pcm_param, 0, sizeof(m_pcm_param)); + m_pcm_param.nSize = (OMX_U32)sizeof(m_pcm_param); + m_pcm_param.nChannels = OMX_QCELP13_DEFAULT_CH_CFG; + m_pcm_param.nSamplingRate = OMX_QCELP13_DEFAULT_SF; + nTimestamp = 0; + + + nNumInputBuf = 0; + nNumOutputBuf = 0; + m_ipc_to_in_th = NULL; // Command server instance + m_ipc_to_out_th = NULL; // Client server instance + m_ipc_to_cmd_th = NULL; // command instance + m_is_out_th_sleep = 0; + m_is_in_th_sleep = 0; + is_out_th_sleep= false; + + is_in_th_sleep=false; + + memset(&m_priority_mgm, 0, sizeof(m_priority_mgm)); + m_priority_mgm.nGroupID =0; + m_priority_mgm.nGroupPriority=0; + + memset(&m_buffer_supplier, 0, sizeof(m_buffer_supplier)); + m_buffer_supplier.nPortIndex=OMX_BufferSupplyUnspecified; + + DEBUG_PRINT_ERROR(" component init: role = %s\n",role); + + DEBUG_PRINT(" component init: role = %s\n",role); + component_Role.nVersion.nVersion = OMX_SPEC_VERSION; + if (!strcmp(role,"OMX.qcom.audio.encoder.qcelp13")) + { + pcm_input = 1; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.qcelp13")) + { + pcm_input = 0; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED \n", role); + } else + { + component_Role.nSize = (OMX_U32)sizeof("\0"); + strlcpy((char *)component_Role.cRole, (const char*)"\0", + sizeof(component_Role.cRole)); + DEBUG_PRINT("\ncomponent_init: Component %s LOADED is invalid\n", role); + } + if(pcm_input) + { + + + m_tmp_meta_buf = (OMX_U8*) malloc(sizeof(OMX_U8) * + (OMX_CORE_INPUT_BUFFER_SIZE + sizeof(META_IN))); + + if (m_tmp_meta_buf == NULL){ + DEBUG_PRINT_ERROR("Mem alloc failed for in meta buf\n"); + return OMX_ErrorInsufficientResources; + } + } + m_tmp_out_meta_buf = + (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_QCELP13_OUTPUT_BUFFER_SIZE); + if ( m_tmp_out_meta_buf == NULL ) { + DEBUG_PRINT_ERROR("Mem alloc failed for out meta buf\n"); + return OMX_ErrorInsufficientResources; + } + + if(0 == pcm_input) + { + m_drv_fd = open("/dev/msm_qcelp_in",O_RDONLY); + DEBUG_PRINT("Driver in Tunnel mode open\n"); + } + else + { + m_drv_fd = open("/dev/msm_qcelp_in",O_RDWR); + DEBUG_PRINT("Driver in Non Tunnel mode open\n"); + } + if (m_drv_fd < 0) + { + DEBUG_PRINT_ERROR("Component_init Open Failed[%d] errno[%d]",\ + m_drv_fd,errno); + + return OMX_ErrorInsufficientResources; + } + if(ioctl(m_drv_fd, AUDIO_GET_SESSION_ID,&m_session_id) == -1) + { + DEBUG_PRINT_ERROR("AUDIO_GET_SESSION_ID FAILED\n"); + } + if(pcm_input) + { + if (!m_ipc_to_in_th) + { + m_ipc_to_in_th = omx_qcelp13_thread_create(process_in_port_msg, + this, (char *)"INPUT_THREAD"); + if (!m_ipc_to_in_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start \ + Input port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + } + + if (!m_ipc_to_cmd_th) + { + m_ipc_to_cmd_th = omx_qcelp13_thread_create(process_command_msg, + this, (char *)"CMD_THREAD"); + if (!m_ipc_to_cmd_th) + { + DEBUG_PRINT_ERROR("ERROR!!!Failed to start " + "command message thread\n"); + return OMX_ErrorInsufficientResources; + } + } + + if (!m_ipc_to_out_th) + { + m_ipc_to_out_th = omx_qcelp13_thread_create(process_out_port_msg, + this, (char *)"OUTPUT_THREAD"); + if (!m_ipc_to_out_th) + { + DEBUG_PRINT_ERROR("ERROR!!! Failed to start output " + "port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + return eRet; +} + +/** + + @brief member function to retrieve version of component + + + + @param hComp handle to this component instance + @param componentName name of component + @param componentVersion pointer to memory space which stores the + version number + @param specVersion pointer to memory sapce which stores version of + openMax specification + @param componentUUID + @return Error status + */ +OMX_ERRORTYPE omx_qcelp13_aenc::get_component_version +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID) +{ + if((hComp == NULL) || (componentName == NULL) || + (specVersion == NULL) || (componentUUID == NULL)) + { + componentVersion = NULL; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + componentVersion->nVersion = OMX_SPEC_VERSION; + specVersion->nVersion = OMX_SPEC_VERSION; + return OMX_ErrorNone; +} +/** + @brief member function handles command from IL client + + This function simply queue up commands from IL client. + Commands will be processed in command server thread context later + + @param hComp handle to component instance + @param cmd type of command + @param param1 parameters associated with the command type + @param cmdData + @return Error status +*/ +OMX_ERRORTYPE omx_qcelp13_aenc::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + int portIndex = (int)param1; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateInvalid == m_state) + { + return OMX_ErrorInvalidState; + } + if ( (cmd == OMX_CommandFlush) && (portIndex > 1) ) + { + return OMX_ErrorBadPortIndex; + } + post_command((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + DEBUG_PRINT("Send Command : returns with OMX_ErrorNone \n"); + DEBUG_PRINT("send_command : recieved state before semwait= %u\n",param1); + sem_wait (&sem_States); + DEBUG_PRINT("send_command : recieved state after semwait\n"); + return OMX_ErrorNone; +} + +/** + @brief member function performs actual processing of commands excluding + empty buffer call + + @param hComp handle to component + @param cmd command type + @param param1 parameter associated with the command + @param cmdData + + @return error status +*/ +OMX_ERRORTYPE omx_qcelp13_aenc::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + // Handle only IDLE and executing + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1; + nState = eState; + + if(hComp == NULL) + { + cmdData = cmdData; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_CommandStateSet == cmd) + { + /***************************/ + /* Current State is Loaded */ + /***************************/ + if (OMX_StateLoaded == m_state) + { + if (OMX_StateIdle == eState) + { + + if (allocate_done() || + (m_inp_bEnabled == OMX_FALSE + && m_out_bEnabled == OMX_FALSE)) + { + DEBUG_PRINT("SCP-->Allocate Done Complete\n"); + } + else + { + DEBUG_PRINT("SCP-->Loaded to Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + bFlag = 0; + } + + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Loaded\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } + + else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->WaitForResources\n"); + eRet = OMX_ErrorNone; + } + + else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Executing\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Pause\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Loaded-->Invalid\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + m_state = OMX_StateInvalid; + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP-->Loaded to Invalid(%d))\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if (OMX_StateIdle == m_state) + { + if (OMX_StateLoaded == eState) + { + if (release_done(-1)) + { + if (ioctl(m_drv_fd, AUDIO_STOP, 0) == -1) + { + DEBUG_PRINT_ERROR("SCP:Idle->Loaded,\ + ioctl stop failed %d\n", errno); + } + + nTimestamp=0; + + DEBUG_PRINT("SCP-->Idle to Loaded\n"); + } else + { + DEBUG_PRINT("SCP--> Idle to Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + else if (OMX_StateExecuting == eState) + { + + struct msm_audio_qcelp_enc_config drv_qcelp13_enc_config; + struct msm_audio_stream_config drv_stream_config; + struct msm_audio_buf_cfg buf_cfg; + struct msm_audio_config pcm_cfg; + + if(ioctl(m_drv_fd, AUDIO_GET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + if(ioctl(m_drv_fd, AUDIO_SET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + + if(ioctl(m_drv_fd, AUDIO_GET_QCELP_ENC_CONFIG, + &drv_qcelp13_enc_config) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_QCELP_ENC_CONFIG failed,\ + errno[%d]\n", errno); + } + drv_qcelp13_enc_config.min_bit_rate = m_qcelp13_param.nMinBitRate; + drv_qcelp13_enc_config.max_bit_rate = m_qcelp13_param.nMaxBitRate; + if(ioctl(m_drv_fd, AUDIO_SET_QCELP_ENC_CONFIG, &drv_qcelp13_enc_config) + == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_QCELP_ENC_CONFIG \ + failed, errno[%d]\n", errno); + } + if (ioctl(m_drv_fd, AUDIO_GET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_BUF_CFG, errno[%d]\n", + errno); + } + buf_cfg.meta_info_enable = 1; + buf_cfg.frames_per_buf = NUMOFFRAMES; + if (ioctl(m_drv_fd, AUDIO_SET_BUF_CFG, &buf_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_BUF_CFG, errno[%d]\n", + errno); + } + if(pcm_input) + { + if (ioctl(m_drv_fd, AUDIO_GET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_GET_CONFIG, errno[%d]\n", + errno); + } + pcm_cfg.channel_count = m_pcm_param.nChannels; + pcm_cfg.sample_rate = m_pcm_param.nSamplingRate; + DEBUG_PRINT("pcm config %u %u\n",m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + + if (ioctl(m_drv_fd, AUDIO_SET_CONFIG, &pcm_cfg) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_SET_CONFIG, errno[%d]\n", + errno); + } + } + if(ioctl(m_drv_fd, AUDIO_START, 0) == -1) + { + DEBUG_PRINT_ERROR("ioctl AUDIO_START failed, errno[%d]\n", + errno); + } + DEBUG_PRINT("SCP-->Idle to Executing\n"); + nState = eState; + } else if (eState == OMX_StateIdle) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Idle\n"); + m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } + + else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Pause\n"); + } + + else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: Idle-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, + this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Idle to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if (OMX_StateExecuting == m_state) + { + if (OMX_StateIdle == eState) + { + DEBUG_PRINT("SCP-->Executing to Idle \n"); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + + } else if (OMX_StatePause == eState) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED PAUSE STATE\n"); + DEBUG_DETAIL("*************************\n"); + //ioctl(m_drv_fd, AUDIO_PAUSE, 0); + } else if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Executing \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n OMXCORE-SM: Executing --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> Executing to %d Not Handled\n", + eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if (OMX_StatePause == m_state) + { + if( (eState == OMX_StateExecuting || eState == OMX_StateIdle) ) + { + pthread_mutex_lock(&m_out_th_lock_1); + if(is_out_th_sleep) + { + DEBUG_DETAIL("PE: WAKING UP OUT THREAD\n"); + is_out_th_sleep = false; + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } + if ( OMX_StateExecuting == eState ) + { + nState = eState; + } else if ( OMX_StateIdle == eState ) + { + DEBUG_PRINT("SCP-->Paused to Idle \n"); + DEBUG_PRINT ("\n Internal flush issued"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + + } else if ( eState == OMX_StateLoaded ) + { + DEBUG_PRINT("\n Pause --> loaded \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("\n Pause --> WaitForResources \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("\n Pause --> Pause \n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("\n Pause --> Invalid \n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT("SCP-->Paused to %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /**************************************/ + /* Current State is WaitForResources */ + /**************************************/ + else if (m_state == OMX_StateWaitForResources) + { + if (eState == OMX_StateLoaded) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Loaded\n"); + } else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT("OMXCORE-SM: \ + WaitForResources-->WaitForResources\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorSameState, + 0, NULL ); + eRet = OMX_ErrorSameState; + } else if (eState == OMX_StateExecuting) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Executing\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StatePause) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Pause\n"); + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorIncorrectStateTransition, + 0, NULL ); + eRet = OMX_ErrorIncorrectStateTransition; + } else if (eState == OMX_StateInvalid) + { + DEBUG_PRINT("OMXCORE-SM: WaitForResources-->Invalid\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, + OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } else + { + DEBUG_PRINT_ERROR("SCP--> %d to %d(Not Handled)\n", + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /****************************/ + /* Current State is Invalid */ + /****************************/ + else if (m_state == OMX_StateInvalid) + { + if (OMX_StateLoaded == eState || OMX_StateWaitForResources == eState + || OMX_StateIdle == eState || OMX_StateExecuting == eState + || OMX_StatePause == eState || OMX_StateInvalid == eState) + { + DEBUG_PRINT("OMXCORE-SM: Invalid-->Loaded/Idle/Executing" + "/Pause/Invalid/WaitForResources\n"); + m_state = OMX_StateInvalid; + this->m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + 0, NULL ); + eRet = OMX_ErrorInvalidState; + } + } else + { + DEBUG_PRINT_ERROR("OMXCORE-SM: %d --> %d(Not Handled)\n",\ + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } else if (OMX_CommandFlush == cmd) + { + DEBUG_DETAIL("*************************\n"); + DEBUG_PRINT("SCP-->RXED FLUSH COMMAND port=%u\n",param1); + DEBUG_DETAIL("*************************\n"); + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || + param1 == OMX_CORE_OUTPUT_PORT_INDEX || + (signed)param1 == -1 ) + { + execute_omx_flush(param1); + } else + { + eRet = OMX_ErrorBadPortIndex; + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError, + OMX_CommandFlush, OMX_ErrorBadPortIndex, NULL ); + } + } else if ( cmd == OMX_CommandPortDisable ) + { + bFlag = 0; + if ( param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL ) + { + DEBUG_PRINT("SCP: Disabling Input port Indx\n"); + m_inp_bEnabled = OMX_FALSE; + if ( (m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(0) ) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_inp_bEnabled=%d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + + else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable in "\ + " param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + // Skip the event notification + + } + + } + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + + DEBUG_PRINT("SCP: Disabling Output port Indx\n"); + m_out_bEnabled = OMX_FALSE; + if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(1)) + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + DEBUG_PRINT("************* OMX_CommandPortDisable:\ + m_out_bEnabled=%d********\n",m_inp_bEnabled); + + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + DEBUG_PRINT("SCP: execute_omx_flush in Disable out "\ + "param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + // Skip the event notification + + } + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortDisable: disable wrong port ID"); + } + + } else if (cmd == OMX_CommandPortEnable) + { + bFlag = 0; + if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_TRUE; + DEBUG_PRINT("SCP: Enabling Input port Indx\n"); + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_inp_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + + } else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + + } + } + + if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + DEBUG_PRINT("SCP: Enabling Output port Indx\n"); + m_out_bEnabled = OMX_TRUE; + if ((m_state == OMX_StateLoaded + && !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources) + || (m_out_bPopulated == OMX_TRUE)) + { + post_command(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } else + { + DEBUG_PRINT("send_command_proxy:OMX_CommandPortEnable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + + } + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_PRINT("SCP:WAKING OUT THR, OMX_CommandPortEnable\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } else + { + DEBUG_PRINT_ERROR("OMX_CommandPortEnable: disable wrong port ID"); + } + + } else + { + DEBUG_PRINT_ERROR("SCP-->ERROR: Invali Command [%d]\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + DEBUG_PRINT("posting sem_States\n"); + sem_post (&sem_States); + if (eRet == OMX_ErrorNone && bFlag) + { + post_command(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + return eRet; +} + +/*============================================================================= +FUNCTION: + execute_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + [IN] param1 + [IN] cmd_cmpl + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_qcelp13_aenc::execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl) +{ + bool bRet = true; + + DEBUG_PRINT("Execute_omx_flush Port[%u]", param1); + struct timespec abs_timeout; + abs_timeout.tv_sec = 1; + abs_timeout.tv_nsec = 0; + + if ((signed)param1 == -1) + { + bFlushinprogress = true; + DEBUG_PRINT("Execute flush for both I/p O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 2; + pthread_mutex_unlock(&m_flush_lock); + + // Send Flush commands to input and output threads + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + // Send Flush to the kernel so that the in and out buffers are released + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("FLush:ioctl flush failed errno=%d\n",errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + + + // sleep till the FLUSH ACK are done by both the input and + // output threads + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + + DEBUG_PRINT("RECIEVED BOTH FLUSH ACK's param1=%u cmd_cmpl=%d",\ + param1,cmd_cmpl); + + // If not going to idle state, Send FLUSH complete message + // to the Client, now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + DEBUG_PRINT("Inside FLUSH.. sending FLUSH CMPL\n"); + } + bFlushinprogress = false; + } + else if (param1 == OMX_CORE_INPUT_PORT_INDEX) + { + DEBUG_PRINT("Execute FLUSH for I/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + post_input(OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) == -1) + DEBUG_PRINT_ERROR("Flush:Input port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + //sleep till the FLUSH ACK are done by both the input and output threads + DEBUG_DETAIL("Executing FLUSH for I/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + wait_for_event(); + DEBUG_DETAIL(" RECIEVED FLUSH ACK FOR I/P PORT param1=%d",param1); + + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX, + NULL ); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == param1) + { + DEBUG_PRINT("Executing FLUSH for O/p port\n"); + pthread_mutex_lock(&m_flush_lock); + m_flush_cnt = 1; + pthread_mutex_unlock(&m_flush_lock); + DEBUG_DETAIL("Executing FLUSH for O/p port\n"); + DEBUG_DETAIL("WAITING FOR FLUSH ACK's param1=%d",param1); + post_output(OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,OMX_COMPONENT_GENERATE_COMMAND); + if (ioctl( m_drv_fd, AUDIO_FLUSH, 0) ==-1) + DEBUG_PRINT_ERROR("Flush:Output port, ioctl flush failed %d\n", + errno); + DEBUG_DETAIL("****************************************"); + DEBUG_DETAIL("is_in_th_sleep=%d is_out_th_sleep=%d\n",\ + is_in_th_sleep,is_out_th_sleep); + DEBUG_DETAIL("****************************************"); + if (is_in_th_sleep) + { + pthread_mutex_lock(&m_in_th_lock_1); + is_in_th_sleep = false; + pthread_mutex_unlock(&m_in_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + + if (is_out_th_sleep) + { + pthread_mutex_lock(&m_out_th_lock_1); + is_out_th_sleep = false; + pthread_mutex_unlock(&m_out_th_lock_1); + DEBUG_DETAIL("For FLUSH-->WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + + // sleep till the FLUSH ACK are done by both the input and + // output threads + wait_for_event(); + // Send FLUSH complete message to the Client, + // now that FLUSH ACK's have been recieved. + if (cmd_cmpl) + { + m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventCmdComplete, + OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX, + NULL ); + } + DEBUG_DETAIL("RECIEVED FLUSH ACK FOR O/P PORT param1=%d",param1); + } else + { + DEBUG_PRINT("Invalid Port ID[%u]",param1); + } + return bRet; +} + +/*============================================================================= +FUNCTION: + execute_input_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_qcelp13_aenc::execute_input_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on input port"); + + pthread_mutex_lock(&m_lock); + do + { + qsize = m_input_q.m_size; + tot_qsize = qsize; + tot_qsize += m_input_ctrl_ebd_q.m_size; + + DEBUG_DETAIL("Input FLUSH-->flushq[%d] ebd[%d]dataq[%d]",\ + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size,qsize); + if (!tot_qsize) + { + DEBUG_DETAIL("Input-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_lock); + break; + } + if (qsize) + { + m_input_q.pop_entry(&p1, &p2, &ident); + if ((ident == OMX_COMPONENT_GENERATE_ETB) || + (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Flush:Input dataq=%p \n", omx_buf); + omx_buf->nFilledLen = 0; + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else if (m_input_ctrl_ebd_q.m_size) + { + m_input_ctrl_ebd_q.pop_entry(&p1, &p2, &ident); + if (ident == OMX_COMPONENT_GENERATE_BUFFER_DONE) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + omx_buf->nFilledLen = 0; + DEBUG_DETAIL("Flush:ctrl dataq=%p \n", omx_buf); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + } + } else + { + } + }while (tot_qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("IN-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_lock); + return true; +} + +/*============================================================================= +FUNCTION: + execute_output_omx_flush + +DESCRIPTION: + Function that flushes buffers that are pending to be written to driver + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_qcelp13_aenc::execute_output_omx_flush() +{ + OMX_BUFFERHEADERTYPE *omx_buf; + unsigned long p1 = 0; // Parameter - 1 + unsigned long p2 = 0; // Parameter - 2 + unsigned char ident = 0; + unsigned qsize=0; // qsize + unsigned tot_qsize=0; // qsize + + DEBUG_PRINT("Execute_omx_flush on output port"); + + pthread_mutex_lock(&m_outputlock); + do + { + qsize = m_output_q.m_size; + DEBUG_DETAIL("OUT FLUSH-->flushq[%d] fbd[%d]dataq[%d]",\ + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size,qsize); + tot_qsize = qsize; + tot_qsize += m_output_ctrl_fbd_q.m_size; + if (!tot_qsize) + { + DEBUG_DETAIL("OUT-->BREAKING FROM execute_input_flush LOOP"); + pthread_mutex_unlock(&m_outputlock); + break; + } + if (qsize) + { + m_output_q.pop_entry(&p1,&p2,&ident); + if ( (OMX_COMPONENT_GENERATE_FTB == ident) || + (OMX_COMPONENT_GENERATE_FRAME_DONE == ident)) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n",\ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FBD FROM FLUSH"); + } + } else if ((qsize = m_output_ctrl_fbd_q.m_size)) + { + m_output_ctrl_fbd_q.pop_entry(&p1, &p2, &ident); + if (OMX_COMPONENT_GENERATE_FRAME_DONE == ident) + { + omx_buf = (OMX_BUFFERHEADERTYPE *) p2; + DEBUG_DETAIL("Ouput Buf_Addr=%p TS[0x%x] \n", \ + omx_buf,nTimestamp); + omx_buf->nTimeStamp = nTimestamp; + omx_buf->nFilledLen = 0; + frame_done_cb((OMX_BUFFERHEADERTYPE *)omx_buf); + DEBUG_DETAIL("CALLING FROM CTRL-FBDQ FROM FLUSH"); + } + } + }while (qsize>0); + DEBUG_DETAIL("*************************\n"); + DEBUG_DETAIL("OUT-->FLUSHING DONE\n"); + DEBUG_DETAIL("*************************\n"); + flush_ack(); + pthread_mutex_unlock(&m_outputlock); + return true; +} + +/*============================================================================= +FUNCTION: + post_input + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_qcelp13_aenc::post_input(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + pthread_mutex_lock(&m_lock); + + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND)) + { + // insert flush message and ebd + m_input_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ((OMX_COMPONENT_GENERATE_BUFFER_DONE == id)) + { + // insert ebd + m_input_ctrl_ebd_q.insert_entry(p1,p2,id); + } else + { + // ETBS in this queue + m_input_q.insert_entry(p1,p2,id); + } + + if (m_ipc_to_in_th) + { + bRet = true; + omx_qcelp13_post_msg(m_ipc_to_in_th, id); + } + + DEBUG_DETAIL("PostInput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d] \n",\ + m_state, + id, + m_input_ctrl_cmd_q.m_size, + m_input_ctrl_ebd_q.m_size, + m_input_q.m_size); + + pthread_mutex_unlock(&m_lock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_command + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_qcelp13_aenc::post_command(unsigned int p1, + unsigned int p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_commandlock); + + m_command_q.insert_entry(p1,p2,id); + + if (m_ipc_to_cmd_th) + { + bRet = true; + omx_qcelp13_post_msg(m_ipc_to_cmd_th, id); + } + + DEBUG_DETAIL("PostCmd-->state[%d]id[%d]cmdq[%d]flags[%x]\n",\ + m_state, + id, + m_command_q.m_size, + m_flags >> 3); + + pthread_mutex_unlock(&m_commandlock); + return bRet; +} + +/*============================================================================= +FUNCTION: + post_output + +DESCRIPTION: + Function that posts command in the command queue + +INPUT/OUTPUT PARAMETERS: + [IN] p1 + [IN] p2 + [IN] id - command ID + [IN] lock - self-locking mode + +RETURN VALUE: + true + false + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +bool omx_qcelp13_aenc::post_output(unsigned long p1, + unsigned long p2, + unsigned char id) +{ + bool bRet = false; + + pthread_mutex_lock(&m_outputlock); + if((OMX_COMPONENT_GENERATE_COMMAND == id) || (id == OMX_COMPONENT_SUSPEND) + || (id == OMX_COMPONENT_RESUME)) + { + // insert flush message and fbd + m_output_ctrl_cmd_q.insert_entry(p1,p2,id); + } else if ( (OMX_COMPONENT_GENERATE_FRAME_DONE == id) ) + { + // insert flush message and fbd + m_output_ctrl_fbd_q.insert_entry(p1,p2,id); + } else + { + m_output_q.insert_entry(p1,p2,id); + } + if ( m_ipc_to_out_th ) + { + bRet = true; + omx_qcelp13_post_msg(m_ipc_to_out_th, id); + } + DEBUG_DETAIL("PostOutput-->state[%d]id[%d]flushq[%d]ebdq[%d]dataq[%d]\n",\ + m_state, + id, + m_output_ctrl_cmd_q.m_size, + m_output_ctrl_fbd_q.m_size, + m_output_q.m_size); + + pthread_mutex_unlock(&m_outputlock); + return bRet; +} +/** + @brief member function that return parameters to IL client + + @param hComp handle to component instance + @param paramIndex Parameter type + @param paramData pointer to memory space which would hold the + paramter + @return error status +*/ +OMX_ERRORTYPE omx_qcelp13_aenc::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (paramData == NULL) + { + DEBUG_PRINT("get_parameter: paramData is NULL\n"); + return OMX_ErrorBadParameter; + } + + switch ((int)paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + DEBUG_PRINT("OMX_IndexParamPortDefinition " \ + "portDefn->nPortIndex = %u\n", + portDefn->nPortIndex); + + portDefn->nVersion.nVersion = OMX_SPEC_VERSION; + portDefn->nSize = (OMX_U32)sizeof(portDefn); + portDefn->eDomain = OMX_PortDomainAudio; + + if (0 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirInput; + portDefn->bEnabled = m_inp_bEnabled; + portDefn->bPopulated = m_inp_bPopulated; + portDefn->nBufferCountActual = m_inp_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_INPUT_BUFFERS; + portDefn->nBufferSize = input_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingPCM; + portDefn->format.audio.pNativeRender = 0; + } else if (1 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirOutput; + portDefn->bEnabled = m_out_bEnabled; + portDefn->bPopulated = m_out_bPopulated; + portDefn->nBufferCountActual = m_out_act_buf_count; + portDefn->nBufferCountMin = OMX_CORE_NUM_OUTPUT_BUFFERS; + portDefn->nBufferSize = output_buffer_size; + portDefn->format.audio.bFlagErrorConcealment = OMX_TRUE; + portDefn->format.audio.eEncoding = OMX_AUDIO_CodingQCELP13; + portDefn->format.audio.pNativeRender = 0; + } else + { + portDefn->eDir = OMX_DirMax; + DEBUG_PRINT_ERROR("Bad Port idx %d\n",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioInit\n"); + + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 2; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioPortFormat\n"); + portFormatType->nVersion.nVersion = OMX_SPEC_VERSION; + portFormatType->nSize = (OMX_U32)sizeof(portFormatType); + + if (OMX_CORE_INPUT_PORT_INDEX == portFormatType->nPortIndex) + { + + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + portFormatType->nPortIndex) + { + DEBUG_PRINT("get_parameter: OMX_IndexParamAudioFormat: "\ + "%u\n", portFormatType->nIndex); + + portFormatType->eEncoding = OMX_AUDIO_CodingQCELP13; + } else + { + DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamAudioQcelp13: + { + OMX_AUDIO_PARAM_QCELP13TYPE *qcelp13Param = + (OMX_AUDIO_PARAM_QCELP13TYPE *) paramData; + DEBUG_PRINT("OMX_IndexParamAudioQcelp13\n"); + if (OMX_CORE_OUTPUT_PORT_INDEX== qcelp13Param->nPortIndex) + { + memcpy(qcelp13Param,&m_qcelp13_param, + sizeof(OMX_AUDIO_PARAM_QCELP13TYPE)); + } else + { + DEBUG_PRINT_ERROR("get_parameter:\ + OMX_IndexParamAudioQcelp13 \ + OMX_ErrorBadPortIndex %d\n", \ + (int)qcelp13Param->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case QOMX_IndexParamAudioSessionId: + { + QOMX_AUDIO_STREAM_INFO_DATA *streaminfoparam = + (QOMX_AUDIO_STREAM_INFO_DATA *) paramData; + streaminfoparam->sessionId = (OMX_U8)m_session_id; + break; + } + + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam = + (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(pcmparam,&m_pcm_param,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + DEBUG_PRINT("get_parameter: Sampling rate %u",\ + pcmparam->nSamplingRate); + DEBUG_PRINT("get_parameter: Number of channels %u",\ + pcmparam->nChannels); + } else + { + DEBUG_PRINT_ERROR("get_parameter:OMX_IndexParamAudioPcm "\ + "OMX_ErrorBadPortIndex %d\n", \ + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamComponentSuspended: + { + OMX_PARAM_SUSPENSIONTYPE *suspend = + (OMX_PARAM_SUSPENSIONTYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamComponentSuspended %p\n", + suspend); + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamVideoInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *priorityMgmtType = + (OMX_PRIORITYMGMTTYPE*)paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamPriorityMgmt\n"); + priorityMgmtType->nSize = (OMX_U32)sizeof(priorityMgmtType); + priorityMgmtType->nVersion.nVersion = OMX_SPEC_VERSION; + priorityMgmtType->nGroupID = m_priority_mgm.nGroupID; + priorityMgmtType->nGroupPriority = + m_priority_mgm.nGroupPriority; + break; + } + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamImageInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + + bufferSupplierType->nSize = (OMX_U32)sizeof(bufferSupplierType); + bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; + if (OMX_CORE_INPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + bufferSupplierType->nPortIndex) + { + bufferSupplierType->nPortIndex = + OMX_BufferSupplyUnspecified; + } else + { + DEBUG_PRINT_ERROR("get_parameter:"\ + "OMX_IndexParamCompBufferSupplier eRet"\ + "%08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT("get_parameter: OMX_IndexParamOtherInit\n"); + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = (OMX_U32)sizeof(portParamType); + portParamType->nPorts = 0; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + componentRole->nSize = component_Role.nSize; + componentRole->nVersion = component_Role.nVersion; + strlcpy((char *)componentRole->cRole, + (const char*)component_Role.cRole, + sizeof(componentRole->cRole)); + DEBUG_PRINT_ERROR("nSize = %d , nVersion = %d, cRole = %s\n", + component_Role.nSize, + component_Role.nVersion, + component_Role.cRole); + break; + + } + default: + { + DEBUG_PRINT_ERROR("unknown param %08x\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; + +} + +/** + @brief member function that set paramter from IL client + + @param hComp handle to component instance + @param paramIndex parameter type + @param paramData pointer to memory space which holds the paramter + @return error status + */ +OMX_ERRORTYPE omx_qcelp13_aenc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("set_parameter is not in proper state\n"); + return OMX_ErrorIncorrectStateOperation; + } + if (paramData == NULL) + { + DEBUG_PRINT("param data is NULL"); + return OMX_ErrorBadParameter; + } + + switch (paramIndex) + { + case OMX_IndexParamAudioQcelp13: + { + DEBUG_PRINT("OMX_IndexParamAudioQcelp13"); + OMX_AUDIO_PARAM_QCELP13TYPE *qcelp13param + = (OMX_AUDIO_PARAM_QCELP13TYPE *) paramData; + memcpy(&m_qcelp13_param,qcelp13param, + sizeof(OMX_AUDIO_PARAM_QCELP13TYPE)); + break; + } + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + if (((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (m_state == OMX_StateWaitForResources && + ((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == true)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == true))) + ||(((OMX_DirInput == portDefn->eDir && + m_inp_bEnabled == false)|| + (OMX_DirInput == portDefn->eDir && + m_out_bEnabled == false)) && + (m_state != OMX_StateWaitForResources))) + { + DEBUG_PRINT("Set Parameter called in valid state\n"); + } else + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + DEBUG_PRINT("OMX_IndexParamPortDefinition portDefn->nPortIndex " + "= %u\n",portDefn->nPortIndex); + if (OMX_CORE_INPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_INPUT_BUFFERS ) + { + m_inp_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_inp_act_buf_count =OMX_CORE_NUM_INPUT_BUFFERS; + } + input_buffer_size = portDefn->nBufferSize; + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == portDefn->nPortIndex) + { + if ( portDefn->nBufferCountActual > + OMX_CORE_NUM_OUTPUT_BUFFERS ) + { + m_out_act_buf_count = portDefn->nBufferCountActual; + } else + { + m_out_act_buf_count =OMX_CORE_NUM_OUTPUT_BUFFERS; + } + output_buffer_size = portDefn->nBufferSize; + } else + { + DEBUG_PRINT(" set_parameter: Bad Port idx %d",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamPriorityMgmt: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt\n"); + + if (m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype + = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamPriorityMgmt %u\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT("set_parameter: priorityMgmtype %u\n", + priorityMgmtype->nGroupPriority); + + m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; + m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + case OMX_IndexParamAudioPortFormat: + { + + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormatType = + (OMX_AUDIO_PARAM_PORTFORMATTYPE *) paramData; + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPortFormat\n"); + + if (OMX_CORE_INPUT_PORT_INDEX== portFormatType->nPortIndex) + { + portFormatType->eEncoding = OMX_AUDIO_CodingPCM; + } else if (OMX_CORE_OUTPUT_PORT_INDEX == + portFormatType->nPortIndex) + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioFormat:"\ + " %u\n", portFormatType->nIndex); + portFormatType->eEncoding = OMX_AUDIO_CodingQCELP13; + } else + { + DEBUG_PRINT_ERROR("set_parameter: Bad port index %d\n", \ + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT("set_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT("set_param: OMX_IndexParamCompBufferSupplier %d",\ + bufferSupplierType->eBufferSupplier); + + if (bufferSupplierType->nPortIndex == OMX_CORE_INPUT_PORT_INDEX + || bufferSupplierType->nPortIndex == + OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT("set_parameter:\ + OMX_IndexParamCompBufferSupplier\n"); + m_buffer_supplier.eBufferSupplier = + bufferSupplierType->eBufferSupplier; + } else + { + DEBUG_PRINT_ERROR("set_param:\ + IndexParamCompBufferSup %08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + + break; } + + case OMX_IndexParamAudioPcm: + { + DEBUG_PRINT("set_parameter: OMX_IndexParamAudioPcm\n"); + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam + = (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(&m_pcm_param,pcmparam,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + DEBUG_PRINT("set_pcm_parameter: %u %u",\ + m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + } else + { + DEBUG_PRINT_ERROR("Set_parameter:OMX_IndexParamAudioPcm " + "OMX_ErrorBadPortIndex %d\n", + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamSuspensionPolicy: + { + eRet = OMX_ErrorNotImplemented; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *componentRole; + componentRole = (OMX_PARAM_COMPONENTROLETYPE*)paramData; + component_Role.nSize = componentRole->nSize; + component_Role.nVersion = componentRole->nVersion; + strlcpy((char *)component_Role.cRole, + (const char*)componentRole->cRole, + sizeof(component_Role.cRole)); + break; + } + + default: + { + DEBUG_PRINT_ERROR("unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *volume = + (OMX_AUDIO_CONFIG_VOLUMETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == volume->nPortIndex) + { + volume->nSize = (OMX_U32)sizeof(volume); + volume->nVersion.nVersion = OMX_SPEC_VERSION; + volume->bLinear = OMX_TRUE; + volume->sVolume.nValue = m_volume; + volume->sVolume.nMax = OMX_AENC_MAX; + volume->sVolume.nMin = OMX_AENC_MIN; + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = + (OMX_AUDIO_CONFIG_MUTETYPE*) configData; + + if (OMX_CORE_INPUT_PORT_INDEX == mute->nPortIndex) + { + mute->nSize = (OMX_U32)sizeof(mute); + mute->nVersion.nVersion = OMX_SPEC_VERSION; + mute->bMute = (BITMASK_PRESENT(&m_flags, + OMX_COMPONENT_MUTED)?OMX_TRUE:OMX_FALSE); + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Set Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if ( m_state == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_IndexConfigAudioVolume: + { + OMX_AUDIO_CONFIG_VOLUMETYPE *vol = + (OMX_AUDIO_CONFIG_VOLUMETYPE*)configData; + if (vol->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if ((vol->sVolume.nValue <= OMX_AENC_MAX) && + (vol->sVolume.nValue >= OMX_AENC_MIN)) + { + m_volume = vol->sVolume.nValue; + if (BITMASK_ABSENT(&m_flags, OMX_COMPONENT_MUTED)) + { + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + + } else + { + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + case OMX_IndexConfigAudioMute: + { + OMX_AUDIO_CONFIG_MUTETYPE *mute = (OMX_AUDIO_CONFIG_MUTETYPE*) + configData; + if (mute->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) + { + if (mute->bMute == OMX_TRUE) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, 0); */ + } else + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_MUTED); + /* ioctl(m_drv_fd, AUDIO_VOLUME, + m_volume * OMX_AENC_VOLUME_STEP); */ + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + } + break; + + default: + eRet = OMX_ErrorUnsupportedIndex; + break; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. <TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::get_extension_index( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if((hComp == NULL) || (paramName == NULL) || (indexType == NULL)) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(strncmp(paramName,"OMX.Qualcomm.index.audio.sessionId", + strlen("OMX.Qualcomm.index.audio.sessionId")) == 0) + { + *indexType =(OMX_INDEXTYPE)QOMX_IndexParamAudioSessionId; + DEBUG_PRINT("Extension index type - %d\n", *indexType); + + } + else + { + return OMX_ErrorBadParameter; + + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::GetState + +DESCRIPTION + Returns the state information back to the caller.<TBD> + +PARAMETERS + <TBD>. + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + *state = m_state; + DEBUG_PRINT("Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. <TBD> + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::component_tunnel_request +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n"); + + if((hComp == NULL) || (peerComponent == NULL) || (tunnelSetup == NULL)) + { + port = port; + peerPort = peerPort; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::allocate_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + if(m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc((nBufSize + \ + sizeof(OMX_BUFFERHEADERTYPE)+sizeof(META_IN)) , 1); + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + free(buf_ptr); + return OMX_ErrorBadParameter; + } + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + sizeof(META_IN)+ + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + m_input_buf_hdrs.insert(bufHdr, NULL); + + m_inp_current_buf_count++; + DEBUG_PRINT("AIB:bufHdr %p bufHdr->pBuffer %p m_inp_buf_cnt=%d \ + bytes=%u", bufHdr, bufHdr->pBuffer,m_inp_current_buf_count, + bytes); + + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT("Input buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +OMX_ERRORTYPE omx_qcelp13_aenc::allocate_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_out_current_buf_count < m_out_act_buf_count) + { + buf_ptr = (char *) calloc( (nBufSize + sizeof(OMX_BUFFERHEADERTYPE)),1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)((buf_ptr) + + sizeof(OMX_BUFFERHEADERTYPE)); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + DEBUG_PRINT("AOB::bufHdr %p bufHdr->pBuffer %p m_out_buf_cnt=%d "\ + "bytes=%u",bufHdr, bufHdr->pBuffer,\ + m_out_current_buf_count, bytes); + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::allocate_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + // What if the client calls again. + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n", + (int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("allocate_buffer: before allocate_done \n"); + if (allocate_done()) + { + DEBUG_PRINT("allocate_buffer: after allocate_done \n"); + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("allocate_buffer: post idle transition event \n"); + } + DEBUG_PRINT("allocate_buffer: complete \n"); + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + m_out_bEnabled = OMX_TRUE; + + DEBUG_PRINT("AllocBuf-->is_out_th_sleep=%d\n",is_out_th_sleep); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("AllocBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("AB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + } + DEBUG_PRINT("Allocate Buffer exit with ret Code %d\n", eRet); + return eRet; +} + +/*============================================================================= +FUNCTION: + use_buffer + +DESCRIPTION: + OMX Use Buffer method implementation. + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_qcelp13_aenc::use_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT("Checking for Output Allocate buffer Done"); + if (allocate_done()) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_IDLE_PENDING); + post_command(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } + if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_command(OMX_CommandPortEnable, OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("UseBuf:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + pthread_mutex_lock(&m_in_th_lock_1); + if(is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("UB:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + } + } + DEBUG_PRINT("Use Buffer for port[%u] eRet[%d]\n", port,eRet); + return eRet; +} +/*============================================================================= +FUNCTION: + use_input_buffer + +DESCRIPTION: + Helper function for Use buffer in the input pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_qcelp13_aenc::use_input_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes, input_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if(bytes < input_buffer_size) + { + /* return if i\p buffer size provided by client + is less than min i\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + if (m_inp_current_buf_count < m_inp_act_buf_count) + { + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_input_buffer:bufHdr %p bufHdr->pBuffer %p \ + bytes=%u", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + input_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_input_buf_hdrs.insert(bufHdr, NULL); + m_inp_current_buf_count++; + } else + { + DEBUG_PRINT("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Input buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +/*============================================================================= +FUNCTION: + use_output_buffer + +DESCRIPTION: + Helper function for Use buffer in the output pin + +INPUT/OUTPUT PARAMETERS: + [INOUT] bufferHdr + [IN] hComp + [IN] port + [IN] appData + [IN] bytes + [IN] buffer + +RETURN VALUE: + OMX_ERRORTYPE + +Dependency: + None + +SIDE EFFECTS: + None +=============================================================================*/ +OMX_ERRORTYPE omx_qcelp13_aenc::use_output_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr; + unsigned nBufSize = MAX(bytes,output_buffer_size); + char *buf_ptr; + + if(hComp == NULL) + { + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (bytes < output_buffer_size) + { + /* return if o\p buffer size provided by client + is less than min o\p buffer size supported by omx component*/ + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT("Inside omx_qcelp13_aenc::use_output_buffer"); + if (m_out_current_buf_count < m_out_act_buf_count) + { + + buf_ptr = (char *) calloc(sizeof(OMX_BUFFERHEADERTYPE), 1); + + if (buf_ptr != NULL) + { + bufHdr = (OMX_BUFFERHEADERTYPE *) buf_ptr; + DEBUG_PRINT("BufHdr=%p buffer=%p\n",bufHdr,buffer); + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + DEBUG_PRINT("use_output_buffer:bufHdr %p bufHdr->pBuffer %p \ + len=%u\n", bufHdr, bufHdr->pBuffer,bytes); + bufHdr->nSize = (OMX_U32)sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = nBufSize; + output_buffer_size = nBufSize; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + bufHdr->nOffset = 0; + m_output_buf_hdrs.insert(bufHdr, NULL); + m_out_current_buf_count++; + + } else + { + DEBUG_PRINT("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + DEBUG_PRINT("Output buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_qcelp13_aenc::search_input_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_input_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_input_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +/** + @brief member function that searches for caller buffer + + @param buffer pointer to buffer header + @return bool value indicating whether buffer is found + */ +bool omx_qcelp13_aenc::search_output_bufhdr(OMX_BUFFERHEADERTYPE *buffer) +{ + + bool eRet = false; + OMX_BUFFERHEADERTYPE *temp = NULL; + + //access only in IL client context + temp = m_output_buf_hdrs.find_ele(buffer); + if (buffer && temp) + { + DEBUG_DETAIL("search_output_bufhdr %p \n", buffer); + eRet = true; + } + return eRet; +} + +// Free Buffer - API call +/** + @brief member function that handles free buffer command from IL client + + This function is a block-call function that handles IL client request to + freeing the buffer + + @param hComp handle to component instance + @param port id of port which holds the buffer + @param buffer buffer header + @return Error status +*/ +OMX_ERRORTYPE omx_qcelp13_aenc::free_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("Free_Buffer buf %p\n", buffer); + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT(" free buffer while Component in Loading pending\n"); + } else if ((m_inp_bEnabled == OMX_FALSE && + port == OMX_CORE_INPUT_PORT_INDEX)|| + (m_out_bEnabled == OMX_FALSE && + port == OMX_CORE_OUTPUT_PORT_INDEX)) + { + DEBUG_PRINT("Free Buffer while port %u disabled\n", port); + } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT("Invalid state to free buffer,ports need to be disabled:\ + OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return eRet; + } else + { + DEBUG_PRINT("free_buffer: Invalid state to free buffer,ports need to be\ + disabled:OMX_ErrorPortUnpopulated\n"); + post_command(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + if (OMX_CORE_INPUT_PORT_INDEX == port) + { + if (m_inp_current_buf_count != 0) + { + m_inp_bPopulated = OMX_FALSE; + if (true == search_input_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:in_buffer[%p]\n",buffer); + m_input_buf_hdrs.erase(buffer); + free(buffer); + m_inp_current_buf_count--; + } else + { + DEBUG_PRINT_ERROR("Free_Buf:Error-->free_buffer, \ + Invalid Input buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + DEBUG_PRINT_ERROR("Error: free_buffer,Port Index calculation \ + came out Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_done(0)) + { + DEBUG_PRINT("INPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } else if (OMX_CORE_OUTPUT_PORT_INDEX == port) + { + if (m_out_current_buf_count != 0) + { + m_out_bPopulated = OMX_FALSE; + if (true == search_output_bufhdr(buffer)) + { + /* Buffer exist */ + //access only in IL client context + DEBUG_PRINT("Free_Buf:out_buffer[%p]\n",buffer); + m_output_buf_hdrs.erase(buffer); + free(buffer); + m_out_current_buf_count--; + } else + { + DEBUG_PRINT("Free_Buf:Error-->free_buffer , \ + Invalid Output buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + + if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_done(1)) + { + DEBUG_PRINT("OUTPUT PORT MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + post_command(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + } else + { + eRet = OMX_ErrorBadPortIndex; + } + if ((OMX_ErrorNone == eRet) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if (release_done(-1)) + { + if(ioctl(m_drv_fd, AUDIO_STOP, 0) < 0) + DEBUG_PRINT_ERROR("AUDIO STOP in free buffer failed\n"); + else + DEBUG_PRINT("AUDIO STOP in free buffer passed\n"); + + + DEBUG_PRINT("Free_Buf: Free buffer\n"); + + + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + DEBUG_PRINT("Before OMX_StateLoaded \ + OMX_COMPONENT_GENERATE_EVENT\n"); + post_command(OMX_CommandStateSet, + OMX_StateLoaded,OMX_COMPONENT_GENERATE_EVENT); + DEBUG_PRINT("After OMX_StateLoaded OMX_COMPONENT_GENERATE_EVENT\n"); + + } + } + return eRet; +} + + +/** + @brief member function that that handles empty this buffer command + + This function meremly queue up the command and data would be consumed + in command server thread context + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_qcelp13_aenc::empty_this_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT("ETB:Buf:%p Len %u TS %lld numInBuf=%d\n", \ + buffer, buffer->nFilledLen, buffer->nTimeStamp, (nNumInputBuf)); + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (!m_inp_bEnabled) + { + DEBUG_PRINT("empty_this_buffer OMX_ErrorIncorrectStateOperation "\ + "Port Status %d \n", m_inp_bEnabled); + return OMX_ErrorIncorrectStateOperation; + } + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_qcelp13_aenc::etb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_qcelp13_aenc::etb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + if ((m_state != OMX_StateExecuting) && + (m_state != OMX_StatePause)) + { + DEBUG_PRINT_ERROR("Invalid state\n"); + eRet = OMX_ErrorInvalidState; + } + if (OMX_ErrorNone == eRet) + { + if (search_input_bufhdr(buffer) == true) + { + post_input((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_ETB); + } else + { + DEBUG_PRINT_ERROR("Bad header %p \n", buffer); + eRet = OMX_ErrorBadParameter; + } + } + pthread_mutex_lock(&in_buf_count_lock); + nNumInputBuf++; + m_qcelp13_pb_stats.etb_cnt++; + pthread_mutex_unlock(&in_buf_count_lock); + return eRet; +} +/** + @brief member function that writes data to kernel driver + + @param hComp handle to component instance + @param buffer pointer to buffer header + @return error status + */ +OMX_ERRORTYPE omx_qcelp13_aenc::empty_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + META_IN meta_in; + //Pointer to the starting location of the data to be transcoded + OMX_U8 *srcStart; + //The total length of the data to be transcoded + srcStart = buffer->pBuffer; + OMX_U8 *data = NULL; + PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer); + memset(&meta_in,0,sizeof(meta_in)); + if ( search_input_bufhdr(buffer) == false ) + { + DEBUG_PRINT("ETBP: INVALID BUF HDR\n"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorBadParameter; + } + if (m_tmp_meta_buf) + { + data = m_tmp_meta_buf; + + // copy the metadata info from the BufHdr and insert to payload + meta_in.offsetVal = (OMX_U16)sizeof(META_IN); + meta_in.nTimeStamp.LowPart = + (unsigned int)((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) & 0xFFFFFFFF); + meta_in.nTimeStamp.HighPart = + (unsigned int)(((((OMX_BUFFERHEADERTYPE*)buffer)->nTimeStamp) >> 32) & 0xFFFFFFFF); + meta_in.nFlags &= ~OMX_BUFFERFLAG_EOS; + if(buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + DEBUG_PRINT("EOS OCCURED \n"); + meta_in.nFlags |= OMX_BUFFERFLAG_EOS; + } + memcpy(data,&meta_in, meta_in.offsetVal); + DEBUG_PRINT("meta_in.nFlags = 0x%8x\n",meta_in.nFlags); + } + + memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen); + write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN)); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (OMX_StateExecuting == state) + { + DEBUG_DETAIL("In Exe state, EBD CB"); + buffer_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + } else + { + /* Assume empty this buffer function has already checked + validity of buffer */ + DEBUG_PRINT("Empty buffer %p to kernel driver\n", buffer); + post_input((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_BUFFER_DONE); + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_qcelp13_aenc::fill_this_buffer_proxy +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_STATETYPE state; + ENC_META_OUT *meta_out = NULL; + ssize_t nReadbytes = 0; + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (true == search_output_bufhdr(buffer)) + { + DEBUG_PRINT("\nBefore Read..m_drv_fd = %d,\n",m_drv_fd); + nReadbytes = read(m_drv_fd,buffer->pBuffer,output_buffer_size ); + DEBUG_DETAIL("FTBP->Al_len[%lu]buf[%p]size[%d]numOutBuf[%d]\n",\ + buffer->nAllocLen,buffer->pBuffer, + nReadbytes,nNumOutputBuf); + if (nReadbytes <= 0) { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + return OMX_ErrorNone; + } else + DEBUG_PRINT("Read bytes %d\n",nReadbytes); + + // Buffer from Driver will have + // 1 byte => Nr of frame field + // (sizeof(ENC_META_OUT) * Nr of frame) bytes => meta_out->offset_to_frame + // Frame Size * Nr of frame => + + meta_out = (ENC_META_OUT *)(buffer->pBuffer + sizeof(unsigned char)); + buffer->nTimeStamp = (((OMX_TICKS)meta_out->msw_ts << 32)+ + meta_out->lsw_ts); + buffer->nFlags |= meta_out->nflags; + buffer->nOffset = (OMX_U32) (meta_out->offset_to_frame + + sizeof(unsigned char)); + buffer->nFilledLen = (OMX_U32)(nReadbytes - buffer->nOffset); + nTimestamp = buffer->nTimeStamp; + DEBUG_PRINT("nflags %d frame_size %d offset_to_frame %d \ + timestamp %lld\n", meta_out->nflags, + meta_out->frame_size, meta_out->offset_to_frame, + buffer->nTimeStamp); + + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + buffer->nFilledLen = 0; + buffer->nOffset = 0; + buffer->nTimeStamp = nTimestamp; + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS ) + { + DEBUG_PRINT("FTBP: Now, Send EOS flag to Client \n"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + } + + return OMX_ErrorNone; + } + DEBUG_PRINT("nState %d \n",nState ); + + pthread_mutex_lock(&m_state_lock); + get_state(&m_cmp, &state); + pthread_mutex_unlock(&m_state_lock); + + if (state == OMX_StatePause) + { + DEBUG_PRINT("FTBP:Post the FBD to event thread currstate=%d\n",\ + state); + post_output((unsigned long) & hComp,(unsigned long) buffer, + OMX_COMPONENT_GENERATE_FRAME_DONE); + } + else + { + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + + } + + } + else + DEBUG_PRINT("\n FTBP-->Invalid buffer in FTB \n"); + + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + + + +PARAMETERS + + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::fill_this_buffer +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + DEBUG_PRINT("omx_qcelp13_aenc::ftb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (m_out_bEnabled == OMX_FALSE) + { + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT("omx_qcelp13_aenc::ftb--> OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) + { + return OMX_ErrorBadPortIndex; + } + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf++; + m_qcelp13_pb_stats.ftb_cnt++; + DEBUG_DETAIL("FTB:nNumOutputBuf is %d", nNumOutputBuf); + pthread_mutex_unlock(&out_buf_count_lock); + post_output((unsigned long)hComp, + (unsigned long) buffer,OMX_COMPONENT_GENERATE_FTB); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::set_callbacks( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + m_cb = *callbacks; + m_app_data = appData; + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateLoaded != m_state && OMX_StateInvalid != m_state) + { + DEBUG_PRINT_ERROR("Warning: Rxed DeInit when not in LOADED state %d\n", + m_state); + } + deinit_encoder(); + +DEBUG_PRINT_ERROR("%s:COMPONENT DEINIT...\n", __FUNCTION__); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::deinit_encoder + +DESCRIPTION + Closes all the threads and release memory allocated to the heap. + +PARAMETERS + None. + +RETURN VALUE + None. + +========================================================================== */ +void omx_qcelp13_aenc::deinit_encoder() +{ + DEBUG_PRINT("Component-deinit being processed\n"); + DEBUG_PRINT("********************************\n"); + DEBUG_PRINT("STATS: in-buf-len[%u]out-buf-len[%u] tot-pb-time[%lld]",\ + m_qcelp13_pb_stats.tot_in_buf_len, + m_qcelp13_pb_stats.tot_out_buf_len, + m_qcelp13_pb_stats.tot_pb_time); + DEBUG_PRINT("STATS: fbd-cnt[%u]ftb-cnt[%u]etb-cnt[%u]ebd-cnt[%u]",\ + m_qcelp13_pb_stats.fbd_cnt,m_qcelp13_pb_stats.ftb_cnt, + m_qcelp13_pb_stats.etb_cnt, + m_qcelp13_pb_stats.ebd_cnt); + memset(&m_qcelp13_pb_stats,0,sizeof(QCELP13_PB_STATS)); + + if((OMX_StateLoaded != m_state) && (OMX_StateInvalid != m_state)) + { + DEBUG_PRINT_ERROR("%s,Deinit called in state[%d]\n",__FUNCTION__,\ + m_state); + // Get back any buffers from driver + if(pcm_input) + execute_omx_flush(-1,false); + else + execute_omx_flush(1,false); + // force state change to loaded so that all threads can be exited + pthread_mutex_lock(&m_state_lock); + m_state = OMX_StateLoaded; + pthread_mutex_unlock(&m_state_lock); + DEBUG_PRINT_ERROR("Freeing Buf:inp_current_buf_count[%d][%d]\n",\ + m_inp_current_buf_count, + m_input_buf_hdrs.size()); + m_input_buf_hdrs.eraseall(); + DEBUG_PRINT_ERROR("Freeing Buf:out_current_buf_count[%d][%d]\n",\ + m_out_current_buf_count, + m_output_buf_hdrs.size()); + m_output_buf_hdrs.eraseall(); + + } + if(pcm_input) + { + pthread_mutex_lock(&m_in_th_lock_1); + if (is_in_th_sleep) + { + is_in_th_sleep = false; + DEBUG_DETAIL("Deinit:WAKING UP IN THREADS\n"); + in_th_wakeup(); + } + pthread_mutex_unlock(&m_in_th_lock_1); + } + pthread_mutex_lock(&m_out_th_lock_1); + if (is_out_th_sleep) + { + is_out_th_sleep = false; + DEBUG_DETAIL("SCP:WAKING UP OUT THREADS\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + if(pcm_input) + { + if (m_ipc_to_in_th != NULL) + { + omx_qcelp13_thread_stop(m_ipc_to_in_th); + m_ipc_to_in_th = NULL; + } + } + + if (m_ipc_to_cmd_th != NULL) + { + omx_qcelp13_thread_stop(m_ipc_to_cmd_th); + m_ipc_to_cmd_th = NULL; + } + if (m_ipc_to_out_th != NULL) + { + DEBUG_DETAIL("Inside omx_qcelp13_thread_stop\n"); + omx_qcelp13_thread_stop(m_ipc_to_out_th); + m_ipc_to_out_th = NULL; + } + + + if(ioctl(m_drv_fd, AUDIO_STOP, 0) <0) + DEBUG_PRINT_ERROR("De-init: AUDIO_STOP FAILED\n"); + + if(pcm_input && m_tmp_meta_buf ) + { + free(m_tmp_meta_buf); + } + + if(m_tmp_out_meta_buf) + { + free(m_tmp_out_meta_buf); + } + nNumInputBuf = 0; + nNumOutputBuf = 0; + bFlushinprogress = 0; + + m_inp_current_buf_count=0; + m_out_current_buf_count=0; + m_out_act_buf_count = 0; + m_inp_act_buf_count = 0; + m_inp_bEnabled = OMX_FALSE; + m_out_bEnabled = OMX_FALSE; + m_inp_bPopulated = OMX_FALSE; + m_out_bPopulated = OMX_FALSE; + + if ( m_drv_fd >= 0 ) + { + if(close(m_drv_fd) < 0) + DEBUG_PRINT("De-init: Driver Close Failed \n"); + m_drv_fd = -1; + } + else + { + DEBUG_PRINT_ERROR(" QCELP13 device already closed\n"); + } + m_comp_deinit=1; + m_is_out_th_sleep = 1; + m_is_in_th_sleep = 1; + DEBUG_PRINT("************************************\n"); + DEBUG_PRINT(" DEINIT COMPLETED"); + DEBUG_PRINT("************************************\n"); + +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation <TBD>. + +PARAMETERS + <TBD>. + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::use_EGL_image +( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + DEBUG_PRINT_ERROR("Error : use_EGL_image: Not Implemented \n"); + + if((hComp == NULL) || (appData == NULL) || (eglImage == NULL)) + { + bufferHdr = bufferHdr; + port = port; + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + <TBD>. + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_qcelp13_aenc::component_role_enum( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + const char *cmp_role = "audio_encoder.qcelp13"; + + if(hComp == NULL) + { + DEBUG_PRINT_ERROR("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (index == 0 && role) + { + memcpy(role, cmp_role, strlen(cmp_role)); + *(((char *) role) + strlen(cmp_role) + 1) = '\0'; + } else + { + eRet = OMX_ErrorNoMore; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_qcelp13_aenc::allocate_done(void) +{ + OMX_BOOL bRet = OMX_FALSE; + if (pcm_input==1) + { + if ((m_inp_act_buf_count == m_inp_current_buf_count) + &&(m_out_act_buf_count == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + + } + if ((m_inp_act_buf_count == m_inp_current_buf_count) && m_inp_bEnabled ) + { + m_inp_bPopulated = OMX_TRUE; + } + + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + } else if (pcm_input==0) + { + if (m_out_act_buf_count == m_out_current_buf_count) + { + bRet=OMX_TRUE; + + } + if ((m_out_act_buf_count == m_out_current_buf_count) && m_out_bEnabled ) + { + m_out_bPopulated = OMX_TRUE; + } + + } + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_qcelp13_aenc::ReleaseDone + +DESCRIPTION + Checks if IL client has released all the buffers. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_qcelp13_aenc::release_done(OMX_U32 param1) +{ + DEBUG_PRINT("Inside omx_qcelp13_aenc::release_done"); + OMX_BOOL bRet = OMX_FALSE; + + if (param1 == OMX_ALL) + { + if ((0 == m_inp_current_buf_count)&&(0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_INPUT_PORT_INDEX ) + { + if ((0 == m_inp_current_buf_count)) + { + bRet=OMX_TRUE; + } + } else if (param1 == OMX_CORE_OUTPUT_PORT_INDEX) + { + if ((0 == m_out_current_buf_count)) + { + bRet=OMX_TRUE; + } + } + return bRet; +} diff --git a/msm8909/mm-audio/aenc-qcelp13/qdsp6/test/omx_qcelp13_enc_test.c b/msm8909/mm-audio/aenc-qcelp13/qdsp6/test/omx_qcelp13_enc_test.c new file mode 100644 index 00000000..432c07a1 --- /dev/null +++ b/msm8909/mm-audio/aenc-qcelp13/qdsp6/test/omx_qcelp13_enc_test.c @@ -0,0 +1,1101 @@ + +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of The Linux Foundation nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + + +/* + An Open max test application .... +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <time.h> +#include <sys/ioctl.h> +#include "OMX_Core.h" +#include "OMX_Component.h" +#include "pthread.h" +#include <signal.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdint.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include<unistd.h> +#include<string.h> +#include <pthread.h> +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#ifdef AUDIOV2 +#include "control.h" +#endif + + +#include <linux/ioctl.h> + +typedef unsigned char uint8; +typedef unsigned char byte; +typedef unsigned int uint32; +typedef unsigned int uint16; +QOMX_AUDIO_STREAM_INFO_DATA streaminfoparam; +/* maximum ADTS frame header length */ +void Release_Encoder(); + +#ifdef AUDIOV2 +unsigned short session_id; +int device_id; +int control = 0; +const char *device="handset_tx"; +#define DIR_TX 2 +#endif + +uint32_t samplerate = 8000; +uint32_t channels = 1; +uint32_t min_bitrate = 0; +uint32_t max_bitrate = 0; +uint32_t cdmarate = 0; +uint32_t rectime = 0; +uint32_t recpath = 0; +uint32_t pcmplayback = 0; +uint32_t tunnel = 0; +uint32_t format = 1; +#define DEBUG_PRINT printf +unsigned to_idle_transition = 0; +unsigned long total_pcm_bytes; + +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ +#define false 0 +#define true 1 + +#define CONFIG_VERSION_SIZE(param) \ + param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ + param.nSize = sizeof(param); + +#define QCP_HEADER_SIZE sizeof(struct qcp_header) +#define MIN_BITRATE 4 /* Bit rate 1 - 13.6 , 2 - 6.2 , 3 - 2.7 , 4 - 1.0 kbps*/ +#define MAX_BITRATE 4 + +#define FAILED(result) (result != OMX_ErrorNone) + +#define SUCCEEDED(result) (result == OMX_ErrorNone) + +/************************************************************************/ +/* GLOBAL DECLARATIONS */ +/************************************************************************/ + +pthread_mutex_t lock; +pthread_cond_t cond; +pthread_mutex_t elock; +pthread_cond_t econd; +pthread_cond_t fcond; +pthread_mutex_t etb_lock; +pthread_mutex_t etb_lock1; +pthread_cond_t etb_cond; +FILE * inputBufferFile; +FILE * outputBufferFile; +OMX_PARAM_PORTDEFINITIONTYPE inputportFmt; +OMX_PARAM_PORTDEFINITIONTYPE outputportFmt; +OMX_AUDIO_PARAM_QCELP13TYPE qcelp13param; +OMX_AUDIO_PARAM_PCMMODETYPE pcmparam; +OMX_PORT_PARAM_TYPE portParam; +OMX_PORT_PARAM_TYPE portFmt; +OMX_ERRORTYPE error; + + + + +#define ID_RIFF 0x46464952 +#define ID_WAVE 0x45564157 +#define ID_FMT 0x20746d66 +#define ID_DATA 0x61746164 + +#define FORMAT_PCM 1 + +struct wav_header { + uint32_t riff_id; + uint32_t riff_sz; + uint32_t riff_fmt; + uint32_t fmt_id; + uint32_t fmt_sz; + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */ + uint16_t block_align; /* num_channels * bps / 8 */ + uint16_t bits_per_sample; + uint32_t data_id; + uint32_t data_sz; +}; +struct enc_meta_out{ + unsigned int offset_to_frame; + unsigned int frame_size; + unsigned int encoded_pcm_samples; + unsigned int msw_ts; + unsigned int lsw_ts; + unsigned int nflags; +} __attribute__ ((packed)); + +struct qcp_header { + /* RIFF Section */ + char riff[4]; + unsigned int s_riff; + char qlcm[4]; + + /* Format chunk */ + char fmt[4]; + unsigned int s_fmt; + char mjr; + char mnr; + unsigned int data1; /* UNIQUE ID of the codec */ + unsigned short data2; + unsigned short data3; + char data4[8]; + unsigned short ver; /* Codec Info */ + char name[80]; + unsigned short abps; /* average bits per sec of the codec */ + unsigned short bytes_per_pkt; + unsigned short samp_per_block; + unsigned short samp_per_sec; + unsigned short bits_per_samp; + unsigned char vr_num_of_rates; /* Rate Header fmt info */ + unsigned char rvd1[3]; + unsigned short vr_bytes_per_pkt[8]; + unsigned int rvd2[5]; + + /* Vrat chunk */ + unsigned char vrat[4]; + unsigned int s_vrat; + unsigned int v_rate; + unsigned int size_in_pkts; + + /* Data chunk */ + unsigned char data[4]; + unsigned int s_data; +} __attribute__ ((packed)); + + /* Common part */ + static struct qcp_header append_header = { + {'R', 'I', 'F', 'F'}, 0, {'Q', 'L', 'C', 'M'}, + {'f', 'm', 't', ' '}, 150, 1, 0, 0, 0, 0,{0}, 0, {0},0,0,160,8000,16,0,{0},{0},{0}, + {'v','r','a','t'},0, 0, 0,{'d','a','t','a'},0 + }; + +static int totaldatalen = 0; +static int framecnt = 0; +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ + +unsigned int input_buf_cnt = 0; +unsigned int output_buf_cnt = 0; +int used_ip_buf_cnt = 0; +volatile int event_is_done = 0; +volatile int ebd_event_is_done = 0; +volatile int fbd_event_is_done = 0; +volatile int etb_event_is_done = 0; +int ebd_cnt; +int bInputEosReached = 0; +int bOutputEosReached = 0; +int bInputEosReached_tunnel = 0; +static int etb_done = 0; +int bFlushing = false; +int bPause = false; +const char *in_filename; +const char *out_filename; + +int timeStampLfile = 0; +int timestampInterval = 100; + +//* OMX Spec Version supported by the wrappers. Version = 1.1 */ +const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; +OMX_COMPONENTTYPE* qcelp13_enc_handle = 0; + +OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; +OMX_BUFFERHEADERTYPE **pOutputBufHdrs = NULL; + +/************************************************************************/ +/* GLOBAL FUNC DECL */ +/************************************************************************/ +int Init_Encoder(char*); +int Play_Encoder(); +OMX_STRING aud_comp; +/**************************************************************************/ +/* STATIC DECLARATIONS */ +/**************************************************************************/ + +static int open_audio_file (); +static int Read_Buffer(OMX_BUFFERHEADERTYPE *pBufHdr ); +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *qcelp13_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize); + + +static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); +static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + +static OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); +static OMX_ERRORTYPE parse_pcm_header(); +void wait_for_event(void) +{ + pthread_mutex_lock(&lock); + DEBUG_PRINT("%s: event_is_done=%d", __FUNCTION__, event_is_done); + while (event_is_done == 0) { + pthread_cond_wait(&cond, &lock); + } + event_is_done = 0; + pthread_mutex_unlock(&lock); +} + +void event_complete(void ) +{ + pthread_mutex_lock(&lock); + if (event_is_done == 0) { + event_is_done = 1; + pthread_cond_broadcast(&cond); + } + pthread_mutex_unlock(&lock); +} + +void etb_wait_for_event(void) +{ + pthread_mutex_lock(&etb_lock1); + DEBUG_PRINT("%s: etb_event_is_done=%d", __FUNCTION__, etb_event_is_done); + while (etb_event_is_done == 0) { + pthread_cond_wait(&etb_cond, &etb_lock1); + } + etb_event_is_done = 0; + pthread_mutex_unlock(&etb_lock1); +} + +void etb_event_complete(void ) +{ + pthread_mutex_lock(&etb_lock1); + if (etb_event_is_done == 0) { + etb_event_is_done = 1; + pthread_cond_broadcast(&etb_cond); + } + pthread_mutex_unlock(&etb_lock1); +} + +static void create_qcp_header(int Datasize, int Frames) +{ + append_header.s_riff = (unsigned)(Datasize + (int)QCP_HEADER_SIZE - 8); + /* exclude riff id and size field */ + append_header.data1 = 0x5E7F6D41; + append_header.data2 = 0xB115; + append_header.data3 = 0x11D0; + append_header.data4[0] = 0xBA; + append_header.data4[1] = 0x91; + append_header.data4[2] = 0x00; + append_header.data4[3] = 0x80; + append_header.data4[4] = 0x5F; + append_header.data4[5] = 0xB4; + append_header.data4[6] = 0xB9; + append_header.data4[7] = 0x7E; + append_header.ver = 0x0002; + memcpy(append_header.name, "Qcelp 13K", 9); + append_header.abps = 13000; + append_header.bytes_per_pkt = 35; + append_header.vr_num_of_rates = 5; + append_header.vr_bytes_per_pkt[0] = 0x0422; + append_header.vr_bytes_per_pkt[1] = 0x0310; + append_header.vr_bytes_per_pkt[2] = 0x0207; + append_header.vr_bytes_per_pkt[3] = 0x0103; + append_header.s_vrat = 0x00000008; + append_header.v_rate = 0x00000001; + append_header.size_in_pkts = (unsigned)Frames; + append_header.s_data = (unsigned)Datasize; + return; +} + +OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ + DEBUG_PRINT("Function %s \n", __FUNCTION__); + + /* To remove warning for unused variable to keep prototype same */ + (void)hComponent; + (void)pAppData; + (void)pEventData; + + switch(eEvent) { + case OMX_EventCmdComplete: + DEBUG_PRINT("\n OMX_EventCmdComplete event=%d data1=%u data2=%u\n",(OMX_EVENTTYPE)eEvent, + nData1,nData2); + event_complete(); + break; + case OMX_EventError: + DEBUG_PRINT("\n OMX_EventError \n"); + break; + case OMX_EventBufferFlag: + DEBUG_PRINT("\n OMX_EventBufferFlag \n"); + bOutputEosReached = true; + event_complete(); + break; + case OMX_EventPortSettingsChanged: + DEBUG_PRINT("\n OMX_EventPortSettingsChanged \n"); + break; + default: + DEBUG_PRINT("\n Unknown Event \n"); + break; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + size_t bytes_writen = 0; + size_t total_bytes_writen = 0; + size_t len = 0; + struct enc_meta_out *meta = NULL; + OMX_U8 *src = pBuffer->pBuffer; + unsigned int num_of_frames = 1; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + if(((pBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + DEBUG_PRINT("FBD::EOS on output port\n "); + bOutputEosReached = true; + return OMX_ErrorNone; + } + if(bInputEosReached_tunnel || bOutputEosReached) + { + DEBUG_PRINT("EOS REACHED NO MORE PROCESSING OF BUFFERS\n"); + return OMX_ErrorNone; + } + if(num_of_frames != src[0]){ + + printf("Data corrupt\n"); + return OMX_ErrorNone; + } + /* Skip the first bytes */ + + + + src += sizeof(unsigned char); + meta = (struct enc_meta_out *)src; + while (num_of_frames > 0) { + meta = (struct enc_meta_out *)src; + /*printf("offset=%d framesize=%d encoded_pcm[%d] msw_ts[%d]lsw_ts[%d] nflags[%d]\n", + meta->offset_to_frame, + meta->frame_size, + meta->encoded_pcm_samples, meta->msw_ts, meta->lsw_ts, meta->nflags);*/ + len = meta->frame_size; + + bytes_writen = fwrite(pBuffer->pBuffer + sizeof(unsigned char) + meta->offset_to_frame,1,len,outputBufferFile); + if(bytes_writen < len) + { + DEBUG_PRINT("error: invalid QCELP13 encoded data \n"); + return OMX_ErrorNone; + } + src += sizeof(struct enc_meta_out); + num_of_frames--; + total_bytes_writen += len; + } + DEBUG_PRINT(" FillBufferDone size writen to file %zu count %d\n",total_bytes_writen, framecnt); + totaldatalen = totaldatalen + (int)total_bytes_writen; + framecnt++; + + DEBUG_PRINT(" FBD calling FTB\n"); + OMX_FillThisBuffer(hComponent,pBuffer); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + int readBytes =0; + + /* To remove warning for unused variable to keep prototype same */ + (void)pAppData; + + ebd_cnt++; + used_ip_buf_cnt--; + pthread_mutex_lock(&etb_lock); + if(!etb_done) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT("Wait till first set of buffers are given to component\n"); + DEBUG_PRINT("\n*********************************************\n"); + etb_done++; + pthread_mutex_unlock(&etb_lock); + etb_wait_for_event(); + } + else + { + pthread_mutex_unlock(&etb_lock); + } + + + if(bInputEosReached) + { + DEBUG_PRINT("\n*********************************************\n"); + DEBUG_PRINT(" EBD::EOS on input port\n "); + DEBUG_PRINT("*********************************************\n"); + return OMX_ErrorNone; + }else if (bFlushing == true) { + DEBUG_PRINT("omx_qcelp13_adec_test: bFlushing is set to TRUE used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + if (used_ip_buf_cnt == 0) { + bFlushing = false; + } else { + DEBUG_PRINT("omx_qcelp13_adec_test: more buffer to come back used_ip_buf_cnt=%d\n",used_ip_buf_cnt); + return OMX_ErrorNone; + } + } + + if((readBytes = Read_Buffer(pBuffer)) > 0) { + pBuffer->nFilledLen = (OMX_U32)readBytes; + used_ip_buf_cnt++; + OMX_EmptyThisBuffer(hComponent,pBuffer); + } + else{ + pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + used_ip_buf_cnt++; + bInputEosReached = true; + pBuffer->nFilledLen = 0; + OMX_EmptyThisBuffer(hComponent,pBuffer); + DEBUG_PRINT("EBD..Either EOS or Some Error while reading file\n"); + } + return OMX_ErrorNone; +} + +void signal_handler(int sig_id) { + + /* Flush */ + if (sig_id == SIGUSR1) { + DEBUG_PRINT("%s Initiate flushing\n", __FUNCTION__); + bFlushing = true; + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandFlush, OMX_ALL, NULL); + } else if (sig_id == SIGUSR2) { + if (bPause == true) { + DEBUG_PRINT("%s resume record\n", __FUNCTION__); + bPause = false; + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); + } else { + DEBUG_PRINT("%s pause record\n", __FUNCTION__); + bPause = true; + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandStateSet, OMX_StatePause, NULL); + } + } +} + +int main(int argc, char **argv) +{ + unsigned int bufCnt=0; + OMX_ERRORTYPE result; + + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = &signal_handler; + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGUSR2, &sa, NULL); + + (void) signal(SIGINT, Release_Encoder); + + pthread_cond_init(&cond, 0); + pthread_mutex_init(&lock, 0); + pthread_cond_init(&etb_cond, 0); + pthread_mutex_init(&etb_lock, 0); + pthread_mutex_init(&etb_lock1, 0); + + if (argc >= 9) { + in_filename = argv[1]; + out_filename = argv[2]; + tunnel = (uint32_t)atoi(argv[3]); + min_bitrate = (uint32_t)atoi(argv[4]); + max_bitrate = (uint32_t)atoi(argv[5]); + cdmarate = (uint32_t)atoi(argv[6]); + recpath = (uint32_t)atoi(argv[7]); // No configuration support yet.. + rectime = (uint32_t)atoi(argv[8]); + + } else { + DEBUG_PRINT(" invalid format: \n"); + DEBUG_PRINT("ex: ./mm-aenc-omxqcelp13-test INPUTFILE OUTPUTFILE Tunnel MINRATE MAXRATE CDMARATE RECORDPATH RECORDTIME\n"); + DEBUG_PRINT("MINRATE, MAXRATE and CDMARATE 1 to 4\n"); + DEBUG_PRINT("RECORDPATH 0(TX),1(RX),2(BOTH),3(MIC)\n"); + DEBUG_PRINT("RECORDTIME in seconds for AST Automation\n"); + return 0; + } + if(recpath != 3) { + DEBUG_PRINT("For RECORDPATH Only MIC supported\n"); + return 0; + } + + if(tunnel == 0) + aud_comp = "OMX.qcom.audio.encoder.qcelp13"; + else + aud_comp = "OMX.qcom.audio.encoder.tunneled.qcelp13"; + if(Init_Encoder(aud_comp)!= 0x00) + { + DEBUG_PRINT("Decoder Init failed\n"); + return -1; + } + + fcntl(0, F_SETFL, O_NONBLOCK); + + if(Play_Encoder() != 0x00) + { + DEBUG_PRINT("Play_Decoder failed\n"); + return -1; + } + + // Wait till EOS is reached... + if(rectime && tunnel) + { + sleep(rectime); + rectime = 0; + bInputEosReached_tunnel = 1; + DEBUG_PRINT("\EOS ON INPUT PORT\n"); + } + else + { + wait_for_event(); + } + + if((bInputEosReached_tunnel) || ((bOutputEosReached) && !tunnel)) + { + + DEBUG_PRINT("\nMoving the decoder to idle state \n"); + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + wait_for_event(); + + DEBUG_PRINT("\nMoving the encoder to loaded state \n"); + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandStateSet, OMX_StateLoaded,0); + sleep(1); + if (!tunnel) + { + DEBUG_PRINT("\nFillBufferDone: Deallocating i/p buffers \n"); + for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(qcelp13_enc_handle, 0, pInputBufHdrs[bufCnt]); + } + } + + DEBUG_PRINT ("\nFillBufferDone: Deallocating o/p buffers \n"); + for(bufCnt=0; bufCnt < output_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(qcelp13_enc_handle, 1, pOutputBufHdrs[bufCnt]); + } + wait_for_event(); + create_qcp_header(totaldatalen, framecnt); + fseek(outputBufferFile, 0,SEEK_SET); + fwrite(&append_header,1,QCP_HEADER_SIZE,outputBufferFile); + + + result = OMX_FreeHandle(qcelp13_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + if(tunnel) + { + #ifdef AUDIOV2 + if (msm_route_stream(DIR_TX,session_id,device_id, 0)) + { + DEBUG_PRINT("\ncould not set stream routing\n"); + return -1; + } + if (msm_en_device(device_id, 0)) + { + DEBUG_PRINT("\ncould not enable device\n"); + return -1; + } + msm_mixer_close(); + #endif + } + OMX_Deinit(); + ebd_cnt=0; + bOutputEosReached = false; + bInputEosReached_tunnel = false; + bInputEosReached = 0; + qcelp13_enc_handle = NULL; + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + fclose(outputBufferFile); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...QCELP13 ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + } + return 0; +} + +void Release_Encoder() +{ + static int cnt=0; + OMX_ERRORTYPE result; + + DEBUG_PRINT("END OF QCELP13 ENCODING: EXITING PLEASE WAIT\n"); + bInputEosReached_tunnel = 1; + event_complete(); + cnt++; + if(cnt > 1) + { + /* FORCE RESET */ + qcelp13_enc_handle = NULL; + ebd_cnt=0; + bInputEosReached_tunnel = false; + + result = OMX_FreeHandle(qcelp13_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + + /* Deinit OpenMAX */ + + OMX_Deinit(); + + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...QCELP13 ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + exit(0); + } +} + +int Init_Encoder(OMX_STRING audio_component) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE omxresult; + OMX_U32 total = 0; + typedef OMX_U8* OMX_U8_PTR; + char *role ="audio_encoder"; + + static OMX_CALLBACKTYPE call_back = { + &EventHandler,&EmptyBufferDone,&FillBufferDone + }; + + /* Init. the OpenMAX Core */ + DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); + omxresult = OMX_Init(); + + if(OMX_ErrorNone != omxresult) { + DEBUG_PRINT("\n Failed to Init OpenMAX core"); + return -1; + } + else { + DEBUG_PRINT("\nOpenMAX Core Init Done\n"); + } + + /* Query for audio decoders*/ + DEBUG_PRINT("Qcelp13_test: Before entering OMX_GetComponentOfRole"); + OMX_GetComponentsOfRole(role, &total, 0); + DEBUG_PRINT ("\nTotal components of role=%s :%u", role, total); + + + omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&qcelp13_enc_handle), + (OMX_STRING)audio_component, NULL, &call_back); + if (FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to Load the component:%s\n", audio_component); + return -1; + } + else + { + DEBUG_PRINT("\nComponent %s is in LOADED state\n", audio_component); + } + + /* Get the port information */ + CONFIG_VERSION_SIZE(portParam); + omxresult = OMX_GetParameter(qcelp13_enc_handle, OMX_IndexParamAudioInit, + (OMX_PTR)&portParam); + + if(FAILED(omxresult)) { + DEBUG_PRINT("\nFailed to get Port Param\n"); + return -1; + } + else + { + DEBUG_PRINT("\nportParam.nPorts:%u\n", portParam.nPorts); + DEBUG_PRINT("\nportParam.nStartPortNumber:%u\n", + portParam.nStartPortNumber); + } + + if(OMX_ErrorNone != omxresult) + { + DEBUG_PRINT("Set parameter failed"); + } + + return 0; +} + +int Play_Encoder() +{ + unsigned int i; + int Size=0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE ret; + OMX_INDEXTYPE index; +#ifdef __LP64__ + DEBUG_PRINT("sizeof[%ld]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#else + DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE)); +#endif + + /* open the i/p and o/p files based on the video file format passed */ + if(open_audio_file()) { + DEBUG_PRINT("\n Returning -1"); + return -1; + } + + /* Query the encoder input min buf requirements */ + CONFIG_VERSION_SIZE(inputportFmt); + + /* Port for which the Client needs to obtain info */ + inputportFmt.nPortIndex = portParam.nStartPortNumber; + + OMX_GetParameter(qcelp13_enc_handle,OMX_IndexParamPortDefinition,&inputportFmt); + DEBUG_PRINT ("\nEnc Input Buffer Count %u\n", inputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Input Buffer Size %u\n", inputportFmt.nBufferSize); + + if(OMX_DirInput != inputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Input Port\n"); + return -1; + } + + pcmparam.nPortIndex = 0; + pcmparam.nChannels = channels; + pcmparam.nSamplingRate = samplerate; + OMX_SetParameter(qcelp13_enc_handle,OMX_IndexParamAudioPcm,&pcmparam); + + + /* Query the encoder outport's min buf requirements */ + CONFIG_VERSION_SIZE(outputportFmt); + /* Port for which the Client needs to obtain info */ + outputportFmt.nPortIndex = portParam.nStartPortNumber + 1; + + OMX_GetParameter(qcelp13_enc_handle,OMX_IndexParamPortDefinition,&outputportFmt); + DEBUG_PRINT ("\nEnc: Output Buffer Count %u\n", outputportFmt.nBufferCountMin); + DEBUG_PRINT ("\nEnc: Output Buffer Size %u\n", outputportFmt.nBufferSize); + + if(OMX_DirOutput != outputportFmt.eDir) { + DEBUG_PRINT ("\nEnc: Expect Output Port\n"); + return -1; + } + + + CONFIG_VERSION_SIZE(qcelp13param); + + qcelp13param.nPortIndex = 1; + qcelp13param.nChannels = channels; //2 ; /* 1-> mono 2-> stereo*/ + qcelp13param.nMinBitRate = min_bitrate; + qcelp13param.nMaxBitRate = max_bitrate; + OMX_SetParameter(qcelp13_enc_handle,OMX_IndexParamAudioQcelp13,&qcelp13param); + OMX_GetExtensionIndex(qcelp13_enc_handle,"OMX.Qualcomm.index.audio.sessionId",&index); + OMX_GetParameter(qcelp13_enc_handle,index,&streaminfoparam); + if(tunnel) { + #ifdef AUDIOV2 + session_id = streaminfoparam.sessionId; + control = msm_mixer_open("/dev/snd/controlC0", 0); + if(control < 0) + printf("ERROR opening the device\n"); + device_id = msm_get_device(device); + DEBUG_PRINT ("\ndevice_id = %d\n",device_id); + DEBUG_PRINT("\nsession_id = %d\n",session_id); + if (msm_en_device(device_id, 1)) + { + perror("could not enable device\n"); + return -1; + } + if (msm_route_stream(DIR_TX,session_id,device_id, 1)) + { + perror("could not set stream routing\n"); + return -1; + } + #endif + } + + DEBUG_PRINT ("\nOMX_SendCommand Encoder -> IDLE\n"); + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + /* wait_for_event(); should not wait here event complete status will + not come until enough buffer are allocated */ + if (tunnel == 0) + { + input_buf_cnt = inputportFmt.nBufferCountActual; // inputportFmt.nBufferCountMin + 5; + DEBUG_PRINT("Transition to Idle State succesful...\n"); + /* Allocate buffer on decoder's i/p port */ + error = Allocate_Buffer(qcelp13_enc_handle, &pInputBufHdrs, inputportFmt.nPortIndex, + input_buf_cnt, inputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pInputBufHdrs == NULL) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Input buffer success\n"); + } + } + output_buf_cnt = outputportFmt.nBufferCountMin ; + + /* Allocate buffer on encoder's O/Pp port */ + error = Allocate_Buffer(qcelp13_enc_handle, &pOutputBufHdrs, outputportFmt.nPortIndex, + output_buf_cnt, outputportFmt.nBufferSize); + if (error != OMX_ErrorNone || pOutputBufHdrs == NULL ) { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer error\n"); + return -1; + } + else { + DEBUG_PRINT ("\nOMX_AllocateBuffer Output buffer success\n"); + } + + wait_for_event(); + + + if (tunnel == 1) + { + DEBUG_PRINT ("\nOMX_SendCommand to enable TUNNEL MODE during IDLE\n"); + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandPortDisable,0,0); // disable input port + wait_for_event(); + } + + DEBUG_PRINT ("\nOMX_SendCommand encoder -> Executing\n"); + OMX_SendCommand(qcelp13_enc_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + + DEBUG_PRINT(" Start sending OMX_FILLthisbuffer\n"); + + for(i=0; i < output_buf_cnt; i++) { + DEBUG_PRINT ("\nOMX_FillThisBuffer on output buf no.%d\n",i); + pOutputBufHdrs[i]->nOutputPortIndex = 1; + pOutputBufHdrs[i]->nFlags = pOutputBufHdrs[i]->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + ret = OMX_FillThisBuffer(qcelp13_enc_handle, pOutputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_FillThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_FillThisBuffer success!\n"); + } + } + +if(tunnel == 0) +{ + DEBUG_PRINT(" Start sending OMX_emptythisbuffer\n"); + for (i = 0;i < input_buf_cnt;i++) { + DEBUG_PRINT ("\nOMX_EmptyThisBuffer on Input buf no.%d\n",i); + pInputBufHdrs[i]->nInputPortIndex = 0; + Size = Read_Buffer(pInputBufHdrs[i]); + if(Size <=0 ){ + DEBUG_PRINT("NO DATA READ\n"); + bInputEosReached = true; + pInputBufHdrs[i]->nFlags= OMX_BUFFERFLAG_EOS; + } + pInputBufHdrs[i]->nFilledLen = (OMX_U32)Size; + pInputBufHdrs[i]->nInputPortIndex = 0; + used_ip_buf_cnt++; + ret = OMX_EmptyThisBuffer(qcelp13_enc_handle, pInputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT("OMX_EmptyThisBuffer failed with result %d\n", ret); + } + else { + DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); + } + if(Size <=0 ){ + break;//eos reached + } + } + pthread_mutex_lock(&etb_lock); + if(etb_done) +{ + DEBUG_PRINT("Component is waiting for EBD to be released.\n"); + etb_event_complete(); + } + else + { + DEBUG_PRINT("\n****************************\n"); + DEBUG_PRINT("EBD not yet happened ...\n"); + DEBUG_PRINT("\n****************************\n"); + etb_done++; + } + pthread_mutex_unlock(&etb_lock); +} + + return 0; +} + + + +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *avc_enc_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + unsigned int bufCntMin, unsigned int bufSize) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + unsigned int bufCnt=0; + + /* To remove warning for unused variable to keep prototype same */ + (void)avc_enc_handle; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE*)*bufCntMin); + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + DEBUG_PRINT("\n OMX_AllocateBuffer No %d \n", bufCnt); + error = OMX_AllocateBuffer(qcelp13_enc_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize); + } + + return error; +} + + + + +static int Read_Buffer (OMX_BUFFERHEADERTYPE *pBufHdr ) +{ + + size_t bytes_read=0; + + + pBufHdr->nFilledLen = 0; + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + + bytes_read = fread(pBufHdr->pBuffer, 1, pBufHdr->nAllocLen , inputBufferFile); + + pBufHdr->nFilledLen = (OMX_U32)bytes_read; + // Time stamp logic + ((OMX_BUFFERHEADERTYPE *)pBufHdr)->nTimeStamp = \ + + (OMX_TICKS) ((total_pcm_bytes * 1000)/(samplerate * channels *2)); + + DEBUG_PRINT ("\n--time stamp -- %ld\n", (unsigned long)((OMX_BUFFERHEADERTYPE *)pBufHdr)->nTimeStamp); + if(bytes_read == 0) + { + pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; + DEBUG_PRINT ("\nBytes read zero\n"); + } + else + { + pBufHdr->nFlags = pBufHdr->nFlags & (unsigned)~OMX_BUFFERFLAG_EOS; + + total_pcm_bytes = (unsigned)(total_pcm_bytes + bytes_read); + } + + return (int)bytes_read;; +} + + + +//In Encoder this Should Open a PCM or WAV file for input. + +static int open_audio_file () +{ + int error_code = 0; + + if (!tunnel) + { + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); + inputBufferFile = fopen (in_filename, "rb"); + if (inputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + in_filename); + error_code = -1; + } + if(parse_pcm_header() != 0x00) + { + DEBUG_PRINT("PCM parser failed \n"); + return -1; + } + } + + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, out_filename); + outputBufferFile = fopen (out_filename, "wb"); + if (outputBufferFile == NULL) { + DEBUG_PRINT("\ni/p file %s could NOT be opened\n", + out_filename); + error_code = -1; + return error_code; + } + fseek(outputBufferFile, QCP_HEADER_SIZE, SEEK_SET); + return error_code; +} + +static OMX_ERRORTYPE parse_pcm_header() +{ + struct wav_header hdr; + + DEBUG_PRINT("\n***************************************************************\n"); + if(fread(&hdr, 1, sizeof(hdr),inputBufferFile)!=sizeof(hdr)) + { + DEBUG_PRINT("Wav file cannot read header\n"); + return -1; + } + + if ((hdr.riff_id != ID_RIFF) || + (hdr.riff_fmt != ID_WAVE)|| + (hdr.fmt_id != ID_FMT)) + { + DEBUG_PRINT("Wav file is not a riff/wave file\n"); + return -1; + } + + if (hdr.audio_format != FORMAT_PCM) + { + DEBUG_PRINT("Wav file is not adpcm format %d and fmt size is %d\n", + hdr.audio_format, hdr.fmt_sz); + return -1; + } + + DEBUG_PRINT("Samplerate is %d\n", hdr.sample_rate); + DEBUG_PRINT("Channel Count is %d\n", hdr.num_channels); + DEBUG_PRINT("\n***************************************************************\n"); + + samplerate = hdr.sample_rate; + channels = hdr.num_channels; + total_pcm_bytes = 0; + + return OMX_ErrorNone; +} diff --git a/msm8909/mm-audio/autogen.sh b/msm8909/mm-audio/autogen.sh new file mode 100644 index 00000000..de72aa19 --- /dev/null +++ b/msm8909/mm-audio/autogen.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# autogen.sh -- Autotools bootstrapping + +libtoolize --copy --force +aclocal &&\ +autoheader &&\ +autoconf &&\ +automake --add-missing --copy + diff --git a/msm8909/mm-audio/configure.ac b/msm8909/mm-audio/configure.ac new file mode 100644 index 00000000..b75d2ed8 --- /dev/null +++ b/msm8909/mm-audio/configure.ac @@ -0,0 +1,44 @@ +# -*- Autoconf -*- + +# configure.ac -- Autoconf script for mm-omxaudio +# + +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.61) +AC_INIT([omxaudio], + 1.0.0) +AM_INIT_AUTOMAKE([-Wall -Werror gnu foreign]) +AM_MAINTAINER_MODE +AC_CONFIG_HEADER([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +#release versioning +OMXAUDIO_MAJOR_VERSION=1 +OMXAUDIO_MINOR_VERSION=0 +OMXAUDIO_MICRO_VERSION=0 + +OMXAUDIO_LIBRARY_VERSION=$OMXAUDIO_MAJOR_VERSION:$OMXAUDIO_MINOR_VERSION:$OMXAUDIO_MICRO_VERSION +AC_SUBST(OMXAUDIO_LIBRARY_VERSION) + +# Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AM_PROG_CC_C_O +AC_PROG_LIBTOOL +AC_PROG_AWK +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET + +AC_CONFIG_FILES([ \ + Makefile \ + adec-aac/Makefile \ + adec-mp3/Makefile \ + aenc-aac/Makefile \ + adec-aac/qdsp6/Makefile \ + adec-mp3/qdsp6/Makefile \ + aenc-aac/qdsp6/Makefile \ + ]) +AC_OUTPUT |