Bug 1250934: Factor out AudioTracksPresent() in MediaStreamGraph, and add checks of 'pending' tracks r?padenot draft
authorRandell Jesup <rjesup@jesup.org>
Fri, 26 Feb 2016 00:36:25 -0500
changeset 334842 ce159423bcfee9cba4db0b813adbe66e6a9e1ba2
parent 334841 f0783430a5a474a59c32a272799a421926a42a75
child 334843 185aeccd9fc2388d58f8bb2ac9d6f388687c7360
push id11645
push userrjesup@wgate.com
push dateFri, 26 Feb 2016 05:38:04 +0000
reviewerspadenot
bugs1250934
milestone47.0a1
Bug 1250934: Factor out AudioTracksPresent() in MediaStreamGraph, and add checks of 'pending' tracks r?padenot MozReview-Commit-ID: Kif0WJvKy9h
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraphImpl.h
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -331,41 +331,62 @@ MediaStreamGraphImpl::WillUnderrun(Media
 
 namespace {
   // Value of mCycleMarker for unvisited streams in cycle detection.
   const uint32_t NOT_VISITED = UINT32_MAX;
   // Value of mCycleMarker for ordered streams in muted cycles.
   const uint32_t IN_MUTED_CYCLE = 1;
 } // namespace
 
-void
-MediaStreamGraphImpl::UpdateStreamOrder()
+bool
+MediaStreamGraphImpl::AudioTrackPresent(bool& aNeedsAEC)
 {
 #ifdef MOZ_WEBRTC
   bool shouldAEC = false;
 #endif
   bool audioTrackPresent = false;
-  for (uint32_t i = 0; i < mStreams.Length(); ++i) {
+  for (uint32_t i = 0; i < mStreams.Length() && audioTrackPresent == false; ++i) {
     MediaStream* stream = mStreams[i];
+    SourceMediaStream* source = stream->AsSourceStream();
 #ifdef MOZ_WEBRTC
-    if (stream->AsSourceStream() &&
-        stream->AsSourceStream()->NeedsMixing()) {
-      shouldAEC = true;
+    if (source && source->NeedsMixing()) {
+      aNeedsAEC = true;
     }
 #endif
     // If this is a AudioNodeStream, force a AudioCallbackDriver.
     if (stream->AsAudioNodeStream()) {
       audioTrackPresent = true;
     } else {
       for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer(), MediaSegment::AUDIO);
            !tracks.IsEnded(); tracks.Next()) {
         audioTrackPresent = true;
       }
     }
+    if (source) {
+      for (auto& data : source->mPendingTracks) {
+        if (data.mData->GetType() == MediaSegment::AUDIO) {
+          audioTrackPresent = true;
+          break;
+        }
+      }
+    }
   }
+
+#ifdef MOZ_WEBRTC
+  aNeedsAEC = shouldAEC;
+#endif
+  return audioTrackPresent;
+}
+
+void
+MediaStreamGraphImpl::UpdateStreamOrder()
+{
+  bool shouldAEC = false;
+  bool audioTrackPresent = AudioTrackPresent(shouldAEC);
+
   // Note that this looks for any audio streams, input or output, and switches to a
   // SystemClockDriver if there are none.  However, if another is already pending, let that
   // switch happen.
 
   if (!audioTrackPresent && mRealtime &&
       CurrentDriver()->AsAudioCallbackDriver()) {
     MonitorAutoLock mon(mMonitor);
     if (CurrentDriver()->AsAudioCallbackDriver()->IsStarted() &&
@@ -1021,30 +1042,18 @@ MediaStreamGraphImpl::CloseAudioInputImp
   mInputWanted = false;
   AudioCallbackDriver *driver = CurrentDriver()->AsAudioCallbackDriver();
   if (driver) {
     driver->RemoveInputListener(aListener);
   }
   mAudioInputs.RemoveElement(aListener);
 
   // Switch Drivers since we're adding or removing an input (to nothing/system or output only)
-  bool audioTrackPresent = false;
-  for (uint32_t i = 0; i < mStreams.Length(); ++i) {
-    MediaStream* stream = mStreams[i];
-    // If this is a AudioNodeStream, force a AudioCallbackDriver.
-    if (stream->AsAudioNodeStream()) {
-      audioTrackPresent = true;
-    } else if (CurrentDriver()->AsAudioCallbackDriver()) {
-      // only if there's a real switch!
-      for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer(), MediaSegment::AUDIO);
-           !tracks.IsEnded(); tracks.Next()) {
-        audioTrackPresent = true;
-      }
-    }
-  }
+  bool shouldAEC = false;
+  bool audioTrackPresent = AudioTrackPresent(shouldAEC);
 
   MonitorAutoLock mon(mMonitor);
   if (mLifecycleState == LIFECYCLE_RUNNING) {
     GraphDriver* driver;
     if (audioTrackPresent) {
       // We still have audio output
       STREAM_LOG(LogLevel::Debug, ("CloseInput: output present (AudioCallback)"));
 
@@ -3268,27 +3277,19 @@ MediaStreamGraphImpl::ApplyAudioContextO
     }
   }
   // Close, suspend: check if we are going to switch to a
   // SystemAudioCallbackDriver, and pass the promise to the AudioCallbackDriver
   // if that's the case, so it can notify the content.
   // This is the same logic as in UpdateStreamOrder, but it's simpler to have it
   // here as well so we don't have to store the Promise(s) on the Graph.
   if (aOperation != AudioContextOperation::Resume) {
-    bool audioTrackPresent = false;
-    for (uint32_t i = 0; i < mStreams.Length(); ++i) {
-      MediaStream* stream = mStreams[i];
-      if (stream->AsAudioNodeStream()) {
-        audioTrackPresent = true;
-      }
-      for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer(), MediaSegment::AUDIO);
-          !tracks.IsEnded(); tracks.Next()) {
-        audioTrackPresent = true;
-      }
-    }
+    bool shouldAEC = false;
+    bool audioTrackPresent = AudioTrackPresent(shouldAEC);
+
     if (!audioTrackPresent && CurrentDriver()->AsAudioCallbackDriver()) {
       CurrentDriver()->AsAudioCallbackDriver()->
         EnqueueStreamAndPromiseForOperation(aDestinationStream, aPromise,
                                             aOperation);
 
       SystemClockDriver* driver;
       if (nextDriver) {
         MOZ_ASSERT(!nextDriver->AsAudioCallbackDriver());
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -329,16 +329,22 @@ public:
   /*
    * 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);
 
   /**
+   * Determine if we have any audio tracks, or are about to add any audiotracks.
+   * Also checks if we'll need the AEC running (i.e. microphone input tracks)
+   */
+  bool AudioTrackPresent(bool& aNeedsAEC);
+
+  /**
    * 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();
 
   /**
    * Returns smallest value of t such that t is a multiple of