summaryrefslogtreecommitdiffstats
path: root/voip
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2011-07-25 12:02:16 -0700
committerEric Laurent <elaurent@google.com>2011-07-27 09:33:22 -0700
commit5fb3ba60afe68060ac1ed291f4a108fef8c622c3 (patch)
tree767d333b00b3b4e031bca5e42c7af43afd488d0b /voip
parentbce8effe75c5477eb42d4e1c4df609da962285a2 (diff)
downloadframeworks_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.mk3
-rw-r--r--voip/jni/rtp/AudioGroup.cpp81
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;
}
//------------------------------------------------------------------------------