OSDN Git Service

Squashed commit of the following:
authorAndreas Huber <andih@google.com>
Tue, 12 Mar 2013 18:01:43 +0000 (11:01 -0700)
committerAndreas Huber <andih@google.com>
Tue, 12 Mar 2013 20:44:58 +0000 (13:44 -0700)
commit f4edf442741886cdbe071e2d15f6e6247269f7c5
Author: Andreas Huber <andih@google.com>
Date:   Tue Mar 12 09:09:18 2013 -0700

    Pass additional flags to the sink, use TCP by default in wolfiecast mode.

    Change-Id: I41e11a2375d4199656e45c4f149d8441d0016092

commit 6302602ed280a38287f507159abfb40a1da38c5a
Author: Andreas Huber <andih@google.com>
Date:   Tue Mar 12 08:51:58 2013 -0700

    tweaks

    Change-Id: Ie29e422d7258be522f4bb1f6c5afcf74c937e547

commit a38a860e4979ba563cadbaafa21b084439449d26
Author: Andreas Huber <andih@google.com>
Date:   Mon Mar 11 16:57:43 2013 -0700

    Report average lateness all the way from NuPlayerRenderer...

    Change-Id: I2e7700703ae656515e44b9c25610d26c75778111

commit a7d49b11675ea88be4029dd8451d1649db94571d
Author: Andreas Huber <andih@google.com>
Date:   Mon Mar 11 14:54:19 2013 -0700

    Make TimeSyncer smarter, enable TunnelRenderer

    Change-Id: I27377a60cd8feb01589da456967fddd34532c20e

commit 0f214c8ef68179f7b61512c37040939554013151
Author: Andreas Huber <andih@google.com>
Date:   Thu Mar 7 15:57:56 2013 -0800

    convert source timestamps to sink timestamps, report lateness.

    Change-Id: I051a60fbbceca2f7b508ae3dac6e01e402bae39e

commit 04a4f8e16bad09157b5615a5fa45310438955832
Author: Andreas Huber <andih@google.com>
Date:   Thu Mar 7 09:00:28 2013 -0800

    Sync time between sink and source.

    Change-Id: Ie8b4d75c957aa48310e7c81d1279761b9f821efe

commit aebe20e6184e3636a99082f8ece08e708015cb8d
Author: Andreas Huber <andih@google.com>
Date:   Wed Mar 6 09:03:12 2013 -0800

    play with back pressure

    Change-Id: I51eb69257e6a79e76f5f9c75ff99d8adbd083947

Change-Id: Ifdf57228667fed7fc71c5090a2c3f7cea1037c5c

18 files changed:
include/media/IStreamSource.h
media/libmediaplayerservice/nuplayer/NuPlayer.cpp
media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
media/libmediaplayerservice/nuplayer/NuPlayerSource.h
media/libmediaplayerservice/nuplayer/StreamingSource.cpp
media/libmediaplayerservice/nuplayer/StreamingSource.h
media/libstagefright/mpeg2ts/ATSParser.cpp
media/libstagefright/mpeg2ts/ATSParser.h
media/libstagefright/wifi-display/ANetworkSession.cpp
media/libstagefright/wifi-display/Android.mk
media/libstagefright/wifi-display/rtp/RTPSender.cpp
media/libstagefright/wifi-display/sink/TunnelRenderer.cpp
media/libstagefright/wifi-display/sink/TunnelRenderer.h
media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
media/libstagefright/wifi-display/source/WifiDisplaySource.h
media/libstagefright/wifi-display/wfd.cpp

index 39e0a9e..677119b 100644 (file)
@@ -37,6 +37,9 @@ struct IStreamSource : public IInterface {
     enum {
         // Video PES packets contain exactly one (aligned) access unit.
         kFlagAlignedVideoData = 1,
+
+        // Timestamps are in ALooper::GetNowUs() units.
+        kFlagIsRealTimeData   = 2,
     };
     virtual uint32_t flags() const { return 0; }
 };
index 2ba6c22..5387e1a 100644 (file)
@@ -381,9 +381,16 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
 
             mSource->start();
 
+            uint32_t flags = 0;
+
+            if (mSource->isRealTime()) {
+                flags |= Renderer::FLAG_REAL_TIME;
+            }
+
             mRenderer = new Renderer(
                     mAudioSink,
-                    new AMessage(kWhatRendererNotify, id()));
+                    new AMessage(kWhatRendererNotify, id()),
+                    flags);
 
             looper()->registerHandler(mRenderer);
 
