Loading include/private/media/AudioTrackShared.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading services/audioflinger/Threads.cpp +17 −1 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -2096,6 +2106,12 @@ bool AudioFlinger::PlaybackThread::threadLoop() logString = NULL; } if (mLatchDValid) { mLatchQ = mLatchD; mLatchDValid = false; mLatchQValid = true; } if (checkForNewParameters_l()) { cacheParameters_l(); } Loading services/audioflinger/Threads.h +11 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading services/audioflinger/Tracks.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -724,8 +724,20 @@ status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& times } Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 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) { Loading Loading
include/private/media/AudioTrackShared.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
services/audioflinger/Threads.cpp +17 −1 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -2096,6 +2106,12 @@ bool AudioFlinger::PlaybackThread::threadLoop() logString = NULL; } if (mLatchDValid) { mLatchQ = mLatchD; mLatchDValid = false; mLatchQValid = true; } if (checkForNewParameters_l()) { cacheParameters_l(); } Loading
services/audioflinger/Threads.h +11 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
services/audioflinger/Tracks.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -724,8 +724,20 @@ status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& times } Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 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) { Loading