OSDN Git Service

NuPlayer: use getTimestamp instead of getPosition
authorLajos Molnar <lajos@google.com>
Thu, 28 Aug 2014 14:27:44 +0000 (07:27 -0700)
committerLajos Molnar <lajos@google.com>
Wed, 17 Sep 2014 23:01:24 +0000 (23:01 +0000)
Bug: 14659809
Bug: 16985287
Change-Id: I59ec72fbd40a9b8d28fe548ddad082c03000c045

include/media/MediaPlayerInterface.h
media/libmediaplayerservice/MediaPlayerService.cpp
media/libmediaplayerservice/MediaPlayerService.h
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h

index 87717da..cf18a45 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <media/mediaplayer.h>
 #include <media/AudioSystem.h>
+#include <media/AudioTimestamp.h>
 #include <media/Metadata.h>
 
 // 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;
index c8cb7ed..8eb1269 100644 (file)
@@ -43,6 +43,7 @@
 #include <utils/Errors.h>  // for status_t
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
+#include <utils/Timers.h>
 #include <utils/Vector.h>
 
 #include <media/IMediaHTTPService.h>
@@ -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;
index 4fe7075..3b96e88 100644 (file)
@@ -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;
index 067784b..8ab777a 100644 (file)
@@ -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();
index 5c7d2d7..2b32c48 100644 (file)
@@ -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();