From 882636a0f769a08e6da244daf78c10b2fe84bf2d Mon Sep 17 00:00:00 2001 From: Arun Kumar Dasari Date: Thu, 10 Mar 2016 17:59:29 +0530 Subject: [PATCH] audio : Add g711 omx component for encoding -Add G711 omx component and omx test app for encoding Change-Id: Idcef6db3af50195c7c701219d38b4032e0347627 --- mm-audio/aenc-g711/Android.mk | 7 + mm-audio/aenc-g711/Makefile | 6 + mm-audio/aenc-g711/qdsp6/Android.mk | 72 + mm-audio/aenc-g711/qdsp6/Makefile | 81 + mm-audio/aenc-g711/qdsp6/inc/Map.h | 245 + mm-audio/aenc-g711/qdsp6/inc/aenc_svr.h | 121 + mm-audio/aenc-g711/qdsp6/inc/omx_g711_aenc.h | 539 ++ mm-audio/aenc-g711/qdsp6/inc/omx_log.h | 61 + mm-audio/aenc-g711/qdsp6/src/aenc_svr.c | 206 + .../aenc-g711/qdsp6/src/omx_g711_aenc.cpp | 4572 +++++++++++++++++ mm-audio/aenc-g711/qdsp6/src/omx_log.cpp | 50 + .../aenc-g711/qdsp6/test/omx_g711_enc_test.c | 1026 ++++ 12 files changed, 6986 insertions(+) create mode 100644 mm-audio/aenc-g711/Android.mk create mode 100644 mm-audio/aenc-g711/Makefile create mode 100644 mm-audio/aenc-g711/qdsp6/Android.mk create mode 100644 mm-audio/aenc-g711/qdsp6/Makefile create mode 100644 mm-audio/aenc-g711/qdsp6/inc/Map.h create mode 100644 mm-audio/aenc-g711/qdsp6/inc/aenc_svr.h create mode 100644 mm-audio/aenc-g711/qdsp6/inc/omx_g711_aenc.h create mode 100644 mm-audio/aenc-g711/qdsp6/inc/omx_log.h create mode 100644 mm-audio/aenc-g711/qdsp6/src/aenc_svr.c create mode 100644 mm-audio/aenc-g711/qdsp6/src/omx_g711_aenc.cpp create mode 100644 mm-audio/aenc-g711/qdsp6/src/omx_log.cpp create mode 100644 mm-audio/aenc-g711/qdsp6/test/omx_g711_enc_test.c diff --git a/mm-audio/aenc-g711/Android.mk b/mm-audio/aenc-g711/Android.mk new file mode 100644 index 00000000..4aff5c6b --- /dev/null +++ b/mm-audio/aenc-g711/Android.mk @@ -0,0 +1,7 @@ +ifneq ($(filter arm aarch64 arm64, $(TARGET_ARCH)),) + +AENC_G7111_PATH:= $(call my-dir) + +include $(AENC_G7111_PATH)/qdsp6/Android.mk + +endif diff --git a/mm-audio/aenc-g711/Makefile b/mm-audio/aenc-g711/Makefile new file mode 100644 index 00000000..83d822bb --- /dev/null +++ b/mm-audio/aenc-g711/Makefile @@ -0,0 +1,6 @@ +all: + @echo "invoking omxaudio make" + $(MAKE) -C qdsp6 + +install: + $(MAKE) -C qdsp6 install diff --git a/mm-audio/aenc-g711/qdsp6/Android.mk b/mm-audio/aenc-g711/qdsp6/Android.mk new file mode 100644 index 00000000..fd071eb1 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/Android.mk @@ -0,0 +1,72 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libOmxG711Enc-def := -g -O3 +libOmxG711Enc-def += -DQC_MODIFIED +libOmxG711Enc-def += -D_ANDROID_ +libOmxG711Enc-def += -D_ENABLE_QC_MSG_LOG_ +libOmxG711Enc-def += -DVERBOSE +libOmxG711Enc-def += -D_DEBUG +libOmxG711Enc-def += -Wconversion +libOmxG711Enc-def += -DAUDIOV2 + +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxG711Enc) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +libOmxG711Enc-inc := $(LOCAL_PATH)/inc +libOmxG711Enc-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := libOmxG711Enc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxG711Enc-def) +LOCAL_C_INCLUDES := $(libOmxG711Enc-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libutils liblog libcutils + +LOCAL_SRC_FILES := src/aenc_svr.c +LOCAL_SRC_FILES += src/omx_g711_aenc.cpp +LOCAL_SRC_FILES += src/omx_log.cpp + +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + + +include $(BUILD_SHARED_LIBRARY) + + +# --------------------------------------------------------------------------------- +# Make the apps-test (mm-aenc-omxg711-test) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +mm-g711-enc-test-inc := $(LOCAL_PATH)/inc +mm-g711-enc-test-inc += $(LOCAL_PATH)/test +mm-g711-enc-test-inc += $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_MODULE := mm-aenc-omxg711-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxG711Enc-def) +LOCAL_C_INCLUDES := $(mm-g711-enc-test-inc) +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libmm-omxcore +LOCAL_SHARED_LIBRARIES += libOmxG711Enc +LOCAL_SRC_FILES := test/omx_g711_enc_test.c + +include $(BUILD_EXECUTABLE) + +endif + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- + diff --git a/mm-audio/aenc-g711/qdsp6/Makefile b/mm-audio/aenc-g711/qdsp6/Makefile new file mode 100644 index 00000000..80dd4e53 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/Makefile @@ -0,0 +1,81 @@ +# --------------------------------------------------------------------------------- +# MM-AUDIO-OSS-8K-AENC-G7111 +# --------------------------------------------------------------------------------- + +# 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: libOmxG711Enc.so.$(LIBVER) mm-aenc-omxg711-test + +install: + echo "intalling aenc-g711 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 libOmxG711Enc.so.$(LIBVER) $(LIBINSTALLDIR) + cd $(LIBINSTALLDIR) && ln -s libOmxG711Enc.so.$(LIBVER) libOmxG711Enc.so.$(LIBMAJOR) + cd $(LIBINSTALLDIR) && ln -s libOmxG711Enc.so.$(LIBMAJOR) libOmxG711Enc.so + install -m 555 mm-aenc-omxg711-test $(BININSTALLDIR) + +# --------------------------------------------------------------------------------- +# COMPILE LIBRARY +# --------------------------------------------------------------------------------- +LDLIBS := -lpthread +LDLIBS += -lstdc++ +LDLIBS += -lOmxCore + +SRCS := src/omx_g711_aenc.cpp +SRCS += src/aenc_svr.c + +libOmxG711Enc.so.$(LIBVER): $(SRCS) + $(CC) $(CPPFLAGS) $(CFLAGS_SO) $(LDFLAGS_SO) -Wl,-soname,libOmxG711Enc.so.$(LIBMAJOR) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# --------------------------------------------------------------------------------- +# COMPILE TEST APP +# --------------------------------------------------------------------------------- +TEST_LDLIBS := -lpthread +TEST_LDLIBS += -ldl +TEST_LDLIBS += -lOmxCore + +#TEST_SRCS := test/omx_g711_enc_test.c + +mm-aenc-omxg711-test: libOmxG711Enc.so.$(LIBVER) $(TEST_SRCS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS) + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- diff --git a/mm-audio/aenc-g711/qdsp6/inc/Map.h b/mm-audio/aenc-g711/qdsp6/inc/Map.h new file mode 100644 index 00000000..22d36343 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/inc/Map.h @@ -0,0 +1,245 @@ +/*-------------------------------------------------------------------------- +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 "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 +using namespace std; + +template +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 *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 +T2 Map::find(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data2; + } + tmp = tmp->next; + } + return 0; +} + +template +T Map::find_ele(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data; + } + tmp = tmp->next; + } + return 0; +} + +template +T2 Map::begin() +{ + tmp = head; + if(tmp) + { + return (tmp->data2); + } + return 0; +} + +template +void Map::show() +{ + tmp = head; + while(tmp) + { + printf("%d-->%d\n",tmp->data,tmp->data2); + tmp = tmp->next; + } +} + +template +int Map::size() +{ + int count =0; + tmp = head; + while(tmp) + { + tmp = tmp->next; + count++; + } + return count; +} + +template +void Map::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 +bool Map::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 +bool Map::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 +bool Map::isempty() +{ + if(!size_of_list) return true; + else return false; +} + +#endif // _MAP_H_ diff --git a/mm-audio/aenc-g711/qdsp6/inc/aenc_svr.h b/mm-audio/aenc-g711/qdsp6/inc/aenc_svr.h new file mode 100644 index 00000000..24132e13 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/inc/aenc_svr.h @@ -0,0 +1,121 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2016, 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 "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 +#include +#include + +#ifdef _ANDROID_ +#define LOG_TAG "QC_G711ENC" +#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 g711_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 g711_ipc_info *omx_g711_thread_create(message_func cb, + void* client_data, + char *th_name); + +struct g711_ipc_info *omx_g711_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_g711_thread_stop(struct g711_ipc_info *g711_ipc); + + +/** + @brief This function post message in the command server + + @param svr handle to command server + @return none + */ +void omx_g711_post_msg(struct g711_ipc_info *g711_ipc, + unsigned char id); + +#ifdef __cplusplus +} +#endif + +#endif /* AENC_SVR */ diff --git a/mm-audio/aenc-g711/qdsp6/inc/omx_g711_aenc.h b/mm-audio/aenc-g711/qdsp6/inc/omx_g711_aenc.h new file mode 100644 index 00000000..9f912995 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/inc/omx_g711_aenc.h @@ -0,0 +1,539 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014, 2016 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 "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 _G711_ENC_H_ +#define _G711_ENC_H_ +/*============================================================================ + Audio Encoder + +@file omx_g711_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 +#include +#include +#include +#include +#include +#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 +#include +#include +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 4 +#define OMX_CORE_NUM_OUTPUT_BUFFERS 8 + +#define OMX_CORE_INPUT_BUFFER_SIZE 4096 // 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_G711_DEFAULT_SF 8000 +#define OMX_G711_DEFAULT_CH_CFG 1 +#define OMX_G711_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 360 +#define OMX_G711_OUTPUT_BUFFER_SIZE ((NUMOFFRAMES * (sizeof(ENC_META_OUT) + MAXFRAMELENGTH) \ + + 1)) + + +class omx_g711_aenc; + +// OMX mo3 audio encoder class +class omx_g711_aenc: public qc_omx_component +{ +public: + omx_g711_aenc(); // constructor + virtual ~omx_g711_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 + input_buffer_map; + + typedef Map + 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 lsw_ts; + unsigned int msw_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; + }G711_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; + bool is_mlaw; + // 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 + G711_PB_STATS m_g711_pb_stats; + struct g711_ipc_info *m_ipc_to_in_th; // for input thread + struct g711_ipc_info *m_ipc_to_out_th; // for output thread + struct g711_ipc_info *m_ipc_to_cmd_th; // for command thread + struct g711_ipc_info *m_ipc_to_event_th; //for txco event thread + OMX_PRIORITYMGMTTYPE m_priority_mgm ; + OMX_AUDIO_PARAM_PCMMODETYPE m_g711_param; // Cache G711 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_g711_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/mm-audio/aenc-g711/qdsp6/inc/omx_log.h b/mm-audio/aenc-g711/qdsp6/inc/omx_log.h new file mode 100644 index 00000000..0080ccc1 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/inc/omx_log.h @@ -0,0 +1,61 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2016, 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 "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 OMX_LOGS_H +#define OMX_LOGS_H + +#include + +using namespace std; + +/* + * Change logging-level at runtime with "persist.debug.omx.logs.level" + * + * level OMX_LOGV OMX_LOGD + * ---------------------------------- + * 0 silent silent + * 1 silent printed + * 2 printed printed + * + * AVLOGI/W/E are printed always + */ + +extern uint32_t gOmxLogLevel; + +#define OMX_LOGV(format, args...) ALOGD_IF((gOmxLogLevel > 1), format, ##args) +#define OMX_LOGD(format, args...) ALOGD_IF((gOmxLogLevel > 0), format, ##args) +#define OMX_LOGI(format, args...) ALOGI(format, ##args) +#define OMX_LOGW(format, args...) ALOGW(format, ##args) +#define OMX_LOGE(format, args...) ALOGE(format, ##args) + +void updateLogLevel(); + + +#endif // OMX_LOGS_H + diff --git a/mm-audio/aenc-g711/qdsp6/src/aenc_svr.c b/mm-audio/aenc-g711/qdsp6/src/aenc_svr.c new file mode 100644 index 00000000..fa446320 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/src/aenc_svr.c @@ -0,0 +1,206 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2016 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 "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 +#include +#include + +#include +#include + +#include + +/** + @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_g711_msg(void *info) +{ + struct g711_ipc_info *g711_info = (struct g711_ipc_info*)info; + unsigned char id; + ssize_t n; + + DEBUG_DETAIL("\n%s: message thread start\n", __FUNCTION__); + while (!g711_info->dead) + { + n = read(g711_info->pipe_in, &id, 1); + if (0 == n) break; + if (1 == n) + { + DEBUG_DETAIL("\n%s-->pipe_in=%d pipe_out=%d\n", + g711_info->thread_name, + g711_info->pipe_in, + g711_info->pipe_out); + + g711_info->process_msg_cb(g711_info->client_data, id); + } + if ((n < 0) && (errno != EINTR)) break; + } + DEBUG_DETAIL("%s: message thread stop\n", __FUNCTION__); + + return 0; +} + +void *omx_g711_events(void *info) +{ + struct g711_ipc_info *g711_info = (struct g711_ipc_info*)info; + unsigned char id = 0; + + DEBUG_DETAIL("%s: message thread start\n", g711_info->thread_name); + g711_info->process_msg_cb(g711_info->client_data, id); + DEBUG_DETAIL("%s: message thread stop\n", g711_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 g711_ipc_info *omx_g711_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct g711_ipc_info *g711_info; + + g711_info = calloc(1, sizeof(struct g711_ipc_info)); + if (!g711_info) + { + return 0; + } + + g711_info->client_data = client_data; + g711_info->process_msg_cb = cb; + strlcpy(g711_info->thread_name, th_name, sizeof(g711_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT_ERROR("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + g711_info->pipe_in = fds[0]; + g711_info->pipe_out = fds[1]; + + r = pthread_create(&g711_info->thr, 0, omx_g711_msg, g711_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", g711_info->thread_name); + return g711_info; + + +fail_thread: + close(g711_info->pipe_in); + close(g711_info->pipe_out); + +fail_pipe: + free(g711_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 g711_ipc_info *omx_g711_event_thread_create( + message_func cb, + void* client_data, + char* th_name) +{ + int r; + int fds[2]; + struct g711_ipc_info *g711_info; + + g711_info = calloc(1, sizeof(struct g711_ipc_info)); + if (!g711_info) + { + return 0; + } + + g711_info->client_data = client_data; + g711_info->process_msg_cb = cb; + strlcpy(g711_info->thread_name, th_name, sizeof(g711_info->thread_name)); + + if (pipe(fds)) + { + DEBUG_PRINT("\n%s: pipe creation failed\n", __FUNCTION__); + goto fail_pipe; + } + + g711_info->pipe_in = fds[0]; + g711_info->pipe_out = fds[1]; + + r = pthread_create(&g711_info->thr, 0, omx_g711_events, g711_info); + if (r < 0) goto fail_thread; + + DEBUG_DETAIL("Created thread for %s \n", g711_info->thread_name); + return g711_info; + + +fail_thread: + close(g711_info->pipe_in); + close(g711_info->pipe_out); + +fail_pipe: + free(g711_info); + + return 0; +} + +void omx_g711_thread_stop(struct g711_ipc_info *g711_info) { + DEBUG_DETAIL("%s stop server\n", __FUNCTION__); + close(g711_info->pipe_in); + close(g711_info->pipe_out); + pthread_join(g711_info->thr,NULL); + g711_info->pipe_out = -1; + g711_info->pipe_in = -1; + DEBUG_DETAIL("%s: message thread close fds%d %d\n", g711_info->thread_name, + g711_info->pipe_in,g711_info->pipe_out); + free(g711_info); +} + +void omx_g711_post_msg(struct g711_ipc_info *g711_info, unsigned char id) { + DEBUG_DETAIL("\n%s id=%d\n", __FUNCTION__,id); + write(g711_info->pipe_out, &id, 1); +} diff --git a/mm-audio/aenc-g711/qdsp6/src/omx_g711_aenc.cpp b/mm-audio/aenc-g711/qdsp6/src/omx_g711_aenc.cpp new file mode 100644 index 00000000..23fe28a1 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/src/omx_g711_aenc.cpp @@ -0,0 +1,4572 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014, 2016 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 "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_g711.c + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + + +#include +#include +#include +#include "omx_g711_aenc.h" +#include "omx_log.h" +#include + +using namespace std; +#define SLEEP_MS 100 + +// omx_cmd_queue destructor +omx_g711_aenc::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_g711_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_g711_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; + OMX_LOGE("ERROR!!! Command Queue Full"); + } + return ret; +} + +bool omx_g711_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; + OMX_LOGE("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_g711_aenc); +} +bool omx_g711_aenc::omx_cmd_queue::get_msg_id(unsigned char *id) +{ + if(m_size > 0) + { + *id = m_q[m_read].id; + OMX_LOGV("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_g711_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) { + OMX_LOGV("Timed out waiting for flush"); + if (ioctl(m_drv_fd, AUDIO_FLUSH, 0) < 0) + { + OMX_LOGE("Flush:Input port, ioctl failed error: rc:%d, %s, no:%d \n", + rc, strerror(errno), errno); + if (m_cb.EventHandler) + m_cb.EventHandler(&this->m_cmp, this->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, + OMX_COMPONENT_GENERATE_EVENT, NULL); + break; + } + } + } + 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_g711_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 g711 object +void omx_g711_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_g711_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_g711_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_g711_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_g711_aenc::omx_g711_aenc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_g711_aenc::omx_g711_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_G711_OUTPUT_BUFFER_SIZE), + input_buffer_size(OMX_CORE_INPUT_BUFFER_SIZE), + m_session_id(0), + is_mlaw(false), + 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_g711_pb_stats, 0, sizeof(m_g711_pb_stats)); + memset(&m_g711_param, 0, sizeof(m_g711_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); + updateLogLevel(); + + if ((cond_ret = pthread_cond_init (&cond, NULL)) != 0) + { + OMX_LOGE("pthread_cond_init returns non zero for cond\n"); + if (cond_ret == EAGAIN) + OMX_LOGE("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + OMX_LOGE("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&in_cond, NULL)) != 0) + { + OMX_LOGE("pthread_cond_init returns non zero for in_cond\n"); + if (cond_ret == EAGAIN) + OMX_LOGE("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + OMX_LOGE("Insufficient memory to initialise \ + condition variable\n"); + } + if ((cond_ret = pthread_cond_init (&out_cond, NULL)) != 0) + { + OMX_LOGE("pthread_cond_init returns non zero for out_cond\n"); + if (cond_ret == EAGAIN) + OMX_LOGE("The system lacked necessary \ + resources(other than mem)\n"); + else if (cond_ret == ENOMEM) + OMX_LOGE("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_g711_aenc::~omx_g711_aenc + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_g711_aenc::~omx_g711_aenc() +{ + OMX_LOGE("G711 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); + OMX_LOGE("OMX G711 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_g711_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_g711_pb_stats.ebd_cnt++; + nNumInputBuf--; + DEBUG_DETAIL("EBD CB:: in_buf_len=%d nNumInputBuf=%d\n ebd_cnt=%d",\ + m_g711_pb_stats.tot_in_buf_len, + nNumInputBuf, m_g711_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_g711_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(); + } + OMX_LOGV("Rxed FLUSH ACK cnt=%d\n",m_flush_cnt); + pthread_mutex_unlock(&m_flush_lock); +} +void omx_g711_aenc::frame_done_cb(OMX_BUFFERHEADERTYPE *bufHdr) +{ + if (m_cb.FillBufferDone) + { + PrintFrameHdr(OMX_COMPONENT_GENERATE_FRAME_DONE,bufHdr); + m_g711_pb_stats.fbd_cnt++; + pthread_mutex_lock(&out_buf_count_lock); + nNumOutputBuf--; + OMX_LOGV("FBD CB:: nNumOutputBuf=%d out_buf_len=%u fbd_cnt=%u\n",\ + nNumOutputBuf, + m_g711_pb_stats.tot_out_buf_len, + m_g711_pb_stats.fbd_cnt); + m_g711_pb_stats.tot_out_buf_len += bufHdr->nFilledLen; + m_g711_pb_stats.tot_pb_time = bufHdr->nTimeStamp; + OMX_LOGV("FBD:in_buf_len=%u out_buf_len=%u\n", + m_g711_pb_stats.tot_in_buf_len, + m_g711_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_g711_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_g711_aenc *pThis = (omx_g711_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 ) + { + OMX_LOGV(" 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)) + { + OMX_LOGV("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); + OMX_LOGV("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + OMX_LOGV("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) + { + OMX_LOGV("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 + { + OMX_LOGE("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_g711_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_g711_aenc *pThis = (omx_g711_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); + OMX_LOGV("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 + { + OMX_LOGE("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 + { + OMX_LOGE("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_g711_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_g711_aenc *pThis = (omx_g711_aenc *) client_data; + OMX_STATETYPE state; + + if (!pThis) + { + OMX_LOGE("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 ) + { + OMX_LOGV(" 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); + OMX_LOGV("IN: ***in OMX_StateLoaded so exiting\n"); + return ; + } else + { + qsize = 0; + OMX_LOGV("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 + { + OMX_LOGE("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_g711_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_g711_param, 0, sizeof(m_g711_param)); + m_g711_param.nSize = (OMX_U32)sizeof(m_g711_param); + m_g711_param.nChannels = OMX_G711_DEFAULT_CH_CFG; + m_g711_param.nSamplingRate = OMX_G711_DEFAULT_SF; + m_volume = OMX_G711_DEFAULT_VOL; /* Close to unity gain */ + memset(&m_g711_pb_stats,0,sizeof(G711_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_G711_DEFAULT_CH_CFG; + m_pcm_param.nSamplingRate = OMX_G711_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; + + OMX_LOGE(" component init: role = %s\n",role); + + OMX_LOGV(" component init: role = %s\n",role); + component_Role.nVersion.nVersion = OMX_SPEC_VERSION; + if (!strcmp(role,"OMX.qcom.audio.encoder.g711mlaw")) + { + pcm_input = 1; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + OMX_LOGV("\ncomponent_init: Component %s LOADED \n", role); + is_mlaw = true; + } else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.g711mlaw")) + { + pcm_input = 0; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + OMX_LOGV("\ncomponent_init: Component %s LOADED \n", role); + is_mlaw = true; + } else if (!strcmp(role,"OMX.qcom.audio.encoder.g711alaw")) + { + pcm_input = 1; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + OMX_LOGV("\ncomponent_init: Component %s LOADED \n", role); + } else if (!strcmp(role,"OMX.qcom.audio.encoder.tunneled.g711alaw")) + { + pcm_input = 0; + component_Role.nSize = (OMX_U32)sizeof(role); + strlcpy((char *)component_Role.cRole, (const char*)role, + sizeof(component_Role.cRole)); + OMX_LOGV("\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)); + OMX_LOGV("\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){ + OMX_LOGV("Mem alloc failed for in meta buf\n"); + return OMX_ErrorInsufficientResources; + } + } + m_tmp_out_meta_buf = + (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_G711_OUTPUT_BUFFER_SIZE); + if ( m_tmp_out_meta_buf == NULL ) { + OMX_LOGV("Mem alloc failed for out meta buf\n"); + return OMX_ErrorInsufficientResources; + } + + if(0 == pcm_input) + { + if (is_mlaw) + { + m_drv_fd = open("/dev/msm_g711mlaw_in",O_RDONLY); + OMX_LOGV("Driver msm_g711mlaw_in in Tunnel mode open\n"); + } + else + { + m_drv_fd = open("/dev/msm_g711alaw_in",O_RDONLY); + OMX_LOGV("Driver msm_g711alaw_in in Tunnel mode open\n"); + } + } + else + { + if (is_mlaw) + { + m_drv_fd = open("/dev/msm_g711mlaw_in",O_RDWR); + OMX_LOGV("Driver msm_g711mlaw_in in Non Tunnel mode open\n"); + } + else + { + m_drv_fd = open("/dev/msm_g711alaw_in",O_RDWR); + OMX_LOGV("Driver msm_g711alaw_in in Non Tunnel mode open\n"); + } + } + if (m_drv_fd < 0) + { + OMX_LOGE("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) + { + OMX_LOGE("AUDIO_GET_SESSION_ID FAILED\n"); + } + if(pcm_input) + { + if (!m_ipc_to_in_th) + { + m_ipc_to_in_th = omx_g711_thread_create(process_in_port_msg, + this, (char *)"INPUT_THREAD"); + if (!m_ipc_to_in_th) + { + OMX_LOGE("ERROR!!! Failed to start \ + Input port thread\n"); + return OMX_ErrorInsufficientResources; + } + } + } + + if (!m_ipc_to_cmd_th) + { + m_ipc_to_cmd_th = omx_g711_thread_create(process_command_msg, + this, (char *)"CMD_THREAD"); + if (!m_ipc_to_cmd_th) + { + OMX_LOGE("ERROR!!!Failed to start " + "command message thread\n"); + return OMX_ErrorInsufficientResources; + } + } + + if (!m_ipc_to_out_th) + { + m_ipc_to_out_th = omx_g711_thread_create(process_out_port_msg, + this, (char *)"OUTPUT_THREAD"); + if (!m_ipc_to_out_th) + { + OMX_LOGE("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_g711_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; + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + OMX_LOGE("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_g711_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; + OMX_LOGE("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); + OMX_LOGV("Send Command : returns with OMX_ErrorNone \n"); + OMX_LOGV("send_command : recieved state before semwait= %u\n",param1); + sem_wait (&sem_States); + OMX_LOGV("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_g711_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; + OMX_LOGE("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)) + { + OMX_LOGV("SCP-->Allocate Done Complete\n"); + } + else + { + OMX_LOGV("SCP-->Loaded to Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + bFlag = 0; + } + + } else if (eState == OMX_StateLoaded) + { + OMX_LOGV("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) + { + OMX_LOGV("OMXCORE-SM: Loaded-->WaitForResources\n"); + eRet = OMX_ErrorNone; + } + + else if (eState == OMX_StateExecuting) + { + OMX_LOGV("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) + { + OMX_LOGV("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) + { + OMX_LOGV("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 + { + OMX_LOGE("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) + { + OMX_LOGE("SCP:Idle->Loaded,\ + ioctl stop failed %d\n", errno); + } + + nTimestamp=0; + + OMX_LOGV("SCP-->Idle to Loaded\n"); + } else + { + OMX_LOGV("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_g711_enc_config drv_g711_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) + { + OMX_LOGE("ioctl AUDIO_GET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + if(ioctl(m_drv_fd, AUDIO_SET_STREAM_CONFIG, &drv_stream_config) + == -1) + { + OMX_LOGE("ioctl AUDIO_SET_STREAM_CONFIG failed, \ + errno[%d]\n", errno); + } + + if(ioctl(m_drv_fd, AUDIO_GET_G711_ENC_CONFIG, + &drv_g711_enc_config) == -1) + { + OMX_LOGE("ioctl AUDIO_GET_G711_ENC_CONFIG failed,\ + errno[%d]\n", errno); + } + if( drv_g711_enc_config.sample_rate != m_g711_param.nSamplingRate) + { + drv_g711_enc_config.sample_rate = m_g711_param.nSamplingRate; + } + OMX_LOGV("sampling rate %d", drv_g711_enc_config.sample_rate); + if(ioctl(m_drv_fd, AUDIO_SET_G711_ENC_CONFIG, &drv_g711_enc_config) + == -1) + { + OMX_LOGE("ioctl AUDIO_SET_G711_ENC_CONFIG \ + failed, errno[%d]\n", errno); + } + if (ioctl(m_drv_fd, AUDIO_GET_BUF_CFG, &buf_cfg) == -1) + { + OMX_LOGE("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) + { + OMX_LOGE("ioctl AUDIO_SET_BUF_CFG, errno[%d]\n", + errno); + } + if(pcm_input) + { + if (ioctl(m_drv_fd, AUDIO_GET_CONFIG, &pcm_cfg) == -1) + { + OMX_LOGE("ioctl AUDIO_GET_CONFIG, errno[%d]\n", + errno); + } + pcm_cfg.channel_count = m_pcm_param.nChannels; + pcm_cfg.sample_rate = m_pcm_param.nSamplingRate; + OMX_LOGV("pcm config %u %u\n",m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + + if (ioctl(m_drv_fd, AUDIO_SET_CONFIG, &pcm_cfg) == -1) + { + OMX_LOGE("ioctl AUDIO_SET_CONFIG, errno[%d]\n", + errno); + } + } + if(ioctl(m_drv_fd, AUDIO_START, 0) == -1) + { + OMX_LOGE("ioctl AUDIO_START failed, errno[%d]\n", + errno); + } + OMX_LOGV("SCP-->Idle to Executing\n"); + nState = eState; + } else if (eState == OMX_StateIdle) + { + OMX_LOGV("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) + { + OMX_LOGV("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) + { + OMX_LOGV("OMXCORE-SM: Idle-->Pause\n"); + } + + else if (eState == OMX_StateInvalid) + { + OMX_LOGV("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 + { + OMX_LOGE("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) + { + OMX_LOGV("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"); + OMX_LOGV("SCP-->RXED PAUSE STATE\n"); + DEBUG_DETAIL("*************************\n"); + //ioctl(m_drv_fd, AUDIO_PAUSE, 0); + } else if (eState == OMX_StateLoaded) + { + OMX_LOGV("\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) + { + OMX_LOGV("\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) + { + OMX_LOGV("\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) + { + OMX_LOGV("\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 + { + OMX_LOGE("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 ) + { + OMX_LOGV("SCP-->Paused to Idle \n"); + OMX_LOGV ("\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 ) + { + OMX_LOGV("\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) + { + OMX_LOGV("\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) + { + OMX_LOGV("\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) + { + OMX_LOGV("\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 + { + OMX_LOGV("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) + { + OMX_LOGV("OMXCORE-SM: WaitForResources-->Loaded\n"); + } else if (eState == OMX_StateWaitForResources) + { + OMX_LOGV("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) + { + OMX_LOGV("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) + { + OMX_LOGV("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) + { + OMX_LOGV("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 + { + OMX_LOGE("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) + { + OMX_LOGV("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 + { + OMX_LOGE("OMXCORE-SM: %d --> %d(Not Handled)\n",\ + m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } else if (OMX_CommandFlush == cmd) + { + DEBUG_DETAIL("*************************\n"); + OMX_LOGV("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 ) + { + OMX_LOGV("SCP: Disabling Input port Indx\n"); + m_inp_bEnabled = OMX_FALSE; + if ( (m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(0) ) + { + OMX_LOGV("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_INPUT_PORT_INDEX:release_done \n"); + OMX_LOGV("************* 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) + { + OMX_LOGV("SCP: execute_omx_flush in Disable in "\ + " param1=%u m_state=%d \n",param1, m_state); + execute_omx_flush(param1); + } + OMX_LOGV("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) + { + + OMX_LOGV("SCP: Disabling Output port Indx\n"); + m_out_bEnabled = OMX_FALSE; + if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_done(1)) + { + OMX_LOGV("send_command_proxy:OMX_CommandPortDisable:\ + OMX_CORE_OUTPUT_PORT_INDEX:release_done \n"); + OMX_LOGV("************* 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) + { + OMX_LOGV("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 + { + OMX_LOGE("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; + OMX_LOGV("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) + { + OMX_LOGV("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 + { + OMX_LOGV("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; + OMX_LOGV("SCP:WAKING OUT THR, OMX_CommandPortEnable\n"); + out_th_wakeup(); + } + pthread_mutex_unlock(&m_out_th_lock_1); + } else + { + OMX_LOGE("OMX_CommandPortEnable: disable wrong port ID"); + } + + } else + { + OMX_LOGE("SCP-->ERROR: Invali Command [%d]\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + OMX_LOGV("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_g711_aenc::execute_omx_flush(OMX_IN OMX_U32 param1, bool cmd_cmpl) +{ + bool bRet = true; + + OMX_LOGV("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; + OMX_LOGV("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) + OMX_LOGE("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(); + + OMX_LOGV("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 ); + OMX_LOGV("Inside FLUSH.. sending FLUSH CMPL\n"); + } + bFlushinprogress = false; + } + else if (param1 == OMX_CORE_INPUT_PORT_INDEX) + { + OMX_LOGV("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) + OMX_LOGE("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) + { + OMX_LOGV("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) + OMX_LOGE("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 + { + OMX_LOGV("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_g711_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 + + OMX_LOGV("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_g711_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 + + OMX_LOGV("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_g711_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_g711_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_g711_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_g711_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_g711_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_g711_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_g711_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) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + OMX_LOGE("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (paramData == NULL) + { + OMX_LOGV("get_parameter: paramData is NULL\n"); + return OMX_ErrorBadParameter; + } + + switch ((int)paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + OMX_LOGV("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_CodingG711; + portDefn->format.audio.pNativeRender = 0; + } else + { + portDefn->eDir = OMX_DirMax; + OMX_LOGE("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; + OMX_LOGV("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; + OMX_LOGV("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) + { + OMX_LOGV("get_parameter: OMX_IndexParamAudioFormat: "\ + "%u\n", portFormatType->nIndex); + + portFormatType->eEncoding = OMX_AUDIO_CodingG711; + } else + { + OMX_LOGE("get_parameter: Bad port index %d\n", + (int)portFormatType->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 || + OMX_CORE_OUTPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(pcmparam,&m_pcm_param,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + OMX_LOGV("get_parameter: Sampling rate %u",\ + pcmparam->nSamplingRate); + OMX_LOGV("get_parameter: Number of channels %u",\ + pcmparam->nChannels); + } else + { + OMX_LOGE("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; + OMX_LOGV("get_parameter: OMX_IndexParamComponentSuspended %p\n", + suspend); + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + OMX_LOGV("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; + OMX_LOGV("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; + OMX_LOGV("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: + { + OMX_LOGV("get_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + OMX_LOGV("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 + { + OMX_LOGE("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; + OMX_LOGV("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)); + OMX_LOGE("nSize = %d , nVersion = %d, cRole = %s\n", + component_Role.nSize, + component_Role.nVersion, + component_Role.cRole); + break; + + } + default: + { + OMX_LOGE("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_g711_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) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state != OMX_StateLoaded) + { + OMX_LOGE("set_parameter is not in proper state\n"); + return OMX_ErrorIncorrectStateOperation; + } + if (paramData == NULL) + { + OMX_LOGV("param data is NULL"); + return OMX_ErrorBadParameter; + } + + switch (paramIndex) + { + 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))) + { + OMX_LOGV("Set Parameter called in valid state\n"); + } else + { + OMX_LOGE("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_LOGV("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 + { + OMX_LOGV(" set_parameter: Bad Port idx %d",\ + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamPriorityMgmt: + { + OMX_LOGV("set_parameter: OMX_IndexParamPriorityMgmt\n"); + + if (m_state != OMX_StateLoaded) + { + OMX_LOGE("Set Parameter called in \ + Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype + = (OMX_PRIORITYMGMTTYPE*) paramData; + OMX_LOGV("set_parameter: OMX_IndexParamPriorityMgmt %u\n", + priorityMgmtype->nGroupID); + + OMX_LOGV("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; + OMX_LOGV("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) + { + OMX_LOGV("set_parameter: OMX_IndexParamAudioFormat:"\ + " %u\n", portFormatType->nIndex); + portFormatType->eEncoding = OMX_AUDIO_CodingG711; + } else + { + OMX_LOGE("set_parameter: Bad port index %d\n", \ + (int)portFormatType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + + case OMX_IndexParamCompBufferSupplier: + { + OMX_LOGV("set_parameter: \ + OMX_IndexParamCompBufferSupplier\n"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType + = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + OMX_LOGV("set_param: OMX_IndexParamCompBufferSupplier %d",\ + bufferSupplierType->eBufferSupplier); + + if (bufferSupplierType->nPortIndex == OMX_CORE_INPUT_PORT_INDEX + || bufferSupplierType->nPortIndex == + OMX_CORE_OUTPUT_PORT_INDEX) + { + OMX_LOGV("set_parameter:\ + OMX_IndexParamCompBufferSupplier\n"); + m_buffer_supplier.eBufferSupplier = + bufferSupplierType->eBufferSupplier; + } else + { + OMX_LOGE("set_param:\ + IndexParamCompBufferSup %08x\n", eRet); + eRet = OMX_ErrorBadPortIndex; + } + + break; + } + case OMX_IndexParamAudioPcm: + { + OMX_LOGV("set_parameter: OMX_IndexParamAudioPcm\n"); + OMX_AUDIO_PARAM_PCMMODETYPE *pcmparam + = (OMX_AUDIO_PARAM_PCMMODETYPE *) paramData; + + if (OMX_CORE_INPUT_PORT_INDEX== pcmparam->nPortIndex || + OMX_CORE_OUTPUT_PORT_INDEX== pcmparam->nPortIndex) + { + memcpy(&m_pcm_param,pcmparam,\ + sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + OMX_LOGV("set_pcm_parameter: %u %u",\ + m_pcm_param.nChannels, + m_pcm_param.nSamplingRate); + } else + { + OMX_LOGE("Set_parameter:OMX_IndexParamAudioPcm " + "OMX_ErrorBadPortIndex %d\n", + (int)pcmparam->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + m_g711_param = m_pcm_param; + 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: + { + OMX_LOGE("unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_g711_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) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + OMX_LOGE("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_g711_aenc::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_g711_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) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + OMX_LOGE("Set Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if ( m_state == OMX_StateExecuting) + { + OMX_LOGE("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_g711_aenc::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_g711_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)) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateInvalid) + { + OMX_LOGE("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; + OMX_LOGV("Extension index type - %d\n", *indexType); + + } + else + { + return OMX_ErrorBadParameter; + + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::GetState + +DESCRIPTION + Returns the state information back to the caller. + +PARAMETERS + . + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_g711_aenc::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + if(hComp == NULL) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + *state = m_state; + OMX_LOGV("Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_g711_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) +{ + OMX_LOGE("Error: component_tunnel_request Not Implemented\n"); + + if((hComp == NULL) || (peerComponent == NULL) || (tunnelSetup == NULL)) + { + port = port; + peerPort = peerPort; + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_g711_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; + OMX_LOGE("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++; + OMX_LOGV("AIB:bufHdr %p bufHdr->pBuffer %p m_inp_buf_cnt=%d \ + bytes=%u", bufHdr, bufHdr->pBuffer,m_inp_current_buf_count, + bytes); + + } else + { + OMX_LOGV("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } + else + { + OMX_LOGV("Input buffer memory allocation failed 2\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +OMX_ERRORTYPE omx_g711_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; + OMX_LOGE("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++; + OMX_LOGV("AOB::bufHdr %p bufHdr->pBuffer %p m_out_buf_cnt=%d "\ + "bytes=%u",bufHdr, bufHdr->pBuffer,\ + m_out_current_buf_count, bytes); + } else + { + OMX_LOGV("Output buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + OMX_LOGV("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_g711_aenc::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_g711_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) + { + OMX_LOGE("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 + { + OMX_LOGE("Error: Invalid Port Index received %d\n", + (int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + OMX_LOGV("allocate_buffer: before allocate_done \n"); + if (allocate_done()) + { + OMX_LOGV("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); + OMX_LOGV("allocate_buffer: post idle transition event \n"); + } + OMX_LOGV("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; + + OMX_LOGV("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); + } + } + } + OMX_LOGV("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_g711_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 + { + OMX_LOGE("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if (eRet == OMX_ErrorNone) + { + OMX_LOGV("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); + } + } + } + OMX_LOGV("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_g711_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; + OMX_LOGE("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); + OMX_LOGV("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 + { + OMX_LOGV("Input buffer memory allocation failed 1 \n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + OMX_LOGV("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_g711_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; + OMX_LOGE("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; + } + + OMX_LOGV("Inside omx_g711_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; + OMX_LOGV("BufHdr=%p buffer=%p\n",bufHdr,buffer); + *bufferHdr = bufHdr; + memset(bufHdr,0,sizeof(OMX_BUFFERHEADERTYPE)); + + bufHdr->pBuffer = (OMX_U8 *)(buffer); + OMX_LOGV("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 + { + OMX_LOGV("Output buffer memory allocation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + } else + { + OMX_LOGV("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_g711_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_g711_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_g711_aenc::free_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + OMX_LOGV("Free_Buffer buf %p\n", buffer); + if(hComp == NULL) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + OMX_LOGV(" 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)) + { + OMX_LOGV("Free Buffer while port %u disabled\n", port); + } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + OMX_LOGV("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 + { + OMX_LOGV("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 + OMX_LOGV("Free_Buf:in_buffer[%p]\n",buffer); + m_input_buf_hdrs.erase(buffer); + free(buffer); + m_inp_current_buf_count--; + } else + { + OMX_LOGE("Free_Buf:Error-->free_buffer, \ + Invalid Input buffer header\n"); + eRet = OMX_ErrorBadParameter; + } + } else + { + OMX_LOGE("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)) + { + OMX_LOGV("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 + OMX_LOGV("Free_Buf:out_buffer[%p]\n",buffer); + m_output_buf_hdrs.erase(buffer); + free(buffer); + m_out_current_buf_count--; + } else + { + OMX_LOGV("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)) + { + OMX_LOGV("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) + OMX_LOGE("AUDIO STOP in free buffer failed\n"); + else + OMX_LOGV("AUDIO STOP in free buffer passed\n"); + + + OMX_LOGV("Free_Buf: Free buffer\n"); + + + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + OMX_LOGV("Before OMX_StateLoaded \ + OMX_COMPONENT_GENERATE_EVENT\n"); + post_command(OMX_CommandStateSet, + OMX_StateLoaded,OMX_COMPONENT_GENERATE_EVENT); + OMX_LOGV("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_g711_aenc::empty_this_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + OMX_LOGV("ETB:Buf:%p Len %u TS %lld numInBuf=%d\n", \ + buffer, buffer->nFilledLen, buffer->nTimeStamp, (nNumInputBuf)); + if (m_state == OMX_StateInvalid) + { + OMX_LOGV("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (!m_inp_bEnabled) + { + OMX_LOGV("empty_this_buffer OMX_ErrorIncorrectStateOperation "\ + "Port Status %d \n", m_inp_bEnabled); + return OMX_ErrorIncorrectStateOperation; + } + if (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE)) + { + OMX_LOGV("omx_g711_aenc::etb--> Buffer Size Invalid\n"); + return OMX_ErrorBadParameter; + } + if (buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + OMX_LOGV("omx_g711_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)) + { + OMX_LOGE("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 + { + OMX_LOGE("Bad header %p \n", buffer); + eRet = OMX_ErrorBadParameter; + } + } + pthread_mutex_lock(&in_buf_count_lock); + nNumInputBuf++; + m_g711_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_g711_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; + ssize_t bytes = 0; + + PrintFrameHdr(OMX_COMPONENT_GENERATE_ETB,buffer); + memset(&meta_in,0,sizeof(meta_in)); + if ( search_input_bufhdr(buffer) == false ) + { + OMX_LOGV("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) + { + OMX_LOGV("EOS OCCURED \n"); + meta_in.nFlags |= OMX_BUFFERFLAG_EOS; + } + memcpy(data,&meta_in, meta_in.offsetVal); + OMX_LOGV("meta_in.nFlags = 0x%8x\n",meta_in.nFlags); + } + + memcpy(&data[sizeof(META_IN)],buffer->pBuffer,buffer->nFilledLen); + bytes = write(m_drv_fd, data, buffer->nFilledLen+sizeof(META_IN)); + if (bytes <= 0) { + frame_done_cb((OMX_BUFFERHEADERTYPE *)buffer); + + if (errno == ENETRESET) + { + ALOGE("In SSR, return error to close the session"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventError, + OMX_ErrorHardware, + 0, NULL ); + } + return OMX_ErrorNone; + } + + 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 */ + OMX_LOGV("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_g711_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)) + { + OMX_LOGV("\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); + + if (errno == ENETRESET) + { + ALOGE("In SSR, return error to close the session"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventError, + OMX_ErrorHardware, + 0, NULL ); + } + return OMX_ErrorNone; + } else + OMX_LOGV("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; + OMX_LOGV("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 ) + { + OMX_LOGV("FTBP: Now, Send EOS flag to Client \n"); + m_cb.EventHandler(&m_cmp, + m_app_data, + OMX_EventBufferFlag, + 1, 1, NULL ); + } + + return OMX_ErrorNone; + } + OMX_LOGV("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) + { + OMX_LOGV("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 + OMX_LOGV("\n FTBP-->Invalid buffer in FTB \n"); + + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_g711_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_g711_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)) + { + OMX_LOGV("omx_g711_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) + { + OMX_LOGV("omx_g711_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_g711_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_g711_aenc::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_g711_aenc::set_callbacks( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + if(hComp == NULL) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + m_cb = *callbacks; + m_app_data = appData; + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_g711_aenc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + if(hComp == NULL) + { + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + if (OMX_StateLoaded != m_state && OMX_StateInvalid != m_state) + { + OMX_LOGE("Warning: Rxed DeInit when not in LOADED state %d\n", + m_state); + } + deinit_encoder(); + +OMX_LOGE("%s:COMPONENT DEINIT...\n", __FUNCTION__); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::deinit_encoder + +DESCRIPTION + Closes all the threads and release memory allocated to the heap. + +PARAMETERS + None. + +RETURN VALUE + None. + +========================================================================== */ +void omx_g711_aenc::deinit_encoder() +{ + OMX_LOGV("Component-deinit being processed\n"); + OMX_LOGV("********************************\n"); + OMX_LOGV("STATS: in-buf-len[%u]out-buf-len[%u] tot-pb-time[%lld]",\ + m_g711_pb_stats.tot_in_buf_len, + m_g711_pb_stats.tot_out_buf_len, + m_g711_pb_stats.tot_pb_time); + OMX_LOGV("STATS: fbd-cnt[%u]ftb-cnt[%u]etb-cnt[%u]ebd-cnt[%u]",\ + m_g711_pb_stats.fbd_cnt,m_g711_pb_stats.ftb_cnt, + m_g711_pb_stats.etb_cnt, + m_g711_pb_stats.ebd_cnt); + memset(&m_g711_pb_stats,0,sizeof(G711_PB_STATS)); + + if((OMX_StateLoaded != m_state) && (OMX_StateInvalid != m_state)) + { + OMX_LOGE("%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); + OMX_LOGE("Freeing Buf:inp_current_buf_count[%d][%d]\n",\ + m_inp_current_buf_count, + m_input_buf_hdrs.size()); + m_input_buf_hdrs.eraseall(); + OMX_LOGE("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_g711_thread_stop(m_ipc_to_in_th); + m_ipc_to_in_th = NULL; + } + } + + if (m_ipc_to_cmd_th != NULL) + { + omx_g711_thread_stop(m_ipc_to_cmd_th); + m_ipc_to_cmd_th = NULL; + } + if (m_ipc_to_out_th != NULL) + { + DEBUG_DETAIL("Inside omx_g711_thread_stop\n"); + omx_g711_thread_stop(m_ipc_to_out_th); + m_ipc_to_out_th = NULL; + } + + + if(ioctl(m_drv_fd, AUDIO_STOP, 0) <0) + OMX_LOGE("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) + OMX_LOGV("De-init: Driver Close Failed \n"); + m_drv_fd = -1; + } + else + { + OMX_LOGE(" G711 device already closed\n"); + } + m_comp_deinit=1; + m_is_out_th_sleep = 1; + m_is_in_th_sleep = 1; + OMX_LOGV("************************************\n"); + OMX_LOGV(" DEINIT COMPLETED"); + OMX_LOGV("************************************\n"); + +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation . + +PARAMETERS + . + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_g711_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) +{ + OMX_LOGE("Error : use_EGL_image: Not Implemented \n"); + + if((hComp == NULL) || (appData == NULL) || (eglImage == NULL)) + { + bufferHdr = bufferHdr; + port = port; + OMX_LOGE("Returning OMX_ErrorBadParameter\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_g711_aenc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_g711_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.g711"; + + if(hComp == NULL) + { + OMX_LOGE("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_g711_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_g711_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_g711_aenc::ReleaseDone + +DESCRIPTION + Checks if IL client has released all the buffers. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_g711_aenc::release_done(OMX_U32 param1) +{ + OMX_LOGV("Inside omx_g711_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/mm-audio/aenc-g711/qdsp6/src/omx_log.cpp b/mm-audio/aenc-g711/qdsp6/src/omx_log.cpp new file mode 100644 index 00000000..39498be6 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/src/omx_log.cpp @@ -0,0 +1,50 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2016 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 "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 +#include +#include + +#include "omx_log.h" + +using namespace std; + +uint32_t gOmxLogLevel; + +void updateLogLevel() { + char level[PROPERTY_VALUE_MAX]; +#ifdef ANDROID + property_get("persist.debug.omx.logs.level", level, "0"); + gOmxLogLevel = atoi(level); +#else + gOmxLogLevel = atoi("0"); +#endif +} + + diff --git a/mm-audio/aenc-g711/qdsp6/test/omx_g711_enc_test.c b/mm-audio/aenc-g711/qdsp6/test/omx_g711_enc_test.c new file mode 100644 index 00000000..54e80ea2 --- /dev/null +++ b/mm-audio/aenc-g711/qdsp6/test/omx_g711_enc_test.c @@ -0,0 +1,1026 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010, 2014, 2016, 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 "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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "OMX_Core.h" +#include "OMX_Component.h" +#include "pthread.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "QOMX_AudioExtensions.h" +#include "QOMX_AudioIndexExtensions.h" +#include + +typedef unsigned char uint8; +typedef unsigned char byte; +typedef unsigned int uint32; +typedef unsigned int uint16; + +QOMX_AUDIO_STREAM_INFO_DATA streaminfoparam; + +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 MIN(A,B) (((A) < (B))?(A):(B)) + +FILE *F1 = NULL; + +uint32_t channels = 1; +uint32_t samplerate = 8000; +uint32_t pcmplayback = 0; +uint32_t tunnel = 0; +uint32_t rectime = 0; +uint32_t encode_format = 0; +#define DEBUG_PRINT printf +unsigned to_idle_transition = 0; + + +/************************************************************************/ +/* #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_PCMMODETYPE pcmParams; +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 ID_FACT 0x74636166 + +#define FORMAT_PCM 0x0001 +#define FORMAT_ALAW 0x0006 +#define FORMAT_MULAW 0x0007 + +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 __attribute__((__packed__)) g711_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; + uint16_t extension_size; + uint32_t fact_id; + uint32_t fact_sz; + uint32_t sample_length; + 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; + +static struct wav_header hdr; +static struct g711_header g711hdr; +/************************************************************************/ +/* 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* g711_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 *g711_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(); +static OMX_ERRORTYPE attach_g711_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 totaldatalen %d\n ", totaldatalen); + bOutputEosReached = true; + g711hdr.data_sz = (uint32_t)totaldatalen; + g711hdr.sample_length = (uint32_t)totaldatalen; + g711hdr.riff_sz = g711hdr.data_sz + sizeof(g711hdr) - 8; + fseek(outputBufferFile, 0, SEEK_SET); + fwrite(&g711hdr,1, sizeof(g711hdr), outputBufferFile); + fseek(outputBufferFile, 0, SEEK_END); + 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; + 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 g711 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_g711_aenc_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_g711_aenc_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(g711_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(g711_enc_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL); + } else { + DEBUG_PRINT("%s pause playback\n", __FUNCTION__); + bPause = true; + OMX_SendCommand(g711_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 >= 5) { + in_filename = argv[1]; + out_filename = argv[2]; + encode_format = (uint32_t)atoi(argv[3]); + tunnel = (uint32_t)atoi(argv[4]); + rectime = (uint32_t)atoi(argv[5]); + + + DEBUG_PRINT("Input parameters: enocder format= %d, tunnel %d, rectime = %d\n", + encode_format, tunnel, rectime); + + } else { + DEBUG_PRINT(" invalid format: \n"); + DEBUG_PRINT("ex: ./mm-aenc-omxg711 INPUTFILE G711_OUTPUTFILE ENCODE_FORMAT TUNNEL RECORDTIME \n"); + DEBUG_PRINT("ENCODE formats are : G711MLAW :0 , G711ALAW: 1"); + DEBUG_PRINT("FOR TUNNEL MOD PASS INPUT FILE AS ZERO\n"); + DEBUG_PRINT("RECORDTIME in seconds for AST Automation ...TUNNEL MODE ONLY\n"); + return 0; + } + if(tunnel == 0) { + if(encode_format == 0) { + aud_comp = "OMX.qcom.audio.encoder.g711mlaw"; + } + else { + aud_comp = "OMX.qcom.audio.encoder.g711alaw"; + } + } else { + if(encode_format == 0) { + aud_comp = "OMX.qcom.audio.encoder.tunneled.g711mlaw"; + } + else { + aud_comp = "OMX.qcom.audio.encoder.tunneled.g711alaw"; + } + } + 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(g711_enc_handle, OMX_CommandStateSet, OMX_StateIdle,0); + wait_for_event(); + DEBUG_PRINT("\nMoving the encoder to loaded state \n"); + OMX_SendCommand(g711_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(g711_enc_handle, 0, pInputBufHdrs[bufCnt]); + } + } + + DEBUG_PRINT ("\nFillBufferDone: Deallocating o/p buffers \n"); + for(bufCnt=0; bufCnt < output_buf_cnt; ++bufCnt) { + OMX_FreeBuffer(g711_enc_handle, 1, pOutputBufHdrs[bufCnt]); + } + wait_for_event(); + + result = OMX_FreeHandle(g711_enc_handle); + if (result != OMX_ErrorNone) { + DEBUG_PRINT ("\nOMX_FreeHandle error. Error code: %d\n", result); + } + OMX_Deinit(); + ebd_cnt=0; + bOutputEosReached = false; + bInputEosReached_tunnel = false; + bInputEosReached = 0; + g711_enc_handle = NULL; + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + fclose(outputBufferFile); + DEBUG_PRINT("*****************************************\n"); + DEBUG_PRINT("******...G711 ENC TEST COMPLETED...***************\n"); + DEBUG_PRINT("*****************************************\n"); + } + return 0; +} + +void Release_Encoder() +{ + static int cnt=0; + OMX_ERRORTYPE result; + + DEBUG_PRINT("END OF G711 ENCODING: EXITING PLEASE WAIT\n"); + bInputEosReached_tunnel = 1; + event_complete(); + cnt++; + if(cnt > 1) + { + /* FORCE RESET */ + g711_enc_handle = NULL; + ebd_cnt=0; + bInputEosReached_tunnel = false; + + result = OMX_FreeHandle(g711_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("******...G711 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("G711_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*)(&g711_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(g711_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(g711_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; + } + + pcmParams.nPortIndex = 0; + pcmParams.nChannels = channels; + pcmParams.bInterleaved = OMX_TRUE; + pcmParams.nSamplingRate = samplerate; + OMX_SetParameter(g711_enc_handle,OMX_IndexParamAudioPcm,&pcmParams); + + + /* 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(g711_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(pcmParams); + + + pcmParams.nPortIndex = 1; + pcmParams.nChannels = channels; //Only mono is supported + pcmParams.nSamplingRate = samplerate; + OMX_SetParameter(g711_enc_handle,OMX_IndexParamAudioPcm,&pcmParams); + OMX_GetExtensionIndex(g711_enc_handle,"OMX.Qualcomm.index.audio.sessionId",&index); + OMX_GetParameter(g711_enc_handle,index,&streaminfoparam); + DEBUG_PRINT ("\nOMX_SendCommand Encoder -> IDLE\n"); + OMX_SendCommand(g711_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(g711_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(g711_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(g711_enc_handle, OMX_CommandPortDisable,0,0); // disable input port + wait_for_event(); + } + + DEBUG_PRINT ("\nOMX_SendCommand encoder -> Executing\n"); + OMX_SendCommand(g711_enc_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + + DEBUG_PRINT(" Start sending OMX_FILLthisbuffer\n"); + + attach_g711_header(); + + 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(g711_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(g711_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(g711_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; +} + +static OMX_ERRORTYPE attach_g711_header() +{ + + memset(&g711hdr, 0, sizeof(struct g711_header)); + + g711hdr.riff_id = ID_RIFF; + g711hdr.riff_fmt = ID_WAVE; + g711hdr.fmt_id = ID_FMT; + g711hdr.fmt_sz = 18; + + //change format type from wav to g711 + if(encode_format == 0) { + g711hdr.audio_format = FORMAT_MULAW; + } + else { + g711hdr.audio_format = FORMAT_ALAW; + } + + g711hdr.num_channels = hdr.num_channels; + g711hdr.sample_rate = hdr.sample_rate; + g711hdr.bits_per_sample = 8; + g711hdr.byte_rate = g711hdr.sample_rate * g711hdr.num_channels * (g711hdr.bits_per_sample / 8); + g711hdr.block_align = (uint16_t)((g711hdr.bits_per_sample / 8) * g711hdr.num_channels); + g711hdr.extension_size = 0; + g711hdr.fact_id = ID_FACT; + g711hdr.fact_sz = 4; + g711hdr.data_id = ID_DATA; + g711hdr.data_sz = 0; + g711hdr.riff_sz = g711hdr.data_sz + sizeof(g711hdr) - 8; + + fwrite(&g711hdr,1, sizeof(g711hdr), outputBufferFile); + + /*To Do : Attach Fact chunk for Non -PCM format */ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE parse_pcm_header() +{ + + 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 pcm format %d and fmt size is %d\n", + hdr.audio_format, hdr.fmt_sz); + return -1; + } + + if ((hdr.sample_rate != 8000) && (hdr.sample_rate != 16000)) { + DEBUG_PRINT("samplerate = %d, not supported, Supported " + "samplerates are 8000, 16000", samplerate); + return -1; + } + + if (hdr.num_channels != 1) { + DEBUG_PRINT("stereo and multi channel are not supported, channels %d" + , hdr.num_channels); + 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; +}