diff options
author | Eric Laurent <elaurent@google.com> | 2011-07-25 12:02:16 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2011-07-27 09:33:22 -0700 |
commit | 5fb3ba60afe68060ac1ed291f4a108fef8c622c3 (patch) | |
tree | 767d333b00b3b4e031bca5e42c7af43afd488d0b /voip | |
parent | bce8effe75c5477eb42d4e1c4df609da962285a2 (diff) | |
download | frameworks_base-5fb3ba60afe68060ac1ed291f4a108fef8c622c3.zip frameworks_base-5fb3ba60afe68060ac1ed291f4a108fef8c622c3.tar.gz frameworks_base-5fb3ba60afe68060ac1ed291f4a108fef8c622c3.tar.bz2 |
Issue 3370834: No Echo canceler for SIP
Added detection of platfrom AEC in AudioGroup. If an AEC
is present, the SIP stack will use it, otherwise the echo suppressor
of the stack will be used.
Change-Id: I4aa45a8868466120f5f9fae71b491fe4ae1162c2
Diffstat (limited to 'voip')
-rw-r--r-- | voip/jni/rtp/Android.mk | 3 | ||||
-rw-r--r-- | voip/jni/rtp/AudioGroup.cpp | 81 |
2 files changed, 66 insertions, 18 deletions
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk index 47ed658..0815294 100644 --- a/voip/jni/rtp/Android.mk +++ b/voip/jni/rtp/Android.mk @@ -49,7 +49,8 @@ LOCAL_C_INCLUDES += \ frameworks/base/media/libstagefright/codecs/amrnb/enc/include \ frameworks/base/media/libstagefright/codecs/amrnb/enc/src \ frameworks/base/media/libstagefright/codecs/amrnb/dec/include \ - frameworks/base/media/libstagefright/codecs/amrnb/dec/src + frameworks/base/media/libstagefright/codecs/amrnb/dec/src \ + system/media/audio_effects/include LOCAL_CFLAGS += -fvisibility=hidden diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index 85ed1c8..529b425 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -40,7 +40,8 @@ #include <media/AudioRecord.h> #include <media/AudioTrack.h> #include <media/mediarecorder.h> - +#include <media/AudioEffect.h> +#include <audio_effects/effect_aec.h> #include <system/audio.h> #include "jni.h" @@ -481,6 +482,7 @@ public: bool sendDtmf(int event); bool add(AudioStream *stream); bool remove(int socket); + bool platformHasAec() { return mPlatformHasAec; } private: enum { @@ -491,6 +493,8 @@ private: LAST_MODE = 3, }; + bool checkPlatformAec(); + AudioStream *mChain; int mEventQueue; volatile int mDtmfEvent; @@ -499,6 +503,7 @@ private: int mSampleRate; int mSampleCount; int mDeviceSocket; + bool mPlatformHasAec; class NetworkThread : public Thread { @@ -550,6 +555,7 @@ AudioGroup::AudioGroup() mDeviceSocket = -1; mNetworkThread = new NetworkThread(this); mDeviceThread = new DeviceThread(this); + mPlatformHasAec = checkPlatformAec(); } AudioGroup::~AudioGroup() @@ -630,10 +636,6 @@ bool AudioGroup::setMode(int mode) if (mode == NORMAL && !strcmp(value, "herring")) { mode = ECHO_SUPPRESSION; } - if (mode == ECHO_SUPPRESSION && AudioSystem::getParameters( - 0, String8("ec_supported")) == "ec_supported=yes") { - mode = NORMAL; - } if (mMode == mode) { return true; } @@ -759,6 +761,25 @@ bool AudioGroup::NetworkThread::threadLoop() return true; } +bool AudioGroup::checkPlatformAec() +{ + effect_descriptor_t fxDesc; + uint32_t numFx; + + if (AudioEffect::queryNumberEffects(&numFx) != NO_ERROR) { + return false; + } + for (uint32_t i = 0; i < numFx; i++) { + if (AudioEffect::queryEffect(i, &fxDesc) != NO_ERROR) { + continue; + } + if (memcmp(&fxDesc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) { + return true; + } + } + return false; +} + bool AudioGroup::DeviceThread::threadLoop() { int mode = mGroup->mMode; @@ -798,10 +819,6 @@ bool AudioGroup::DeviceThread::threadLoop() } LOGD("latency: output %d, input %d", track.latency(), record.latency()); - // Initialize echo canceler. - EchoSuppressor echo(sampleCount, - (track.latency() + record.latency()) * sampleRate / 1000); - // Give device socket a reasonable buffer size. setsockopt(deviceSocket, SOL_SOCKET, SO_RCVBUF, &output, sizeof(output)); setsockopt(deviceSocket, SOL_SOCKET, SO_SNDBUF, &output, sizeof(output)); @@ -810,6 +827,33 @@ bool AudioGroup::DeviceThread::threadLoop() char c; while (recv(deviceSocket, &c, 1, MSG_DONTWAIT) == 1); + // check if platform supports echo cancellation and do not active local echo suppression in + // this case + EchoSuppressor *echo = NULL; + AudioEffect *aec = NULL; + if (mode == ECHO_SUPPRESSION) { + if (mGroup->platformHasAec()) { + aec = new AudioEffect(FX_IID_AEC, + NULL, + 0, + 0, + 0, + record.getSessionId(), + record.getInput()); + status_t status = aec->initCheck(); + if (status == NO_ERROR || status == ALREADY_EXISTS) { + aec->setEnabled(true); + } else { + delete aec; + aec = NULL; + } + } + // Create local echo suppressor if platform AEC cannot be used. + if (aec == NULL) { + echo = new EchoSuppressor(sampleCount, + (track.latency() + record.latency()) * sampleRate / 1000); + } + } // Start AudioRecord before AudioTrack. This prevents AudioTrack from being // disabled due to buffer underrun while waiting for AudioRecord. if (mode != MUTED) { @@ -843,7 +887,7 @@ bool AudioGroup::DeviceThread::threadLoop() track.releaseBuffer(&buffer); } else if (status != TIMED_OUT && status != WOULD_BLOCK) { LOGE("cannot write to AudioTrack"); - return true; + goto exit; } } @@ -859,7 +903,7 @@ bool AudioGroup::DeviceThread::threadLoop() record.releaseBuffer(&buffer); } else if (status != TIMED_OUT && status != WOULD_BLOCK) { LOGE("cannot read from AudioRecord"); - return true; + goto exit; } } } @@ -870,15 +914,18 @@ bool AudioGroup::DeviceThread::threadLoop() } if (mode != MUTED) { - if (mode == NORMAL) { - send(deviceSocket, input, sizeof(input), MSG_DONTWAIT); - } else { - echo.run(output, input); - send(deviceSocket, input, sizeof(input), MSG_DONTWAIT); + if (echo != NULL) { + LOGV("echo->run()"); + echo->run(output, input); } + send(deviceSocket, input, sizeof(input), MSG_DONTWAIT); } } - return false; + +exit: + delete echo; + delete aec; + return true; } //------------------------------------------------------------------------------ |