index 3c63e80..723af09 100644 (file)
@@ -378,6 +378,7 @@ status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
             int mode = request.readInt32();
             return mPlayer->setVideoScalingMode(mode);
         }
+
         default:
         {
             return INVALID_OPERATION;
index 1ba76a5..404b56f 100644 (file)
@@ -31,9 +31,11 @@ const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
 
 NuPlayer::Renderer::Renderer(
         const sp<MediaPlayerBase::AudioSink> &sink,
-        const sp<AMessage> &notify)
+        const sp<AMessage> &notify,
+        uint32_t flags)
     : mAudioSink(sink),
       mNotify(notify),
+      mFlags(flags),
       mNumFramesWritten(0),
       mDrainAudioQueuePending(false),
       mDrainVideoQueuePending(false),
@@ -323,6 +325,11 @@ void NuPlayer::Renderer::postDrainVideoQueue() {
     if (entry.mBuffer == NULL) {
         // EOS doesn't carry a timestamp.
         delayUs = 0;
+    } else if (mFlags & FLAG_REAL_TIME) {
+        int64_t mediaTimeUs;
+        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+        delayUs = mediaTimeUs - ALooper::GetNowUs();
     } else {
         int64_t mediaTimeUs;
         CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
@@ -368,12 +375,17 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
         return;
     }
 
-    int64_t mediaTimeUs;
-    CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
+    int64_t realTimeUs;
+    if (mFlags & FLAG_REAL_TIME) {
+        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
+    } else {
+        int64_t mediaTimeUs;
+        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+        realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
+    }
 
-    int64_t realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
     mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
-
     bool tooLate = (mVideoLateByUs > 40000);
 
     if (tooLate) {
index e4368c7..c9796e2 100644 (file)
@@ -25,8 +25,12 @@ namespace android {
 struct ABuffer;
 
 struct NuPlayer::Renderer : public AHandler {
+    enum Flags {
+        FLAG_REAL_TIME = 1,
+    };
     Renderer(const sp<MediaPlayerBase::AudioSink> &sink,
-             const sp<AMessage> &notify);
+             const sp<AMessage> &notify,
+             uint32_t flags = 0);
 
     void queueBuffer(
             bool audio,
@@ -79,6 +83,7 @@ private:
 
     sp<MediaPlayerBase::AudioSink> mAudioSink;
     sp<AMessage> mNotify;
+    uint32_t mFlags;
     List<QueueEntry> mAudioQueue;
     List<QueueEntry> mVideoQueue;
     uint32_t mNumFramesWritten;
index 8622abe..1cbf575 100644 (file)
@@ -74,6 +74,10 @@ struct NuPlayer::Source : public AHandler {
         return INVALID_OPERATION;
     }
 
+    virtual bool isRealTime() const {
+        return false;
+    }
+
 protected:
     virtual ~Source() {}
 
index df03f86..28f0d50 100644 (file)
@@ -182,5 +182,9 @@ status_t NuPlayer::StreamingSource::dequeueAccessUnit(
     return err;
 }
 
+bool NuPlayer::StreamingSource::isRealTime() const {
+    return mSource->flags() & IStreamSource::kFlagIsRealTimeData;
+}
+
 }  // namespace android
 
index 80b061c..412b6c4 100644 (file)
@@ -38,6 +38,8 @@ struct NuPlayer::StreamingSource : public NuPlayer::Source {
 
     virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
 
+    virtual bool isRealTime() const;
+
 protected:
     virtual ~StreamingSource();
 
index a167b5a..c12572f 100644 (file)
@@ -452,6 +452,10 @@ int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
         timeUs += mParser->mAbsoluteTimeAnchorUs;
     }
 
+    if (mParser->mTimeOffsetValid) {
+        timeUs += mParser->mTimeOffsetUs;
+    }
+
     return timeUs;
 }
 
@@ -930,6 +934,8 @@ sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
 ATSParser::ATSParser(uint32_t flags)
     : mFlags(flags),
       mAbsoluteTimeAnchorUs(-1ll),
+      mTimeOffsetValid(false),
+      mTimeOffsetUs(0ll),
       mNumTSPacketsParsed(0),
       mNumPCRs(0) {
     mPSISections.add(0 /* PID */, new PSISection);
@@ -960,6 +966,13 @@ void ATSParser::signalDiscontinuity(
         CHECK(mPrograms.empty());
         mAbsoluteTimeAnchorUs = timeUs;
         return;
+    } else if (type == DISCONTINUITY_TIME_OFFSET) {
+        int64_t offset;
+        CHECK(extra->findInt64("offset", &offset));
+
+        mTimeOffsetValid = true;
+        mTimeOffsetUs = offset;
+        return;
     }
 
     for (size_t i = 0; i < mPrograms.size(); ++i) {
index 46edc45..a10edc9 100644 (file)
@@ -39,6 +39,7 @@ struct ATSParser : public RefBase {
         DISCONTINUITY_AUDIO_FORMAT      = 2,
         DISCONTINUITY_VIDEO_FORMAT      = 4,
         DISCONTINUITY_ABSOLUTE_TIME     = 8,
+        DISCONTINUITY_TIME_OFFSET       = 16,
 
         DISCONTINUITY_SEEK              = DISCONTINUITY_TIME,
 
@@ -106,6 +107,9 @@ private:
 
     int64_t mAbsoluteTimeAnchorUs;
 
+    bool mTimeOffsetValid;
+    int64_t mTimeOffsetUs;
+
     size_t mNumTSPacketsParsed;
 
     void parseProgramAssociationTable(ABitReader *br);
index cb6011c..465f4c4 100644 (file)
@@ -27,6 +27,7 @@
 #include <net/if.h>
 #include <netdb.h>
 #include <netinet/in.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 
 #include <media/stagefright/foundation/ABuffer.h>
@@ -507,6 +508,14 @@ status_t ANetworkSession::Session::writeMore() {
         mSawSendFailure = true;
     }
 
+#if 0
+    int numBytesQueued;
+    int res = ioctl(mSocket, SIOCOUTQ, &numBytesQueued);
+    if (res == 0 && numBytesQueued > 102400) {
+        ALOGI("numBytesQueued = %d", numBytesQueued);
+    }
+#endif
+
     return err;
 }
 
index 19f560c..f81929c 100644 (file)
@@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \
         sink/TunnelRenderer.cpp         \
         sink/WifiDisplaySink.cpp        \
         SNTPClient.cpp                  \
+        TimeSyncer.cpp                  \
         source/Converter.cpp            \
         source/MediaPuller.cpp          \
         source/PlaybackSession.cpp      \
index 85c5933..b60853d 100644 (file)
@@ -577,6 +577,8 @@ status_t RTPSender::onRTCPData(const sp<ABuffer> &buffer) {
 
             case 202:  // SDES
             case 203:
+                break;
+
             case 204:  // APP
                 break;
 
index d9d8a76..6b185db 100644 (file)
@@ -27,6 +27,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <media/IMediaPlayerService.h>
 #include <media/IStreamSource.h>
+#include <media/mediaplayer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -60,6 +61,8 @@ struct TunnelRenderer::StreamSource : public BnStreamSource {
 
     void doSomeWork();
 
+    void setTimeOffset(int64_t offset);
+
 protected:
     virtual ~StreamSource();
 
@@ -75,6 +78,9 @@ private:
 
     size_t mNumDeqeued;
 
+    int64_t mTimeOffsetUs;
+    bool mTimeOffsetChanged;
+
     DISALLOW_EVIL_CONSTRUCTORS(StreamSource);
 };
 
@@ -82,7 +88,9 @@ private:
 
 TunnelRenderer::StreamSource::StreamSource(TunnelRenderer *owner)
     : mOwner(owner),
-      mNumDeqeued(0) {
+      mNumDeqeued(0),
+      mTimeOffsetUs(0ll),
+      mTimeOffsetChanged(false) {
 }
 
 TunnelRenderer::StreamSource::~StreamSource() {
@@ -110,7 +118,7 @@ void TunnelRenderer::StreamSource::onBufferAvailable(size_t index) {
 }
 
 uint32_t TunnelRenderer::StreamSource::flags() const {
-    return kFlagAlignedVideoData;
+    return kFlagAlignedVideoData | kFlagIsRealTimeData;
 }
 
 void TunnelRenderer::StreamSource::doSomeWork() {
@@ -124,21 +132,21 @@ void TunnelRenderer::StreamSource::doSomeWork() {
 
         ++mNumDeqeued;
 
-        if (mNumDeqeued == 1) {
-            ALOGI("fixing real time now.");
-
+        if (mTimeOffsetChanged) {
             sp<AMessage> extra = new AMessage;
 
             extra->setInt32(
                     IStreamListener::kKeyDiscontinuityMask,
-                    ATSParser::DISCONTINUITY_ABSOLUTE_TIME);
+                    ATSParser::DISCONTINUITY_TIME_OFFSET);
 
-            extra->setInt64("timeUs", ALooper::GetNowUs());
+            extra->setInt64("offset", mTimeOffsetUs);
 
             mListener->issueCommand(
                     IStreamListener::DISCONTINUITY,
                     false /* synchronous */,
                     extra);
+
+            mTimeOffsetChanged = false;
         }
 
         ALOGV("dequeue TS packet of size %d", srcBuffer->size());
@@ -155,18 +163,32 @@ void TunnelRenderer::StreamSource::doSomeWork() {
     }
 }
 
+void TunnelRenderer::StreamSource::setTimeOffset(int64_t offset) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (offset != mTimeOffsetUs) {
+        mTimeOffsetUs = offset;
+        mTimeOffsetChanged = true;
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 TunnelRenderer::TunnelRenderer(
         const sp<IGraphicBufferProducer> &bufferProducer)
     : mSurfaceTex(bufferProducer),
       mStartup(true) {
+    mStreamSource = new StreamSource(this);
 }
 
 TunnelRenderer::~TunnelRenderer() {
     destroyPlayer();
 }
 
+void TunnelRenderer::setTimeOffset(int64_t offset) {
+    mStreamSource->setTimeOffset(offset);
+}
+
 void TunnelRenderer::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
         default:
@@ -209,8 +231,6 @@ void TunnelRenderer::initPlayer() {
     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
     CHECK(service.get() != NULL);
 
-    mStreamSource = new StreamSource(this);
-
     mPlayerClient = new PlayerClient;
 
     mPlayer = service->create(mPlayerClient, 0);
@@ -226,6 +246,8 @@ void TunnelRenderer::initPlayer() {
 void TunnelRenderer::destroyPlayer() {
     mStreamSource.clear();
 
+    mPlayer->setVideoSurfaceTexture(NULL);
+
     mPlayer->stop();
     mPlayer.clear();
 
index 8e96665..479e73c 100644 (file)
@@ -39,6 +39,12 @@ struct TunnelRenderer : public AHandler {
     void queueBuffer(const sp<ABuffer> &buffer);
     sp<ABuffer> dequeueBuffer();
 
+    void setTimeOffset(int64_t offset);
+
+    int64_t getAvgLatenessUs() {
+        return 0ll;
+    }
+
 protected:
     virtual void onMessageReceived(const sp<AMessage> &msg);
     virtual ~TunnelRenderer();
index b8524f6..de66bde 100644 (file)
@@ -23,6 +23,7 @@
 #include "Parameters.h"
 #include "ParsedMessage.h"
 #include "rtp/RTPSender.h"
+#include "TimeSyncer.h"
 
 #include <binder/IServiceManager.h>
 #include <gui/IGraphicBufferProducer.h>
@@ -157,6 +158,12 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
             }
 
             if (err == OK) {
+                sp<AMessage> notify = new AMessage(kWhatTimeSyncerNotify, id());
+                mTimeSyncer = new TimeSyncer(mNetSession, notify);
+                looper()->registerHandler(mTimeSyncer);
+
+                mTimeSyncer->startServer(8123);
+
                 mState = AWAITING_CLIENT_CONNECTION;
             }
 
@@ -520,6 +527,11 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
             break;
         }
 
+        case kWhatTimeSyncerNotify:
+        {
+            break;
+        }
+
         default:
             TRESPASS();
     }
index 724462c..9e72682 100644 (file)
@@ -30,6 +30,7 @@ namespace android {
 struct IHDCP;
 struct IRemoteDisplayClient;
 struct ParsedMessage;
+struct TimeSyncer;
 
 // Represents the RTSP server acting as a wifi display source.
 // Manages incoming connections, sets up Playback sessions as necessary.
@@ -81,6 +82,7 @@ private:
         kWhatHDCPNotify,
         kWhatFinishStop2,
         kWhatTeardownTriggerTimedOut,
+        kWhatTimeSyncerNotify,
     };
 
     struct ResponseID {
@@ -114,6 +116,7 @@ private:
     VideoFormats mSupportedSourceVideoFormats;
     sp<ANetworkSession> mNetSession;
     sp<IRemoteDisplayClient> mClient;
+    sp<TimeSyncer> mTimeSyncer;
     struct in_addr mInterfaceAddr;
     int32_t mSessionID;
 
index 3f4216a..0b18484 100644 (file)
@@ -321,7 +321,10 @@ int main(int argc, char **argv) {
     sp<ALooper> looper = new ALooper;
 
     sp<WifiDisplaySink> sink = new WifiDisplaySink(
-            session, surface->getIGraphicBufferProducer());
+            0 /* flags */,
+            session,
+            surface->getIGraphicBufferProducer());
+
     looper->registerHandler(sink);
 
     if (connectToPort >= 0) {