Bug 1189506. Convert ChangeExplicitBlockerCount to MediaStream::Suspend/Resume. r=padenot
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 11 Sep 2015 01:45:36 +1200
changeset 295491 2624ea64e7ab556386c4ad081f49e85a42961c84
parent 295490 c8d75cd4d9eaac0af060d9b28e8f68825dfbe236
child 295492 90258efcf37f787976ffabf6c924b36e3dae05a0
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1189506
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1189506. Convert ChangeExplicitBlockerCount to MediaStream::Suspend/Resume. r=padenot
dom/camera/CameraPreviewMediaStream.cpp
dom/camera/CameraPreviewMediaStream.h
dom/media/MediaRecorder.cpp
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/mediasink/DecodedStream.cpp
dom/media/webaudio/AudioDestinationNode.cpp
dom/media/webspeech/synth/nsSpeechTask.cpp
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -87,21 +87,16 @@ CameraPreviewMediaStream::RemoveVideoOut
   mIsConsumed = false;
   for (uint32_t j = 0; j < mListeners.Length(); ++j) {
     MediaStreamListener* l = mListeners[j];
     l->NotifyConsumptionChanged(mFakeMediaStreamGraph, MediaStreamListener::NOT_CONSUMED);
   }
 }
 
 void
-CameraPreviewMediaStream::ChangeExplicitBlockerCount(int32_t aDelta)
-{
-}
-
-void
 CameraPreviewMediaStream::AddListener(MediaStreamListener* aListener)
 {
   MutexAutoLock lock(mMutex);
 
   MediaStreamListener* listener = *mListeners.AppendElement() = aListener;
   listener->NotifyBlockingChanged(mFakeMediaStreamGraph, MediaStreamListener::UNBLOCKED);
   listener->NotifyHasCurrentData(mFakeMediaStreamGraph);
 }
--- a/dom/camera/CameraPreviewMediaStream.h
+++ b/dom/camera/CameraPreviewMediaStream.h
@@ -43,17 +43,18 @@ public:
   explicit CameraPreviewMediaStream(DOMMediaStream* aWrapper);
 
   virtual CameraPreviewMediaStream* AsCameraPreviewStream() override { return this; };
   virtual void AddAudioOutput(void* aKey) override;
   virtual void SetAudioOutputVolume(void* aKey, float aVolume) override;
   virtual void RemoveAudioOutput(void* aKey) override;
   virtual void AddVideoOutput(VideoFrameContainer* aContainer) override;
   virtual void RemoveVideoOutput(VideoFrameContainer* aContainer) override;
-  virtual void ChangeExplicitBlockerCount(int32_t aDelta) override;
+  virtual void Suspend() override {}
+  virtual void Resume() override {}
   virtual void AddListener(MediaStreamListener* aListener) override;
   virtual void RemoveListener(MediaStreamListener* aListener) override;
   virtual void Destroy() override;
   void OnPreviewStateChange(bool aActive);
 
   void Invalidate();
 
   // Call these on any thread.
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -402,28 +402,28 @@ public:
   }
 
   nsresult Pause()
   {
     LOG(LogLevel::Debug, ("Session.Pause"));
     MOZ_ASSERT(NS_IsMainThread());
 
     NS_ENSURE_TRUE(mTrackUnionStream, NS_ERROR_FAILURE);
-    mTrackUnionStream->ChangeExplicitBlockerCount(1);
+    mTrackUnionStream->Suspend();
 
     return NS_OK;
   }
 
   nsresult Resume()
   {
     LOG(LogLevel::Debug, ("Session.Resume"));
     MOZ_ASSERT(NS_IsMainThread());
 
     NS_ENSURE_TRUE(mTrackUnionStream, NS_ERROR_FAILURE);
-    mTrackUnionStream->ChangeExplicitBlockerCount(-1);
+    mTrackUnionStream->Resume();
 
     return NS_OK;
   }
 
   nsresult RequestData()
   {
     LOG(LogLevel::Debug, ("Session.RequestData"));
     MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -2139,36 +2139,55 @@ MediaStream::RemoveVideoOutput(VideoFram
       mStream->RemoveVideoOutputImpl(mContainer);
     }
     nsRefPtr<VideoFrameContainer> mContainer;
   };
   GraphImpl()->AppendMessage(new Message(this, aContainer));
 }
 
 void
