Bug 1305353. Part 1 - publish output time to DecodedStream using MediaEventProducer. r=pehrsons
authorJW Wang <jwwang@mozilla.com>
Mon, 26 Sep 2016 15:08:12 +0800
changeset 315810 a3ac424edcd3bb4a6ea319692e941f5cefbdd8ef
parent 315809 79dc7e53e78e25d51b26d6f743d8d15a995f070d
child 315811 1929112d6a82f5d950abc63f289570baade1db26
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspehrsons
bugs1305353
milestone52.0a1
Bug 1305353. Part 1 - publish output time to DecodedStream using MediaEventProducer. r=pehrsons MozReview-Commit-ID: 5f37RfBhDA
dom/media/mediasink/DecodedStream.cpp
dom/media/mediasink/DecodedStream.h
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -42,16 +42,17 @@ public:
   }
 
   void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) override
   {
     MutexAutoLock lock(mMutex);
     if (mStream) {
       mLastOutputTime = mStream->StreamTimeToMicroseconds(
           mStream->GraphTimeToStreamTime(aCurrentTime));
+      mOnOutput.Notify(mLastOutputTime);
     }
   }
 
   void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent event) override
   {
     if (event == MediaStreamGraphEvent::EVENT_FINISHED) {
       nsCOMPtr<nsIRunnable> event =
         NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
@@ -73,17 +74,24 @@ public:
   void Forget()
   {
     MOZ_ASSERT(NS_IsMainThread());
     mFinishPromise.ResolveIfExists(true, __func__);
     MutexAutoLock lock(mMutex);
     mStream = nullptr;
   }
 
+  MediaEventSource<int64_t>& OnOutput()
+  {
+    return mOnOutput;
+  }
+
 private:
+  MediaEventProducer<int64_t> mOnOutput;
+
   Mutex mMutex;
   // Members below are protected by mMutex.
   RefPtr<MediaStream> mStream;
   int64_t mLastOutputTime; // microseconds
   // Main thread only.
   MozPromiseHolder<GenericPromise> mFinishPromise;
 };
 
@@ -118,16 +126,17 @@ UpdateStreamSuspended(MediaStream* aStre
 class DecodedStreamData {
 public:
   DecodedStreamData(OutputStreamManager* aOutputStreamManager,
                     PlaybackInfoInit&& aInit,
                     MozPromiseHolder<GenericPromise>&& aPromise);
   ~DecodedStreamData();
   int64_t GetPosition() const;
   void SetPlaying(bool aPlaying);
+  MediaEventSource<int64_t>& OnOutput();
 
   /* The following group of fields are protected by the decoder's monitor
    * and can be read or written on any thread.
    */
   // Count of audio frames written to the stream
   int64_t mAudioFramesWritten;
   // mNextVideoTime is the end timestamp for the last packet sent to the stream.
   // Therefore video packets starting at or after this time need to be copied
@@ -193,16 +202,22 @@ DecodedStreamData::~DecodedStreamData()
 }
 
 int64_t
 DecodedStreamData::GetPosition() const
 {
   return mListener->GetLastOutputTime();
 }
 
+MediaEventSource<int64_t>&
+DecodedStreamData::OnOutput()
+{
+  return mListener->OnOutput();
+}
+
 void
 DecodedStreamData::SetPlaying(bool aPlaying)
 {
   if (mPlaying != aPlaying) {
     mPlaying = aPlaying;
     UpdateStreamSuspended(mStream, !mPlaying);
   }
 }
@@ -261,16 +276,17 @@ DecodedStream::OnEnded(TrackType aType)
 
 void
 DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
 {
   AssertOwnerThread();
   MOZ_ASSERT(mStartTime.isNothing(), "playback already started.");
 
   mStartTime.emplace(aStartTime);
+  mLastOutputTime = 0;
   mInfo = aInfo;
   mPlaying = true;
   ConnectListener();
 
   class R : public Runnable {
     typedef MozPromiseHolder<GenericPromise> Promise;
   public:
     R(PlaybackInfoInit&& aInit, Promise&& aPromise, OutputStreamManager* aManager)
@@ -309,16 +325,18 @@ DecodedStream::Start(int64_t aStartTime,
     aStartTime, aInfo
   };
   nsCOMPtr<nsIRunnable> r = new R(Move(init), Move(promise), mOutputStreamManager);
   nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
   SyncRunnable::DispatchToThread(mainThread, r);
   mData = static_cast<R*>(r.get())->ReleaseData();
 
   if (mData) {
+    mOutputListener = mData->OnOutput().Connect(
+      mOwnerThread, this, &DecodedStream::NotifyOutput);
     mData->SetPlaying(mPlaying);
     SendData();
   }
 }
 
 void
 DecodedStream::Stop()
 {
@@ -352,16 +370,18 @@ void
 DecodedStream::DestroyData(UniquePtr<DecodedStreamData> aData)
 {
   AssertOwnerThread();
 
   if (!aData) {
     return;
   }
 
+  mOutputListener.Disconnect();
+
   DecodedStreamData* data = aData.release();
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
     delete data;
   });
   AbstractThread::MainThread()->Dispatch(r.forget());
 }
 
 void
@@ -690,16 +710,23 @@ DecodedStream::GetPosition(TimeStamp* aT
   MOZ_ASSERT(mStartTime.isSome());
   if (aTimeStamp) {
     *aTimeStamp = TimeStamp::Now();
   }
   return mStartTime.ref() + (mData ? mData->GetPosition() : 0);
 }
 
 void
+DecodedStream::NotifyOutput(int64_t aTime)
+{
+  AssertOwnerThread();
+  mLastOutputTime = aTime;
+}
+
+void
 DecodedStream::ConnectListener()
 {
   AssertOwnerThread();
 
   mAudioPushListener = mAudioQueue.PushEvent().Connect(
     mOwnerThread, this, &DecodedStream::SendData);
   mAudioFinishListener = mAudioQueue.FinishEvent().Connect(
     mOwnerThread, this, &DecodedStream::SendData);
--- a/dom/media/mediasink/DecodedStream.h
+++ b/dom/media/mediasink/DecodedStream.h
@@ -67,16 +67,17 @@ protected:
   virtual ~DecodedStream();
 
 private:
   void DestroyData(UniquePtr<DecodedStreamData> aData);
   void AdvanceTracks();
   void SendAudio(double aVolume, bool aIsSameOrigin, const PrincipalHandle& aPrincipalHandle);
   void SendVideo(bool aIsSameOrigin, const PrincipalHandle& aPrincipalHandle);
   void SendData();
+  void NotifyOutput(int64_t aTime);
 
   void AssertOwnerThread() const {
     MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   }
 
   void ConnectListener();
   void DisconnectListener();
 
@@ -96,22 +97,24 @@ private:
 
   bool mPlaying;
   const bool& mSameOrigin; // valid until Shutdown() is called.
   const PrincipalHandle& mPrincipalHandle; // valid until Shutdown() is called.
 
   PlaybackParams mParams;
 
   Maybe<int64_t> mStartTime;
+  int64_t mLastOutputTime = 0; // microseconds
   MediaInfo mInfo;
 
   MediaQueue<MediaData>& mAudioQueue;
   MediaQueue<MediaData>& mVideoQueue;
 
   MediaEventListener mAudioPushListener;
   MediaEventListener mVideoPushListener;
   MediaEventListener mAudioFinishListener;
   MediaEventListener mVideoFinishListener;
+  MediaEventListener mOutputListener;
 };
 
 } // namespace mozilla
 
 #endif // DecodedStream_h_