summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/private/media/AudioTrackShared.h3
-rw-r--r--services/audioflinger/Threads.cpp18
-rw-r--r--services/audioflinger/Threads.h11
-rw-r--r--services/audioflinger/Tracks.cpp14
4 files changed, 44 insertions, 2 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index ad00c6d..d6e7ac4 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 8bc70ba..99d0ac2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -958,7 +958,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);
@@ -1826,6 +1828,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
@@ -2104,6 +2114,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 176314a..15278ce 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -608,6 +608,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 392707b..690f1dd 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -733,7 +733,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)