Bug 1250934: Factor out AudioTracksPresent() in MediaStreamGraph, and add checks of 'pending' tracks r?padenot
MozReview-Commit-ID: Kif0WJvKy9h
--- 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