diff options
author | Glenn Kasten <gkasten@google.com> | 2014-06-09 17:12:32 -0700 |
---|---|---|
committer | Glenn Kasten <gkasten@google.com> | 2014-06-10 15:51:52 -0700 |
commit | ced6e74215937182fe2f9f6b0867f7c28ccd02c1 (patch) | |
tree | 576dcfc6d7631c817a3ecd65387e3ae64b41230a /services/audioflinger | |
parent | 0d843fdc91c98d447c3c3e357020d07b783c7bc0 (diff) | |
download | frameworks_av-ced6e74215937182fe2f9f6b0867f7c28ccd02c1.zip frameworks_av-ced6e74215937182fe2f9f6b0867f7c28ccd02c1.tar.gz frameworks_av-ced6e74215937182fe2f9f6b0867f7c28ccd02c1.tar.bz2 |
Fix non-monotonic AudioTrack::getTimestamp after pause
Bug: 15523502
Change-Id: Ifd4aa7fca197bc041c1620fc3f7d953a8902551a
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/PlaybackTracks.h | 6 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 33 |
2 files changed, 36 insertions, 3 deletions
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 6f1f293..6130084 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -157,6 +157,12 @@ private: AudioTrackServerProxy* mAudioTrackServerProxy; bool mResumeToStopping; // track was paused in stopping state. bool mFlushHwPending; // track requests for thread flush + + // for last call to getTimestamp + bool mPreviousValid; + uint32_t mPreviousFramesWritten; + AudioTimestamp mPreviousTimestamp; + }; // end of Track class TimedTrack : public Track { diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index f698fa2..cf71d65 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -370,7 +370,10 @@ AudioFlinger::PlaybackThread::Track::Track( mIsInvalid(false), mAudioTrackServerProxy(NULL), mResumeToStopping(false), - mFlushHwPending(false) + mFlushHwPending(false), + mPreviousValid(false), + mPreviousFramesWritten(0) + // mPreviousTimestamp { if (mCblk == NULL) { return; @@ -835,27 +838,51 @@ status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& times { // Client should implement this using SSQ; the unpresented frame count in latch is irrelevant if (isFastTrack()) { + // FIXME no lock held to set mPreviousValid = false return INVALID_OPERATION; } sp<ThreadBase> thread = mThread.promote(); if (thread == 0) { + // FIXME no lock held to set mPreviousValid = false return INVALID_OPERATION; } Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); if (!isOffloaded()) { if (!playbackThread->mLatchQValid) { + mPreviousValid = false; return INVALID_OPERATION; } uint32_t unpresentedFrames = ((int64_t) playbackThread->mLatchQ.mUnpresentedFrames * mSampleRate) / playbackThread->mSampleRate; uint32_t framesWritten = mAudioTrackServerProxy->framesReleased(); + bool checkPreviousTimestamp = mPreviousValid && framesWritten >= mPreviousFramesWritten; if (framesWritten < unpresentedFrames) { + mPreviousValid = false; return INVALID_OPERATION; } - timestamp.mPosition = framesWritten - unpresentedFrames; - timestamp.mTime = playbackThread->mLatchQ.mTimestamp.mTime; + mPreviousFramesWritten = framesWritten; + uint32_t position = framesWritten - unpresentedFrames; + struct timespec time = playbackThread->mLatchQ.mTimestamp.mTime; + if (checkPreviousTimestamp) { + if (time.tv_sec < mPreviousTimestamp.mTime.tv_sec || + (time.tv_sec == mPreviousTimestamp.mTime.tv_sec && + time.tv_nsec < mPreviousTimestamp.mTime.tv_nsec)) { + ALOGW("Time is going backwards"); + } + // position can bobble slightly as an artifact; this hides the bobble + static const uint32_t MINIMUM_POSITION_DELTA = 8u; + if ((position <= mPreviousTimestamp.mPosition) || + (position - mPreviousTimestamp.mPosition) < MINIMUM_POSITION_DELTA) { + position = mPreviousTimestamp.mPosition; + time = mPreviousTimestamp.mTime; + } + } + timestamp.mPosition = position; + timestamp.mTime = time; + mPreviousTimestamp = timestamp; + mPreviousValid = true; return NO_ERROR; } |