From 06ad1528e6dd4c866c085d3cad9235d2752eb3ed Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 28 Aug 2014 07:27:44 -0700 Subject: NuPlayer: use getTimestamp instead of getPosition Bug: 14659809 Bug: 16985287 Change-Id: I59ec72fbd40a9b8d28fe548ddad082c03000c045 --- include/media/MediaPlayerInterface.h | 2 + media/libmediaplayerservice/MediaPlayerService.cpp | 16 ++++++ media/libmediaplayerservice/MediaPlayerService.h | 2 + .../nuplayer/NuPlayerRenderer.cpp | 60 ++++++++++++++-------- .../nuplayer/NuPlayerRenderer.h | 3 +- 5 files changed, 60 insertions(+), 23 deletions(-) diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 87717da..cf18a45 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -27,6 +27,7 @@ #include #include +#include #include // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is @@ -97,6 +98,7 @@ public: virtual uint32_t latency() const = 0; virtual float msecsPerFrame() const = 0; virtual status_t getPosition(uint32_t *position) const = 0; + virtual status_t getTimestamp(AudioTimestamp &ts) const = 0; virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0; virtual int getSessionId() const = 0; virtual audio_stream_type_t getAudioStreamType() const = 0; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index c8cb7ed..8eb1269 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -43,6 +43,7 @@ #include // for status_t #include #include +#include #include #include @@ -1496,6 +1497,12 @@ status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const return mTrack->getPosition(position); } +status_t MediaPlayerService::AudioOutput::getTimestamp(AudioTimestamp &ts) const +{ + if (mTrack == 0) return NO_INIT; + return mTrack->getTimestamp(ts); +} + status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const { if (mTrack == 0) return NO_INIT; @@ -1971,6 +1978,15 @@ status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const return NO_ERROR; } +status_t MediaPlayerService::AudioCache::getTimestamp(AudioTimestamp &ts) const +{ + ts.mPosition = mSize / mFrameSize; + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + ts.mTime.tv_sec = now / 1000000000LL; + ts.mTime.tv_nsec = now - (1000000000LL * ts.mTime.tv_sec); + return NO_ERROR; +} + status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const { if (written == 0) return BAD_VALUE; diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 4fe7075..3b96e88 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -85,6 +85,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual uint32_t latency() const; virtual float msecsPerFrame() const; virtual status_t getPosition(uint32_t *position) const; + virtual status_t getTimestamp(AudioTimestamp &ts) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; virtual int getSessionId() const; virtual uint32_t getSampleRate() const; @@ -198,6 +199,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual uint32_t latency() const; virtual float msecsPerFrame() const; virtual status_t getPosition(uint32_t *position) const; + virtual status_t getTimestamp(AudioTimestamp &ts) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; virtual int getSessionId() const; virtual uint32_t getSampleRate() const; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 067784b..8ab777a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -343,15 +343,13 @@ size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) { mFirstAudioTimeUs = mediaTimeUs; } - uint32_t numFramesPlayed; - CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK); - - // TODO: figure out how to calculate initial latency. - // Otherwise, the initial time is not correct till the first sample - // is played. - mAnchorTimeMediaUs = mFirstAudioTimeUs - + (numFramesPlayed * mAudioSink->msecsPerFrame()) * 1000ll; - mAnchorTimeRealUs = ALooper::GetNowUs(); + // TODO: figure out how to calculate initial latency if + // getTimestamp is not available. Otherwise, the initial time + // is not correct till the first sample is played. + int64_t nowUs = ALooper::GetNowUs(); + mAnchorTimeMediaUs = + mFirstAudioTimeUs + getPlayedOutAudioDurationUs(nowUs); + mAnchorTimeRealUs = nowUs; } size_t copy = entry->mBuffer->size() - entry->mOffset; @@ -413,7 +411,7 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { // EOS int64_t postEOSDelayUs = 0; if (mAudioSink->needsTrailingPadding()) { - postEOSDelayUs = getAudioPendingPlayoutUs() + 1000 * mAudioSink->latency(); + postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs()); } notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs); @@ -428,8 +426,8 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6); mAnchorTimeMediaUs = mediaTimeUs; - mAnchorTimeRealUs = ALooper::GetNowUs() - + getAudioPendingPlayoutUs() + 1000 * mAudioSink->latency() / 2; + int64_t nowUs = ALooper::GetNowUs(); + mAnchorTimeRealUs = nowUs + getPendingAudioPlayoutDurationUs(nowUs); } size_t copy = entry->mBuffer->size() - entry->mOffset; @@ -483,12 +481,10 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { return !mAudioQueue.empty(); } -int64_t NuPlayer::Renderer::getAudioPendingPlayoutUs() { - uint32_t numFramesPlayed; - CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK); - - uint32_t numFramesPendingPlayout = mNumFramesWritten - numFramesPlayed; - return numFramesPendingPlayout * mAudioSink->msecsPerFrame() * 1000; +int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) { + int64_t writtenAudioDurationUs = + mNumFramesWritten * 1000LL * mAudioSink->msecsPerFrame(); + return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs); } void NuPlayer::Renderer::postDrainVideoQueue() { @@ -937,17 +933,37 @@ void NuPlayer::Renderer::onResume() { } } -void NuPlayer::Renderer::onAudioOffloadTearDown() { +int64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) { + // FIXME: getTimestamp sometimes returns negative frame count. + // Since we do not handle the rollover at this point (which can + // happen every 14 hours), simply treat the timestamp as signed. uint32_t numFramesPlayed; - CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK); + int64_t numFramesPlayedAt; + AudioTimestamp ts; + status_t res = mAudioSink->getTimestamp(ts); + if (res == OK) { + numFramesPlayed = ts.mPosition; + numFramesPlayedAt = + ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000; + } else { + res = mAudioSink->getPosition(&numFramesPlayed); + CHECK_EQ(res, (status_t)OK); + numFramesPlayedAt = nowUs; + numFramesPlayedAt += 1000LL * mAudioSink->latency() / 2; /* XXX */ + } + return (int32_t)numFramesPlayed * 1000LL * mAudioSink->msecsPerFrame() + + nowUs - numFramesPlayedAt; +} +void NuPlayer::Renderer::onAudioOffloadTearDown() { int64_t firstAudioTimeUs; { Mutex::Autolock autoLock(mLock); firstAudioTimeUs = mFirstAudioTimeUs; } - int64_t currentPositionUs = firstAudioTimeUs - + (numFramesPlayed * mAudioSink->msecsPerFrame()) * 1000ll; + + int64_t currentPositionUs = + firstAudioTimeUs + getPlayedOutAudioDurationUs(ALooper::GetNowUs()); mAudioSink->stop(); mAudioSink->flush(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 5c7d2d7..2b32c48 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -130,7 +130,8 @@ private: size_t fillAudioBuffer(void *buffer, size_t size); bool onDrainAudioQueue(); - int64_t getAudioPendingPlayoutUs(); + int64_t getPendingAudioPlayoutDurationUs(int64_t nowUs); + int64_t getPlayedOutAudioDurationUs(int64_t nowUs); void postDrainAudioQueue_l(int64_t delayUs = 0); void onDrainVideoQueue(); -- cgit v1.1