diff options
author | Eric Laurent <elaurent@google.com> | 2012-03-13 19:33:56 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2012-03-13 19:51:46 -0700 |
commit | 2ca7b0f4515b844a8bcc42b0c45a60e1173ef570 (patch) | |
tree | 5667450de2c893e02398bdecdee844e4147da39a | |
parent | 22c420fc8998f1ac9764d187fea919a774154667 (diff) | |
download | wingray-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.cpp | 15 | ||||
-rw-r--r-- | libaudio/AudioPostProcessor.h | 2 |
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; |