summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2012-03-13 19:33:56 -0700
committerEric Laurent <elaurent@google.com>2012-03-13 19:51:46 -0700
commit2ca7b0f4515b844a8bcc42b0c45a60e1173ef570 (patch)
tree5667450de2c893e02398bdecdee844e4147da39a
parent22c420fc8998f1ac9764d187fea919a774154667 (diff)
downloadwingray-ics-mr1.tar.gz
fix issue when capturing with pre processingics-mr1
When capturing audio with AEC or NS enabled there is a risk that audio buffers are lost. This happens if the capture is started with a particular timing with regard to playback. A particular case if when placing an outgoing video chat with gTalk. The problem is with the mechanism used to pass buffers between the capture thread and the preprocessing thread. It is possible that the preprocessing thread locks in with the timing of the capture thread and always gets a condition where buffers are not ready in which case it will read new data from the driver causing every other buffer to be dropped. The fix consists in modifying the buffer sync mechanism and have the preprocessing thread wait for a condition in case the read buffer is not available yet. Change-Id: I8ff33f762d600d6dbe8b0dda58973e96d68d02f9
-rw-r--r--libaudio/AudioPostProcessor.cpp15
-rw-r--r--libaudio/AudioPostProcessor.h2
2 files changed, 16 insertions, 1 deletions
diff --git a/libaudio/AudioPostProcessor.cpp b/libaudio/AudioPostProcessor.cpp
index a94204d..2db86e5 100644
--- a/libaudio/AudioPostProcessor.cpp
+++ b/libaudio/AudioPostProcessor.cpp
@@ -141,6 +141,7 @@ void AudioPostProcessor::enableEcns(int value)
{
if (mEcnsEnabled!=value) {
LOGD("enableEcns() new %08x old %08x)", value, mEcnsEnabled);
+ mEcnsThread->broadcastReadCond();
mEcnsThread->requestExitAndWait();
stopEcns();
cleanupEcns();
@@ -666,6 +667,7 @@ int AudioPostProcessor::EcnsThread::readData(int fd, void * buffer, int bytes, i
run("AudioPostProcessor::EcnsThread", ANDROID_PRIORITY_HIGHEST);
mIsRunning = true;
}
+ mEcnsReadCond.signal();
if (mEcnsReadCond.waitRelative(mEcnsReadLock, seconds(1)) != NO_ERROR) {
LOGE("%s: ECNS thread is stalled.", __FUNCTION__);
mClientBuf = 0;
@@ -712,6 +714,17 @@ bool AudioPostProcessor::EcnsThread::threadLoop()
GETTIMEOFDAY(&mtv3, NULL);
mEcnsReadLock.lock();
ecnsStatus = mProcessor->applyUplinkEcns(mReadBuf, mReadSize, mRate);
+
+ // wait for client buffer if not ready
+ if (!mClientBuf) {
+ if(exitPending()) {
+ mEcnsReadLock.unlock();
+ goto error;
+ }
+ if (mEcnsReadCond.waitRelative(mEcnsReadLock, seconds(1)) != NO_ERROR) {
+ LOGE("%s: client stalled.", __FUNCTION__);
+ }
+ }
if (mClientBuf && mReadSize) {
// Give the buffer to the client.
memcpy(mClientBuf, mReadBuf, mReadSize);
@@ -719,8 +732,8 @@ bool AudioPostProcessor::EcnsThread::threadLoop()
ret1 = ::read(mFd, mReadBuf, mReadSize/2);
half_done = true;
GETTIMEOFDAY(&mtv7, NULL);
- mEcnsReadCond.signal();
mClientBuf = 0;
+ mEcnsReadCond.signal();
} else {
half_done = false;
LOGV("%s: Read overflow (ECNS sanity preserved)", __FUNCTION__);
diff --git a/libaudio/AudioPostProcessor.h b/libaudio/AudioPostProcessor.h
index 5ecf898..3a9ea29 100644
--- a/libaudio/AudioPostProcessor.h
+++ b/libaudio/AudioPostProcessor.h
@@ -117,6 +117,8 @@ public:
~EcnsThread();
int readData(int fd, void * buffer, int bytes, int rate,
AudioPostProcessor * pp);
+ void broadcastReadCond() { mEcnsReadCond.broadcast(); }
+
private:
bool threadLoop();
Mutex mEcnsReadLock;