summaryrefslogtreecommitdiff
authorJing Wei <jing.wei@amlogic.com>2015-07-23 06:08:19 (GMT)
committer Jing Wei <jing.wei@amlogic.com>2015-07-23 07:16:48 (GMT)
commit327eadef2b307230360aec3f53d2a6cc5764c69a (patch)
treefbcee9c3c13424c70c0d12e48a0a0d3aa94cdece
parente891f0fb2527a54865cb3e7fd4425fd71d981c90 (diff)
downloadaudio-327eadef2b307230360aec3f53d2a6cc5764c69a.zip
audio-327eadef2b307230360aec3f53d2a6cc5764c69a.tar.gz
audio-327eadef2b307230360aec3f53d2a6cc5764c69a.tar.bz2
PD #109887: g9tv:merge tv audio
Change-Id: I6dc565fc88bccfc42038032054423464c893948f
Diffstat
-rw-r--r--Android.mk1
-rw-r--r--libTVaudio/Android.mk32
-rw-r--r--libTVaudio/audio/Android.mk30
-rw-r--r--libTVaudio/audio/DDP_media_source.cpp754
-rw-r--r--libTVaudio/audio/DDP_media_source.h143
-rw-r--r--libTVaudio/audio/amaudio_main.cpp74
-rw-r--r--libTVaudio/audio/aml_audio.c1864
-rw-r--r--libTVaudio/audio/aml_audio.h73
-rw-r--r--libTVaudio/audio/android_out.cpp160
-rw-r--r--libTVaudio/audio/android_out.h15
-rw-r--r--libTVaudio/audio/audio_amaudio.cpp209
-rw-r--r--libTVaudio/audio/audio_effect_control.c423
-rw-r--r--libTVaudio/audio/audio_effect_control.h48
-rw-r--r--libTVaudio/audio/audio_usb_check.cpp29
-rw-r--r--libTVaudio/audio/audio_usb_check.h18
-rw-r--r--libTVaudio/audio_amaudio.h38
16 files changed, 3911 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
index e32c5bf..86f6eaa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -120,3 +120,4 @@ include $(BUILD_SHARED_LIBRARY)
endif # USE_CUSTOM_AUDIO_POLICY
endif # BOARD_ALSA_AUDIO
+include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
diff --git a/libTVaudio/Android.mk b/libTVaudio/Android.mk
new file mode 100644
index 0000000..91ef7dc
--- a/dev/null
+++ b/libTVaudio/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libTVaudio
+
+LOCAL_SHARED_LIBRARIES := libcutils libutils libtinyalsa libdl \
+ libmedia libbinder libusbhost libstagefright
+
+LOCAL_C_INCLUDES := \
+ external/tinyalsa/include \
+ frameworks/av/include/media/stagefright \
+ frameworks/av/include/media \
+ frameworks/native/include/media/openmax \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/audio \
+
+LOCAL_SRC_FILES := \
+ audio/aml_audio.c \
+ audio/audio_effect_control.c \
+ audio/android_out.cpp \
+ audio/audio_amaudio.cpp \
+ audio/audio_usb_check.cpp \
+ audio/amaudio_main.cpp \
+ audio/DDP_media_source.cpp \
+
+LOCAL_CFLAGS := -DANDROID_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libTVaudio/audio/Android.mk b/libTVaudio/audio/Android.mk
new file mode 100644
index 0000000..eeb030f
--- a/dev/null
+++ b/libTVaudio/audio/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := aml_audio_test
+
+LOCAL_SHARED_LIBRARIES := libcutils libutils libtinyalsa libdl \
+ libmedia libbinder libusbhost libstagefright
+
+LOCAL_C_INCLUDES := \
+ external/tinyalsa/include \
+ frameworks/av/include/media/stagefright \
+ frameworks/native/include/media/openmax \
+ $(LOCAL_PATH)/ \
+
+LOCAL_SRC_FILES := \
+ aml_audio.c \
+ audio_effect_control.c \
+ android_out.cpp \
+ audio_amaudio.cpp \
+ audio_usb_check.cpp \
+ amaudio_main.cpp \
+ DDP_media_source.cpp \
+
+LOCAL_CFLAGS := -DANDROID_PLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_EXECUTABLE)
diff --git a/libTVaudio/audio/DDP_media_source.cpp b/libTVaudio/audio/DDP_media_source.cpp
new file mode 100644
index 0000000..14eb6bf
--- a/dev/null
+++ b/libTVaudio/audio/DDP_media_source.cpp
@@ -0,0 +1,754 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <android/log.h>
+#include <cutils/properties.h>
+#include <pthread.h>
+
+#include "DDP_media_source.h"
+#include "aml_audio.h"
+
+extern struct circle_buffer android_out_buffer;
+extern struct circle_buffer DDP_out_buffer;
+
+namespace android {
+
+#define LOG_TAG "DDP_Media_Source"
+
+static DDPerr ddbs_init(DDPshort * buf, DDPshort bitptr,DDP_BSTRM *p_bstrm)
+{
+ p_bstrm->buf = buf;
+ p_bstrm->bitptr = bitptr;
+ p_bstrm->data = *buf;
+ return 0;
+}
+static DDPerr ddbs_unprj(DDP_BSTRM *p_bstrm,DDPshort *p_data, DDPshort numbits)
+{
+ DDPushort data;
+ *p_data = (DDPshort)((p_bstrm->data << p_bstrm->bitptr) & msktab[numbits]);
+ p_bstrm->bitptr += numbits;
+ if (p_bstrm->bitptr >= BITSPERWRD)
+ {
+ p_bstrm->buf++;
+ p_bstrm->data = *p_bstrm->buf;
+ p_bstrm->bitptr -= BITSPERWRD;
+ data = (DDPushort)p_bstrm->data;
+ *p_data |= ((data >> (numbits - p_bstrm->bitptr)) & msktab[numbits]);
+ }
+ *p_data = (DDPshort)((DDPushort)(*p_data) >> (BITSPERWRD - numbits));
+ return 0;
+}
+
+
+static int Get_DD_Parameters(void *buf, int *sample_rate, int *frame_size,int *ChNum)
+{
+ int numch=0;
+ DDP_BSTRM bstrm={0};
+ DDP_BSTRM *p_bstrm=&bstrm;
+ short tmp=0,acmod,lfeon,fscod,frmsizecod;
+ ddbs_init((short*)buf,0,p_bstrm);
+
+ ddbs_unprj(p_bstrm, &tmp, 16);
+ if (tmp!= SYNCWRD)
+ {
+ ALOGI("Invalid synchronization word");
+ return 0;
+ }
+ ddbs_unprj(p_bstrm, &tmp, 16);
+ ddbs_unprj(p_bstrm, &fscod, 2);
+ if (fscod == MAXFSCOD)
+ {
+ ALOGI("Invalid sampling rate code");
+ return 0;
+ }
+
+ if (fscod == 0) *sample_rate = 48000;
+ else if (fscod == 1) *sample_rate = 44100;
+ else if (fscod == 2) *sample_rate = 32000;
+
+ ddbs_unprj(p_bstrm, &frmsizecod, 6);
+ if (frmsizecod >= MAXDDDATARATE)
+ {
+ ALOGI("Invalid frame size code");
+ return 0;
+ }
+
+ *frame_size=2*frmsizetab[fscod][frmsizecod];
+
+ ddbs_unprj(p_bstrm, &tmp, 5);
+ if (!ISDD(tmp))
+ {
+ ALOGI("Unsupported bitstream id");
+ return 0;
+ }
+
+ ddbs_unprj(p_bstrm, &tmp, 3);
+ ddbs_unprj(p_bstrm, &acmod, 3);
+
+ if ((acmod!= MODE10) && (acmod& 0x1))
+ {
+ ddbs_unprj(p_bstrm, &tmp, 2);
+ }
+ if (acmod& 0x4)
+ {
+ ddbs_unprj(p_bstrm, &tmp, 2);
+ }
+
+ if (acmod == MODE20)
+ {
+ ddbs_unprj(p_bstrm,&tmp, 2);
+ }
+ ddbs_unprj(p_bstrm, &lfeon, 1);
+
+
+ numch = chanary[acmod];
+ if (0)
+ {
+ if (numch >= 3)
+ numch = 8;
+ else
+ numch = 2;
+ }else{
+ numch = 2;
+ }
+ *ChNum=numch;
+ //ALOGI("DEBUG:numch=%d sample_rate=%d %p [%s %d]",ChNum,sample_rate,this,__FUNCTION__,__LINE__);
+ return numch;
+}
+
+static int Get_DDP_Parameters(void *buf, int *sample_rate, int *frame_size,int *ChNum)
+{
+ int numch = 0;
+ DDP_BSTRM bstrm={0};
+ DDP_BSTRM *p_bstrm=&bstrm;
+ short tmp=0,acmod,lfeon,strmtyp;
+ ddbs_init((short*)buf,0,p_bstrm);
+ ddbs_unprj(p_bstrm, &tmp, 16);
+ if (tmp!= SYNCWRD) {
+ ALOGI("Invalid synchronization word");
+ return -1;
+ }
+
+ ddbs_unprj(p_bstrm, &strmtyp, 2);
+ ddbs_unprj(p_bstrm, &tmp, 3);
+ ddbs_unprj(p_bstrm, &tmp, 11);
+
+ *frame_size = 2 * (tmp + 1);
+ if (strmtyp != 0 && strmtyp != 2) {
+ return -1;
+ }
+ ddbs_unprj(p_bstrm, &tmp, 2);
+
+ if (tmp == 0x3) {
+ ALOGI("Half sample rate unsupported");
+ return -1;
+ } else {
+ if (tmp == 0)
+ *sample_rate = 48000;
+ else if (tmp == 1)
+ *sample_rate = 44100;
+ else if (tmp == 2)
+ *sample_rate = 32000;
+
+ ddbs_unprj(p_bstrm, &tmp, 2);
+ }
+ ddbs_unprj(p_bstrm, &acmod, 3);
+ ddbs_unprj(p_bstrm, &lfeon, 1);
+ numch = chanary[acmod];
+ numch = 2;
+ *ChNum = numch;
+ //ALOGI("DEBUG[%s %d]:numch=%d,sr=%d,frs=%d",__FUNCTION__,__LINE__,*ChNum,*sample_rate,*frame_size);
+ return 0;
+
+}
+
+static DDPerr ddbs_skip(DDP_BSTRM *p_bstrm, DDPshort numbits)
+{
+ p_bstrm->bitptr += numbits;
+ while (p_bstrm->bitptr >= BITSPERWRD)
+ {
+ p_bstrm->buf++;
+ p_bstrm->data = *p_bstrm->buf;
+ p_bstrm->bitptr -= BITSPERWRD;
+ }
+
+ return 0;
+}
+
+static DDPerr ddbs_getbsid(DDP_BSTRM *p_inbstrm, DDPshort *p_bsid)
+{
+ DDP_BSTRM bstrm;
+
+ ddbs_init(p_inbstrm->buf, p_inbstrm->bitptr, &bstrm);
+ ddbs_skip(&bstrm, BS_BITOFFSET);
+ ddbs_unprj(&bstrm, p_bsid, 5);
+ if (!ISDDP(*p_bsid) && !ISDD(*p_bsid))
+ {
+ ALOGI("Unsupported bitstream id");
+ }
+
+ return 0;
+}
+
+static int Get_Parameters(void *buf, int *sample_rate, int *frame_size,int *ChNum)
+ {
+ DDP_BSTRM bstrm={0};
+ DDP_BSTRM *p_bstrm=&bstrm;
+ DDPshort bsid;
+ int chnum = 0;
+ uint8_t ptr8[PTR_HEAD_SIZE];
+
+ memcpy(ptr8, buf, PTR_HEAD_SIZE);
+
+ //ALOGI("LZG->ptr_head:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",
+ // ptr8[0],ptr8[1],ptr8[2], ptr8[3],ptr8[4],ptr8[5] );
+ if ((ptr8[0] == 0x0b) && (ptr8[1] == 0x77)) {
+ int i;
+ uint8_t tmp;
+ for (i = 0; i < PTR_HEAD_SIZE; i += 2) {
+ tmp = ptr8[i];
+ ptr8[i] = ptr8[i + 1];
+ ptr8[i + 1] = tmp;
+ }
+ }
+
+ ddbs_init((short*)ptr8,0,p_bstrm);
+ int ret = ddbs_getbsid(p_bstrm, &bsid);
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (ISDDP(bsid)) {
+ Get_DDP_Parameters(ptr8, sample_rate, frame_size, ChNum);
+ }else if (ISDD(bsid)){
+ Get_DD_Parameters(ptr8, sample_rate, frame_size, ChNum);
+ }
+
+ return 0;
+}
+
+//----------------------------DDP Media Source----------------------------------------------
+
+static pthread_mutex_t decode_dev_op_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int decode_ThreadExitFlag = 0; //0:exit from thread; 1:thread looping
+static int decode_ThreadStopFlag = 1; //0:start; 1: stop
+static pthread_t decode_ThreadID = 0;
+
+DDP_Media_Source::DDP_Media_Source(void) {
+ ALOGI("[%s: %d]\n", __FUNCTION__, __LINE__);
+ mStarted = false;
+ mMeta = new MetaData;
+ mGroup = NULL;
+ mSample_rate = 0;
+ mChNum = 0;
+ mFrame_size = 0;
+ mStop_ReadBuf_Flag = 0; //0:start 1:stop
+}
+
+DDP_Media_Source::~DDP_Media_Source() {
+}
+
+int DDP_Media_Source::GetSampleRate() {
+ ALOGI("[DDP_Media_Source::%s: %d]\n", __FUNCTION__, __LINE__);
+ return mSample_rate;
+}
+int DDP_Media_Source::GetChNum() {
+ ALOGI("[DDP_Media_Source::%s: %d]\n", __FUNCTION__, __LINE__);
+ return mChNum;
+}
+
+int DDP_Media_Source::Get_Stop_ReadBuf_Flag() {
+ return mStop_ReadBuf_Flag;
+}
+
+int DDP_Media_Source::Set_Stop_ReadBuf_Flag(int Stop) {
+ //ALOGI("[DDP_Media_Source::%s: %d]\n",__FUNCTION__,__LINE__);
+ mStop_ReadBuf_Flag = Stop;
+ return 0;
+}
+
+sp<MetaData> DDP_Media_Source::getFormat() {
+ ALOGI("[DDP_Media_Source::%s: %d]\n", __FUNCTION__, __LINE__);
+ return mMeta;
+}
+
+status_t DDP_Media_Source::start(MetaData *params) {
+ ALOGI("[DDP_Media_Source::%s: %d]\n", __FUNCTION__, __LINE__);
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(4096));
+ mStarted = true;
+ return OK;
+}
+
+status_t DDP_Media_Source::stop() {
+ ALOGI("[DDP_Media_Source::%s: %d]\n", __FUNCTION__, __LINE__);
+ delete mGroup;
+ mGroup = NULL;
+ mStarted = false;
+ return OK;
+}
+
+int DDP_Media_Source::MediaSourceRead_buffer(unsigned char *buffer, int size) {
+ int readcnt = -1;
+ int sleep_time = 0;
+ if ((mStop_ReadBuf_Flag == 1) || (decode_ThreadStopFlag == 1)) {
+ ALOGI("[DDP_Media_Source::%s] ddp mediasource stop!\n ", __FUNCTION__);
+ return -1;
+ }
+ while ((readcnt < size) && (mStop_ReadBuf_Flag == 0)
+ && (decode_ThreadStopFlag == 0)) {
+ readcnt = buffer_read(&android_out_buffer, (char*) buffer, size);
+ if (readcnt < 0) {
+ sleep_time++;
+ usleep(1000); //1ms
+ }
+ if (sleep_time > 2000) { //wait for max 1s to get audio data
+ ALOGE("[%s] time out to read audio buffer data! wait for 2s\n ",
+ __FUNCTION__);
+ return -1;
+ }
+ }
+ return readcnt;
+}
+
+status_t DDP_Media_Source::read(MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+ unsigned char ptr_head[PTR_HEAD_SIZE] = { 0 };
+ int readedbytes;
+ int SyncFlag = 0;
+
+ resync: mFrame_size = 0;
+ SyncFlag = 0;
+
+ if ((mStop_ReadBuf_Flag == 1) || (decode_ThreadStopFlag == 1)) {
+ ALOGI("Stop Flag is set, stop read_buf [%s %d]", __FUNCTION__,
+ __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+
+ if (MediaSourceRead_buffer(&ptr_head[0], 6) < 6) {
+ readedbytes = 6;
+ ALOGI("WARNING:read %d bytes failed [%s %d]!\n", readedbytes,
+ __FUNCTION__, __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+
+ if ((mStop_ReadBuf_Flag == 1) || (decode_ThreadStopFlag == 1)) {
+ ALOGI("Stop Flag is set, stop read_buf [%s %d]", __FUNCTION__,
+ __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+
+ while (!SyncFlag) {
+ int i;
+ for (i = 0; i <= 4; i++) {
+ if ((ptr_head[i] == 0x0b && ptr_head[i + 1] == 0x77)
+ || (ptr_head[i] == 0x77 && ptr_head[i + 1] == 0x0b)) {
+ memcpy(&ptr_head[0], &ptr_head[i], 6 - i);
+ if (MediaSourceRead_buffer(&ptr_head[6 - i], i) < i) {
+ readedbytes = i;
+ ALOGI("WARNING: read %d bytes failed [%s %d]!\n",
+ readedbytes, __FUNCTION__, __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+
+ if ((mStop_ReadBuf_Flag == 1) || (decode_ThreadStopFlag == 1)) {
+ ALOGI("Stop Flag is set, stop read_buf [%s %d]",
+ __FUNCTION__, __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+ SyncFlag = 1;
+ break;
+ }
+ }
+
+ if (SyncFlag == 0) {
+ ptr_head[0] = ptr_head[5];
+ if (MediaSourceRead_buffer(&ptr_head[1], 5) < 5) {
+ readedbytes = 5;
+ ALOGI("WARNING: fpread_buffer read %d bytes failed [%s %d]!\n",
+ readedbytes, __FUNCTION__, __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+
+ if ((mStop_ReadBuf_Flag == 1) || (decode_ThreadStopFlag == 1)) {
+ ALOGI("Stop Flag is set, stop read_buf [%s %d]", __FUNCTION__,
+ __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+ }
+ }
+ if (MediaSourceRead_buffer(&ptr_head[6], PTR_HEAD_SIZE - 6)
+ < (PTR_HEAD_SIZE - 6)) {
+ readedbytes = PTR_HEAD_SIZE - 6;
+ ALOGI("WARNING: fpread_buffer read %d bytes failed [%s %d]!\n",
+ readedbytes, __FUNCTION__, __LINE__);
+ return ERROR_END_OF_STREAM;
+ }
+
+ Get_Parameters(ptr_head, &mSample_rate, &mFrame_size, &mChNum);
+ if ((mFrame_size == 0) || (mFrame_size < PTR_HEAD_SIZE) || (mChNum == 0)
+ || (mSample_rate == 0)) {
+ goto resync;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+ memcpy((unsigned char*) (buffer->data()), ptr_head, PTR_HEAD_SIZE);
+ if (MediaSourceRead_buffer(
+ (unsigned char*) (buffer->data()) + PTR_HEAD_SIZE,
+ mFrame_size - PTR_HEAD_SIZE) != (mFrame_size - PTR_HEAD_SIZE)) {
+ ALOGI("[%s %d]stream read failed:bytes_req/%d\n", __FUNCTION__,
+ __LINE__, (mFrame_size - PTR_HEAD_SIZE));
+ buffer->release();
+ buffer = NULL;
+ return ERROR_END_OF_STREAM;
+ }
+
+ buffer->set_range(0, mFrame_size);
+ buffer->meta_data()->setInt64(kKeyTime, 0);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+
+ *out = buffer;
+ return OK;
+}
+
+//-------------------------------OMX codec------------------------------------------------
+
+const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";
+Aml_OMX_Codec::Aml_OMX_Codec(void) {
+ ALOGI("[Aml_OMX_Codec::%s: %d]\n", __FUNCTION__, __LINE__);
+ m_codec = NULL;
+ status_t m_OMXClientConnectStatus = m_OMXClient.connect();
+ lock_init();
+ locked();
+ buf_decode_offset = 0;
+ buf_decode_offset_pre = 0;
+
+ if (m_OMXClientConnectStatus != OK) {
+ ALOGE("Err:omx client connect error\n");
+ } else {
+ const char *mine_type = NULL;
+ mine_type = MEDIA_MIMETYPE_AUDIO_AC3;
+ m_OMXMediaSource = new DDP_Media_Source();
+ sp < MetaData > metadata = m_OMXMediaSource->getFormat();
+ metadata->setCString(kKeyMIMEType, mine_type);
+ m_codec = OMXCodec::Create(m_OMXClient.interface(), metadata, false, // createEncoder
+ m_OMXMediaSource, 0, 0);
+
+ if (m_codec != NULL) {
+ ALOGI("OMXCodec::Create success %s %d \n", __FUNCTION__, __LINE__);
+ } else {
+ ALOGE("Err: OMXCodec::Create failed %s %d \n", __FUNCTION__,
+ __LINE__);
+ }
+ }
+ unlocked();
+}
+
+Aml_OMX_Codec::~Aml_OMX_Codec() {
+}
+
+status_t Aml_OMX_Codec::read(unsigned char *buf, unsigned *size, int *exit) {
+ MediaBuffer *srcBuffer;
+ status_t status;
+
+ m_OMXMediaSource->Set_Stop_ReadBuf_Flag(*exit);
+
+ if (*exit) {
+ ALOGI("NOTE:exit flag enabled! [%s %d] \n", __FUNCTION__, __LINE__);
+ *size = 0;
+ return OK;
+ }
+
+ status = m_codec->read(&srcBuffer, NULL);
+
+ if (srcBuffer == NULL) {
+ *size = 0;
+ return OK;
+ }
+
+ *size = srcBuffer->range_length();
+
+ if (status == OK && (*size != 0)) {
+ memcpy((unsigned char *) buf,
+ (unsigned char *) srcBuffer->data() + srcBuffer->range_offset(),
+ *size);
+ srcBuffer->set_range(srcBuffer->range_offset() + (*size),
+ srcBuffer->range_length() - (*size));
+ srcBuffer->meta_data()->findInt64(kKeyTime, &buf_decode_offset);
+ }
+
+ if (srcBuffer->range_length() == 0) {
+ srcBuffer->release();
+ srcBuffer = NULL;
+ }
+
+ return OK;
+}
+
+status_t Aml_OMX_Codec::start() {
+ ALOGI("[Aml_OMX_Codec::%s %d] enter!\n", __FUNCTION__, __LINE__);
+ status_t status = m_codec->start();
+ if (status != OK) {
+ ALOGE("Err:OMX client can't start OMX decoder! status=%d (0x%08x)\n",
+ (int) status, (int) status);
+ m_codec.clear();
+ }
+ return status;
+}
+
+void Aml_OMX_Codec::stop() {
+ ALOGI("[Aml_OMX_Codec::%s %d] enter!\n", __FUNCTION__, __LINE__);
+ if (m_codec != NULL) {
+ if (m_OMXMediaSource->Get_Stop_ReadBuf_Flag())
+ m_OMXMediaSource->Set_Stop_ReadBuf_Flag(1);
+ m_codec->pause();
+ m_codec->stop();
+ wp < MediaSource > tmp = m_codec;
+ m_codec.clear();
+ while (tmp.promote() != NULL) {
+ ALOGI("[Aml_OMX_Codec::%s %d]wait m_codec free OK!\n", __FUNCTION__,
+ __LINE__);
+ usleep(1000);
+ }
+ m_OMXClient.disconnect();
+ m_OMXMediaSource.clear();
+ } else
+ ALOGE("m_codec==NULL, m_codec->stop() failed! [%s %d] \n", __FUNCTION__,
+ __LINE__);
+}
+
+void Aml_OMX_Codec::pause() {
+ ALOGI("[Aml_OMX_Codec::%s %d] \n", __FUNCTION__, __LINE__);
+ if (m_codec != NULL)
+ m_codec->pause();
+ else
+ ALOGE("m_codec==NULL, m_codec->pause() failed! [%s %d] \n",
+ __FUNCTION__, __LINE__);
+}
+
+int Aml_OMX_Codec::GetDecBytes() {
+ int used_len = 0;
+ used_len = buf_decode_offset - buf_decode_offset_pre;
+ buf_decode_offset_pre = buf_decode_offset;
+ return used_len;
+}
+
+void Aml_OMX_Codec::lock_init() {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&lock, &attr);
+ pthread_mutexattr_destroy(&attr);
+}
+void Aml_OMX_Codec::locked() {
+ pthread_mutex_lock (&lock);
+}
+void Aml_OMX_Codec::unlocked() {
+ pthread_mutex_unlock (&lock);
+}
+
+//--------------------------------OMX_Codec_local API-------------------------------------------------
+
+Aml_OMX_Codec *arm_omx_codec = NULL;
+
+void omx_codec_pause() {
+ if (arm_omx_codec != NULL) {
+ arm_omx_codec->locked();
+ arm_omx_codec->pause();
+ arm_omx_codec->unlocked();
+ } else
+ ALOGE("arm_omx_codec==NULL arm_omx_codec->pause failed! %s %d \n",
+ __FUNCTION__, __LINE__);
+}
+
+void omx_codec_read(unsigned char *buf, unsigned *size, int *exit) {
+ if (arm_omx_codec != NULL) {
+ arm_omx_codec->locked();
+ arm_omx_codec->read(buf, size, exit);
+ arm_omx_codec->unlocked();
+ } else
+ ALOGE("arm_omx_codec==NULL arm_omx_codec->read failed! %s %d \n",
+ __FUNCTION__, __LINE__);
+}
+
+int omx_codec_get_declen() {
+ int declen = 0;
+ if (arm_omx_codec != NULL) {
+ arm_omx_codec->locked();
+ declen = arm_omx_codec->GetDecBytes();
+ arm_omx_codec->unlocked();
+ } else {
+ ALOGI(
+ "NOTE:arm_omx_codec==NULL arm_omx_codec_get_declen() return 0! %s %d \n",
+ __FUNCTION__, __LINE__);
+ }
+ return declen;
+}
+
+int omx_codec_get_FS() {
+ if (arm_omx_codec != NULL) {
+ return arm_omx_codec->m_OMXMediaSource->GetSampleRate();
+
+ } else {
+ ALOGI(
+ "NOTE:arm_omx_codec==NULL arm_omx_codec_get_FS() return 0! %s %d \n",
+ __FUNCTION__, __LINE__);
+ return 0;
+ }
+}
+
+int omx_codec_get_Nch() {
+ if (arm_omx_codec != NULL) {
+ return arm_omx_codec->m_OMXMediaSource->GetChNum();
+ } else {
+ ALOGI(
+ "NOTE:arm_omx_codec==NULL arm_omx_codec_get_Nch() return 0! %s %d \n",
+ __FUNCTION__, __LINE__);
+ return 0;
+ }
+}
+
+//--------------------------------------Decoder ThreadLoop--------------------------------------------
+
+void *decode_threadloop(void *args) {
+ unsigned int outlen = 0;
+ int write_sucessed = 1;
+ int ret = 0;
+ unsigned char tmp[8192];
+
+ ALOGI("[%s %d] enter!\n", __FUNCTION__, __LINE__);
+ while (decode_ThreadStopFlag == 0) {
+ if (write_sucessed == 1) {
+ outlen = 0;
+ omx_codec_read(&tmp[0], &outlen, &(decode_ThreadStopFlag));
+ }
+ if (decode_ThreadStopFlag == 1) {
+ ALOGD("%s, exit threadloop! \n", __FUNCTION__);
+ break;
+ }
+ if (outlen > 0) {
+ ret = buffer_write(&DDP_out_buffer, (char *) (&tmp[0]), outlen);
+ if (ret < 0) {
+ write_sucessed = 0;
+ usleep(10 * 1000); //10ms
+ } else {
+ write_sucessed = 1;
+ }
+ }
+ }
+
+ decode_ThreadExitFlag = 0;
+ ALOGD("%s, exiting...\n", __FUNCTION__);
+ return NULL;
+}
+
+static int start_decode_thread_omx(void) {
+ pthread_attr_t attr;
+ struct sched_param param;
+ int ret = 0;
+
+ ALOGI("[%s %d] enter!\n", __FUNCTION__, __LINE__);
+ pthread_mutex_lock(&decode_dev_op_mutex);
+ pthread_attr_init(&attr);
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ param.sched_priority = sched_get_priority_max(SCHED_RR);
+ pthread_attr_setschedparam(&attr, &param);
+ decode_ThreadStopFlag = 0;
+ decode_ThreadExitFlag = 1;
+ ret = pthread_create(&decode_ThreadID, &attr, &decode_threadloop, NULL);
+ pthread_attr_destroy(&attr);
+ if (ret != 0) {
+ ALOGE("%s, Create thread fail!\n", __FUNCTION__);
+ pthread_mutex_unlock(&decode_dev_op_mutex);
+ return -1;
+ }
+ pthread_mutex_unlock(&decode_dev_op_mutex);
+ ALOGD("[%s] exiting...\n", __FUNCTION__);
+ return 0;
+}
+
+static int stop_decode_thread_omx(void) {
+ int i = 0, tmp_timeout_count = 1000;
+
+ ALOGI("[%s %d] enter!\n", __FUNCTION__, __LINE__);
+ pthread_mutex_lock(&decode_dev_op_mutex);
+
+ decode_ThreadStopFlag = 1;
+ while (1) {
+ if (decode_ThreadExitFlag == 0)
+ break;
+ if (i >= tmp_timeout_count)
+ break;
+ i++;
+ usleep(1000);
+ }
+ if (i >= tmp_timeout_count) {
+ ALOGE(
+ "%s, Timeout: we have try %d ms, but the aml audio thread's exec flag is still(%d)!!!\n",
+ __FUNCTION__, tmp_timeout_count, decode_ThreadExitFlag);
+ } else {
+ ALOGD("%s, kill decode thread success after try %d ms.\n", __FUNCTION__,
+ i);
+ }
+
+ pthread_join(decode_ThreadID, NULL);
+ decode_ThreadID = 0;
+
+ ALOGD("%s, aml audio close success.\n", __FUNCTION__);
+ pthread_mutex_unlock(&decode_dev_op_mutex);
+ return 0;
+}
+
+//-------------------------------------external OMX_codec_api-----------------------------------------
+extern "C" {
+int omx_codec_init(void) {
+ int ret = 0;
+ ALOGI("omx_codec_init!\n");
+ arm_omx_codec = new android::Aml_OMX_Codec();
+ if (arm_omx_codec == NULL) {
+ ALOGE("Err:arm_omx_codec_init failed!\n");
+ return -1;
+ }
+
+ arm_omx_codec->locked();
+ ret = arm_omx_codec->start();
+ arm_omx_codec->unlocked();
+ if (ret < 0) {
+ goto Exit;
+ }
+
+ ret = start_decode_thread_omx();
+ if (ret == 0)
+ return 0;
+ Exit: arm_omx_codec->stop();
+ delete arm_omx_codec;
+ arm_omx_codec = NULL;
+ return -1;
+}
+
+void omx_codec_close(void) {
+ int ret = 0;
+ if (arm_omx_codec == NULL) {
+ ALOGI(
+ "NOTE:arm_omx_codec==NULL arm_omx_codec_close() do nothing! %s %d \n",
+ __FUNCTION__, __LINE__);
+ return;
+ }
+ ALOGI("omx_codec_close!\n");
+ stop_decode_thread_omx();
+ arm_omx_codec->locked();
+ arm_omx_codec->stop();
+ arm_omx_codec->unlocked();
+ delete arm_omx_codec;
+ arm_omx_codec = NULL;
+ return;
+}
+
+}
+}
+
diff --git a/libTVaudio/audio/DDP_media_source.h b/libTVaudio/audio/DDP_media_source.h
new file mode 100644
index 0000000..8df117d
--- a/dev/null
+++ b/libTVaudio/audio/DDP_media_source.h
@@ -0,0 +1,143 @@
+#ifndef __DDP_MEDIA_SOURCE_H__
+#define __DDP_MEDIA_SOURCE_H__
+
+#include "MediaSource.h"
+#include "DataSource.h"
+#include "MediaBufferGroup.h"
+#include "MetaData.h"
+#include "OMXCodec.h"
+#include "OMX_Index.h"
+#include "OMX_Core.h"
+#include "OMXClient.h"
+
+namespace android {
+
+#define DDPshort short
+#define DDPerr short
+#define DDPushort unsigned short
+#define BYTESPERWRD 2
+#define BITSPERWRD (BYTESPERWRD*8)
+#define SYNCWRD ((DDPshort)0x0b77)
+#define MAXFSCOD 3
+#define MAXDDDATARATE 38
+#define BS_STD 8
+#define ISDD(bsid) ((bsid) <= BS_STD)
+#define MAXCHANCFGS 8
+#define BS_AXE 16
+#define ISDDP(bsid) ((bsid) <= BS_AXE && (bsid) > 10)
+#define BS_BITOFFSET 40
+#define PTR_HEAD_SIZE 7//20
+
+
+typedef struct {
+ DDPshort *buf;
+ DDPshort bitptr;
+ DDPshort data;
+} DDP_BSTRM;
+
+const DDPshort chanary[MAXCHANCFGS] = { 2, 1, 2, 3, 3, 4, 4, 5 };
+enum {
+ MODE11 = 0,
+ MODE_RSVD = 0,
+ MODE10,
+ MODE20,
+ MODE30,
+ MODE21,
+ MODE31,
+ MODE22,
+ MODE32
+};
+const DDPushort msktab[] = { 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800,
+ 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc,
+ 0xfffe, 0xffff };
+const DDPshort frmsizetab[MAXFSCOD][MAXDDDATARATE] = {
+ /* 48kHz */
+ {
+ 64, 64, 80, 80, 96, 96, 112, 112,
+ 128, 128, 160, 160, 192, 192, 224, 224,
+ 256, 256, 320, 320, 384, 384, 448, 448,
+ 512, 512, 640, 640, 768, 768, 896, 896,
+ 1024, 1024, 1152, 1152, 1280, 1280
+ },
+ /* 44.1kHz */
+ {
+ 69, 70, 87, 88, 104, 105, 121, 122,
+ 139, 140, 174, 175, 208, 209, 243, 244,
+ 278, 279, 348, 349, 417, 418, 487, 488,
+ 557, 558, 696, 697, 835, 836, 975, 976,
+ 1114, 1115, 1253, 1254, 1393, 1394
+ },
+ /* 32kHz */
+ {
+ 96, 96, 120, 120, 144, 144, 168, 168,
+ 192, 192, 240, 240, 288, 288, 336, 336,
+ 384, 384, 480, 480, 576, 576, 672, 672,
+ 768, 768, 960, 960, 1152, 1152, 1344, 1344,
+ 1536, 1536, 1728, 1728, 1920, 1920
+ }
+};
+
+//--------------------------------------------------------------------------------
+class DDP_Media_Source: public MediaSource {
+public:
+ DDP_Media_Source(void);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+ virtual status_t read(MediaBuffer **buffer, const ReadOptions *options =
+ NULL);
+
+ virtual int GetSampleRate();
+ virtual int GetChNum();
+
+ virtual int Get_Stop_ReadBuf_Flag();
+ virtual int Set_Stop_ReadBuf_Flag(int StopFlag);
+ virtual int MediaSourceRead_buffer(unsigned char *buffer, int size);
+
+protected:
+ virtual ~DDP_Media_Source();
+
+private:
+
+ bool mStarted;
+ sp<MetaData> mMeta;
+ MediaBufferGroup *mGroup;
+ int mSample_rate;
+ int mChNum;
+ int mFrame_size;
+ int mStop_ReadBuf_Flag;
+
+ DDP_Media_Source(const DDP_Media_Source &);
+ DDP_Media_Source &operator=(const DDP_Media_Source &);
+};
+
+//----------------------------------------------------------------------------------
+class Aml_OMX_Codec {
+public:
+
+ Aml_OMX_Codec(void);
+
+ OMXClient m_OMXClient;
+ sp<DDP_Media_Source> m_OMXMediaSource;
+ sp<MediaSource> m_codec;
+
+ int read(unsigned char *buf, unsigned *size, int* exit);
+ status_t start();
+ void pause();
+ void stop();
+ void lock_init();
+ void locked();
+ void unlocked();
+ int GetDecBytes();
+
+ int64_t buf_decode_offset;
+ int64_t buf_decode_offset_pre;
+ pthread_mutex_t lock;
+
+ ~Aml_OMX_Codec();
+};
+
+}
+
+#endif
diff --git a/libTVaudio/audio/amaudio_main.cpp b/libTVaudio/audio/amaudio_main.cpp
new file mode 100644
index 0000000..f236820
--- a/dev/null
+++ b/libTVaudio/audio/amaudio_main.cpp
@@ -0,0 +1,74 @@
+/*
+ This file is used for testing audio fuction.
+ */
+
+#include <unistd.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
+#include "../audio_amaudio.h"
+#include "audio_usb_check.h"
+
+using namespace android;
+
+int main(int argc, char** argv) {
+ sp < ProcessState > proc(ProcessState::self());
+ sp < IServiceManager > sm = defaultServiceManager();
+
+ //test for audio volume control
+ amAudioSetAndroidVolumeEnable(1);
+ amAudioSetAndroidVolume(60, 60);
+ sleep(10);
+
+ //test for S805 HDMI_IN BOX
+ amAudioOpen(48000, CC_IN_USE_SPDIF_DEVICE, CC_OUT_USE_AMAUDIO);
+ amAudioOpen(48000, CC_IN_USE_SPDIF_DEVICE, CC_OUT_USE_ANDROID);
+ sleep(100);
+
+ //test for TV
+ amAudioOpen(48000, CC_IN_USE_I2S_DEVICE, CC_OUT_USE_AMAUDIO);
+ amAudioOpen(48000, CC_IN_USE_I2S_DEVICE, CC_OUT_USE_ANDROID);
+ sleep(100);
+
+ //test for data mix mode and mix volume
+ sleep(10);
+ amAudioSetOutputMode(2);
+ amAudioSetMusicGain(60);
+ sleep(10);
+ amAudioSetMusicGain(256);
+ sleep(10);
+ amAudioSetAndroidVolumeEnable(0);
+ sleep(10);
+ amAudioSetOutputMode(0);
+ amAudioSetLeftGain(256);
+ amAudioSetRightGain(256);
+
+ //test for audio effect
+ sleep(30);
+ //EQ parameters
+ int gain_val_buf[5] = { 3, 2, 0, 2, 3 };
+ amAudioSetEQGain(gain_val_buf, sizeof(gain_val_buf));
+ amAudioSetEQEnable(1);
+ sleep(30);
+
+ //srs parameters
+ amAudioSetSRSTrubassSpeakerSize(4);
+ amAudioSetSRSTrubassGain(0.3);
+ amAudioSetSRSDialogClarityGain(0.2);
+ amAudioSetSRSDefinitionGain(0.5);
+ amAudioSetSRSSurroundGain(0.6);
+ amAudioSetSRSDialogClaritySwitch(1);
+ amAudioSetSRSSurroundSwitch(1);
+ amAudioSetSRSTrubassSwitch(1);
+
+ sleep(500);
+
+ amAudioClose();
+
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+
+ return 0;
+}
diff --git a/libTVaudio/audio/aml_audio.c b/libTVaudio/audio/aml_audio.c
new file mode 100644
index 0000000..4791eec
--- a/dev/null
+++ b/libTVaudio/audio/aml_audio.c
@@ -0,0 +1,1864 @@
+/*
+ ** aml_audio.c
+ **
+ ** This program is designed for TV application.
+ ** author: Wang Zhe
+ ** Email: Zhe.Wang@amlogic.com
+ **
+ */
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <math.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include "tinyalsa/asoundlib.h"
+
+#include "android_out.h"
+#include "aml_audio.h"
+
+#define LOG_TAG "aml_audio"
+
+#define ANDROID_OUT_BUFFER_SIZE (2048*8*2)//in byte
+#define DDP_OUT_BUFFER_SIZE (2048*8*2)//in byte
+#define DEFAULT_OUT_SAMPLE_RATE (48000)
+#define DEFAULT_IN_SAMPLE_RATE (48000)
+#define PLAYBACK_PERIOD_SIZE (512)
+#define CAPTURE_PERIOD_SIZE (512)
+#define PLAYBACK_PERIOD_COUNT (4)
+#define CAPTURE_PERIOD_COUNT (4)
+#define TEMP_BUFFER_SIZE (PLAYBACK_PERIOD_SIZE * 4 * 3)
+//output device ID from audio.h
+#define AUDIO_DEVICE_OUT_SPEAKER (0x2)
+#define AUDIO_DEVICE_OUT_REMOTE_SUBMIX (0x8000)
+
+static struct pcm_config pcm_config_out = {
+ .channels = 2,
+ .rate = DEFAULT_OUT_SAMPLE_RATE,
+ .period_size = PLAYBACK_PERIOD_SIZE,
+ .period_count = PLAYBACK_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .stop_threshold = PLAYBACK_PERIOD_SIZE*PLAYBACK_PERIOD_COUNT,
+};
+
+static struct pcm_config pcm_config_in = {
+ .channels = 2,
+ .rate = DEFAULT_IN_SAMPLE_RATE,
+ .period_size = CAPTURE_PERIOD_SIZE,
+ .period_count = CAPTURE_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .stop_threshold = CAPTURE_PERIOD_SIZE*CAPTURE_PERIOD_COUNT*10,
+};
+
+struct buffer_status {
+ short *start_add;
+ int size;
+ int level;
+ unsigned int rd;
+ unsigned int wr;
+};
+
+struct resample_para {
+ unsigned int FractionStep;
+ unsigned int SampleFraction;
+ short lastsample_left;
+ short lastsample_right;
+};
+
+struct aml_stream_in {
+ pthread_mutex_t lock;
+ struct pcm_config config;
+ struct pcm *pcm;
+ int card;
+ int device;
+ int standby;
+ int resample_request;
+ void *resample_temp_buffer;
+ struct resample_para resample;
+ int max_bytes;
+ void *temp_buffer;
+ void *write_buffer;
+};
+
+struct aml_stream_out {
+ pthread_mutex_t lock;
+ struct pcm_config config;
+ struct pcm *pcm;
+ int card;
+ int device;
+ int standby;
+ int max_bytes;
+ void *temp_buffer;
+ void *read_buffer;
+ int output_device;
+ int amAudio_OutHandle;
+ struct buffer_status playback_buf;
+ struct buffer_status read_buf;
+ int amaudio_out_read_enable;
+ int user_set_device;
+};
+
+struct aml_dev {
+ struct aml_stream_in in;
+ struct aml_stream_out out;
+ pthread_t aml_Audio_ThreadID;
+ int aml_Audio_ThreadTurnOnFlag;
+ int aml_Audio_ThreadExecFlag;
+ int has_EQ_lib;
+ int has_SRS_lib;
+ int output_deviceID;
+};
+
+static void *start_temp_buffer = NULL;
+
+static struct aml_dev gmAmlDevice = {
+ .in = {
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .config = {
+ .channels = 2,
+ .rate = DEFAULT_IN_SAMPLE_RATE,
+ .period_size = CAPTURE_PERIOD_SIZE,
+ .period_count = CAPTURE_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .stop_threshold = CAPTURE_PERIOD_SIZE*CAPTURE_PERIOD_COUNT*10,
+ },
+ .pcm = NULL,
+ .card = 0,
+ .device = 0,
+ .standby = 0,
+ .resample_request = 0,
+ .resample_temp_buffer = NULL,
+ .resample = {
+ .FractionStep = 0,
+ .SampleFraction = 0,
+ .lastsample_left = 0,
+ .lastsample_right = 0,
+ },
+ .max_bytes = 0,
+ .temp_buffer = NULL,
+ .write_buffer = NULL,
+ },
+
+ .out = {
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .config = {
+ .channels = 2,
+ .rate = DEFAULT_OUT_SAMPLE_RATE,
+ .period_size = PLAYBACK_PERIOD_SIZE,
+ .period_count = PLAYBACK_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .stop_threshold = PLAYBACK_PERIOD_SIZE*PLAYBACK_PERIOD_COUNT,
+ },
+ .pcm = NULL,
+ .card = 0,
+ .device = 0,
+ .standby = 0,
+ .max_bytes = 0,
+ .temp_buffer = NULL,
+ .read_buffer = NULL,
+ .output_device = 0,
+ .amAudio_OutHandle = 0,
+ .playback_buf = {
+ .start_add = NULL,
+ .size = 0,
+ .level = 0,
+ .rd = 0,
+ .wr = 0,
+ },
+ .read_buf = {
+ .start_add = NULL,
+ .size = 0,
+ .level = 0,
+ .rd = 0,
+ .wr = 0,
+ },
+ .amaudio_out_read_enable = 0,
+ .user_set_device = 0,
+ },
+
+ .aml_Audio_ThreadID = 0,
+ .aml_Audio_ThreadTurnOnFlag = 0,
+ .aml_Audio_ThreadExecFlag = 0,
+ .has_EQ_lib = 0,
+ .has_SRS_lib = 0,
+ .output_deviceID = 0,
+};
+
+struct circle_buffer android_out_buffer = {
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .start_add = NULL,
+ .rd = NULL,
+ .wr = NULL,
+ .size = 0,
+};
+
+struct circle_buffer DDP_out_buffer = {
+ .lock = PTHREAD_MUTEX_INITIALIZER,
+ .start_add = NULL,
+ .rd = NULL,
+ .wr = NULL,
+ .size = 0,
+};
+
+static struct aml_dev *gpAmlDevice = NULL;
+static pthread_mutex_t amaudio_dev_op_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+extern int omx_codec_init(void);
+extern void omx_codec_close(void);
+extern int I2S_state;
+
+#define PCM_DATA 0
+#define RAW_DATA 1
+#define HDMI_IN_AUDIO_TYPE "HDMI Audio Type"
+#define SPDIF_IN_AUDIO_TYPE "SPDIFIN Audio Type"
+#define Audio_In_Source_TYPE "Audio In Source"
+#define AMAUDIO_IN "/dev/amaudio2_in"
+#define AMAUDIO_OUT "/dev/amaudio2_out"
+#define AMAUDIO2_PREENABLE "/sys/class/amaudio2/aml_amaudio2_enable"
+
+#define AMAUDIO_IOC_MAGIC 'A'
+#define AMAUDIO_IOC_GET_SIZE _IOW(AMAUDIO_IOC_MAGIC, 0x00, int)
+#define AMAUDIO_IOC_GET_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x01, int)
+#define AMAUDIO_IOC_RESET _IOW(AMAUDIO_IOC_MAGIC, 0x02, int)
+#define AMAUDIO_IOC_UPDATE_APP_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x03, int)
+#define AMAUDIO_IOC_AUDIO_OUT_MODE _IOW(AMAUDIO_IOC_MAGIC, 0x04, int)
+#define AMAUDIO_IOC_MIC_LEFT_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x05, int)
+#define AMAUDIO_IOC_MIC_RIGHT_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x06, int)
+#define AMAUDIO_IOC_MUSIC_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x07, int)
+#define AMAUDIO_IOC_GET_PTR_READ _IOW(AMAUDIO_IOC_MAGIC, 0x08, int)
+#define AMAUDIO_IOC_UPDATE_APP_PTR_READ _IOW(AMAUDIO_IOC_MAGIC, 0x09, int)
+#define AMAUDIO_IOC_OUT_READ_ENABLE _IOW(AMAUDIO_IOC_MAGIC, 0x0a, int)
+#define AMAUDIO_IOC_SET_ANDROID_VOLUME_ENABLE _IOW(AMAUDIO_IOC_MAGIC, 0x0b, int)
+#define AMAUDIO_IOC_SET_ANDROID_LEFT_VOLUME _IOW(AMAUDIO_IOC_MAGIC, 0x0c, int)
+#define AMAUDIO_IOC_SET_ANDROID_RIGHT_VOLUME _IOW(AMAUDIO_IOC_MAGIC, 0x0d, int)
+
+#define CC_DUMP_SRC_TYPE_INPUT (0)
+#define CC_DUMP_SRC_TYPE_OUTPUT (1)
+#define CC_DUMP_SRC_TYPE_IN_OUT (2)
+#define CC_DUMP_SRC_TYPE_OUT_IN (3)
+
+static int amaudio2_out_handle = -1;
+static int gDumpDataFlag = 0;
+static int gDumpDataFd1 = -1;
+static int gDumpDataFd2 = -1;
+static int audioin_type = 0;
+static int omx_started = 0;
+static int raw_data_counter = 0;
+int output_record_enable = 0;
+pthread_mutex_t device_change_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void DoDumpData(void *data_buf, int size, int aud_src_type);
+
+inline int GetWriteSpace(char *WritePoint, char *ReadPoint, int buffer_size) {
+ int bytes;
+
+ if (WritePoint >= ReadPoint) {
+ bytes = buffer_size - (WritePoint - ReadPoint);
+ } else {
+ bytes = ReadPoint - WritePoint;
+ }
+ return bytes;
+}
+
+inline int GetReadSpace(char *WritePoint, char *ReadPoint, int buffer_size) {
+ int bytes;
+
+ if (WritePoint >= ReadPoint) {
+ bytes = WritePoint - ReadPoint;
+ } else {
+ bytes = buffer_size - (ReadPoint - WritePoint);
+ }
+ return bytes;
+}
+
+inline int write_to_buffer(char *current_pointer, char *buffer, int bytes,
+ char *start_buffer, int buffer_size) {
+ int left_bytes = start_buffer + buffer_size - current_pointer;
+
+ if (left_bytes >= bytes) {
+ memcpy(current_pointer, buffer, bytes);
+ } else {
+ memcpy(current_pointer, buffer, left_bytes);
+ memcpy(start_buffer, buffer + left_bytes, bytes - left_bytes);
+ }
+ return 0;
+}
+
+inline int read_from_buffer(char *current_pointer, char *buffer, int bytes,
+ char *start_buffer, int buffer_size) {
+ int left_bytes = start_buffer + buffer_size - current_pointer;
+
+ if (left_bytes >= bytes) {
+ memcpy(buffer, current_pointer, bytes);
+ } else {
+ memcpy(buffer, current_pointer, left_bytes);
+ memcpy(buffer + left_bytes, start_buffer, bytes - left_bytes);
+ }
+ return 0;
+}
+
+inline void* update_pointer(char *current_pointer, int bytes,
+ char *start_buffer, int buffer_size) {
+ current_pointer += bytes;
+ if (current_pointer >= start_buffer + buffer_size) {
+ current_pointer -= buffer_size;
+ }
+ return current_pointer;
+}
+
+//Clip from 16.16 fixed-point to 0.15 fixed-point.
+inline static short clip(int x) {
+ if (x < -32768) {
+ return -32768;
+ } else if (x > 32767) {
+ return 32767;
+ } else {
+ return x;
+ }
+}
+
+static int resampler_init(struct aml_stream_in *in) {
+ ALOGD("%s, Init Resampler!\n", __FUNCTION__);
+
+ static const double kPhaseMultiplier = 1L << 28;
+
+ in->resample.FractionStep = (unsigned int) (in->config.rate
+ * kPhaseMultiplier / pcm_config_in.rate);
+ in->resample.SampleFraction = 0;
+
+ size_t buffer_size = in->config.period_size * 4;
+ in->resample_temp_buffer = malloc(buffer_size);
+ if (in->resample_temp_buffer == NULL) {
+ ALOGE("%s, Malloc resample buffer failed!\n", __FUNCTION__);
+ return -1;
+ }
+ in->max_bytes = (in->config.period_size * pcm_config_in.rate
+ / in->config.rate + 1) << 2;
+ return 0;
+}
+
+static int resample_process(struct aml_stream_in *in, unsigned int in_frame,
+ short* input, short* output) {
+ unsigned int inputIndex = 0;
+ unsigned int outputIndex = 0;
+ unsigned int FractionStep = in->resample.FractionStep;
+
+ static const uint32_t kPhaseMask = (1LU << 28) - 1;
+ unsigned int frac = in->resample.SampleFraction;
+ short lastsample_left = in->resample.lastsample_left;
+ short lastsample_right = in->resample.lastsample_right;
+
+ while (inputIndex == 0) {
+ *output++ = clip(
+ (int) lastsample_left
+ + ((((int) input[0] - (int) lastsample_left)
+ * ((int) frac >> 13)) >> 15));
+ *output++ = clip(
+ (int) lastsample_right
+ + ((((int) input[1] - (int) lastsample_right)
+ * ((int) frac >> 13)) >> 15));
+
+ frac += FractionStep;
+ inputIndex += (frac >> 28);
+ frac = (frac & kPhaseMask);
+ outputIndex++;
+ }
+
+ while (inputIndex < in_frame) {
+ *output++ = clip(
+ (int) input[2 * inputIndex - 2]
+ + ((((int) input[2 * inputIndex]
+ - (int) input[2 * inputIndex - 2])
+ * ((int) frac >> 13)) >> 15));
+ *output++ = clip(
+ (int) input[2 * inputIndex - 1]
+ + ((((int) input[2 * inputIndex + 1]
+ - (int) input[2 * inputIndex - 1])
+ * ((int) frac >> 13)) >> 15));
+
+ frac += FractionStep;
+ inputIndex += (frac >> 28);
+ frac = (frac & kPhaseMask);
+ outputIndex++;
+ }
+
+ in->resample.lastsample_left = input[2 * in_frame - 2];
+ in->resample.lastsample_right = input[2 * in_frame - 1];
+ in->resample.SampleFraction = frac;
+
+ return outputIndex;
+}
+
+static int tmp_buffer_init(struct circle_buffer *tmp, int buffer_size) {
+ struct circle_buffer *buf = tmp;
+ pthread_mutex_lock(&buf->lock);
+
+ buf->size = buffer_size;
+ buf->start_add = malloc(buffer_size * sizeof(char));
+ if (buf->start_add == NULL) {
+ ALOGD("%s, Malloc android out buffer error!\n", __FUNCTION__);
+ pthread_mutex_unlock(&buf->lock);
+ return -1;
+ }
+ buf->rd = buf->start_add;
+ buf->wr = buf->start_add + buf->size / 2;
+
+ pthread_mutex_unlock(&buf->lock);
+ return 0;
+}
+
+static int tmp_buffer_release(struct circle_buffer *tmp) {
+ struct circle_buffer *buf = tmp;
+ pthread_mutex_lock(&buf->lock);
+
+ if (buf->start_add != NULL) {
+ free(buf->start_add);
+ buf->start_add = NULL;
+ }
+ buf->rd = NULL;
+ buf->wr = NULL;
+ buf->size = 0;
+
+ pthread_mutex_unlock(&buf->lock);
+ return 0;
+}
+
+static int tmp_buffer_reset(struct circle_buffer *tmp) {
+ struct circle_buffer *buf = tmp;
+ buf->rd = buf->wr + buf->size / 2;
+ if (buf->rd >= (buf->start_add + buf->size))
+ buf->rd -= buf->size;
+ return 0;
+}
+
+int buffer_write(struct circle_buffer *tmp, char* buffer, size_t bytes) {
+ struct circle_buffer *buf = tmp;
+ pthread_mutex_lock(&buf->lock);
+ if (buf->start_add == NULL || buf->wr == NULL || buf->wr == NULL
+ || buf->size == 0) {
+ ALOGE("%s, Buffer malloc fail!\n", __FUNCTION__);
+ pthread_mutex_unlock(&buf->lock);
+ return -1;
+ }
+ size_t write_space = GetWriteSpace(buf->wr, buf->rd, buf->size);
+ if (write_space < bytes) {
+ //tmp_buffer_reset(buf);
+ //ALOGD("%s, no space to write %d bytes to buffer.\n", __FUNCTION__,bytes);
+ pthread_mutex_unlock(&buf->lock);
+ return -1;
+ }
+ write_to_buffer(buf->wr, buffer, bytes, buf->start_add, buf->size);
+ buf->wr = update_pointer(buf->wr, bytes, buf->start_add, buf->size);
+ pthread_mutex_unlock(&buf->lock);
+ return bytes;
+}
+
+int buffer_read(struct circle_buffer *tmp, char* buffer, size_t bytes) {
+ struct circle_buffer *buf = tmp;
+ pthread_mutex_lock(&buf->lock);
+ if (buf->start_add == NULL || buf->wr == NULL || buf->wr == NULL
+ || buf->size == 0) {
+ ALOGE("%s, Buffer malloc fail!\n", __FUNCTION__);
+ pthread_mutex_unlock(&buf->lock);
+ return -1;
+ }
+ size_t read_space = GetReadSpace(buf->wr, buf->rd, buf->size);
+ if (read_space < bytes) {
+ //tmp_buffer_reset(buf);
+ //ALOGD("%s, no space to read %d bytes to buffer.\n", __FUNCTION__,bytes);
+ pthread_mutex_unlock(&buf->lock);
+ return -1;
+ }
+ read_from_buffer(buf->rd, buffer, bytes, buf->start_add, buf->size);
+ buf->rd = update_pointer(buf->rd, bytes, buf->start_add, buf->size);
+ pthread_mutex_unlock(&buf->lock);
+ return bytes;
+}
+
+int GetOutputdevice(void) {
+ if (gpAmlDevice == NULL)
+ return -1;
+ return gpAmlDevice->output_deviceID;
+}
+
+static int set_input_stream_sample_rate(unsigned int sr,
+ struct aml_stream_in *in) {
+ if (check_input_stream_sr(sr) == 0) {
+ in->config.rate = sr;
+ } else {
+ if (sr == 0) {
+ in->config.rate = pcm_config_in.rate;
+ } else {
+ ALOGE("%s, The sample rate (%u) is invalid!\n", __FUNCTION__, sr);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int get_aml_card(void) {
+ int card = -1, err = -1;
+ int fd = -1;
+ unsigned fileSize = 512;
+ char *read_buf = NULL, *pd = NULL;
+ static const char * const SOUND_CARDS_PATH = "/proc/asound/cards";
+ fd = open(SOUND_CARDS_PATH, O_RDONLY);
+ if (fd < 0) {
+ ALOGE("ERROR: failed to open config file %s error: %d\n",
+ SOUND_CARDS_PATH, errno);
+ return -EINVAL;
+ }
+
+ read_buf = (char *) malloc(fileSize);
+ if (!read_buf) {
+ ALOGE("Failed to malloc read_buf");
+ close(fd);
+ return -ENOMEM;
+ }
+ memset(read_buf, 0x0, fileSize);
+ err = read(fd, read_buf, fileSize);
+ if (err < 0) {
+ ALOGE("ERROR: failed to read config file %s error: %d\n",
+ SOUND_CARDS_PATH, errno);
+ close(fd);
+ free(read_buf);
+ return -EINVAL;
+ }
+ pd = strstr(read_buf, "AML");
+ card = *(pd - 3) - '0';
+
+ free(read_buf);
+ close(fd);
+ return card;
+}
+
+static int alsa_in_open(struct aml_stream_in *in) {
+ in->config.channels = pcm_config_in.channels;
+ in->config.period_size = pcm_config_in.period_size;
+ in->config.period_count = pcm_config_in.period_count;
+ in->config.format = pcm_config_in.format;
+ in->config.stop_threshold = CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT * 4;
+ in->standby = 1;
+ in->resample_request = 0;
+ in->resample_temp_buffer = NULL;
+ in->max_bytes = in->config.period_size << 2;
+
+ if (in->config.rate == 0) {
+ in->config.rate = pcm_config_in.rate;
+ }
+
+ if (in->config.rate != pcm_config_in.rate) {
+ in->resample_request = 1;
+ int ret = resampler_init(in);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+
+ pthread_mutex_lock(&in->lock);
+ in->card = get_aml_card();
+ ALOGE("pcm in card ID = %d \n", in->card);
+ in->pcm = pcm_open(in->card, in->device, PCM_IN, &pcm_config_in);
+ if (!pcm_is_ready(in->pcm)) {
+ ALOGE("%s, Unable to open PCM device in: %s\n", __FUNCTION__,
+ pcm_get_error(in->pcm));
+ pcm_close(in->pcm);
+ pthread_mutex_unlock(&in->lock);
+ return -1;
+ }
+
+ in->standby = 0;
+ ALOGD("%s, Input device is opened: card(%d), device(%d)\n", __FUNCTION__,
+ in->card, in->device);
+ pthread_mutex_unlock(&in->lock);
+ return 0;
+}
+
+static int alsa_in_close(struct aml_stream_in *in) {
+ ALOGD("%s, Do input close!\n", __FUNCTION__);
+
+ pthread_mutex_lock(&in->lock);
+ if (!in->standby) {
+ pcm_close(in->pcm);
+ in->pcm = NULL;
+ in->standby = 1;
+ }
+ if (in->resample_request && (in->resample_temp_buffer != NULL)) {
+ free(in->resample_temp_buffer);
+ in->resample_temp_buffer = NULL;
+ }
+ pthread_mutex_unlock(&in->lock);
+ return 0;
+}
+
+static int get_in_framesize(struct aml_stream_in *in) {
+ int sample_format = 0;
+ if (in->config.format == PCM_FORMAT_S16_LE) {
+ sample_format = 2;
+ }
+ return sample_format * in->config.channels;
+}
+
+static int alsa_in_read(struct aml_stream_in *in, void* buffer, size_t bytes) {
+ int ret;
+
+ pthread_mutex_lock(&in->lock);
+ if (in->standby) {
+ pthread_mutex_unlock(&in->lock);
+ ALOGD("%s, Input device is closed!\n", __FUNCTION__);
+ return 0;
+ }
+ //if raw data in HDMI-in, no need to resample
+ if (GetOutputdevice() == 2) {
+ in->resample_request == 0;
+ }
+
+ int output_size = 0;
+ if (in->resample_request == 1) {
+ ret = pcm_read(in->pcm, in->resample_temp_buffer, bytes);
+ if (ret < 0) {
+ //wait for next frame
+ usleep(bytes * 1000000 / get_in_framesize(in) / in->config.rate);
+ pthread_mutex_unlock(&in->lock);
+ return ret;
+ }
+
+ DoDumpData(in->resample_temp_buffer, bytes, CC_DUMP_SRC_TYPE_INPUT);
+
+ output_size = resample_process(in, bytes >> 2,
+ (short *) in->resample_temp_buffer, (short *) buffer) << 2;
+ } else {
+ ret = pcm_read(in->pcm, buffer, bytes);
+ if (ret < 0) {
+ //wait for next frame
+ usleep(bytes * 1000000 / get_in_framesize(in) / in->config.rate);
+ pthread_mutex_unlock(&in->lock);
+ return ret;
+ }
+
+ DoDumpData(buffer, bytes, CC_DUMP_SRC_TYPE_INPUT);
+
+ output_size = bytes;
+ }
+ pthread_mutex_unlock(&in->lock);
+ return output_size;
+}
+
+static int alsa_out_open(struct aml_stream_out *out) {
+ out->config.channels = pcm_config_out.channels;
+ out->config.rate = pcm_config_out.rate;
+ out->config.period_size = pcm_config_out.period_size;
+ out->config.period_count = pcm_config_out.period_count;
+ out->config.format = pcm_config_out.format;
+ out->config.stop_threshold = PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT;
+ out->standby = 1;
+ out->max_bytes = out->config.period_size << 2;
+ out->amaudio_out_read_enable = 0;
+
+ pthread_mutex_lock(&out->lock);
+ out->card = get_aml_card();
+ out->pcm = pcm_open(out->card, out->device, PCM_OUT, &pcm_config_out);
+ if (!pcm_is_ready(out->pcm)) {
+ ALOGE("%s, Unable to open PCM device out: %s\n", __FUNCTION__,
+ pcm_get_error(out->pcm));
+ pcm_close(out->pcm);
+ pthread_mutex_unlock(&out->lock);
+ return -1;
+ }
+ out->standby = 0;
+ ALOGD("%s, Output device is opened: card(%d), device(%d)\n", __FUNCTION__,
+ out->card, out->device);
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+}
+
+static int alsa_out_close(struct aml_stream_out *out) {
+ ALOGD("%s, Do output close!\n", __FUNCTION__);
+
+ pthread_mutex_lock(&out->lock);
+ if (!out->standby) {
+ pcm_close(out->pcm);
+ out->pcm = NULL;
+ out->standby = 1;
+ }
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+}
+
+static int get_out_framesize(struct aml_stream_out *out) {
+ int sample_format = 0;
+ if (out->config.format == PCM_FORMAT_S16_LE)
+ sample_format = 2;
+ return sample_format * out->config.channels;
+}
+
+static int alsa_out_write(struct aml_stream_out *out, void* buffer,
+ size_t bytes) {
+ int ret;
+
+ pthread_mutex_lock(&out->lock);
+ if (out->standby) {
+ pthread_mutex_unlock(&out->lock);
+ ALOGD("%s, Output device is closed!\n", __FUNCTION__);
+ return 0;
+ }
+
+ ret = pcm_write(out->pcm, buffer, bytes);
+ if (ret < 0) {
+ usleep(bytes * 1000000 / get_out_framesize(out) / out->config.rate);
+ pthread_mutex_unlock(&out->lock);
+ return ret;
+ }
+
+ pthread_mutex_unlock(&out->lock);
+ return bytes;
+}
+
+static int reset_amaudio(struct aml_stream_out *out, int delay_size) {
+ struct buffer_status *buf = &out->playback_buf;
+ buf->rd = 0;
+ buf->wr = 0;
+ buf->level = buf->size;
+ struct buffer_status *buf1 = &out->read_buf;
+ buf1->rd = 0;
+ buf1->wr = 0;
+ buf1->level = 0;
+ int ret = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_RESET, delay_size);
+ if (ret < 0) {
+ ALOGE("%s, amaudio reset delay_size error!\n", __FUNCTION__);
+ return -1;
+ }
+ return 0;
+}
+
+static int set_amaudio2_enable(int flag) {
+ int fd = 0;
+ char string[16];
+ fd = open(AMAUDIO2_PREENABLE, O_CREAT | O_RDWR, 0664);
+ if (fd < 0) {
+ ALOGE("unable to open file %s \n", AMAUDIO2_PREENABLE);
+ return -1;
+ }
+ sprintf(string, "%d", flag);
+ write(fd, string, strlen(string));
+ close(fd);
+ return 0;
+}
+static int new_audiotrack(struct aml_stream_out *out) {
+ int i = 0, ret = 0;
+ int dly_tm = 20 * 1000, dly_cnt = 1000; //20s
+
+ pthread_mutex_lock(&out->lock);
+
+ ALOGD("%s, entering...\n", __FUNCTION__);
+ set_amaudio2_enable(1);
+ ret = new_android_audiotrack();
+ if (ret < 0) {
+ ALOGE("%s, New an audio track is fail!\n", __FUNCTION__);
+ pthread_mutex_unlock(&out->lock);
+ return -1;
+ }
+
+ while (I2S_state < 10) {
+ usleep(dly_tm);
+
+ i++;
+ if (i >= dly_cnt) {
+ release_android_audiotrack();
+ pthread_mutex_unlock(&out->lock);
+ ALOGE("%s, Time out error: wait %d ms for waiting I2S ready.\n",
+ __FUNCTION__, i * dly_tm / 1000);
+ return -1;
+ }
+ }
+ ALOGD("%s, sucess: wait %d ms for waiting I2S ready.\n", __FUNCTION__,
+ i * dly_tm / 1000);
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+}
+
+static int new_audiotrack_nowait(struct aml_stream_out *out) {
+ int ret = 0;
+ pthread_mutex_lock(&out->lock);
+ ALOGD("%s, entering...\n", __FUNCTION__);
+ set_amaudio2_enable(1);
+ ret = new_android_audiotrack();
+ if (ret < 0) {
+ ALOGE("%s, New an audio track is fail!\n", __FUNCTION__);
+ pthread_mutex_unlock(&out->lock);
+ return -1;
+ }
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+}
+
+static int release_audiotrack(struct aml_stream_out *out) {
+ ALOGD("%s, Release audio track!\n", __FUNCTION__);
+ pthread_mutex_lock(&out->lock);
+ int ret = release_android_audiotrack();
+ if (ret < 0) {
+ ALOGE("%s, Delete audio track is fail!\n", __FUNCTION__);
+ }
+ set_amaudio2_enable(0);
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+}
+
+static int amaudio_out_open(struct aml_stream_out *out) {
+
+ out->config.channels = pcm_config_out.channels;
+ out->config.rate = pcm_config_out.rate;
+ out->config.period_size = pcm_config_out.period_size;
+ out->config.period_count = pcm_config_out.period_count;
+ out->config.format = pcm_config_out.format;
+
+ out->standby = 1;
+ out->max_bytes = out->config.period_size << 2;
+ out->amaudio_out_read_enable = 0;
+
+ pthread_mutex_lock(&out->lock);
+ out->amAudio_OutHandle = -1;
+ out->amAudio_OutHandle = open(AMAUDIO_OUT, O_RDWR);
+ if (out->amAudio_OutHandle < 0) {
+ close(out->amAudio_OutHandle);
+ out->amAudio_OutHandle = -1;
+ release_android_audiotrack();
+ pthread_mutex_unlock(&out->lock);
+ ALOGE("%s, The device amaudio_out cant't be opened!\n", __FUNCTION__);
+ return -1;
+ }
+
+ struct buffer_status *buf = &out->playback_buf;
+ buf->size = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_SIZE);
+ buf->start_add = (short*) mmap(NULL, buf->size, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_SHARED, out->amAudio_OutHandle, 0);
+ if (buf->start_add == 0) {
+ close(out->amAudio_OutHandle);
+ out->amAudio_OutHandle = -1;
+ release_android_audiotrack();
+ pthread_mutex_unlock(&out->lock);
+ ALOGE("%s, Error create mmap!\n", __FUNCTION__);
+ return -1;
+ }
+
+ struct buffer_status *buf1 = &out->read_buf;
+ buf1->size = buf->size;
+
+ out->standby = 0;
+ pthread_mutex_unlock(&out->lock);
+ ALOGD("%s, Amaudio device is opened!\n", __FUNCTION__);
+ return 0;
+}
+
+static int amaudio_out_close(struct aml_stream_out *out) {
+ ALOGD("%s, Do amaudio device close!\n", __FUNCTION__);
+ pthread_mutex_lock(&out->lock);
+ if (out->amAudio_OutHandle > 0) {
+ close(out->amAudio_OutHandle);
+ out->amAudio_OutHandle = -1;
+ munmap(out->playback_buf.start_add, out->playback_buf.size);
+ }
+ pthread_mutex_unlock(&out->lock);
+ return 0;
+}
+
+static int amaudio_out_write(struct aml_stream_out *out, void* buffer,
+ size_t bytes) {
+ int block = bytes >> 6 << 6; //align 2^6
+ char *in_ptr = (char *) buffer;
+ char *out_ptr = NULL;
+
+ int k = 0, i = 0;
+ struct buffer_status *buf = &out->playback_buf;
+
+ pthread_mutex_lock(&out->lock);
+
+ //get rd ptr, and calculate write space
+ buf->rd = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_PTR);
+ buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size);
+
+ if (buf->level <= block) {
+ ALOGD("Reset amaudio: buf->level=%x,buf->rd = %x,buf->wr=%x\n",
+ buf->level, buf->rd, buf->wr);
+ pthread_mutex_unlock(&out->lock);
+ return -1;
+ }
+
+ out_ptr = &(buf->start_add[buf->wr / 2]);
+ memcpy(out_ptr, in_ptr, block);
+
+ // update the write pointer and write space
+ buf->wr = (buf->wr + block) % buf->size;
+ buf->level = buf->size - ((buf->size + buf->wr - buf->rd) % buf->size);
+ ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_UPDATE_APP_PTR, buf->wr);
+ pthread_mutex_unlock(&out->lock);
+
+ return block;
+}
+
+int amaudio_out_read_enable(int enable) {
+ int ret;
+
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__);
+ return -1;
+ }
+
+ int OutHandle = gpAmlDevice->out.amAudio_OutHandle;
+ if (OutHandle < 0) {
+ ALOGE("%s, amaudio out handle error!\n", __FUNCTION__);
+ return -1;
+ }
+
+ pthread_mutex_lock(&gpAmlDevice->out.lock);
+ gpAmlDevice->out.amaudio_out_read_enable = enable;
+ reset_amaudio(&gpAmlDevice->out, 64 * 32 * 2);
+ ioctl(OutHandle, AMAUDIO_IOC_OUT_READ_ENABLE, enable);
+ ALOGD("%s, out read enable :%d!\n", __FUNCTION__, enable);
+ pthread_mutex_unlock(&gpAmlDevice->out.lock);
+ return 0;
+}
+
+static int amaudio_out_read(struct aml_stream_out *out, void* buffer,
+ size_t bytes) {
+ int block = bytes >> 6 << 6; //align 2^6
+ char *in = (char *) buffer;
+ struct buffer_status *buf = &out->read_buf;
+
+ pthread_mutex_lock(&out->lock);
+
+ buf->wr = ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_GET_PTR_READ);
+ buf->level = (buf->size + buf->wr - buf->rd) % buf->size;
+
+ if (buf->level < block) {
+ usleep(5000);
+ pthread_mutex_unlock(&out->lock);
+ ALOGD("buf->level=%d,buf->rd = %d,buf->wr=%d\n", buf->level, buf->rd,
+ buf->wr);
+ return 0;
+ }
+
+ int Ret = read(out->amAudio_OutHandle, (char *) buffer, block);
+ if (Ret != block) {
+ ALOGE("%s, amAudio2 read from hardware buffer failed!\n", __FUNCTION__);
+ pthread_mutex_unlock(&out->lock);
+ return -1;
+ }
+
+ // update the read pointer
+ buf->rd += block;
+ buf->rd %= buf->size;
+ buf->level = (buf->size + buf->wr - buf->rd) % buf->size;
+
+ ioctl(out->amAudio_OutHandle, AMAUDIO_IOC_UPDATE_APP_PTR_READ, buf->rd);
+ pthread_mutex_unlock(&out->lock);
+ return block;
+}
+
+static int malloc_buffer(struct aml_dev *device) {
+ void *buffer = NULL;
+ struct aml_stream_in *in = &device->in;
+ struct aml_stream_out *out = &device->out;
+
+ buffer = malloc(TEMP_BUFFER_SIZE);
+ if (buffer == NULL) {
+ ALOGD("%s, Malloc temp buffer failed!\n", __FUNCTION__);
+ return -1;
+ }
+ start_temp_buffer = buffer;
+ in->write_buffer = buffer;
+ out->read_buffer = buffer;
+
+ in->temp_buffer = malloc(in->max_bytes);
+ if (in->temp_buffer == NULL) {
+ ALOGD("%s, Malloc input temp buffer failed!\n", __FUNCTION__);
+ return -1;
+ }
+
+ out->temp_buffer = malloc(pcm_config_out.period_size << 2);
+ if (out->temp_buffer == NULL) {
+ ALOGD("%s, Malloc output temp buffer failed!\n", __FUNCTION__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int release_buffer(struct aml_dev *device) {
+ struct aml_stream_in *in = &device->in;
+ struct aml_stream_out *out = &device->out;
+
+ if (start_temp_buffer != NULL) {
+ free(start_temp_buffer);
+ start_temp_buffer = NULL;
+ in->write_buffer = NULL;
+ out->read_buffer = NULL;
+ }
+ if (in->temp_buffer != NULL) {
+ free(in->temp_buffer);
+ in->temp_buffer = NULL;
+ }
+ if (out->temp_buffer != NULL) {
+ free(out->temp_buffer);
+ out->temp_buffer = NULL;
+ }
+ return 0;
+}
+
+static int audio_effect_release() {
+ unload_EQ_lib();
+ unload_SRS_lib();
+ return 0;
+}
+
+static int set_output_deviceID(int deviceID) {
+ int ret;
+
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__);
+ return -1;
+ }
+
+ gpAmlDevice->output_deviceID = deviceID;
+ ALOGE("%s, set output device ID: %d!\n", __FUNCTION__, deviceID);
+ return 0;
+}
+
+static int aml_device_init(struct aml_dev *device) {
+ int ret;
+
+ ALOGD("%s, start to open Devices!\n", __FUNCTION__);
+
+ //Malloc temp buffer for audiotrak out
+ ret = tmp_buffer_init(&android_out_buffer, ANDROID_OUT_BUFFER_SIZE);
+ if (ret < 0) {
+ ALOGE("%s, malloc temp buffer error!\n", __FUNCTION__);
+ goto error1;
+ }
+
+ ret = tmp_buffer_init(&DDP_out_buffer, DDP_OUT_BUFFER_SIZE);
+ if (ret < 0) {
+ ALOGE("%s, malloc ddp buffer failed!\n", __FUNCTION__);
+ goto error2;
+ }
+
+ //open input device of tinyalsa
+ ret = alsa_in_open(&device->in);
+ if (ret < 0) {
+ ALOGE("%s, open alsa in device open error!\n", __FUNCTION__);
+ goto error3;
+ }
+
+ //Malloc temp buffer for input and output
+ ret = malloc_buffer(device);
+ if (ret < 0) {
+ ALOGE("%s, malloc buffer error!\n", __FUNCTION__);
+ goto error4;
+ }
+
+ if (device->out.user_set_device == CC_OUT_USE_ALSA) {
+ set_output_deviceID(0);
+ //open output device of tinyalsa
+ ret = alsa_out_open(&device->out);
+ if (ret < 0) {
+ ALOGE("%s, open alsa out device open error!\n", __FUNCTION__);
+ goto error5;
+ }
+ } else if (device->out.user_set_device == CC_OUT_USE_AMAUDIO) {
+ set_output_deviceID(0);
+ //open output device of amaudio
+ ret = new_audiotrack(&device->out);
+ if (ret < 0) {
+ ALOGE("%s, new audiotrack error!\n", __FUNCTION__);
+ goto error5;
+ }
+ ret = amaudio_out_open(&device->out);
+ if (ret < 0) {
+ release_audiotrack(&device->out);
+ ALOGE("%s, open amaudio out device error!\n", __FUNCTION__);
+ goto error5;
+ }
+ } else if (device->out.user_set_device == CC_OUT_USE_ANDROID) {
+ set_output_deviceID(1);
+ ret = new_audiotrack_nowait(&device->out);
+ if (ret < 0) {
+ ALOGE("%s, open android out device error!\n", __FUNCTION__);
+ goto error5;
+ }
+ }
+
+ //EQ lib load and init EQ
+ ret = load_EQ_lib();
+ if (ret < 0) {
+ ALOGE("%s, Load EQ lib fail!\n", __FUNCTION__);
+ device->has_EQ_lib = 0;
+ } else {
+ ret = HPEQ_init();
+ if (ret < 0) {
+ device->has_EQ_lib = 0;
+ } else {
+ device->has_EQ_lib = 1;
+ }
+ HPEQ_enable(1);
+ }
+
+ //load srs lib and init it. SRS is behand resampling, so sample rate is as default sr.
+ ret = load_SRS_lib();
+ if (ret < 0) {
+ ALOGE("%s, Load EQ lib fail!\n", __FUNCTION__);
+ device->has_SRS_lib = 0;
+ } else {
+ ret = srs_init(device->out.config.rate);
+ if (ret < 0) {
+ device->has_SRS_lib = 0;
+ } else {
+ device->has_SRS_lib = 1;
+ }
+ }
+
+ ALOGD("%s, exiting...\n", __FUNCTION__);
+ return 0;
+
+ error5: release_buffer(device);
+ error4: alsa_in_close(&device->in);
+ error3: tmp_buffer_release (&DDP_out_buffer);
+ error2: tmp_buffer_release (&android_out_buffer);
+ error1: return ret;
+
+}
+
+static int aml_device_close(struct aml_dev *device) {
+ struct aml_stream_in *in = &device->in;
+ struct aml_stream_out *out = &device->out;
+
+ alsa_in_close(in);
+
+ if (out->output_device == CC_OUT_USE_ALSA) {
+ alsa_out_close(out);
+ } else if (out->output_device == CC_OUT_USE_AMAUDIO) {
+ amaudio_out_close(out);
+ release_audiotrack(out);
+ } else if (out->output_device == CC_OUT_USE_ANDROID) {
+ release_audiotrack(out);
+ }
+ omx_codec_close();
+ omx_started = 0;
+ tmp_buffer_release (&DDP_out_buffer);
+ tmp_buffer_release (&android_out_buffer);
+ release_buffer(device);
+ audio_effect_release();
+ return 0;
+}
+
+static int gUSBCheckLastFlag = 0;
+static int gUSBCheckFlag = 0;
+
+static void USB_check(struct aml_stream_out *out) {
+
+ gUSBCheckFlag = GetUsbAudioCheckFlag();
+ if (gUSBCheckLastFlag == gUSBCheckFlag) {
+ return;
+ }
+
+ ALOGI("Audio Device is changed from %x to %x!\n", gUSBCheckLastFlag, gUSBCheckFlag);
+
+ //if audio record from submix, don't change device
+ if ((gUSBCheckFlag & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) != 0) {
+ gUSBCheckLastFlag = gUSBCheckFlag;
+ set_output_record_enable(1);
+ return;
+ } else if((gUSBCheckLastFlag & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) != 0) {
+ gUSBCheckLastFlag = gUSBCheckFlag;
+ set_output_record_enable(0);
+ return;
+ }
+
+ if ((gUSBCheckFlag & AUDIO_DEVICE_OUT_SPEAKER) == 0) {
+ if (out->output_device == CC_OUT_USE_AMAUDIO && omx_started == 0) {
+ amaudio_out_close(out);
+ set_output_deviceID(1);
+ out->output_device = CC_OUT_USE_ANDROID;
+ } else if (out->output_device == CC_OUT_USE_ALSA && omx_started == 0) {
+ alsa_out_close(out);
+ new_audiotrack_nowait(out);
+ set_output_deviceID(1);
+ out->output_device = CC_OUT_USE_ANDROID;
+ }
+ ALOGI("%s, USB audio playback device is in.\n", __FUNCTION__);
+ } else if ((gUSBCheckFlag & AUDIO_DEVICE_OUT_SPEAKER) != 0 && gUSBCheckLastFlag != 0) {
+ if (out->user_set_device == CC_OUT_USE_AMAUDIO && omx_started == 0) {
+ amaudio_out_open(out);
+ set_output_deviceID(0);
+ out->output_device = CC_OUT_USE_AMAUDIO;
+ } else if (out->user_set_device == CC_OUT_USE_ALSA
+ && omx_started == 0) {
+ release_audiotrack(out);
+ alsa_out_open(out);
+ set_output_deviceID(0);
+ out->output_device = CC_OUT_USE_ALSA;
+ }
+ ALOGI("%s, USB audio playback device is out.\n", __FUNCTION__);
+ }
+ gUSBCheckLastFlag = gUSBCheckFlag;
+ return;
+}
+
+static int get_channel_status(void) {
+ struct mixer *pmixer;
+ struct mixer_ctl *pctl;
+ int card_id;
+ int type_HDMI = -1;
+ int type_SPDIF = -1;
+ int type_AUDIO_IN = -1;
+
+ card_id = get_aml_card();
+ pmixer = mixer_open(card_id);
+ if (NULL == pmixer) {
+ ALOGE("[%s:%d] Failed to open mixer\n", __FUNCTION__, __LINE__);
+ goto err_exit;
+ }
+ pctl = mixer_get_ctl_by_name(pmixer, Audio_In_Source_TYPE);
+ if (NULL != pctl) {
+ type_AUDIO_IN = mixer_ctl_get_value(pctl, 0);
+ if (type_AUDIO_IN != 2) {
+ mixer_close(pmixer);
+ return PCM_DATA;
+ }
+ }
+
+ pctl = mixer_get_ctl_by_name(pmixer, SPDIF_IN_AUDIO_TYPE);
+ if (NULL != pctl) {
+ type_SPDIF = mixer_ctl_get_value(pctl, 0);
+ }
+
+ pctl = mixer_get_ctl_by_name(pmixer, HDMI_IN_AUDIO_TYPE);
+ if (NULL != pctl) {
+ type_HDMI = mixer_ctl_get_value(pctl, 0);
+ }
+
+ if (type_SPDIF == RAW_DATA || type_HDMI == RAW_DATA) {
+ mixer_close(pmixer);
+ return RAW_DATA;
+ } else {
+ mixer_close(pmixer);
+ return PCM_DATA;
+ }
+ err_exit: if (NULL != pmixer) {
+ mixer_close(pmixer);
+ }
+ return -1;
+}
+
+static int set_rawdata_in_enable(struct aml_stream_out *out) {
+ if (out->output_device == CC_OUT_USE_AMAUDIO) {
+ amaudio_out_close(out);
+ } else if (out->output_device == CC_OUT_USE_ALSA) {
+ alsa_out_close(out);
+ new_audiotrack_nowait(out);
+ }
+ set_output_deviceID(2);
+ out->output_device = CC_OUT_USE_ANDROID;
+ omx_codec_init();
+ return 0;
+}
+
+static int set_rawdata_in_disable(struct aml_stream_out *out) {
+ omx_codec_close();
+ if (gUSBCheckFlag == 0) {
+ if (out->user_set_device == CC_OUT_USE_AMAUDIO) {
+ set_output_deviceID(0);
+ amaudio_out_open(out);
+ out->output_device = CC_OUT_USE_AMAUDIO;
+ } else if (out->user_set_device == CC_OUT_USE_ANDROID) {
+ set_output_deviceID(1);
+ out->output_device = CC_OUT_USE_ANDROID;
+ } else if (out->user_set_device == CC_OUT_USE_ALSA) {
+ release_audiotrack(out);
+ alsa_out_open(out);
+ set_output_deviceID(0);
+ out->output_device = CC_OUT_USE_ALSA;
+ }
+ } else if (gUSBCheckFlag == 1) {
+ set_output_deviceID(1);
+ out->output_device = CC_OUT_USE_ANDROID;
+ }
+ return 0;
+}
+
+int set_output_record_enable(int enable) {
+ pthread_mutex_lock(&device_change_lock);
+ if (enable == 0) {
+ output_record_enable = 0;
+ ALOGI("%s, set output record disable!\n", __FUNCTION__);
+ } else if (enable == 1) {
+ output_record_enable = 1;
+ ALOGI("%s, set output record enable\n", __FUNCTION__);
+ } else {
+ ALOGE("%s, invalid setting!\n", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&device_change_lock);
+ return 0;
+}
+
+static int check_audio_type(struct aml_stream_out *out) {
+ audioin_type = get_channel_status();
+
+ if (audioin_type == 1 && omx_started == 0) {
+ raw_data_counter++;
+ }
+
+ if (raw_data_counter >= 3 && omx_started == 0) {
+ ALOGI("%s, audio type is changed to RAW data input!\n", __FUNCTION__);
+ set_rawdata_in_enable(out);
+ omx_started = 1;
+ raw_data_counter = 0;
+ } else if (audioin_type == 0 && omx_started == 1) {
+ ALOGI("%s, audio type is changed to PCM data input!\n", __FUNCTION__);
+ set_rawdata_in_disable(out);
+ omx_started = 0;
+ }
+ return 0;
+}
+
+static void* aml_audio_threadloop(void *data) {
+ struct aml_stream_in *in = NULL;
+ struct aml_stream_out *out = NULL;
+ int output_size = 0;
+
+ ALOGD("%s, entering...\n", __FUNCTION__);
+
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, gpAmlDevice is NULL\n", __FUNCTION__);
+ return ((void *) 0);
+ }
+
+ in = &gpAmlDevice->in;
+ out = &gpAmlDevice->out;
+ out->max_bytes = pcm_config_out.period_size << 2;
+
+ gpAmlDevice->aml_Audio_ThreadExecFlag = 1;
+ ALOGD("%s, set aml_Audio_ThreadExecFlag as 1.\n", __FUNCTION__);
+
+ if (gpAmlDevice->out.user_set_device == CC_OUT_USE_AMAUDIO) {
+ int delay_size = 64 * 32 * 2; //less than 10.67*2 ms delay
+ reset_amaudio(out, delay_size);
+ }
+
+ gUSBCheckLastFlag = 0;
+ gUSBCheckFlag = 0;
+
+ while (gpAmlDevice != NULL && gpAmlDevice->aml_Audio_ThreadTurnOnFlag) {
+ //exit threadloop
+ if (gpAmlDevice->aml_Audio_ThreadTurnOnFlag == 0) {
+ ALOGD("%s, aml_Audio_ThreadTurnOnFlag is 0 break now.\n",
+ __FUNCTION__);
+ break;
+ }
+ if (GetWriteSpace((char *) in->write_buffer, (char *) out->read_buffer,
+ TEMP_BUFFER_SIZE) > in->max_bytes) {
+ output_size = alsa_in_read(in, in->temp_buffer,
+ in->config.period_size * 4);
+ if (output_size < 0) {
+ //ALOGE("%s, alsa_in_read fail!\n", __FUNCTION__);
+ } else {
+ if (gpAmlDevice->has_EQ_lib && (GetOutputdevice() == 0)) {
+ HPEQ_process((short *) in->temp_buffer,
+ (short *) in->temp_buffer, output_size >> 2);
+ }
+ write_to_buffer((char *) in->write_buffer,
+ (char *) in->temp_buffer, output_size,
+ (char *) start_temp_buffer, TEMP_BUFFER_SIZE);
+ in->write_buffer = update_pointer((char *) in->write_buffer,
+ output_size, (char *) start_temp_buffer,
+ TEMP_BUFFER_SIZE);
+ check_audio_type(out);
+ }
+
+ }
+
+ USB_check(out);
+
+ if (GetReadSpace((char *) in->write_buffer, (char *) out->read_buffer,
+ TEMP_BUFFER_SIZE) > out->max_bytes) {
+ read_from_buffer((char *) out->read_buffer,
+ (char *) out->temp_buffer, out->max_bytes,
+ (char *) start_temp_buffer, TEMP_BUFFER_SIZE);
+
+ output_size = out->max_bytes;
+ if (gpAmlDevice->has_SRS_lib && (GetOutputdevice() == 0)) {
+ output_size = srs_process((short *) out->temp_buffer,
+ (short *) out->temp_buffer, out->max_bytes >> 2);
+ }
+ if (gpAmlDevice->out.output_device == CC_OUT_USE_ALSA) {
+ output_size = alsa_out_write(out, out->temp_buffer,
+ output_size);
+ } else if (gpAmlDevice->out.output_device == CC_OUT_USE_AMAUDIO) {
+ output_size = amaudio_out_write(out, out->temp_buffer,
+ output_size);
+ if (output_size < 0) {
+ amaudio_out_close(out);
+ set_output_deviceID(0);
+ amaudio_out_open(out);
+ reset_amaudio(out, 4096);
+ }
+ if (output_record_enable == 1) {
+ buffer_write(&android_out_buffer, out->temp_buffer,
+ output_size);
+ }
+ } else if (gpAmlDevice->out.output_device == CC_OUT_USE_ANDROID) {
+ output_size = buffer_write(&android_out_buffer,
+ out->temp_buffer, output_size);
+ }
+
+ if (output_size < 0) {
+ //ALOGE("%s, out_write fail! bytes = %d \n", __FUNCTION__, output_size);
+ } else {
+ out->read_buffer = update_pointer((char *) out->read_buffer,
+ output_size, (char *) start_temp_buffer,
+ TEMP_BUFFER_SIZE);
+ DoDumpData(out->temp_buffer, output_size,
+ CC_DUMP_SRC_TYPE_OUTPUT);
+ memset(out->temp_buffer, 0, output_size);
+ }
+ }
+ }
+
+ if (gpAmlDevice != NULL) {
+ gpAmlDevice->aml_Audio_ThreadTurnOnFlag = 0;
+ ALOGD("%s, set aml_Audio_ThreadTurnOnFlag as 0.\n", __FUNCTION__);
+ gpAmlDevice->aml_Audio_ThreadExecFlag = 0;
+ ALOGD("%s, set aml_Audio_ThreadExecFlag as 0.\n", __FUNCTION__);
+ }
+
+ ALOGD("%s, exiting...\n", __FUNCTION__);
+ return ((void *) 0);
+}
+
+static int clrDevice(struct aml_dev *device) {
+ memset((void *) device, 0, sizeof(struct aml_dev));
+
+ device->in.config.channels = 2;
+ device->in.config.rate = DEFAULT_IN_SAMPLE_RATE;
+ device->in.config.period_size = CAPTURE_PERIOD_SIZE;
+ device->in.config.period_count = CAPTURE_PERIOD_COUNT;
+ device->in.config.format = PCM_FORMAT_S16_LE;
+
+ device->out.config.channels = 2;
+ device->out.config.rate = DEFAULT_OUT_SAMPLE_RATE;
+ device->out.config.period_size = PLAYBACK_PERIOD_SIZE;
+ device->out.config.period_count = PLAYBACK_PERIOD_COUNT;
+ device->out.config.format = PCM_FORMAT_S16_LE;
+
+ return 0;
+}
+
+int aml_audio_open(unsigned int sr, int input_device, int output_device) {
+ pthread_attr_t attr;
+ struct sched_param param;
+ int ret;
+
+ ALOGD("%s, sr = %d, output_device = %d\n", __FUNCTION__, sr, output_device);
+
+ aml_audio_close();
+
+ pthread_mutex_lock(&amaudio_dev_op_mutex);
+
+ gpAmlDevice = &gmAmlDevice;
+ clrDevice(gpAmlDevice);
+
+ ret = set_input_stream_sample_rate(sr, &gpAmlDevice->in);
+ if (ret < 0) {
+ ALOGE("%s, set_input_stream_sample_rate fail!\n", __FUNCTION__);
+ clrDevice(gpAmlDevice);
+ gpAmlDevice = NULL;
+ pthread_mutex_unlock(&amaudio_dev_op_mutex);
+ return -1;
+ }
+
+ gpAmlDevice->out.output_device = output_device;
+ gpAmlDevice->out.user_set_device = output_device;
+ if (gpAmlDevice->out.user_set_device == CC_OUT_USE_ALSA) {
+ ALOGD("%s,Use tinyalsa as output device!\n", __FUNCTION__);
+ } else if (gpAmlDevice->out.user_set_device == CC_OUT_USE_AMAUDIO) {
+ ALOGD("%s, Use amlogic amaudio as output device!\n", __FUNCTION__);
+ } else if (gpAmlDevice->out.user_set_device == CC_OUT_USE_ANDROID) {
+ ALOGD("%s, Use amlogic android as output device!\n", __FUNCTION__);
+ } else {
+ ALOGE("%s, Unkown output device, use default amaudio\n", __FUNCTION__);
+ gpAmlDevice->out.user_set_device = CC_OUT_USE_AMAUDIO;
+ }
+
+ gpAmlDevice->in.device = input_device;
+
+ ret = aml_device_init(gpAmlDevice);
+ if (ret < 0) {
+ ALOGE("%s, Devices fail opened!\n", __FUNCTION__);
+ clrDevice(gpAmlDevice);
+ gpAmlDevice = NULL;
+ pthread_mutex_unlock(&amaudio_dev_op_mutex);
+ return -1;
+ }
+
+ pthread_attr_init(&attr);
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ param.sched_priority = sched_get_priority_max(SCHED_RR);
+ pthread_attr_setschedparam(&attr, &param);
+ gpAmlDevice->aml_Audio_ThreadTurnOnFlag = 1;
+ ALOGD("%s, set aml_Audio_ThreadTurnOnFlag as 1.\n", __FUNCTION__);
+ gpAmlDevice->aml_Audio_ThreadExecFlag = 0;
+ ALOGD("%s, set aml_Audio_ThreadExecFlag as 0.\n", __FUNCTION__);
+ ret = pthread_create(&gpAmlDevice->aml_Audio_ThreadID, &attr,
+ &aml_audio_threadloop, NULL);
+ pthread_attr_destroy(&attr);
+ if (ret != 0) {
+ ALOGE("%s, Create thread fail!\n", __FUNCTION__);
+ aml_device_close(gpAmlDevice);
+ clrDevice(gpAmlDevice);
+ gpAmlDevice = NULL;
+ pthread_mutex_unlock(&amaudio_dev_op_mutex);
+ return -1;
+ }
+
+ pthread_mutex_unlock(&amaudio_dev_op_mutex);
+
+ ALOGD("%s, exiting...\n", __FUNCTION__);
+ return 0;
+}
+
+int aml_audio_close(void) {
+ int i = 0, tmp_timeout_count = 1000;
+
+ ALOGD("%s, gpAmlDevice = %p\n", __FUNCTION__, gpAmlDevice);
+
+ pthread_mutex_lock(&amaudio_dev_op_mutex);
+
+ if (gpAmlDevice != NULL) {
+ gpAmlDevice->aml_Audio_ThreadTurnOnFlag = 0;
+ ALOGD("%s, set aml_Audio_ThreadTurnOnFlag as 0.\n", __FUNCTION__);
+ while (1) {
+ if (gpAmlDevice->aml_Audio_ThreadExecFlag == 0) {
+ break;
+ }
+
+ if (i >= tmp_timeout_count) {
+ break;
+ }
+
+ i++;
+
+ usleep(10 * 1000);
+ }
+
+ if (i >= tmp_timeout_count) {
+ ALOGE(
+ "%s, we have try %d times, but the aml audio thread's exec flag is still(%d)!!!\n",
+ __FUNCTION__, tmp_timeout_count,
+ gpAmlDevice->aml_Audio_ThreadExecFlag);
+ } else {
+ ALOGD("%s, kill aml audio thread success after try %d times.\n",
+ __FUNCTION__, i);
+ }
+
+ pthread_join(gpAmlDevice->aml_Audio_ThreadID, NULL);
+ gpAmlDevice->aml_Audio_ThreadID = 0;
+
+ aml_device_close(gpAmlDevice);
+ clrDevice(gpAmlDevice);
+ gpAmlDevice = NULL;
+
+ ALOGD("%s, aml audio close success.\n", __FUNCTION__);
+ }
+
+ pthread_mutex_unlock(&amaudio_dev_op_mutex);
+ return 0;
+}
+
+int check_input_stream_sr(unsigned int sr) {
+ if (sr >= 8000 && sr <= 48000) {
+ return 0;
+ }
+ return -1;
+}
+
+int set_android_volume_enable(int enable) {
+ if (amaudio2_out_handle < 0) {
+ amaudio2_out_handle = open(AMAUDIO_OUT, O_RDWR);
+ if (amaudio2_out_handle < 0) {
+ ALOGE("%s, The device amaudio_out cant't be opened!\n",
+ __FUNCTION__);
+ return -1;
+ }
+ ALOGI("%s, get amaudio2 handle = %d!\n", __FUNCTION__,
+ amaudio2_out_handle);
+ }
+
+ if (enable != 0 && enable != 1) {
+ ALOGE("invalid value: enable = %d. (warning: 0 or 1 is valid)\n",
+ enable);
+ return -1;
+ }
+
+ ioctl(amaudio2_out_handle, AMAUDIO_IOC_SET_ANDROID_VOLUME_ENABLE, enable);
+
+ return 0;
+}
+
+int set_android_volume(int left, int right) {
+ if (amaudio2_out_handle < 0) {
+ amaudio2_out_handle = open(AMAUDIO_OUT, O_RDWR);
+ if (amaudio2_out_handle < 0) {
+ ALOGE("%s, The device amaudio_out cant't be opened!\n",
+ __FUNCTION__);
+ return -1;
+ }
+ ALOGI("%s, get amaudio2 handle = %d!\n", __FUNCTION__,
+ amaudio2_out_handle);
+ }
+
+ if (left < 0 || left > 256 || right < 0 || right > 256) {
+ ALOGE(
+ "invalid value: left = %d, right = %d. (warning: 0-256 is valid)\n",
+ left, right);
+ return -1;
+ }
+
+ ioctl(amaudio2_out_handle, AMAUDIO_IOC_SET_ANDROID_LEFT_VOLUME, left);
+ ioctl(amaudio2_out_handle, AMAUDIO_IOC_SET_ANDROID_RIGHT_VOLUME, right);
+ return 0;
+}
+
+int set_output_mode(int mode) {
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (mode < CC_OUT_MODE_DIRECT || mode > CC_OUT_MODE_DIRECT_MIX) {
+ ALOGE("%s, mode error: mode = %d!\n", __FUNCTION__, mode);
+ return -1;
+ }
+
+ int OutHandle = gpAmlDevice->out.amAudio_OutHandle;
+ if (OutHandle < 0) {
+ ALOGE("%s, amaudio out handle error!\n", __FUNCTION__);
+ return -1;
+ }
+
+ pthread_mutex_lock(&gpAmlDevice->out.lock);
+ ioctl(OutHandle, AMAUDIO_IOC_AUDIO_OUT_MODE, mode);
+ pthread_mutex_unlock(&gpAmlDevice->out.lock);
+ return 0;
+}
+
+int set_music_gain(int gain) {
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__);
+ return -1;
+ }
+
+ int OutHandle = gpAmlDevice->out.amAudio_OutHandle;
+ if (OutHandle < 0) {
+ ALOGE("%s, amaudio out handle error!\n", __FUNCTION__);
+ return -1;
+ }
+
+ pthread_mutex_lock(&gpAmlDevice->out.lock);
+ if (gain > 256) {
+ gain = 256;
+ }
+ if (gain < 0) {
+ gain = 0;
+ }
+ ioctl(OutHandle, AMAUDIO_IOC_MUSIC_GAIN, gain);
+ ALOGD("%s, music gain :%d!\n", __FUNCTION__, gain);
+ pthread_mutex_unlock(&gpAmlDevice->out.lock);
+ return 0;
+}
+
+int set_left_gain(int left_gain) {
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__);
+ return -1;
+ }
+
+ int OutHandle = gpAmlDevice->out.amAudio_OutHandle;
+ if (OutHandle < 0) {
+ ALOGE("%s, amaudio out handle error!\n", __FUNCTION__);
+ return -1;
+ }
+ pthread_mutex_lock(&gpAmlDevice->out.lock);
+ if (left_gain > 256) {
+ left_gain = 256;
+ }
+ if (left_gain < 0) {
+ left_gain = 0;
+ }
+ ioctl(OutHandle, AMAUDIO_IOC_MIC_LEFT_GAIN, left_gain);
+ ALOGD("%s, left mic gain :%d!\n", __FUNCTION__, left_gain);
+ pthread_mutex_unlock(&gpAmlDevice->out.lock);
+ return 0;
+}
+
+int set_right_gain(int right_gain) {
+ if (gpAmlDevice == NULL) {
+ ALOGE("%s, aml audio is not open, must open it first!\n", __FUNCTION__);
+ return -1;
+ }
+ int OutHandle = gpAmlDevice->out.amAudio_OutHandle;
+ if (OutHandle < 0) {
+ ALOGE("%s, amaudio out handle error!\n", __FUNCTION__);
+ return -1;
+ }
+ pthread_mutex_lock(&gpAmlDevice->out.lock);
+ if (right_gain > 256) {
+ right_gain = 256;
+ }
+ if (right_gain < 0) {
+ right_gain = 0;
+ }
+ ioctl(OutHandle, AMAUDIO_IOC_MIC_RIGHT_GAIN, right_gain);
+ ALOGD("%s, right mic gain :%d!\n", __FUNCTION__, right_gain);
+ pthread_mutex_unlock(&gpAmlDevice->out.lock);
+ return 0;
+}
+
+int SetDumpDataFlag(int tmp_flag) {
+ int tmp_val;
+ tmp_val = gDumpDataFlag;
+ gDumpDataFlag = tmp_flag;
+ return tmp_val;
+}
+
+int GetDumpDataFlag(void) {
+ int tmp_val = 0;
+ tmp_val = gDumpDataFlag;
+ return tmp_val;
+}
+
+static void DoDumpData(void *data_buf, int size, int aud_src_type) {
+ int tmp_type = 0;
+ char prop_value[PROPERTY_VALUE_MAX] = { 0 };
+ char file_path_01[PROPERTY_VALUE_MAX] = { 0 };
+ char file_path_02[PROPERTY_VALUE_MAX] = { 0 };
+
+ if (GetDumpDataFlag() == 0) {
+ return;
+ }
+
+ memset(prop_value, '\0', PROPERTY_VALUE_MAX);
+ property_get("audio.dumpdata.en", prop_value, "null");
+ if (strcasecmp(prop_value, "null") == 0
+ || strcasecmp(prop_value, "0") == 0) {
+ if (gDumpDataFd1 >= 0) {
+ close(gDumpDataFd1);
+ gDumpDataFd1 = -1;
+ }
+ if (gDumpDataFd2 >= 0) {
+ close(gDumpDataFd2);
+ gDumpDataFd2 = -1;
+ }
+
+ return;
+ }
+
+ tmp_type = CC_DUMP_SRC_TYPE_INPUT;
+ property_get("audio.dumpdata.src", prop_value, "null");
+ if (strcasecmp(prop_value, "null") == 0
+ || strcasecmp(prop_value, "input") == 0) {
+ tmp_type = CC_DUMP_SRC_TYPE_INPUT;
+ } else if (strcasecmp(prop_value, "output") == 0) {
+ tmp_type = CC_DUMP_SRC_TYPE_OUTPUT;
+ } else if (strcasecmp(prop_value, "input,output") == 0) {
+ tmp_type = CC_DUMP_SRC_TYPE_IN_OUT;
+ } else if (strcasecmp(prop_value, "output,input") == 0) {
+ tmp_type = CC_DUMP_SRC_TYPE_OUT_IN;
+ }
+
+ if (tmp_type == CC_DUMP_SRC_TYPE_INPUT
+ || tmp_type == CC_DUMP_SRC_TYPE_OUTPUT) {
+ if (tmp_type != aud_src_type) {
+ return;
+ }
+ }
+
+ memset(file_path_01, '\0', PROPERTY_VALUE_MAX);
+ property_get("audio.dumpdata.path", file_path_01, "null");
+ if (strcasecmp(file_path_01, "null") == 0) {
+ file_path_01[0] = '\0';
+ }
+
+ if (tmp_type == CC_DUMP_SRC_TYPE_IN_OUT
+ || tmp_type == CC_DUMP_SRC_TYPE_OUT_IN) {
+ memset(file_path_02, '\0', PROPERTY_VALUE_MAX);
+ property_get("audio.dumpdata.path2", file_path_02, "null");
+ if (strcasecmp(file_path_02, "null") == 0) {
+ file_path_02[0] = '\0';
+ }
+ }
+
+ if (gDumpDataFd1 < 0 && file_path_01[0] != '\0') {
+ if (access(file_path_01, 0) == 0) {
+ gDumpDataFd1 = open(file_path_01, O_RDWR | O_SYNC);
+ if (gDumpDataFd1 < 0) {
+ ALOGE("%s, Open device file \"%s\" error: %s.\n", __FUNCTION__,
+ file_path_01, strerror(errno));
+ }
+ } else {
+ gDumpDataFd1 = open(file_path_01, O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR);
+ if (gDumpDataFd1 < 0) {
+ ALOGE("%s, Create device file \"%s\" error: %s.\n",
+ __FUNCTION__, file_path_01, strerror(errno));
+ }
+ }
+ }
+
+ if (gDumpDataFd2 < 0 && file_path_02[0] != '\0'
+ && (tmp_type == CC_DUMP_SRC_TYPE_IN_OUT
+ || tmp_type == CC_DUMP_SRC_TYPE_OUT_IN)) {
+ if (access(file_path_02, 0) == 0) {
+ gDumpDataFd2 = open(file_path_02, O_RDWR | O_SYNC);
+ if (gDumpDataFd2 < 0) {
+ ALOGE("%s, Open device file \"%s\" error: %s.\n", __FUNCTION__,
+ file_path_02, strerror(errno));
+ }
+ } else {
+ gDumpDataFd2 = open(file_path_02, O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR);
+ if (gDumpDataFd2 < 0) {
+ ALOGE("%s, Create device file \"%s\" error: %s.\n",
+ __FUNCTION__, file_path_02, strerror(errno));
+ }
+ }
+ }
+
+ if (tmp_type == CC_DUMP_SRC_TYPE_IN_OUT) {
+ if (aud_src_type == CC_DUMP_SRC_TYPE_INPUT && gDumpDataFd1 >= 0) {
+ write(gDumpDataFd1, data_buf, size);
+ } else if (aud_src_type == CC_DUMP_SRC_TYPE_OUTPUT
+ && gDumpDataFd2 >= 0) {
+ write(gDumpDataFd2, data_buf, size);
+ }
+ } else if (tmp_type == CC_DUMP_SRC_TYPE_OUT_IN) {
+ if (aud_src_type == CC_DUMP_SRC_TYPE_OUTPUT && gDumpDataFd1 >= 0) {
+ write(gDumpDataFd1, data_buf, size);
+ } else if (aud_src_type == CC_DUMP_SRC_TYPE_INPUT
+ && gDumpDataFd2 >= 0) {
+ write(gDumpDataFd2, data_buf, size);
+ }
+ } else {
+ if (gDumpDataFd1 >= 0) {
+ write(gDumpDataFd1, data_buf, size);
+ }
+ }
+}
diff --git a/libTVaudio/audio/aml_audio.h b/libTVaudio/audio/aml_audio.h
new file mode 100644
index 0000000..1e37f07
--- a/dev/null
+++ b/libTVaudio/audio/aml_audio.h
@@ -0,0 +1,73 @@
+#ifndef __TV_AML_AUDIO_H__
+#define __TV_AML_AUDIO_H__
+
+#include "audio_effect_control.h"
+#include "audio_usb_check.h"
+
+/*
+ In this system, input device is always ALSA_in, but There are 3 devices outpurt.
+ For TV application, AMAUDIO OUT is suggested. This mode has low latency.
+ IF HMDI/SPDIF has raw data input, ANDROID OUT is suggested.
+ */
+#define CC_OUT_USE_AMAUDIO (0)
+#define CC_OUT_USE_ALSA (1)
+#define CC_OUT_USE_ANDROID (2)
+
+/*
+ mix mode:
+ DIRECT, input is direct to output, cover the local sound.
+ INTER_MIX, left and right input channels mix first as one channel, and then mix with local sound.
+ DIRECT_MIX,left input channel mix with local left channel, right input channel mix with local right channel
+ */
+#define CC_OUT_MODE_DIRECT (0)
+#define CC_OUT_MODE_INTER_MIX (1)
+#define CC_OUT_MODE_DIRECT_MIX (2)
+
+/*
+ There are two input device, spdif or i2s.
+ */
+#define CC_IN_USE_I2S_DEVICE (0)
+#define CC_IN_USE_SPDIF_DEVICE (1)
+
+#define CC_SINGLE_OUTPUT (0)
+#define CC_DOUBLE_OUTPUT (1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct circle_buffer {
+ pthread_mutex_t lock;
+ char *start_add;
+ char *rd;
+ char *wr;
+ int size;
+};
+
+/*
+ In this system, input stream sample rate can be set from 8K-48K, and output sample rate is fixed 48K.
+ When input stream sample rate is different from output, inlined reample is in operation. If input stream sr is not set,
+ the input stream is default 48K.
+ */
+int GetOutputdevice(void);
+int aml_audio_open(unsigned int sr, int input_device, int output_device);
+int aml_audio_close(void);
+int check_input_stream_sr(unsigned int sr);
+int SetDumpDataFlag(int tmp_flag);
+int GetDumpDataFlag();
+int set_output_mode(int mode);
+int set_music_gain(int gain);
+int set_left_gain(int left_gain);
+int set_right_gain(int right_gain);
+int buffer_read(struct circle_buffer *tmp, char* buffer, size_t bytes);
+int buffer_write(struct circle_buffer *tmp, char* buffer, size_t bytes);
+int getUSBCheckFlag();
+int set_android_volume_enable(int enable);
+int set_android_volume(int left, int right);
+int set_output_record_enable(int enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TV_AML_AUDIO_H__
diff --git a/libTVaudio/audio/android_out.cpp b/libTVaudio/audio/android_out.cpp
new file mode 100644
index 0000000..65922d9
--- a/dev/null
+++ b/libTVaudio/audio/android_out.cpp
@@ -0,0 +1,160 @@
+/*
+ android_out.cpp
+ New an audio track in android, but no data in this track. Only push FIFO pointer.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <cutils/log.h>
+
+#include <media/AudioTrack.h>
+
+#include "audio_usb_check.h"
+#include "android_out.h"
+#include "aml_audio.h"
+#include "DDP_media_source.h"
+
+using namespace android;
+
+#define LOG_TAG "android_out"
+
+static AudioTrack *glpTracker = NULL;
+
+#if ANDROID_PLATFORM_SDK_VERSION >= 19
+static sp<AudioTrack> gmpAudioTracker;
+#endif
+
+extern struct circle_buffer android_out_buffer;
+extern struct circle_buffer DDP_out_buffer;
+extern int output_record_enable;
+extern pthread_mutex_t device_change_lock;
+
+int I2S_state = 0;
+
+static void AudioTrackCallback(int event, void* user, void *info) {
+ AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info);
+
+ if (event != AudioTrack::EVENT_MORE_DATA) {
+ ALOGD("%s, audio track envent = %d!\n", __FUNCTION__, event);
+ return;
+ }
+ if (buffer == NULL || buffer->size == 0) {
+ return;
+ }
+
+ int bytes = 0;
+
+ pthread_mutex_lock(&device_change_lock);
+
+ if (GetOutputdevice() == 1) {
+ bytes = buffer_read(&android_out_buffer, (char *) buffer->raw,
+ buffer->size);
+ if (bytes < 0)
+ buffer->size = 0;
+ } else if (GetOutputdevice() == 2) {
+ bytes = buffer_read(&DDP_out_buffer, (char *) buffer->raw,
+ buffer->size);
+ if (bytes < 0)
+ buffer->size = 0;
+ } else {
+ if (output_record_enable == 1) {
+ bytes = buffer_read(&android_out_buffer, (char *) buffer->raw,
+ buffer->size);
+ if (bytes < 0)
+ buffer->size = 0;
+ } else {
+ memset(buffer->i16, 0, buffer->size);
+ }
+ }
+
+ pthread_mutex_unlock(&device_change_lock);
+ I2S_state += 1;
+ return;
+}
+
+static int AudioTrackRelease(void) {
+#if ANDROID_PLATFORM_SDK_VERSION < 19
+ if (glpTracker != NULL) {
+ glpTracker->stop();
+ delete glpTracker;
+ glpTracker = NULL;
+ }
+#else
+ if (glpTracker != NULL ) {
+ glpTracker->stop();
+ glpTracker = NULL;
+ }
+
+ if (gmpAudioTracker != NULL ) {
+ gmpAudioTracker.clear();
+ }
+#endif
+ return 0;
+}
+
+static int AudioTrackInit(void) {
+ status_t Status;
+
+ ALOGD("%s, entering...\n", __FUNCTION__);
+
+ I2S_state = 0;
+
+#if ANDROID_PLATFORM_SDK_VERSION < 19
+ glpTracker = new AudioTrack();
+ if (glpTracker == NULL) {
+ ALOGE("%s, new AudioTrack failed.\n", __FUNCTION__);
+ return -1;
+ }
+#else
+ gmpAudioTracker = new AudioTrack();
+ if (gmpAudioTracker == NULL) {
+ ALOGE("%s, new AudioTrack failed.\n", __FUNCTION__);
+ return -1;
+ }
+ glpTracker = gmpAudioTracker.get();
+#endif
+
+ Status = glpTracker->set(AUDIO_STREAM_MUSIC, 48000, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_STEREO, 0, AUDIO_OUTPUT_FLAG_NONE,
+ AudioTrackCallback, NULL, 0, 0, false, 0);
+
+ if (Status != NO_ERROR) {
+ ALOGE("%s, AudioTrack set failed.\n", __FUNCTION__);
+
+ AudioTrackRelease();
+ return -1;
+ }
+
+ Status = glpTracker->initCheck();
+ if (Status != NO_ERROR) {
+ ALOGE("%s, AudioTrack initCheck failed.\n", __FUNCTION__);
+
+ AudioTrackRelease();
+ return -1;
+ }
+
+ glpTracker->start();
+
+ Status = glpTracker->setVolume(1.0, 1.0);
+ if (Status != NO_ERROR) {
+ ALOGE("%s, AudioTrack setVolume failed.\n", __FUNCTION__);
+
+ AudioTrackRelease();
+ return -1;
+ }
+
+ ALOGD("%s, exit...\n", __FUNCTION__);
+
+ return 0;
+}
+
+int new_android_audiotrack(void) {
+ return AudioTrackInit();
+}
+
+int release_android_audiotrack(void) {
+ return AudioTrackRelease();
+}
+
diff --git a/libTVaudio/audio/android_out.h b/libTVaudio/audio/android_out.h
new file mode 100644
index 0000000..9deef75
--- a/dev/null
+++ b/libTVaudio/audio/android_out.h
@@ -0,0 +1,15 @@
+#ifndef __TV_ANDROID_OUT_H__
+#define __TV_ANDROID_OUT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int new_android_audiotrack(void);
+int release_android_audiotrack(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TV_ANDROID_OUT_H__
diff --git a/libTVaudio/audio/audio_amaudio.cpp b/libTVaudio/audio/audio_amaudio.cpp
new file mode 100644
index 0000000..5ad5f51
--- a/dev/null
+++ b/libTVaudio/audio/audio_amaudio.cpp
@@ -0,0 +1,209 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <math.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#include "audio_effect_control.h"
+#include "../audio_amaudio.h"
+
+#define LOG_TAG "LibAudioCtl"
+
+int amAudioOpen(unsigned int sr, int input_device, int output_device) {
+ return aml_audio_open(sr, input_device, output_device);
+}
+
+int amAudioClose(void) {
+ return aml_audio_close();
+}
+
+int amAudioSetInputSr(unsigned int sr, int input_device, int output_device) {
+ int tmpRet = 0;
+
+ if (check_input_stream_sr(sr) < 0) {
+ ALOGE("%s, The sample rate (%u) is invalid!\n", __FUNCTION__, sr);
+ return -1;
+ }
+
+ ALOGD("%s, sr = %d\n", __FUNCTION__, sr);
+
+ tmpRet |= amAudioClose();
+ tmpRet |= amAudioOpen(sr, input_device, output_device);
+
+ return tmpRet;
+}
+
+int amAudioSetOutputSr(unsigned int sr, int output_device) {
+ ALOGD("%s, sr = %d\n", __FUNCTION__, sr);
+ ALOGE("%s, amAudio not support set output sample rate\n", __FUNCTION__);
+
+ return 0;
+}
+
+int amAudioSetDumpDataFlag(int tmp_flag) {
+ return SetDumpDataFlag(tmp_flag);
+}
+
+int amAudioGetDumpDataFlag() {
+ return GetDumpDataFlag();
+}
+
+int amAudioSetOutputMode(int mode) {
+ return set_output_mode(mode);
+}
+
+int amAudioSetMusicGain(int gain) {
+ return set_music_gain(gain);
+}
+
+int amAudioSetLeftGain(int gain) {
+ return set_left_gain(gain);
+}
+
+int amAudioSetRightGain(int gain) {
+ return set_right_gain(gain);
+}
+
+int amAudioSetAndroidVolumeEnable(int enable) {
+ return set_android_volume_enable(enable);
+}
+
+int amAudioSetAndroidVolume(int left, int right) {
+ return set_android_volume(left, right);
+}
+
+int amAudioSetEQGain(int gain_val_buf[], int buf_item_cnt) {
+ int i = 0;
+ int tmp_buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+ if (buf_item_cnt > 5) {
+ buf_item_cnt = 5;
+ }
+
+ for (i = 0; i < buf_item_cnt; i++) {
+ tmp_buf[i] = gain_val_buf[i];
+ }
+
+ HPEQ_setParameter(tmp_buf[0], tmp_buf[1], tmp_buf[2], tmp_buf[3],
+ tmp_buf[4]);
+
+ return 0;
+}
+
+int amAudioGetEQGain(int gain_val_buf[], int buf_item_cnt) {
+ int i = 0, tmp_cnt = 0;
+ int tmp_buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+ HPEQ_getParameter(tmp_buf);
+
+ tmp_cnt = buf_item_cnt;
+
+ if (buf_item_cnt > 5) {
+ tmp_cnt = 5;
+ }
+
+ for (i = 0; i < buf_item_cnt; i++) {
+ if (i < tmp_cnt) {
+ gain_val_buf[i] = tmp_buf[i];
+ } else {
+ gain_val_buf[i] = 0;
+ }
+ }
+
+ return 0;
+}
+
+int amAudioSetEQEnable(int en_val) {
+ return HPEQ_enable(en_val);
+}
+
+int amAudioGetEQEnable() {
+ return 0;
+}
+
+int amAudioSetDoubleOutput(int en_val, unsigned int sr, int input_device,
+ int output_device) {
+ return amAudioSetInputSr(sr, input_device, output_device);
+}
+
+int amAudioSetOutputRecordEnable(int enable) {
+ return 0; //set_output_record_enable(enable);
+}
+
+#define CC_SET_TYPE_TRUBASS_SPEAKERSIZE (0)
+#define CC_SET_TYPE_TRUBASS_GAIN (1)
+#define CC_SET_TYPE_DIALOGCLARITY_GAIN (2)
+#define CC_SET_TYPE_DEFINITION_GAIN (3)
+#define CC_SET_TYPE_SURROUND_GAIN (4)
+#define CC_SET_TYPE_MAX (CC_SET_TYPE_SURROUND_GAIN)
+
+static int amAudioSetSRSParameter(int set_type, int gain_val) {
+ int tmp_buf[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ if (srs_getParameter(tmp_buf) < 0) {
+ ALOGE("%s, srs_getParameter error.\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (set_type < 0 || set_type > CC_SET_TYPE_MAX) {
+ ALOGE("%s, not support param set type (%d).\n", __FUNCTION__, set_type);
+ return -1;
+ }
+
+ tmp_buf[set_type] = gain_val;
+
+ return srs_setParameter(tmp_buf);
+}
+
+int amAudioSetSRSSurroundSwitch(int switch_val) {
+ return srs_surround_enable(switch_val);
+}
+
+int amAudioSetSRSSurroundGain(int gain_val) {
+ return amAudioSetSRSParameter(CC_SET_TYPE_SURROUND_GAIN, gain_val);
+}
+
+int amAudioSetSRSTrubassSwitch(int switch_val) {
+ return srs_truebass_enable(switch_val);
+}
+
+int amAudioSetSRSTrubassGain(int gain_val) {
+ return amAudioSetSRSParameter(CC_SET_TYPE_TRUBASS_GAIN, gain_val);
+}
+
+int amAudioSetSRSDialogClaritySwitch(int switch_val) {
+ return srs_dialogclarity_enable(switch_val);
+}
+
+int amAudioSetSRSDialogClarityGain(int gain_val) {
+ return amAudioSetSRSParameter(CC_SET_TYPE_DIALOGCLARITY_GAIN, gain_val);
+}
+
+int amAudioSetSRSDefinitionGain(int gain_val) {
+ return amAudioSetSRSParameter(CC_SET_TYPE_DEFINITION_GAIN, gain_val);
+}
+
+int amAudioSetSRSTrubassSpeakerSize(int tmp_val) {
+ int tmp_buf[8] = { 40, 60, 100, 150, 200, 250, 300, 400 };
+ int gain_val = 40;
+
+ if (tmp_val >= 0 && tmp_val < (int) sizeof(tmp_buf)) {
+ gain_val = tmp_buf[tmp_val];
+ }
+
+ return amAudioSetSRSParameter(CC_SET_TYPE_TRUBASS_SPEAKERSIZE, gain_val);
+}
diff --git a/libTVaudio/audio/audio_effect_control.c b/libTVaudio/audio/audio_effect_control.c
new file mode 100644
index 0000000..02247b1
--- a/dev/null
+++ b/libTVaudio/audio/audio_effect_control.c
@@ -0,0 +1,423 @@
+/*
+ audio_effect_control.c
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <dlfcn.h>
+
+#include <cutils/log.h>
+
+#include "aml_audio.h"
+#include "audio_effect_control.h"
+
+#define LOG_TAG "audioeffect"
+
+//------------------------------------EQ control------------------------------------------------
+int (*EQ_process)(short *in, short *out, int framecount);
+int (*EQ_init)(void);
+int (*EQ_setParameter)(int band1, int band2, int band3, int band4, int band5);
+int (*EQ_getParameter)(int *band1, int *band2, int *band3, int *band4,
+ int *band5);
+int (*EQ_enable)(bool enable);
+int (*EQ_release)(void);
+
+static void *gEQLibHandler = NULL;
+
+int unload_EQ_lib(void) {
+ ALOGD("%s, entering...\n", __FUNCTION__);
+
+ HPEQ_release();
+
+ EQ_process = NULL;
+ EQ_init = NULL;
+ EQ_setParameter = NULL;
+ EQ_getParameter = NULL;
+ EQ_enable = NULL;
+ EQ_release = NULL;
+
+ if (gEQLibHandler != NULL) {
+ dlclose(gEQLibHandler);
+ gEQLibHandler = NULL;
+ }
+
+ return 0;
+}
+
+int load_EQ_lib(void) {
+ char *error;
+
+ unload_EQ_lib();
+
+ ALOGD("%s, entering...\n", __FUNCTION__);
+
+ gEQLibHandler = dlopen("/system/lib/soundfx/libhpeq.so", RTLD_NOW);
+ if (!gEQLibHandler) {
+ ALOGE("%s, failed to load EQ lib (libhpeq.so)\n", __FUNCTION__);
+ goto Error;
+ }
+
+ EQ_release = (int (*)(void))dlsym(gEQLibHandler, "HPEQ_release_api");
+ if (EQ_release == NULL) {
+ ALOGE("%s, fail find fun HPEQ_release_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ EQ_process = (int (*)(short*, short*,
+ int))dlsym(gEQLibHandler, "HPEQ_process_api");
+ if (EQ_process == NULL) {
+ ALOGE("%s, fail find fun HPEQ_process_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ EQ_init = (int (*)(void))dlsym(gEQLibHandler, "HPEQ_init_api");
+ if (EQ_init == NULL) {
+ ALOGE("%s, fail find fun HPEQ_init_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ EQ_setParameter = (int (*)(int, int, int, int,
+ int))dlsym(gEQLibHandler, "HPEQ_setParameter_api");
+ if (EQ_setParameter == NULL) {
+ ALOGE("%s, fail find fun HPEQ_setParameter_api\n", __FUNCTION__);
+ goto Error;
+ }
+ EQ_getParameter = (int (*)(int*, int*, int*, int*,
+ int*))dlsym(gEQLibHandler, "HPEQ_getParameter_api");
+ if (EQ_getParameter == NULL) {
+ ALOGE("%s, fail find fun HPEQ_getParameter_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ EQ_enable = (int (*)(bool))dlsym(gEQLibHandler, "HPEQ_enable_api");
+ if (EQ_enable == NULL) {
+ ALOGE("%s, fail find fun HPEQ_enable_api()\n", __FUNCTION__);
+ goto Error;
+ }
+
+ return 0;
+
+ Error: //
+ unload_EQ_lib();
+ return -1;
+}
+
+int HPEQ_process(short *in, short *out, int framecount) {
+ int ret = 0;
+
+ if (EQ_process == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*EQ_process)(in, out, framecount);
+
+ return ret;
+}
+
+int HPEQ_init(void) {
+ int ret = 0;
+
+ if (EQ_init == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*EQ_init)();
+
+ return ret;
+}
+
+int HPEQ_setParameter(int band1, int band2, int band3, int band4, int band5) {
+ int ret = 0;
+
+ if (EQ_setParameter == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*EQ_setParameter)(band1, band2, band3, band4, band5);
+
+ return ret;
+}
+int HPEQ_getParameter(int EQ_user_config[]) {
+ int ret = 0;
+
+ if (EQ_getParameter == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ (*EQ_getParameter)(&EQ_user_config[0], &EQ_user_config[1],
+ &EQ_user_config[2], &EQ_user_config[3], &EQ_user_config[4]);
+
+ return 0;
+}
+
+int HPEQ_enable(bool enable) {
+ int ret = 0;
+
+ if (EQ_enable == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*EQ_enable)(enable);
+
+ return ret;
+}
+
+int HPEQ_release(void) {
+ int ret = 0;
+
+ if (EQ_release == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*EQ_release)();
+
+ return ret;
+}
+
+//-------------------------SRS control---------------------------------------------------------
+int (*SRS_init)(int sample_rate);
+int (*SRS_release)(void);
+int (*SRS_setParameter)(int truebass_spker_size, float truebass_gain,
+ float dialogclarity_gain, float definition_gain, float surround_gain);
+int (*SRS_getParameter)(int *truebass_spker_size, float *truebass_gain,
+ float *dialogclarity_gain, float *definition_gain,
+ float *surround_gain);
+int (*SRS_TRUEBASS_ENABLE)(int value);
+int (*SRS_DIALOGCLARITY_ENABLE)(int value);
+int (*SRS_SURROUND_ENABLE)(int value);
+int (*SRS_process)(short *in, short *out, int framecount);
+
+static void *gSRSLibHandler = NULL;
+
+int unload_SRS_lib(void) {
+ ALOGD("%s, entering...\n", __FUNCTION__);
+
+ srs_release();
+
+ SRS_release = NULL;
+ SRS_process = NULL;
+ SRS_init = NULL;
+ SRS_setParameter = NULL;
+ SRS_getParameter = NULL;
+ SRS_TRUEBASS_ENABLE = NULL;
+ SRS_DIALOGCLARITY_ENABLE = NULL;
+ SRS_SURROUND_ENABLE = NULL;
+
+ if (gSRSLibHandler != NULL) {
+ dlclose(gSRSLibHandler);
+ gSRSLibHandler = NULL;
+ }
+
+ return 0;
+}
+
+int load_SRS_lib(void) {
+ char *error;
+
+ unload_SRS_lib();
+
+ ALOGD("%s, entering...\n", __FUNCTION__);
+
+ gSRSLibHandler = dlopen("/system/lib/soundfx/libsrs.so", RTLD_NOW);
+ if (!gSRSLibHandler) {
+ ALOGE("%s, failed to load SRS lib (libsrs.so)\n", __FUNCTION__);
+ goto Error;
+ }
+
+ SRS_release = (int (*)(void))dlsym(gSRSLibHandler, "SRS_release_api");
+ if (SRS_release == NULL) {
+ ALOGE("%s, fail find fun SRS_release_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_process = (int (*)(short*, short*,
+ int))dlsym(gSRSLibHandler, "SRS_process_api");
+ if (SRS_process == NULL) {
+ ALOGE("%s, fail find fun SRS_process_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_init = (int (*)(int))dlsym(gSRSLibHandler, "SRS_init_api");
+ if (SRS_init == NULL) {
+ ALOGE("%s, fail find fun SRS_init_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_setParameter = (int (*)(int, float, float, float,
+ float))dlsym(gSRSLibHandler, "SRS_setParameter_api");
+ if (SRS_setParameter == NULL) {
+ ALOGE("%s, fail find fun SRS_setParameter_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_getParameter = (int (*)(int*, float*, float*, float*,
+ float*))dlsym(gSRSLibHandler, "SRS_getParameter_api");
+ if (SRS_getParameter == NULL) {
+ ALOGE("%s, fail find fun SRS_getParameter_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_TRUEBASS_ENABLE = (int (*)(
+ int))dlsym(gSRSLibHandler, "SRS_TRUEBASS_ENABLE_api");
+ if (SRS_TRUEBASS_ENABLE == NULL) {
+ ALOGE("%s, fail find fun SRS_TRUEBASS_ENABLE_api()\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_DIALOGCLARITY_ENABLE = (int (*)(
+ int))dlsym(gSRSLibHandler, "SRS_DIALOGCLARITY_ENABLE_api");
+ if (SRS_DIALOGCLARITY_ENABLE == NULL) {
+ ALOGE("%s, fail find fun SRS_DIALOGCLARITY_ENABLE_api\n", __FUNCTION__);
+ goto Error;
+ }
+ SRS_SURROUND_ENABLE = (int (*)(
+ int))dlsym(gSRSLibHandler, "SRS_SURROUND_ENABLE_api");
+ if (SRS_SURROUND_ENABLE == NULL) {
+ ALOGE("%s, fail find fun SRS_SURROUND_ENABLE_api\n", __FUNCTION__);
+ goto Error;
+ }
+
+ return 0;
+
+ Error: //
+ unload_SRS_lib();
+ return -1;
+}
+
+int srs_init(int sample_rate) {
+ int ret = 0;
+
+ if (SRS_init == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*SRS_init)(sample_rate);
+
+ return ret;
+}
+
+int srs_release(void) {
+ int ret = 0;
+
+ if (SRS_release == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*SRS_release)();
+
+ return ret;
+}
+
+int srs_setParameter(int SRS_user_config[]) {
+ int ret = 0;
+ int truebass_spker_size;
+ float truebass_gain;
+ float dialogclarity_gain;
+ float definition_gain;
+ float surround_gain;
+
+ if (SRS_setParameter == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (SRS_user_config == NULL) {
+ ALOGE("%s, SRS_user_config buf pointer is NULL.\n", __FUNCTION__);
+ return -1;
+ }
+
+ truebass_spker_size = SRS_user_config[0];
+ truebass_gain = (float) SRS_user_config[1] / (float) 100;
+ dialogclarity_gain = (float) SRS_user_config[1] / (float) 100;
+ definition_gain = (float) SRS_user_config[1] / (float) 100;
+ surround_gain = (float) SRS_user_config[1] / (float) 100;
+
+ ret = (*SRS_setParameter)(truebass_spker_size, truebass_gain,
+ dialogclarity_gain, definition_gain, surround_gain);
+
+ return ret;
+}
+
+int srs_getParameter(int SRS_user_config[]) {
+ int ret = 0;
+ int truebass_spker_size;
+ float truebass_gain;
+ float dialogclarity_gain;
+ float definition_gain;
+ float surround_gain;
+
+ if (SRS_getParameter == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (SRS_user_config == NULL) {
+ ALOGE("%s, SRS_user_config buf pointer is NULL.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*SRS_getParameter)(&truebass_spker_size, &truebass_gain,
+ &dialogclarity_gain, &definition_gain, &surround_gain);
+
+ SRS_user_config[0] = truebass_spker_size;
+ SRS_user_config[1] = (int) (truebass_gain * 100);
+ SRS_user_config[2] = (int) (dialogclarity_gain * 100);
+ SRS_user_config[3] = (int) (definition_gain * 100);
+ SRS_user_config[4] = (int) (surround_gain * 100);
+
+ return 0;
+}
+
+int srs_truebass_enable(int enable) {
+ int ret = 0;
+
+ if (SRS_TRUEBASS_ENABLE == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*SRS_TRUEBASS_ENABLE)(enable);
+
+ return ret;
+}
+
+int srs_dialogclarity_enable(int enable) {
+ int ret = 0;
+
+ if (SRS_DIALOGCLARITY_ENABLE == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*SRS_DIALOGCLARITY_ENABLE)(enable);
+
+ return ret;
+}
+
+int srs_surround_enable(int enable) {
+ int ret = 0;
+
+ if (SRS_SURROUND_ENABLE == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = (*SRS_SURROUND_ENABLE)(enable);
+
+ return ret;
+}
+
+int srs_process(short *in, short *out, int framecount) {
+ int output_framecount = 0;
+
+ //In SRS prosess, framecount must be aligned by 64.
+ int input_framecount = framecount >> 6 << 6;
+
+ if (SRS_process == NULL) {
+ ALOGE("%s, pls load lib first.\n", __FUNCTION__);
+ return -1;
+ }
+
+ output_framecount = (*SRS_process)(in, out, input_framecount);
+
+ return output_framecount << 2;
+}
diff --git a/libTVaudio/audio/audio_effect_control.h b/libTVaudio/audio/audio_effect_control.h
new file mode 100644
index 0000000..4e2cc7c
--- a/dev/null
+++ b/libTVaudio/audio/audio_effect_control.h
@@ -0,0 +1,48 @@
+#ifndef __TV_AUDIO_EFFECT_CONTROL_H__
+#define __TV_AUDIO_EFFECT_CONTROL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ When aml audio system is open, EQ is init, but not enable. Set EQ band value first, then enable it.
+ EQ has 5 bands, the gains are from -12dB to 12dB. When EQ is enabled, the main volume is 6 dB lowered.
+ */
+
+int unload_EQ_lib(void);
+int load_EQ_lib(void);
+int HPEQ_process(short *in, short *out, int framecount);
+int HPEQ_init(void);
+int HPEQ_setParameter(int band1, int band2, int band3, int band4, int band5);
+int HPEQ_getParameter(int EQ_user_config[]);
+int HPEQ_enable(bool enable);
+int HPEQ_release(void);
+
+/*
+ When aml audio system is open, SRS is init, but not enable. Set SRS parameters as default value.
+ truebass_spker_size = 2 (40, 60, 100, 150, 200, 250, 300, 400)Hz
+ truebass_gain = 0.3 (0.0~1.0)
+ dialogclarity_gain = 0.2 (0.0~1.0)
+ definition_gain = 0.3 (0.0~1.0)
+ surround_gain = 0.5 (0.0~1.0)
+ When set srs_truebass_enable(1), srs works in default value. You can set other values before enable.
+ SRS works only when framecount is aligned by 64, else it will make noise.
+ */
+
+int unload_SRS_lib(void);
+int load_SRS_lib(void);
+int srs_init(int sample_rate);
+int srs_release(void);
+int srs_setParameter(int SRS_user_config[]);
+int srs_getParameter(int SRS_user_config[]);
+int srs_truebass_enable(int enable);
+int srs_dialogclarity_enable(int enable);
+int srs_surround_enable(int enable);
+int srs_process(short *in, short *out, int framecount);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TV_AUDIO_EFFECT_CONTROL_H__
diff --git a/libTVaudio/audio/audio_usb_check.cpp b/libTVaudio/audio/audio_usb_check.cpp
new file mode 100644
index 0000000..2cbcc28
--- a/dev/null
+++ b/libTVaudio/audio/audio_usb_check.cpp
@@ -0,0 +1,29 @@
+/*
+ audio_usb_check.cpp
+ check usb audio device.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cutils/log.h>
+#include <media/AudioSystem.h>
+
+#include "audio_usb_check.h"
+
+#define LOG_TAG "audio_usb_check"
+
+namespace android {
+
+extern "C" int GetUsbAudioCheckFlag() {
+ int device = (int)AudioSystem::getDevicesForStream(AUDIO_STREAM_MUSIC);
+ return device;
+}
+
+}
+
+int createMonitorUsbHostBusThread() {
+ return 0;
+}
+
diff --git a/libTVaudio/audio/audio_usb_check.h b/libTVaudio/audio/audio_usb_check.h
new file mode 100644
index 0000000..8116c13
--- a/dev/null
+++ b/libTVaudio/audio/audio_usb_check.h
@@ -0,0 +1,18 @@
+#ifndef __TV_USB_AUDIO_CHECK_H__
+#define __TV_USB_AUDIO_CHECK_H__
+
+#define CC_USB_AUDIO_PLAYBACK_BIT_IND (0)
+#define CC_USB_AUDIO_CAPTURE_BIT_IND (1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int createMonitorUsbHostBusThread();
+int GetUsbAudioCheckFlag();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TV_USB_AUDIO_CHECK_H__
diff --git a/libTVaudio/audio_amaudio.h b/libTVaudio/audio_amaudio.h
new file mode 100644
index 0000000..eafaf88
--- a/dev/null
+++ b/libTVaudio/audio_amaudio.h
@@ -0,0 +1,38 @@
+#ifndef __TV_AUDIO_AMAUDIO_H__
+#define __TV_AUDIO_AMAUDIO_H__
+
+#include "audio/aml_audio.h"
+#include "audio/audio_usb_check.h"
+
+int amAudioOpen(unsigned int sr, int input_device, int output_device);
+int amAudioClose(void);
+int amAudioSetInputSr(unsigned int sr, int input_device, int output_device);
+int amAudioSetOutputSr(unsigned int sr, int output_device);
+int amAudioSetDumpDataFlag(int tmp_flag);
+int amAudioGetDumpDataFlag();
+
+int amAudioSetOutputMode(int mode);
+int amAudioSetMusicGain(int gain);
+int amAudioSetLeftGain(int gain);
+int amAudioSetRightGain(int gain);
+int amAudioSetAndroidVolumeEnable(int enable);
+int amAudioSetAndroidVolume(int left, int right);
+int amAudioSetOutputRecordEnable(int enable);
+int amAudioSetDoubleOutput(int en_val, unsigned int sr, int input_device,
+ int output_device);
+
+int amAudioSetEQGain(int gain_val_buf[], int buf_item_cnt);
+int amAudioGetEQGain(int gain_val_buf[], int buf_item_cnt);
+int amAudioSetEQEnable(int en_val);
+int amAudioGetEQEnable();
+
+int amAudioSetSRSSurroundSwitch(int switch_val);
+int amAudioSetSRSSurroundGain(int gain_val);
+int amAudioSetSRSTrubassSwitch(int switch_val);
+int amAudioSetSRSTrubassGain(int gain_val);
+int amAudioSetSRSDialogClaritySwitch(int switch_val);
+int amAudioSetSRSDialogClarityGain(int gain_val);
+int amAudioSetSRSDefinitionGain(int gain_val);
+int amAudioSetSRSTrubassSpeakerSize(int tmp_val);
+
+#endif //__TV_AUDIO_AMAUDIO_H__