-MediaStream::ChangeExplicitBlockerCount(int32_t aDelta)
+MediaStream::Suspend()
 {
   class Message : public ControlMessage {
   public:
-    Message(MediaStream* aStream, int32_t aDelta) :
-      ControlMessage(aStream), mDelta(aDelta) {}
+    explicit Message(MediaStream* aStream) :
+      ControlMessage(aStream) {}
     virtual void Run()
     {
-      mStream->ChangeExplicitBlockerCountImpl(
-          mStream->GraphImpl()->mStateComputedTime, mDelta);
+      mStream->GraphImpl()->IncrementSuspendCount(mStream);
     }
-    int32_t mDelta;
   };
 
   // This can happen if this method has been called asynchronously, and the
   // stream has been destroyed since then.
   if (mMainThreadDestroyed) {
     return;
   }
-  GraphImpl()->AppendMessage(new Message(this, aDelta));
+  GraphImpl()->AppendMessage(new Message(this));
+}
+
+void
+MediaStream::Resume()
+{
+  class Message : public ControlMessage {
+  public:
+    explicit Message(MediaStream* aStream) :
+      ControlMessage(aStream) {}
+    virtual void Run()
+    {
+      mStream->GraphImpl()->DecrementSuspendCount(mStream);
+    }
+  };
+
+  // This can happen if this method has been called asynchronously, and the
+  // stream has been destroyed since then.
+  if (mMainThreadDestroyed) {
+    return;
+  }
+  GraphImpl()->AppendMessage(new Message(this));
 }
 
 void
 MediaStream::BlockStreamIfNeeded()
 {
   class Message : public ControlMessage {
   public:
     explicit Message(MediaStream* aStream) : ControlMessage(aStream)
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -357,19 +357,23 @@ public:
   virtual void AddAudioOutput(void* aKey);
   virtual void SetAudioOutputVolume(void* aKey, float aVolume);
   virtual void RemoveAudioOutput(void* aKey);
   // Since a stream can be played multiple ways, we need to be able to
   // play to multiple VideoFrameContainers.
   // Only the first enabled video track is played.
   virtual void AddVideoOutput(VideoFrameContainer* aContainer);
   virtual void RemoveVideoOutput(VideoFrameContainer* aContainer);
-  // Explicitly block. Useful for example if a media element is pausing
-  // and we need to stop its stream emitting its buffered data.
-  virtual void ChangeExplicitBlockerCount(int32_t aDelta);
+  // Explicitly suspend. Useful for example if a media element is pausing
+  // and we need to stop its stream emitting its buffered data. As soon as the
+  // Suspend message reaches the graph, the stream stops processing. It
+  // ignores its inputs and produces silence/no video until Resumed. Its
+  // current time does not advance.
+  virtual void Suspend();
+  virtual void Resume();
   void BlockStreamIfNeeded();
   void UnblockStreamIfNeeded();
   // Events will be dispatched by calling methods of aListener.
   virtual void AddListener(MediaStreamListener* aListener);
   virtual void RemoveListener(MediaStreamListener* aListener);
   // A disabled track has video replaced by black, and audio replaced by
   // silence.
   void SetTrackEnabled(TrackID aTrackID, bool aEnabled);
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -81,24 +81,31 @@ private:
   nsRefPtr<MediaStream> mStream;
   int64_t mLastOutputTime; // microseconds
   bool mStreamFinishedOnMainThread;
   // Main thread only.
   MozPromiseHolder<GenericPromise> mFinishPromise;
 };
 
 static void
-UpdateStreamBlocking(MediaStream* aStream, bool aBlocking)
+UpdateStreamSuspended(MediaStream* aStream, bool aBlocking)
 {
-  int32_t delta = aBlocking ? 1 : -1;
   if (NS_IsMainThread()) {
-    aStream->ChangeExplicitBlockerCount(delta);
+    if (aBlocking) {
+      aStream->Suspend();
+    } else {
+      aStream->Resume();
+    }
   } else {
-    nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<int32_t>(
-      aStream, &MediaStream::ChangeExplicitBlockerCount, delta);
+    nsCOMPtr<nsIRunnable> r;
+    if (aBlocking) {
+      r = NS_NewRunnableMethod(aStream, &MediaStream::Suspend);
+    } else {
+      r = NS_NewRunnableMethod(aStream, &MediaStream::Resume);
+    }
     AbstractThread::MainThread()->Dispatch(r.forget());
   }
 }
 
 /*
  * All MediaStream-related data is protected by the decoder's monitor.
  * We have at most one DecodedStreamDaata per MediaDecoder. Its stream
  * is used as the input for each ProcessedMediaStream created by calls to
@@ -184,17 +191,17 @@ DecodedStreamData::GetPosition() const
   return mListener->GetLastOutputTime();
 }
 
 void
 DecodedStreamData::SetPlaying(bool aPlaying)
 {
   if (mPlaying != aPlaying) {
     mPlaying = aPlaying;
-    UpdateStreamBlocking(mStream, !mPlaying);
+    UpdateStreamSuspended(mStream, !mPlaying);
   }
 }
 
 OutputStreamData::~OutputStreamData()
 {
   MOZ_ASSERT(NS_IsMainThread());
   // Break the connection to the input stream if necessary.
   if (mPort) {
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -675,27 +675,27 @@ AudioDestinationNode::SetIsOnlyNodeForCo
     // Don't block the destination stream for offline AudioContexts, since
     // we expect the zero data produced when there are no other nodes to
     // show up in its result buffer. Also, we would get confused by adding
     // ExtraCurrentTime before StartRendering has even been called.
     return;
   }
 
   if (aIsOnlyNode) {
-    mStream->ChangeExplicitBlockerCount(1);
+    mStream->Suspend();
     mStartedBlockingDueToBeingOnlyNode = TimeStamp::Now();
     // Don't do an update of mExtraCurrentTimeSinceLastStartedBlocking until the next stable state.
     mExtraCurrentTimeUpdatedSinceLastStableState = true;
     ScheduleStableStateNotification();
   } else {
     // Force update of mExtraCurrentTimeSinceLastStartedBlocking if necessary
     ExtraCurrentTime();
     mExtraCurrentTime += mExtraCurrentTimeSinceLastStartedBlocking;
     mExtraCurrentTimeSinceLastStartedBlocking = 0;
-    mStream->ChangeExplicitBlockerCount(-1);
+    mStream->Resume();
     mStartedBlockingDueToBeingOnlyNode = TimeStamp();
   }
 }
 
 void
 AudioDestinationNode::InputMuted(bool aMuted)
 {
   MOZ_ASSERT(Context() && !Context()->IsOffline());
--- a/dom/media/webspeech/synth/nsSpeechTask.cpp
+++ b/dom/media/webspeech/synth/nsSpeechTask.cpp
@@ -558,17 +558,17 @@ nsSpeechTask::Pause()
   MOZ_ASSERT(XRE_IsParentProcess());
 
   if (mCallback) {
     DebugOnly<nsresult> rv = mCallback->OnPause();
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to call onPause() callback");
   }
 
   if (mStream) {
-    mStream->ChangeExplicitBlockerCount(1);
+    mStream->Suspend();
   }
 
   if (!mInited) {
     mPrePaused = true;
   }
 
   if (!mIndirectAudio) {
     DispatchPauseImpl(GetCurrentTime(), GetCurrentCharOffset());
@@ -581,17 +581,17 @@ nsSpeechTask::Resume()
   MOZ_ASSERT(XRE_IsParentProcess());
 
   if (mCallback) {
     DebugOnly<nsresult> rv = mCallback->OnResume();
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to call onResume() callback");
   }
 
   if (mStream) {
-    mStream->ChangeExplicitBlockerCount(-1);
+    mStream->Resume();
   }
 
   if (mPrePaused) {
     mPrePaused = false;
     nsSynthVoiceRegistry::GetInstance()->ResumeQueue();
   }
 
   if (!mIndirectAudio) {
@@ -607,33 +607,33 @@ nsSpeechTask::Cancel()
   LOG(LogLevel::Debug, ("nsSpeechTask::Cancel"));
 
   if (mCallback) {
     DebugOnly<nsresult> rv = mCallback->OnCancel();
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to call onCancel() callback");
   }
 
   if (mStream) {
-    mStream->ChangeExplicitBlockerCount(1);
+    mStream->Suspend();
   }
 
   if (!mInited) {
     mPreCanceled = true;
   }
 
   if (!mIndirectAudio) {
     DispatchEndInner(GetCurrentTime(), GetCurrentCharOffset());
   }
 }
 
 void
 nsSpeechTask::ForceEnd()
 {
   if (mStream) {
-    mStream->ChangeExplicitBlockerCount(1);
+    mStream->Suspend();
   }
 
   if (!mInited) {
     mPreCanceled = true;
   }
 
   DispatchEndInner(GetCurrentTime(), GetCurrentCharOffset());
 }