summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/AudioFlinger.cpp')
-rw-r--r--services/audioflinger/AudioFlinger.cpp55
1 files changed, 42 insertions, 13 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 69560e5..780c0d2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2066,7 +2066,21 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
// The first time a track is added we wait
// for all its buffers to be filled before processing it
mAudioMixer->setActiveTrack(track->name());
- if (cblk->framesReady() && track->isReady() &&
+ // make sure that we have enough frames to mix one full buffer.
+ // enforce this condition only once to enable draining the buffer in case the client
+ // app does not call stop() and relies on underrun to stop:
+ // hence the test on (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed
+ // during last round
+ uint32_t minFrames = 1;
+ if (!track->isStopped() && !track->isPausing() &&
+ (track->mRetryCount >= kMaxTrackRetries)) {
+ if (t->sampleRate() == (int)mSampleRate) {
+ minFrames = mFrameCount;
+ } else {
+ minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1;
+ }
+ }
+ if ((cblk->framesReady() >= minFrames) && track->isReady() &&
!track->isPaused() && !track->isTerminated())
{
//LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
@@ -7014,11 +7028,17 @@ void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
int sessionId)
- : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0),
+ : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
{
mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ return;
+ }
+ mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+ thread->frameCount();
}
AudioFlinger::EffectChain::~EffectChain()
@@ -7086,22 +7106,31 @@ void AudioFlinger::EffectChain::process_l()
}
bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
(mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
- bool tracksOnSession = false;
+ // always process effects unless no more tracks are on the session and the effect tail
+ // has been rendered
+ bool doProcess = true;
if (!isGlobalSession) {
- tracksOnSession = (trackCnt() != 0);
- }
+ bool tracksOnSession = (trackCnt() != 0);
+
+ if (!tracksOnSession && mTailBufferCount == 0) {
+ doProcess = false;
+ }
- // if no track is active, input buffer must be cleared here as the mixer process
- // will not do it
- if (tracksOnSession &&
- activeTrackCnt() == 0) {
- size_t numSamples = thread->frameCount() * thread->channelCount();
- memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+ if (activeTrackCnt() == 0) {
+ // if no track is active and the effect tail has not been rendered,
+ // the input buffer must be cleared here as the mixer process will not do it
+ if (tracksOnSession || mTailBufferCount > 0) {
+ size_t numSamples = thread->frameCount() * thread->channelCount();
+ memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+ if (mTailBufferCount > 0) {
+ mTailBufferCount--;
+ }
+ }
+ }
}
size_t size = mEffects.size();
- // do not process effect if no track is present in same audio session
- if (isGlobalSession || tracksOnSession) {
+ if (doProcess) {
for (size_t i = 0; i < size; i++) {
mEffects[i]->process();
}