Bug 805721. Recursively mark streams as consumed starting at the consumption point and working backwards through the graph. r=jesup
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 29 Oct 2012 17:34:17 +1300
changeset 119591 c1b7d0153476c21fb2030b78d1e2af0305ced9fc
parent 119590 bf45387fc47cbad4cae24d2e2b8723ebb67aff40
child 119592 ed720383aab39b79ec98f1c9d6cc9658f49718ef
push id1997
push userakeybl@mozilla.com
push dateMon, 07 Jan 2013 21:25:26 +0000
treeherdermozilla-beta@4baf45cdcf21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs805721
milestone19.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 805721. Recursively mark streams as consumed starting at the consumption point and working backwards through the graph. r=jesup
content/media/MediaStreamGraph.cpp
content/media/MediaStreamGraph.h
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -219,19 +219,19 @@ public:
   void UpdateBufferSufficiencyState(SourceMediaStream* aStream);
   /*
    * If aStream hasn't already been ordered, push it onto aStack and order
    * its children.
    */
   void UpdateStreamOrderForStream(nsTArray<MediaStream*>* aStack,
                                   already_AddRefed<MediaStream> aStream);
   /**
-   * Compute aStream's mIsConsumed.
+   * Mark aStream and all its inputs (recursively) as consumed.
    */
-  static void DetermineWhetherStreamIsConsumed(MediaStream* aStream);
+  static void MarkConsumed(MediaStream* aStream);
   /**
    * 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
@@ -878,33 +878,30 @@ MediaStreamGraphImpl::WillUnderrun(Media
     return true;
   }
   // Reconsider decisions at bufferEnd
   *aEnd = NS_MIN(*aEnd, bufferEnd);
   return false;
 }
 
 void
-MediaStreamGraphImpl::DetermineWhetherStreamIsConsumed(MediaStream* aStream)
+MediaStreamGraphImpl::MarkConsumed(MediaStream* aStream)
 {
-  if (aStream->mKnowIsConsumed)
-    return;
-  aStream->mKnowIsConsumed = true;
-  if (!aStream->mAudioOutputs.IsEmpty() ||
-      !aStream->mVideoOutputs.IsEmpty()) {
-    aStream->mIsConsumed = true;
+  if (aStream->mIsConsumed) {
     return;
   }
-  for (uint32_t i = 0; i < aStream->mConsumers.Length(); ++i) {
-    MediaStream* dest = aStream->mConsumers[i]->mDest;
-    DetermineWhetherStreamIsConsumed(dest);
-    if (dest->mIsConsumed) {
-      aStream->mIsConsumed = true;
-      return;
-    }
+  aStream->mIsConsumed = true;
+
+  ProcessedMediaStream* ps = aStream->AsProcessedStream();
+  if (!ps) {
+    return;
+  }
+  // Mark all the inputs to this stream as consumed
+  for (uint32_t i = 0; i < ps->mInputs.Length(); ++i) {
+    MarkConsumed(ps->mInputs[i]->mSource);
   }
 }
 
 void
 MediaStreamGraphImpl::UpdateStreamOrderForStream(nsTArray<MediaStream*>* aStack,
                                                  already_AddRefed<MediaStream> aStream)
 {
   nsRefPtr<MediaStream> stream = aStream;
@@ -912,17 +909,16 @@ MediaStreamGraphImpl::UpdateStreamOrderF
   if (stream->mIsOnOrderingStack) {
     for (int32_t i = aStack->Length() - 1; ; --i) {
       aStack->ElementAt(i)->AsProcessedStream()->mInCycle = true;
       if (aStack->ElementAt(i) == stream)
         break;
     }
     return;
   }
-  DetermineWhetherStreamIsConsumed(stream);
   ProcessedMediaStream* ps = stream->AsProcessedStream();
   if (ps) {
     aStack->AppendElement(stream);
     stream->mIsOnOrderingStack = true;
     for (uint32_t i = 0; i < ps->mInputs.Length(); ++i) {
       MediaStream* source = ps->mInputs[i]->mSource;
       if (!source->mHasBeenOrdered) {
         nsRefPtr<MediaStream> s = source;
@@ -940,30 +936,33 @@ MediaStreamGraphImpl::UpdateStreamOrderF
 void
 MediaStreamGraphImpl::UpdateStreamOrder()
 {
   nsTArray<nsRefPtr<MediaStream> > oldStreams;
   oldStreams.SwapElements(mStreams);
   for (uint32_t i = 0; i < oldStreams.Length(); ++i) {
     MediaStream* stream = oldStreams[i];
     stream->mHasBeenOrdered = false;
-    stream->mKnowIsConsumed = false;
     stream->mIsConsumed = false;
     stream->mIsOnOrderingStack = false;
     stream->mInBlockingSet = false;
     ProcessedMediaStream* ps = stream->AsProcessedStream();
     if (ps) {
       ps->mInCycle = false;
     }
   }
 
   nsAutoTArray<MediaStream*,10> stack;
   for (uint32_t i = 0; i < oldStreams.Length(); ++i) {
-    if (!oldStreams[i]->mHasBeenOrdered) {
-      UpdateStreamOrderForStream(&stack, oldStreams[i].forget());
+    nsRefPtr<MediaStream>& s = oldStreams[i];
+    if (!s->mAudioOutputs.IsEmpty() || !s->mVideoOutputs.IsEmpty()) {
+      MarkConsumed(s);
+    }
+    if (!s->mHasBeenOrdered) {
+      UpdateStreamOrderForStream(&stack, s.forget());
     }
   }
 }
 
 void
 MediaStreamGraphImpl::RecomputeBlocking(GraphTime aEndBlockingDecisions)
 {
   bool blockingDecisionsWillChange = false;
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -456,22 +456,19 @@ protected:
    * When true, mFinished is true and we've played all the data in this stream
    * and fired NotifyFinished notifications.
    */
   bool mNotifiedFinished;
 
   // Temporary data for ordering streams by dependency graph
   bool mHasBeenOrdered;
   bool mIsOnOrderingStack;
-  // Temporary data to record if the stream is being consumed
-  // (i.e. has track data being played, or is feeding into some stream
-  // that is being consumed).
+  // True if the stream is being consumed (i.e. has track data being played,
+  // or is feeding into some stream that is being consumed).
   bool mIsConsumed;
-  // True if the above value is accurate.
-  bool mKnowIsConsumed;
   // Temporary data for computing blocking status of streams
   // True if we've added this stream to the set of streams we're computing
   // blocking for.
   bool mInBlockingSet;
   // True if this stream should be blocked in this phase.
   bool mBlockInThisPhase;
 
   // This state is only used on the main thread.