diff options
author | Glenn Kasten <gkasten@google.com> | 2014-06-12 00:03:41 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-06-12 00:03:41 +0000 |
commit | 14c403fbab456a4a63586a767fbae498f5f8c260 (patch) | |
tree | cb0cd7d78276aa28bbd780e5ccbacf08cd688eb5 /services | |
parent | 999c78d17f635e93f10fbad0a83cdfb4f41228f2 (diff) | |
parent | 0ac53364b79dc72ee0c09f0efc46a22ab4374dbf (diff) | |
download | frameworks_av-14c403fbab456a4a63586a767fbae498f5f8c260.zip frameworks_av-14c403fbab456a4a63586a767fbae498f5f8c260.tar.gz frameworks_av-14c403fbab456a4a63586a767fbae498f5f8c260.tar.bz2 |
am 0ac53364: Merge "Fix non-monotonic AudioTrack::getTimestamp after pause" into lmp-preview-dev
* commit '0ac53364b79dc72ee0c09f0efc46a22ab4374dbf':
Fix non-monotonic AudioTrack::getTimestamp after pause
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; } |