diff options
-rw-r--r-- | include/private/media/AudioTrackShared.h | 3 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 18 | ||||
-rw-r--r-- | services/audioflinger/Threads.h | 11 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 14 |
4 files changed, 44 insertions, 2 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 1379379..ad7409d 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -422,6 +422,9 @@ public: // Return the total number of frames which AudioFlinger desired but were unavailable, // and thus which resulted in an underrun. virtual uint32_t getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; } + + // Return the total number of frames that AudioFlinger has obtained and released + virtual size_t framesReleased() const { return mCblk->mServer; } }; class StaticAudioTrackServerProxy : public AudioTrackServerProxy { diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 2c2931f..bc01ede 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -943,7 +943,9 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mDraining(false), mScreenState(AudioFlinger::mScreenState), // index 0 is reserved for normal mixer's submix - mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1) + mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1), + // mLatchD, mLatchQ, + mLatchDValid(false), mLatchQValid(false) { snprintf(mName, kNameLength, "AudioOut_%X", id); mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mName); @@ -1818,6 +1820,14 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write() } else { bytesWritten = framesWritten; } + status_t status = INVALID_OPERATION; // mLatchD.mTimestamp is invalid + if (status == NO_ERROR) { + size_t totalFramesWritten = mNormalSink->framesWritten(); + if (totalFramesWritten >= mLatchD.mTimestamp.mPosition) { + mLatchD.mUnpresentedFrames = totalFramesWritten - mLatchD.mTimestamp.mPosition; + mLatchDValid = true; + } + } // otherwise use the HAL / AudioStreamOut directly } else { // Direct output and offload threads @@ -2096,6 +2106,12 @@ bool AudioFlinger::PlaybackThread::threadLoop() logString = NULL; } + if (mLatchDValid) { + mLatchQ = mLatchD; + mLatchDValid = false; + mLatchQValid = true; + } + if (checkForNewParameters_l()) { cacheParameters_l(); } diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 31d5323..1333de2 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -606,6 +606,17 @@ protected: // accessed by both binder threads and within threadLoop(), lock on mutex needed unsigned mFastTrackAvailMask; // bit i set if fast track [i] is available virtual void flushOutput_l(); + +private: + // timestamp latch: + // D input is written by threadLoop_write while mutex is unlocked, and read while locked + // Q output is written while locked, and read while locked + struct { + AudioTimestamp mTimestamp; + uint32_t mUnpresentedFrames; + } mLatchD, mLatchQ; + bool mLatchDValid; // true means mLatchD is valid, and clock it into latch at next opportunity + bool mLatchQValid; // true means mLatchQ is valid }; class MixerThread : public PlaybackThread { diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 687217b..9622709 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -724,7 +724,19 @@ status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& times } Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); - return INVALID_OPERATION; + if (!playbackThread->mLatchQValid) { + return INVALID_OPERATION; + } + uint32_t unpresentedFrames = + ((int64_t) playbackThread->mLatchQ.mUnpresentedFrames * mSampleRate) / + playbackThread->mSampleRate; + uint32_t framesWritten = mAudioTrackServerProxy->framesReleased(); + if (framesWritten < unpresentedFrames) { + return INVALID_OPERATION; + } + timestamp.mPosition = framesWritten - unpresentedFrames; + timestamp.mTime = playbackThread->mLatchQ.mTimestamp.mTime; + return NO_ERROR; } status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId) |