Bug 1189506. Make suspending/resuming streams more reusable. r=padenot
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 03 Sep 2015 23:54:00 +1200
changeset 295489 3a81598dc929419c5595f1110a7d0b0f46fd7dad
parent 295488 82ac981a8b0d79753740cb61200b0427973c2951
child 295490 c8d75cd4d9eaac0af060d9b28e8f68825dfbe236
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. Make suspending/resuming streams more reusable. r=padenot
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraphImpl.h
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -390,16 +390,17 @@ MediaStreamGraphImpl::UpdateCurrentTimeF
 
     if (streamHasOutput) {
       StreamNotifyOutput(stream);
     }
 
     if (stream->mFinished && !stream->mNotifiedFinished) {
       StreamReadyToFinish(stream);
     }
+
   }
 }
 
 bool
 MediaStreamGraphImpl::WillUnderrun(MediaStream* aStream, GraphTime aTime,
                                    GraphTime aEndBlockingDecisions, GraphTime* aEnd)
 {
   // Finished streams can't underrun. ProcessedMediaStreams also can't cause
@@ -3158,51 +3159,57 @@ MediaStreamGraph::NotifyWhenGraphStarted
 
   if (!aStream->IsDestroyed()) {
     MediaStreamGraphImpl* graphImpl = static_cast<MediaStreamGraphImpl*>(this);
     graphImpl->AppendMessage(new GraphStartedNotificationControlMessage(aStream));
   }
 }
 
 void
-MediaStreamGraphImpl::ResetVisitedStreamState()
+MediaStreamGraphImpl::IncrementSuspendCount(MediaStream* aStream)
 {
-  // Reset the visited/consumed/blocked state of the streams.
-  for (MediaStream* stream : AllStreams()) {
-    ProcessedMediaStream* ps = stream->AsProcessedStream();
+  if (!aStream->IsSuspended()) {
+    MOZ_ASSERT(mStreams.Contains(aStream));
+    mStreams.RemoveElement(aStream);
+    mSuspendedStreams.AppendElement(aStream);
+    SetStreamOrderDirty();
+  }
+  aStream->IncrementSuspendCount();
+}
+
+void
+MediaStreamGraphImpl::DecrementSuspendCount(MediaStream* aStream)
+{
+  bool wasSuspended = aStream->IsSuspended();
+  aStream->DecrementSuspendCount();
+  if (wasSuspended && !aStream->IsSuspended()) {
+    MOZ_ASSERT(mSuspendedStreams.Contains(aStream));
+    mSuspendedStreams.RemoveElement(aStream);
+    mStreams.AppendElement(aStream);
+    ProcessedMediaStream* ps = aStream->AsProcessedStream();
     if (ps) {
       ps->mCycleMarker = NOT_VISITED;
       ps->mIsConsumed = false;
       ps->mInBlockingSet = false;
     }
+    SetStreamOrderDirty();
   }
 }
 
 void
 MediaStreamGraphImpl::SuspendOrResumeStreams(AudioContextOperation aAudioContextOperation,
                                              const nsTArray<MediaStream*>& aStreamSet)
 {
   // For our purpose, Suspend and Close are equivalent: we want to remove the
   // streams from the set of streams that are going to be processed.
-  nsTArray<MediaStream*>& from =
-    aAudioContextOperation == AudioContextOperation::Resume ? mSuspendedStreams
-                                                            : mStreams;
-  nsTArray<MediaStream*>& to =
-    aAudioContextOperation == AudioContextOperation::Resume ? mStreams
-                                                            : mSuspendedStreams;
-
   for (MediaStream* stream : aStreamSet) {
-    auto i = from.IndexOf(stream);
-    MOZ_ASSERT(i != from.NoIndex);
-    from.RemoveElementAt(i);
-    to.AppendElement(stream);
     if (aAudioContextOperation == AudioContextOperation::Resume) {
-      stream->DecrementSuspendCount();
+      DecrementSuspendCount(stream);
     } else {
-      stream->IncrementSuspendCount();
+      IncrementSuspendCount(stream);
     }
   }
   STREAM_LOG(LogLevel::Debug, ("Moving streams between suspended and running"
       "state: mStreams: %d, mSuspendedStreams: %d\n", mStreams.Length(),
       mSuspendedStreams.Length()));
 #ifdef DEBUG
   // The intersection of the two arrays should be null.
   for (uint32_t i = 0; i < mStreams.Length(); i++) {
@@ -3240,20 +3247,16 @@ MediaStreamGraphImpl::AudioContextOperat
 
 void
 MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
     MediaStream* aDestinationStream, const nsTArray<MediaStream*>& aStreams,
     AudioContextOperation aOperation, void* aPromise)
 {
   MOZ_ASSERT(CurrentDriver()->OnThread());
 
-  SetStreamOrderDirty();
-
-  ResetVisitedStreamState();
-
   SuspendOrResumeStreams(aOperation, aStreams);
 
   // If we have suspended the last AudioContext, and we don't have other
   // streams that have audio, this graph will automatically switch to a
   // SystemCallbackDriver, because it can't find a MediaStream that has an audio
   // track. When resuming, force switching to an AudioCallbackDriver (if we're
   // not already switching). It would have happened at the next iteration
   // anyways, but doing this now save some time.
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -267,29 +267,34 @@ public:
    * Apply and AudioContext operation (suspend/resume/closed), on the graph
    * thread.
    */
   void ApplyAudioContextOperationImpl(MediaStream* aDestinationStream,
                                       const nsTArray<MediaStream*>& aStreams,
                                       dom::AudioContextOperation aOperation,
                                       void* aPromise);
 
+  /**
+   * Increment suspend count on aStream and move it to mSuspendedStreams if
+   * necessary.
+   */
+  void IncrementSuspendCount(MediaStream* aStream);
+  /**
+   * Increment suspend count on aStream and move it to mStreams if
+   * necessary.
+   */
+  void DecrementSuspendCount(MediaStream* aStream);
+
   /*
    * Move streams from the mStreams to mSuspendedStream if suspending/closing an
    * AudioContext, or the inverse when resuming an AudioContext.
    */
   void SuspendOrResumeStreams(dom::AudioContextOperation aAudioContextOperation,
                               const nsTArray<MediaStream*>& aStreamSet);
 
-  /*
-   * Reset some state about the streams before suspending them, or resuming
-   * them.
-   */
-  void ResetVisitedStreamState();
-
   /**
    * Sort mStreams so that every stream not in a cycle is after any streams
    * it depends on, and every stream in a cycle is marked as being in a cycle.
    * Also sets mIsConsumed on every stream.
    */
   void UpdateStreamOrder();
   /**
    * Compute the blocking states of streams from mStateComputedTime