From f609b661a610c79f615036fd6b9547afb1b364d4 Mon Sep 17 00:00:00 2001 From: John Grossman Date: Thu, 19 Apr 2012 12:08:17 -0700 Subject: [PATCH] TimedAudioTrack: Fix continuity threshold handling. DO NOT MERGE this change must be hand-merged into master due to directory restructuring. Fix issues with continuity threshold handling; notably + If the steady-state continuity threshold is exceeded, be sure to clear the on-time flag. Failure to do this will result in the system picking a new mix point which simply satisfies the steady-state continuity threshold instead of the startup threshold. Since we are putting a discontinuity in presentation anyway, we really want to pick a perfect point, not just an OK point. + Tighten the steady-state continuity threshold. It was currently set to 100mSec which is enormous. 4mSec (the new setting) is much more appropriate. On systems with a VCXO (like tungsten) this should never be wrong by more than a sample. If TimedAudioTracks are ever to be used on VCXO-less systems, this threshold should probably be a a parameter configurable by applications on a track by track basis so they can make the tradeoff between allowed error and frequency of disruptive corrections. + Reset the on-time flag if the mixer provides no PTS during a mix operation. This makes for a convenient way for the HAL to reset timed tracks when it makes changes for delay compensation across multiple outputs. Change-Id: I2cb23de5a3d1f75618abc1c8ab903db883837aa8 Signed-off-by: John Grossman --- services/audioflinger/AudioFlinger.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 18eb8ca5e361b..4052d6edbb559 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -4053,6 +4053,7 @@ status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer( if (pts == AudioBufferProvider::kInvalidPTS) { buffer->raw = 0; buffer->frameCount = 0; + mTimedAudioOutputOnTime = false; return INVALID_OPERATION; } @@ -4151,21 +4152,28 @@ status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer( // the current output position is within this threshold, then we will // concatenate the next input samples to the previous output const int64_t kSampleContinuityThreshold = - (static_cast(sampleRate()) << 32) / 10; + (static_cast(sampleRate()) << 32) / 250; // if this is the first buffer of audio that we're emitting from this track // then it should be almost exactly on time. const int64_t kSampleStartupThreshold = 1LL << 32; if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) || - (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) { + (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) { // the next input is close enough to being on time, so concatenate it // with the last output timedYieldSamples_l(buffer); - LOGVV("*** on time: head.pos=%d frameCount=%u", head.position(), buffer->frameCount); + LOGVV("*** on time: head.pos=%d frameCount=%u", + head.position(), buffer->frameCount); return NO_ERROR; - } else if (sampleDelta > 0) { + } + + // Looks like our output is not on time. Reset our on timed status. + // Next time we mix samples from our input queue, then should be within + // the StartupThreshold. + mTimedAudioOutputOnTime = false; + if (sampleDelta > 0) { // the gap between the current output position and the proper start of // the next input sample is too big, so fill it with silence uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;