diff options
author | Glenn Kasten <gkasten@google.com> | 2014-06-11 17:10:46 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-06-10 22:06:31 +0000 |
commit | 0ac53364b79dc72ee0c09f0efc46a22ab4374dbf (patch) | |
tree | d2ae61d98423e9ea9ed865b7637a897f610344a1 /services | |
parent | 421c34ef58f89f4cc39737118bb58b762e84e1c9 (diff) | |
parent | ced6e74215937182fe2f9f6b0867f7c28ccd02c1 (diff) | |
download | frameworks_av-0ac53364b79dc72ee0c09f0efc46a22ab4374dbf.zip frameworks_av-0ac53364b79dc72ee0c09f0efc46a22ab4374dbf.tar.gz frameworks_av-0ac53364b79dc72ee0c09f0efc46a22ab4374dbf.tar.bz2 |
Merge "Fix non-monotonic AudioTrack::getTimestamp after pause" into lmp-preview-dev
Diffstat (limited to 'services')
-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 8d5dc7b..4e8a058 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -382,7 +382,10 @@ AudioFlinger::PlaybackThread::Track::Track( mIsInvalid(false), mAudioTrackServerProxy(NULL), mResumeToStopping(false), - mFlushHwPending(false) + mFlushHwPending(false), + mPreviousValid(false), + mPreviousFramesWritten(0) + // mPreviousTimestamp { if (mCblk == NULL) { return; @@ -847,27 +850,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; } |