Bug 1423241 - Remove MediaStreamListener \o/. r=padenot
authorAndreas Pehrson <apehrson@mozilla.com>
Fri, 23 Nov 2018 15:03:00 +0000
changeset 507063 ed8ffdb9c33abedb857904f146b5e5995232ea37
parent 507062 929905c7782b6f0ba4cb57ade1cb1daa7429043e
child 507064 3ec97b5fccd710460f860a8e4f0d43f251392c00
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1423241
milestone65.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 1423241 - Remove MediaStreamListener \o/. r=padenot Differential Revision: https://phabricator.services.mozilla.com/D12284
dom/media/AudioCaptureStream.cpp
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/MediaStreamGraphImpl.h
dom/media/MediaStreamListener.h
dom/media/TrackUnionStream.cpp
dom/media/imagecapture/CaptureTask.cpp
dom/media/webaudio/AudioNodeStream.cpp
--- a/dom/media/AudioCaptureStream.cpp
+++ b/dom/media/AudioCaptureStream.cpp
@@ -25,20 +25,17 @@ using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 
 // We are mixing to mono until PeerConnection can accept stereo
 static const uint32_t MONO = 1;
 
 AudioCaptureStream::AudioCaptureStream(TrackID aTrackId)
-    : ProcessedMediaStream(),
-      mTrackId(aTrackId),
-      mStarted(false),
-      mTrackCreated(false) {
+    : ProcessedMediaStream(), mTrackId(aTrackId), mStarted(false) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_COUNT_CTOR(AudioCaptureStream);
   mMixer.AddCallback(this);
 }
 
 AudioCaptureStream::~AudioCaptureStream() {
   MOZ_COUNT_DTOR(AudioCaptureStream);
   mMixer.RemoveCallback(this);
@@ -61,27 +58,16 @@ void AudioCaptureStream::Start() {
 void AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
                                       uint32_t aFlags) {
   if (!mStarted) {
     return;
   }
 
   uint32_t inputCount = mInputs.Length();
   StreamTracks::Track* track = EnsureTrack(mTrackId);
-  // Notify the DOM everything is in order.
-  if (!mTrackCreated) {
-    for (uint32_t i = 0; i < mListeners.Length(); i++) {
-      MediaStreamListener* l = mListeners[i];
-      AudioSegment tmp;
-      l->NotifyQueuedTrackChanges(Graph(), mTrackId, 0,
-                                  TrackEventCommand::TRACK_EVENT_CREATED, tmp);
-      l->NotifyFinishedTrackCreation(Graph());
-    }
-    mTrackCreated = true;
-  }
 
   if (IsFinishedOnGraphThread()) {
     return;
   }
 
   // If the captured stream is connected back to a object on the page (be it an
   // HTMLMediaElement with a stream as source, or an AudioContext), a cycle
   // situation occur. This can work if it's an AudioContext with at least one
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -50,17 +50,16 @@ LazyLogModule gMediaStreamGraphLog("Medi
 #ifdef LOG
 #undef LOG
 #endif  // LOG
 #define LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
 
 enum SourceMediaStream::TrackCommands : uint32_t {
   TRACK_CREATE = TrackEventCommand::TRACK_EVENT_CREATED,
   TRACK_END = TrackEventCommand::TRACK_EVENT_ENDED,
-  TRACK_UNUSED = TrackEventCommand::TRACK_EVENT_UNUSED,
 };
 
 /**
  * A hash table containing the graph instances, one per document.
  *
  * The key is a hash of nsPIDOMWindowInner, see `WindowToHash`.
  */
 static nsDataHashtable<nsUint32HashKey, MediaStreamGraphImpl*> gGraphs;
@@ -146,55 +145,31 @@ GraphTime MediaStreamGraphImpl::Iteratio
   MOZ_ASSERT(OnGraphThreadOrNotRunning());
   return CurrentDriver()->IterationEnd();
 }
 
 void MediaStreamGraphImpl::UpdateCurrentTimeForStreams(
     GraphTime aPrevCurrentTime) {
   MOZ_ASSERT(OnGraphThread());
   for (MediaStream* stream : AllStreams()) {
-    bool isAnyBlocked = stream->mStartBlocking < mStateComputedTime;
-    bool isAnyUnblocked = stream->mStartBlocking > aPrevCurrentTime;
+    // Shouldn't have already notified of finish *and* have output!
+    MOZ_ASSERT_IF(stream->mStartBlocking > aPrevCurrentTime,
+                  !stream->mNotifiedFinished);
 
     // Calculate blocked time and fire Blocked/Unblocked events
     GraphTime blockedTime = mStateComputedTime - stream->mStartBlocking;
     NS_ASSERTION(blockedTime >= 0, "Error in blocking time");
     stream->AdvanceTimeVaryingValuesToCurrentTime(mStateComputedTime,
                                                   blockedTime);
     LOG(LogLevel::Verbose,
         ("%p: MediaStream %p bufferStartTime=%f blockedTime=%f", this, stream,
          MediaTimeToSeconds(stream->mTracksStartTime),
          MediaTimeToSeconds(blockedTime)));
     stream->mStartBlocking = mStateComputedTime;
 
-    if (isAnyUnblocked && stream->mNotifiedBlocked) {
-      for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
-        MediaStreamListener* l = stream->mListeners[j];
-        l->NotifyBlockingChanged(this, MediaStreamListener::UNBLOCKED);
-      }
-      stream->mNotifiedBlocked = false;
-    }
-    if (isAnyBlocked && !stream->mNotifiedBlocked) {
-      for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
-        MediaStreamListener* l = stream->mListeners[j];
-        l->NotifyBlockingChanged(this, MediaStreamListener::BLOCKED);
-      }
-      stream->mNotifiedBlocked = true;
-    }
-
-    if (isAnyUnblocked) {
-      NS_ASSERTION(
-          !stream->mNotifiedFinished,
-          "Shouldn't have already notified of finish *and* have output!");
-      for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
-        MediaStreamListener* l = stream->mListeners[j];
-        l->NotifyOutput(this, mProcessedTime);
-      }
-    }
-
     for (StreamTracks::TrackIter track(stream->mTracks); !track.IsEnded();
          track.Next()) {
       StreamTime streamCurrentTime =
           stream->GraphTimeToStreamTime(mStateComputedTime);
       if (track->IsEnded() && track->GetEnd() <= streamCurrentTime) {
         if (!track->NotifiedEnded()) {
           // Playout of this track ended and listeners have not been notified.
           track->NotifyEnded();
@@ -219,20 +194,16 @@ void MediaStreamGraphImpl::UpdateCurrent
 
     // The stream is fully finished when all of its track data has been played
     // out.
     if (stream->mFinished && !stream->mNotifiedFinished &&
         mProcessedTime >= stream->StreamTimeToGraphTime(
                               stream->GetStreamTracks().GetAllTracksEnd())) {
       stream->mNotifiedFinished = true;
       SetStreamOrderDirty();
-      for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
-        MediaStreamListener* l = stream->mListeners[j];
-        l->NotifyEvent(this, MediaStreamGraphEvent::EVENT_FINISHED);
-      }
     }
   }
 }
 
 template <typename C, typename Chunk>
 void MediaStreamGraphImpl::ProcessChunkMetadataForInterval(MediaStream* aStream,
                                                            TrackID aTrackID,
                                                            C& aSegment,
@@ -585,26 +556,16 @@ void MediaStreamGraphImpl::UpdateStreamO
         ++orderedStreamCount;
       }
     }
   }
 
   MOZ_ASSERT(orderedStreamCount == mFirstCycleBreaker);
 }
 
-void MediaStreamGraphImpl::NotifyHasCurrentData(MediaStream* aStream) {
-  if (!aStream->mNotifiedHasCurrentData && aStream->mHasCurrentData) {
-    for (uint32_t j = 0; j < aStream->mListeners.Length(); ++j) {
-      MediaStreamListener* l = aStream->mListeners[j];
-      l->NotifyHasCurrentData(this);
-    }
-    aStream->mNotifiedHasCurrentData = true;
-  }
-}
-
 void MediaStreamGraphImpl::CreateOrDestroyAudioStreams(MediaStream* aStream) {
   MOZ_ASSERT(OnGraphThread());
   MOZ_ASSERT(mRealtime,
              "Should only attempt to create audio streams in real-time mode");
 
   if (aStream->mAudioOutputs.IsEmpty()) {
     aStream->mAudioOutputStreams.Clear();
     return;
@@ -1258,20 +1219,22 @@ void MediaStreamGraphImpl::UpdateGraph(G
           if (i->IsEnded()) {
             continue;
           }
           if (i->GetEnd() <
               stream->GraphTimeToStreamTime(aEndBlockingDecisions)) {
             LOG(LogLevel::Error,
                 ("%p: SourceMediaStream %p track %u (%s) is live and pulled, "
                  "but wasn't fed "
-                 "enough data. Listeners=%zu. Track-end=%f, Iteration-end=%f",
+                 "enough data. TrackListeners=%zu. Track-end=%f, "
+                 "Iteration-end=%f",
                  this, stream, i->GetID(),
                  (i->GetType() == MediaSegment::AUDIO ? "audio" : "video"),
-                 stream->mListeners.Length(), MediaTimeToSeconds(i->GetEnd()),
+                 stream->mTrackListeners.Length(),
+                 MediaTimeToSeconds(i->GetEnd()),
                  MediaTimeToSeconds(
                      stream->GraphTimeToStreamTime(aEndBlockingDecisions))));
             MOZ_DIAGNOSTIC_ASSERT(false,
                                   "A non-finished SourceMediaStream wasn't fed "
                                   "enough data by NotifyPull");
           }
         }
       }
@@ -1337,17 +1300,16 @@ void MediaStreamGraphImpl::Process() {
                            ProcessedMediaStream::ALLOW_FINISH);
           NS_ASSERTION(
               stream->mTracks.GetEnd() >=
                   GraphTimeToStreamTimeWithBlocking(stream, mStateComputedTime),
               "Stream did not produce enough data");
         }
       }
     }
-    NotifyHasCurrentData(stream);
     // Only playback audio and video in real-time mode
     if (mRealtime) {
       CreateOrDestroyAudioStreams(stream);
       if (CurrentDriver()->AsAudioCallbackDriver()) {
         StreamTime ticksPlayedForThisStream = PlayAudio(stream);
         if (!ticksPlayed) {
           ticksPlayed = ticksPlayedForThisStream;
         } else {
@@ -1868,19 +1830,17 @@ void MediaStreamGraphImpl::Dispatch(alre
 }
 
 MediaStream::MediaStream()
     : mTracksStartTime(0),
       mStartBlocking(GRAPH_TIME_MAX),
       mSuspendedCount(0),
       mFinished(false),
       mNotifiedFinished(false),
-      mNotifiedBlocked(false),
       mHasCurrentData(false),
-      mNotifiedHasCurrentData(false),
       mMainThreadCurrentTime(0),
       mMainThreadFinished(false),
       mFinishedNotificationSent(false),
       mMainThreadDestroyed(false),
       mNrOfMainThreadUsers(0),
       mGraph(nullptr) {
   MOZ_COUNT_CTOR(MediaStream);
 }
@@ -1896,23 +1856,23 @@ size_t MediaStream::SizeOfExcludingThis(
   size_t amount = 0;
 
   // Not owned:
   // - mGraph - Not reported here
   // - mConsumers - elements
   // Future:
   // - mVideoOutputs - elements
   // - mLastPlayedVideoFrame
-  // - mListeners - elements
+  // - mTrackListeners - elements
   // - mAudioOutputStream - elements
 
   amount += mTracks.SizeOfExcludingThis(aMallocSizeOf);
   amount += mAudioOutputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
   amount += mVideoOutputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
-  amount += mListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  amount += mTrackListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
   amount += mMainThreadListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
   amount += mDisabledTracks.ShallowSizeOfExcludingThis(aMallocSizeOf);
   amount += mConsumers.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   return amount;
 }
 
 size_t MediaStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
@@ -2005,40 +1965,24 @@ void MediaStream::FinishOnGraphThread() 
 
 StreamTracks::Track* MediaStream::FindTrack(TrackID aID) const {
   return mTracks.FindTrack(aID);
 }
 
 StreamTracks::Track* MediaStream::EnsureTrack(TrackID aTrackId) {
   StreamTracks::Track* track = mTracks.FindTrack(aTrackId);
   if (!track) {
-    nsAutoPtr<MediaSegment> segment(new AudioSegment());
-    for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-      MediaStreamListener* l = mListeners[j];
-      l->NotifyQueuedTrackChanges(Graph(), aTrackId, 0,
-                                  TrackEventCommand::TRACK_EVENT_CREATED,
-                                  *segment);
-      // TODO If we ever need to ensure several tracks at once, we will have to
-      // change this.
-      l->NotifyFinishedTrackCreation(Graph());
-    }
-    track = &mTracks.AddTrack(aTrackId, 0, segment.forget());
+    track = &mTracks.AddTrack(aTrackId, 0, new AudioSegment());
   }
   return track;
 }
 
 void MediaStream::RemoveAllListenersImpl() {
   GraphImpl()->AssertOnGraphThreadOrNotRunning();
 
-  auto streamListeners(mListeners);
-  for (auto& l : streamListeners) {
-    l->NotifyEvent(GraphImpl(), MediaStreamGraphEvent::EVENT_REMOVED);
-  }
-  mListeners.Clear();
-
   auto trackListeners(mTrackListeners);
   for (auto& l : trackListeners) {
     l.mListener->NotifyRemoved();
   }
   mTrackListeners.Clear();
 
   RemoveAllDirectListenersImpl();
 
@@ -2254,93 +2198,16 @@ void MediaStream::Resume() {
   // This can happen if this method has been called asynchronously, and the
   // stream has been destroyed since then.
   if (mMainThreadDestroyed) {
     return;
   }
   GraphImpl()->AppendMessage(MakeUnique<Message>(this));
 }
 
-void MediaStream::AddListenerImpl(
-    already_AddRefed<MediaStreamListener> aListener) {
-  MediaStreamListener* listener = *mListeners.AppendElement() = aListener;
-  listener->NotifyBlockingChanged(
-      GraphImpl(), mNotifiedBlocked ? MediaStreamListener::BLOCKED
-                                    : MediaStreamListener::UNBLOCKED);
-
-  for (StreamTracks::TrackIter it(mTracks); !it.IsEnded(); it.Next()) {
-    MediaStream* inputStream = nullptr;
-    TrackID inputTrackID = TRACK_INVALID;
-    if (ProcessedMediaStream* ps = AsProcessedStream()) {
-      // The only ProcessedMediaStream where we should have listeners is
-      // TrackUnionStream - it's what's used as owned stream in DOMMediaStream,
-      // the only main-thread exposed stream type.
-      // TrackUnionStream guarantees that each of its tracks has an input track.
-      // Other types do not implement GetInputStreamFor() and will return null.
-      inputStream = ps->GetInputStreamFor(it->GetID());
-      if (!inputStream && it->IsEnded()) {
-        // If this track has no input anymore we assume there's no data for the
-        // current iteration either and thus no need to expose it to a listener.
-        continue;
-      }
-      MOZ_ASSERT(inputStream);
-      inputTrackID = ps->GetInputTrackIDFor(it->GetID());
-      MOZ_ASSERT(IsTrackIDExplicit(inputTrackID));
-    }
-
-    uint32_t flags = TrackEventCommand::TRACK_EVENT_CREATED;
-    if (it->IsEnded()) {
-      flags |= TrackEventCommand::TRACK_EVENT_ENDED;
-    }
-    nsAutoPtr<MediaSegment> segment(it->GetSegment()->CreateEmptyClone());
-    listener->NotifyQueuedTrackChanges(Graph(), it->GetID(), it->GetEnd(),
-                                       static_cast<TrackEventCommand>(flags),
-                                       *segment, inputStream, inputTrackID);
-  }
-  if (mNotifiedFinished) {
-    listener->NotifyEvent(GraphImpl(), MediaStreamGraphEvent::EVENT_FINISHED);
-  }
-  if (mNotifiedHasCurrentData) {
-    listener->NotifyHasCurrentData(GraphImpl());
-  }
-}
-
-void MediaStream::AddListener(MediaStreamListener* aListener) {
-  class Message : public ControlMessage {
-   public:
-    Message(MediaStream* aStream, MediaStreamListener* aListener)
-        : ControlMessage(aStream), mListener(aListener) {}
-    void Run() override { mStream->AddListenerImpl(mListener.forget()); }
-    RefPtr<MediaStreamListener> mListener;
-  };
-  GraphImpl()->AppendMessage(MakeUnique<Message>(this, aListener));
-}
-
-void MediaStream::RemoveListenerImpl(MediaStreamListener* aListener) {
-  // wouldn't need this if we could do it in the opposite order
-  RefPtr<MediaStreamListener> listener(aListener);
-  mListeners.RemoveElement(aListener);
-  listener->NotifyEvent(GraphImpl(), MediaStreamGraphEvent::EVENT_REMOVED);
-}
-
-void MediaStream::RemoveListener(MediaStreamListener* aListener) {
-  class Message : public ControlMessage {
-   public:
-    Message(MediaStream* aStream, MediaStreamListener* aListener)
-        : ControlMessage(aStream), mListener(aListener) {}
-    void Run() override { mStream->RemoveListenerImpl(mListener); }
-    RefPtr<MediaStreamListener> mListener;
-  };
-  // If the stream is destroyed the Listeners have or will be
-  // removed.
-  if (!IsDestroyed()) {
-    GraphImpl()->AppendMessage(MakeUnique<Message>(this, aListener));
-  }
-}
-
 void MediaStream::AddTrackListenerImpl(
     already_AddRefed<MediaStreamTrackListener> aListener, TrackID aTrackID) {
   TrackBound<MediaStreamTrackListener>* l = mTrackListeners.AppendElement();
   l->mListener = aListener;
   l->mTrackID = aTrackID;
 
   StreamTracks::Track* track = FindTrack(aTrackID);
   if (!track) {
@@ -2650,23 +2517,16 @@ bool SourceMediaStream::PullNewData(Grap
   StreamTime current = mTracks.GetEnd();
   LOG(LogLevel::Verbose,
       ("%p: Calling NotifyPull aStream=%p t=%f current end=%f", GraphImpl(),
        this, GraphImpl()->MediaTimeToSeconds(t),
        GraphImpl()->MediaTimeToSeconds(current)));
   if (t <= current) {
     return false;
   }
-  for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-    MediaStreamListener* l = mListeners[j];
-    {
-      MutexAutoUnlock unlock(mMutex);
-      l->NotifyPull(GraphImpl(), t);
-    }
-  }
   for (const TrackData& track : mUpdateTracks) {
     if (track.mCommands & TrackEventCommand::TRACK_EVENT_ENDED) {
       continue;
     }
     current = track.mEndOfFlushedData + track.mData->GetDuration();
     if (t <= current) {
       continue;
     }
@@ -2679,71 +2539,30 @@ bool SourceMediaStream::PullNewData(Grap
   }
   return true;
 }
 
 void SourceMediaStream::ExtractPendingInput(GraphTime aCurrentTime) {
   MutexAutoLock lock(mMutex);
 
   bool finished = mFinishPending;
-  bool shouldNotifyTrackCreated = false;
   StreamTime streamCurrentTime = GraphTimeToStreamTime(aCurrentTime);
 
   for (int32_t i = mUpdateTracks.Length() - 1; i >= 0; --i) {
     SourceMediaStream::TrackData* data = &mUpdateTracks[i];
     ApplyTrackDisabling(data->mID, data->mData);
     // Dealing with NotifyQueuedTrackChanges and NotifyQueuedAudioData part.
 
     // The logic is different from the manipulating of aStream->mTracks part.
     // So it is not combined with the manipulating of aStream->mTracks part.
     StreamTime offset =
         (data->mCommands & SourceMediaStream::TRACK_CREATE)
             ? streamCurrentTime
             : mTracks.FindTrack(data->mID)->GetSegment()->GetDuration();
 
-    // Audio case.
-    if (data->mData->GetType() == MediaSegment::AUDIO) {
-      if (data->mCommands) {
-        MOZ_ASSERT(!(data->mCommands & SourceMediaStream::TRACK_UNUSED));
-        for (MediaStreamListener* l : mListeners) {
-          if (data->mCommands & SourceMediaStream::TRACK_END) {
-            l->NotifyQueuedAudioData(
-                GraphImpl(), data->mID, offset,
-                *(static_cast<AudioSegment*>(data->mData.get())));
-          }
-          l->NotifyQueuedTrackChanges(
-              GraphImpl(), data->mID, offset,
-              static_cast<TrackEventCommand>(data->mCommands), *data->mData);
-          if (data->mCommands & SourceMediaStream::TRACK_CREATE) {
-            l->NotifyQueuedAudioData(
-                GraphImpl(), data->mID, offset,
-                *(static_cast<AudioSegment*>(data->mData.get())));
-          }
-        }
-      } else {
-        for (MediaStreamListener* l : mListeners) {
-          l->NotifyQueuedAudioData(
-              GraphImpl(), data->mID, offset,
-              *(static_cast<AudioSegment*>(data->mData.get())));
-        }
-      }
-    }
-
-    // Video case.
-    if (data->mData->GetType() == MediaSegment::VIDEO) {
-      if (data->mCommands) {
-        MOZ_ASSERT(!(data->mCommands & SourceMediaStream::TRACK_UNUSED));
-        for (MediaStreamListener* l : mListeners) {
-          l->NotifyQueuedTrackChanges(
-              GraphImpl(), data->mID, offset,
-              static_cast<TrackEventCommand>(data->mCommands), *data->mData);
-        }
-      }
-    }
-
     for (TrackBound<MediaStreamTrackListener>& b : mTrackListeners) {
       if (b.mTrackID != data->mID) {
         continue;
       }
       b.mListener->NotifyQueuedChanges(GraphImpl(), offset, *data->mData);
     }
     if (data->mCommands & SourceMediaStream::TRACK_CREATE) {
       MediaSegment* segment = data->mData.forget();
@@ -2755,37 +2574,31 @@ void SourceMediaStream::ExtractPendingIn
 
       data->mEndOfFlushedData += segment->GetDuration();
       segment->InsertNullDataAtStart(streamCurrentTime);
       mTracks.AddTrack(data->mID, streamCurrentTime, segment);
       // The track has taken ownership of data->mData, so let's replace
       // data->mData with an empty clone.
       data->mData = segment->CreateEmptyClone();
       data->mCommands &= ~SourceMediaStream::TRACK_CREATE;
-      shouldNotifyTrackCreated = true;
     } else if (data->mData->GetDuration() > 0) {
       MediaSegment* dest = mTracks.FindTrack(data->mID)->GetSegment();
       LOG(LogLevel::Verbose,
           ("%p: SourceMediaStream %p track %d, advancing end from %" PRId64
            " to %" PRId64,
            GraphImpl(), this, data->mID, int64_t(dest->GetDuration()),
            int64_t(dest->GetDuration() + data->mData->GetDuration())));
       data->mEndOfFlushedData += data->mData->GetDuration();
       dest->AppendFrom(data->mData);
     }
     if (data->mCommands & SourceMediaStream::TRACK_END) {
       mTracks.FindTrack(data->mID)->SetEnded();
       mUpdateTracks.RemoveElementAt(i);
     }
   }
-  if (shouldNotifyTrackCreated) {
-    for (MediaStreamListener* l : mListeners) {
-      l->NotifyFinishedTrackCreation(GraphImpl());
-    }
-  }
   if (!mFinished) {
     mTracks.AdvanceKnownTracksTime(mUpdateKnownTracksTime);
   }
 
   if (mTracks.GetEnd() > 0) {
     mHasCurrentData = true;
   }
 
@@ -2911,37 +2724,16 @@ void SourceMediaStream::NotifyDirectCons
     }
     StreamTime offset = 0;  // FIX! need a separate StreamTime.... or the end of
                             // the internal buffer
     source.mListener->NotifyRealtimeTrackDataAndApplyTrackDisabling(
         Graph(), offset, *aSegment);
   }
 }
 
-// These handle notifying all the listeners of an event
-void SourceMediaStream::NotifyListenersEventImpl(MediaStreamGraphEvent aEvent) {
-  for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-    MediaStreamListener* l = mListeners[j];
-    l->NotifyEvent(GraphImpl(), aEvent);
-  }
-}
-
-void SourceMediaStream::NotifyListenersEvent(MediaStreamGraphEvent aNewEvent) {
-  class Message : public ControlMessage {
-   public:
-    Message(SourceMediaStream* aStream, MediaStreamGraphEvent aEvent)
-        : ControlMessage(aStream), mEvent(aEvent) {}
-    void Run() override {
-      mStream->AsSourceStream()->NotifyListenersEventImpl(mEvent);
-    }
-    MediaStreamGraphEvent mEvent;
-  };
-  GraphImpl()->AppendMessage(MakeUnique<Message>(this, aNewEvent));
-}
-
 void SourceMediaStream::AddDirectTrackListenerImpl(
     already_AddRefed<DirectMediaStreamTrackListener> aListener,
     TrackID aTrackID) {
   MOZ_ASSERT(IsTrackIDExplicit(aTrackID));
   MutexAutoLock lock(mMutex);
 
   RefPtr<DirectMediaStreamTrackListener> listener = aListener;
   LOG(LogLevel::Debug, ("%p: Adding direct track listener %p bound to track %d "
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -176,17 +176,16 @@ struct AudioNodeSizes {
 
 class AudioNodeEngine;
 class AudioNodeExternalInputStream;
 class AudioNodeStream;
 class AudioSegment;
 class DirectMediaStreamTrackListener;
 class MediaInputPort;
 class MediaStreamGraphImpl;
-class MediaStreamListener;
 class MediaStreamTrackListener;
 class MediaStreamVideoSink;
 class ProcessedMediaStream;
 class SourceMediaStream;
 class TrackUnionStream;
 
 /**
  * Helper struct for binding a track listener to a specific TrackID.
@@ -315,18 +314,16 @@ class MediaStream : public mozilla::Link
   // 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();
   // Events will be dispatched by calling methods of aListener.
-  virtual void AddListener(MediaStreamListener* aListener);
-  virtual void RemoveListener(MediaStreamListener* aListener);
   virtual void AddTrackListener(MediaStreamTrackListener* aListener,
                                 TrackID aTrackID);
   virtual void RemoveTrackListener(MediaStreamTrackListener* aListener,
                                    TrackID aTrackID);
 
   /**
    * Adds aListener to the source stream of track aTrackID in this stream.
    * When the MediaStreamGraph processes the added listener, it will traverse
@@ -428,18 +425,16 @@ class MediaStream : public mozilla::Link
   void DumpTrackInfo() const { return mTracks.DumpTrackInfo(); }
 #endif
   void SetAudioOutputVolumeImpl(void* aKey, float aVolume);
   void AddAudioOutputImpl(void* aKey);
   void RemoveAudioOutputImpl(void* aKey);
   void AddVideoOutputImpl(already_AddRefed<MediaStreamVideoSink> aSink,
                           TrackID aID);
   void RemoveVideoOutputImpl(MediaStreamVideoSink* aSink, TrackID aID);
-  void AddListenerImpl(already_AddRefed<MediaStreamListener> aListener);
-  void RemoveListenerImpl(MediaStreamListener* aListener);
 
   /**
    * Removes all direct listeners and signals to them that they have been
    * uninstalled.
    */
   virtual void RemoveAllDirectListenersImpl() {}
   void RemoveAllListenersImpl();
   virtual void AddTrackListenerImpl(
@@ -576,17 +571,16 @@ class MediaStream : public mozilla::Link
     void* mKey;
     float mVolume;
   };
   nsTArray<AudioOutput> mAudioOutputs;
   nsTArray<TrackBound<MediaStreamVideoSink>> mVideoOutputs;
   // We record the last played video frame to avoid playing the frame again
   // with a different frame id.
   VideoFrame mLastPlayedVideoFrame;
-  nsTArray<RefPtr<MediaStreamListener>> mListeners;
   nsTArray<TrackBound<MediaStreamTrackListener>> mTrackListeners;
   nsTArray<MainThreadMediaStreamListener*> mMainThreadListeners;
   // List of disabled TrackIDs and their associated disabled mode.
   // They can either by disabled by frames being replaced by black, or by
   // retaining the previous frame.
   nsTArray<DisabledTrack> mDisabledTracks;
 
   // GraphTime at which this stream starts blocking.
@@ -626,31 +620,22 @@ class MediaStream : public mozilla::Link
    */
   bool mFinished;
   /**
    * When true, mFinished is true and we've played all the data in this stream
    * and fired NotifyFinished notifications.
    */
   bool mNotifiedFinished;
   /**
-   * When true, the last NotifyBlockingChanged delivered to the listeners
-   * indicated that the stream is blocked.
-   */
-  bool mNotifiedBlocked;
-  /**
    * True if some data can be present by this stream if/when it's unblocked.
    * Set by the stream itself on the MediaStreamGraph thread. Only changes
    * from false to true once a stream has data, since we won't
    * unblock it until there's more data.
    */
   bool mHasCurrentData;
-  /**
-   * True if mHasCurrentData is true and we've notified listeners.
-   */
-  bool mNotifiedHasCurrentData;
 
   // Main-thread views of state
   StreamTime mMainThreadCurrentTime;
   bool mMainThreadFinished;
   bool mFinishedNotificationSent;
   bool mMainThreadDestroyed;
   int mNrOfMainThreadUsers;
 
@@ -691,37 +676,29 @@ class SourceMediaStream : public MediaSt
   void CloseAudioInput(Maybe<CubebUtils::AudioDeviceID>& aID,
                        AudioDataListener* aListener);
 
   // MediaStreamGraph thread only
   void DestroyImpl() override;
 
   // Call these on any thread.
   /**
-   * Call all MediaStreamListeners to request new data via the NotifyPull API
-   * (if enabled).
+   * Call all MediaStreamTrackListeners to request new data via the NotifyPull
+   * API (if enabled).
    * aDesiredUpToTime (in): end time of new data requested.
    *
    * Returns true if new data is about to be added.
    */
   bool PullNewData(GraphTime aDesiredUpToTime);
 
   /**
    * Extract any state updates pending in the stream, and apply them.
    */
   void ExtractPendingInput(GraphTime aCurrentTime);
 
-  /**
-   * These add/remove DirectListeners, which allow bypassing the graph and any
-   * synchronization delays for e.g. PeerConnection, which wants the data ASAP
-   * and lets the far-end handle sync and playout timing.
-   */
-  void NotifyListenersEventImpl(MediaStreamGraphEvent aEvent);
-  void NotifyListenersEvent(MediaStreamGraphEvent aEvent);
-
   enum {
     ADDTRACK_QUEUED = 0x01  // Queue track add until FinishAddTracks()
   };
   /**
    * Add a new track to the stream starting at the stream's current time
    * (which must be greater than or equal to the last time passed to
    * AdvanceKnownTracksTime). Takes ownership of aSegment.
    */
@@ -1317,17 +1294,17 @@ class MediaStreamGraph {
    */
   void StartNonRealtimeProcessing(uint32_t aTicksToProcess);
 
   /**
    * Media graph thread only.
    * Dispatches a runnable that will run on the main thread after all
    * main-thread stream state has been next updated.
    *
-   * Should only be called during MediaStreamListener callbacks or during
+   * Should only be called during MediaStreamTrackListener callbacks or during
    * ProcessedMediaStream::ProcessInput().
    *
    * Note that if called during shutdown the runnable will be ignored and
    * released on main thread.
    */
   void DispatchToMainThreadAfterStreamStateUpdate(
       already_AddRefed<nsIRunnable> aRunnable);
 
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -251,17 +251,17 @@ class MediaStreamGraphImpl : public Medi
   /**
    * Do all the processing and play the audio and video, from
    * mProcessedTime to mStateComputedTime.
    */
   void Process();
 
   /**
    * For use during ProcessedMediaStream::ProcessInput() or
-   * MediaStreamListener callbacks, when graph state cannot be changed.
+   * MediaStreamTrackListener callbacks, when graph state cannot be changed.
    * Schedules |aMessage| to run after processing, at a time when graph state
    * can be changed.  Graph thread.
    */
   void RunMessageAfterProcessing(UniquePtr<ControlMessage> aMessage);
 
   /**
    * Called when a suspend/resume/close operation has been completed, on the
    * graph thread.
@@ -336,20 +336,16 @@ class MediaStreamGraphImpl : public Medi
   /**
    * Given a graph time aTime, convert it to a stream time taking into
    * account the time during which aStream is scheduled to be blocked.
    */
   StreamTime GraphTimeToStreamTimeWithBlocking(const MediaStream* aStream,
                                                GraphTime aTime) const;
 
   /**
-   * Call NotifyHaveCurrentData on aStream's listeners.
-   */
-  void NotifyHasCurrentData(MediaStream* aStream);
-  /**
    * If aStream needs an audio stream but doesn't have one, create it.
    * If aStream doesn't need an audio stream but has one, destroy it.
    */
   void CreateOrDestroyAudioStreams(MediaStream* aStream);
   /**
    * Queue audio (mix of stream audio and silence for blocked intervals)
    * to the audio output stream. Returns the number of frames played.
    */
--- a/dom/media/MediaStreamListener.h
+++ b/dom/media/MediaStreamListener.h
@@ -15,123 +15,16 @@ namespace mozilla {
 
 class AudioSegment;
 class MediaStream;
 class MediaStreamGraph;
 class MediaStreamVideoSink;
 class VideoSegment;
 
 /**
- * This is a base class for media graph thread listener callbacks.
- * Override methods to be notified of audio or video data or changes in stream
- * state.
- *
- * This can be used by stream recorders or network connections that receive
- * stream input. It could also be used for debugging.
- *
- * All notification methods are called from the media graph thread. Overriders
- * of these methods are responsible for all synchronization. Beware!
- * These methods are called without the media graph monitor held, so
- * reentry into media graph methods is possible, although very much discouraged!
- * You should do something non-blocking and non-reentrant (e.g. dispatch an
- * event to some thread) and return.
- * The listener is not allowed to add/remove any listeners from the stream.
- *
- * When a listener is first attached, we guarantee to send a
- * NotifyBlockingChanged callback to notify of the initial blocking state. Also,
- * if a listener is attached to a stream that has already finished, we'll call
- * NotifyFinished.
- */
-class MediaStreamListener {
- protected:
-  // Protected destructor, to discourage deletion outside of Release():
-  virtual ~MediaStreamListener() {}
-
- public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStreamListener)
-
-  /**
-   * When a SourceMediaStream has pulling enabled, and the MediaStreamGraph
-   * control loop is ready to pull, this gets called. A NotifyPull
-   * implementation is allowed to call the SourceMediaStream methods that alter
-   * track data. It is not allowed to make other MediaStream API calls,
-   * including calls to add or remove MediaStreamListeners. It is not allowed to
-   * block for any length of time. aDesiredTime is the stream time we would like
-   * to get data up to. Data beyond this point will not be played until
-   * NotifyPull runs again, so there's not much point in providing it. Note that
-   * if the stream is blocked for some reason, then data before aDesiredTime may
-   * not be played immediately.
-   */
-  virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) {}
-
-  enum Blocking { BLOCKED, UNBLOCKED };
-  /**
-   * Notify that the blocking status of the stream changed. The initial state
-   * is assumed to be BLOCKED.
-   */
-  virtual void NotifyBlockingChanged(MediaStreamGraph* aGraph,
-                                     Blocking aBlocked) {}
-
-  /**
-   * Notify that the stream has data in each track
-   * for the stream's current time. Once this state becomes true, it will
-   * always be true since we block stream time from progressing to times where
-   * there isn't data in each track.
-   */
-  virtual void NotifyHasCurrentData(MediaStreamGraph* aGraph) {}
-
-  /**
-   * Notify that the stream output is advancing. aCurrentTime is the graph's
-   * current time. MediaStream::GraphTimeToStreamTime can be used to get the
-   * stream time.
-   */
-  virtual void NotifyOutput(MediaStreamGraph* aGraph, GraphTime aCurrentTime) {}
-
-  /**
-   * Notify that an event has occurred on the Stream
-   */
-  virtual void NotifyEvent(MediaStreamGraph* aGraph,
-                           MediaStreamGraphEvent aEvent) {}
-
-  /**
-   * Notify that changes to one of the stream tracks have been queued.
-   * aTrackEvents can be any combination of TRACK_EVENT_CREATED and
-   * TRACK_EVENT_ENDED. aQueuedMedia is the data being added to the track
-   * at aTrackOffset (relative to the start of the stream).
-   * aInputStream and aInputTrackID will be set if the changes originated
-   * from an input stream's track. In practice they will only be used for
-   * ProcessedMediaStreams.
-   */
-  virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
-                                        StreamTime aTrackOffset,
-                                        TrackEventCommand aTrackEvents,
-                                        const MediaSegment& aQueuedMedia,
-                                        MediaStream* aInputStream = nullptr,
-                                        TrackID aInputTrackID = TRACK_INVALID) {
-  }
-
-  /**
-   * Notify queued audio data. Only audio data need to be queued. The video data
-   * will be notified by MediaStreamVideoSink::SetCurrentFrame.
-   */
-  virtual void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
-                                     StreamTime aTrackOffset,
-                                     const AudioSegment& aQueuedMedia,
-                                     MediaStream* aInputStream = nullptr,
-                                     TrackID aInputTrackID = TRACK_INVALID) {}
-
-  /**
-   * Notify that all new tracks this iteration have been created.
-   * This is to ensure that tracks added atomically to MediaStreamGraph
-   * are also notified of atomically to MediaStreamListeners.
-   */
-  virtual void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) {}
-};
-
-/**
  * This is a base class for media graph thread listener callbacks locked to
  * specific tracks. Override methods to be notified of audio or video data or
  * changes in track state.
  *
  * All notification methods are called from the media graph thread. Overriders
  * of these methods are responsible for all synchronization. Beware!
  * These methods are called without the media graph monitor held, so
  * reentry into media graph methods is possible, although very much discouraged!
@@ -142,32 +35,63 @@ class MediaStreamListener {
  *
  * If a listener is attached to a track that has already ended, we guarantee
  * to call NotifyEnded.
  */
 class MediaStreamTrackListener {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStreamTrackListener)
 
  public:
+  /**
+   * When a SourceMediaStream has pulling enabled, and the MediaStreamGraph
+   * control loop is ready to pull, this gets called for each track in the
+   * SourceMediaStream that is lacking data for the current iteration.
+   * A NotifyPull implementation is allowed to call the SourceMediaStream
+   * methods that alter track data.
+   *
+   * It is not allowed to make other MediaStream API calls, including
+   * calls to add or remove MediaStreamTrackListeners. It is not allowed to
+   * block for any length of time.
+   *
+   * aEndOfAppendedData is the duration of the data that has already been
+   * appended to this track, in stream time.
+   *
+   * aDesiredTime is the stream time we should append data up to. Data
+   * beyond this point will not be played until NotifyPull runs again, so
+   * there's not much point in providing it. Note that if the stream is blocked
+   * for some reason, then data before aDesiredTime may not be played
+   * immediately.
+   */
   virtual void NotifyPull(MediaStreamGraph* aGraph,
                           StreamTime aEndOfAppendedData,
                           StreamTime aDesiredTime) {}
 
   virtual void NotifyQueuedChanges(MediaStreamGraph* aGraph,
                                    StreamTime aTrackOffset,
                                    const MediaSegment& aQueuedMedia) {}
 
   virtual void NotifyPrincipalHandleChanged(
       MediaStreamGraph* aGraph, const PrincipalHandle& aNewPrincipalHandle) {}
 
+  /**
+   * Notify that the stream output is advancing. aCurrentTrackTime is the number
+   * of samples that has been played out for this track in stream time.
+   */
   virtual void NotifyOutput(MediaStreamGraph* aGraph,
                             StreamTime aCurrentTrackTime) {}
 
+  /**
+   * Notify that this track has been ended and all data has been played out.
+   */
   virtual void NotifyEnded() {}
 
+  /**
+   * Notify that this track listener has been removed from the graph, either
+   * after shutdown or RemoveTrackListener.
+   */
   virtual void NotifyRemoved() {}
 
  protected:
   virtual ~MediaStreamTrackListener() {}
 };
 
 /**
  * This is a base class for media graph thread listener direct callbacks from
--- a/dom/media/TrackUnionStream.cpp
+++ b/dom/media/TrackUnionStream.cpp
@@ -88,17 +88,16 @@ void TrackUnionStream::ProcessInput(Grap
       // XXX we really should check whether 'stream' has finished within time
       // aTo, not just that it's finishing when all its queued data eventually
       // runs out.
       allFinished = false;
     }
     if (!stream->HasCurrentData()) {
       allHaveCurrentData = false;
     }
-    bool trackAdded = false;
     for (StreamTracks::TrackIter tracks(stream->GetStreamTracks());
          !tracks.IsEnded(); tracks.Next()) {
       bool found = false;
       for (uint32_t j = 0; j < mTrackMap.Length(); ++j) {
         TrackMapEntry* map = &mTrackMap[j];
         if (map->mInputPort == inputs[i] &&
             map->mInputTrackID == tracks->GetID()) {
           bool trackFinished = false;
@@ -113,28 +112,22 @@ void TrackUnionStream::ProcessInput(Grap
           }
           mappedTracksFinished[j] = trackFinished;
           mappedTracksWithMatchingInputTracks[j] = true;
           break;
         }
       }
       if (!found && inputs[i]->AllowCreationOf(tracks->GetID())) {
         bool trackFinished = false;
-        trackAdded = true;
         uint32_t mapIndex = AddTrack(inputs[i], tracks.get(), aFrom);
         CopyTrackData(tracks.get(), mapIndex, aFrom, aTo, &trackFinished);
         mappedTracksFinished.AppendElement(trackFinished);
         mappedTracksWithMatchingInputTracks.AppendElement(true);
       }
     }
-    if (trackAdded) {
-      for (MediaStreamListener* l : mListeners) {
-        l->NotifyFinishedTrackCreation(Graph());
-      }
-    }
   }
   for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) {
     if (mappedTracksFinished[i]) {
       EndTrack(i);
     } else {
       allFinished = false;
     }
     if (!mappedTracksWithMatchingInputTracks[i]) {
@@ -205,22 +198,16 @@ uint32_t TrackUnionStream::AddTrack(Medi
 
   // Round up the track start time so the track, if anything, starts a
   // little later than the true time. This means we'll have enough
   // samples in our input stream to go just beyond the destination time.
   StreamTime outputStart = GraphTimeToStreamTimeWithBlocking(aFrom);
 
   nsAutoPtr<MediaSegment> segment;
   segment = aTrack->GetSegment()->CreateEmptyClone();
-  for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-    MediaStreamListener* l = mListeners[j];
-    l->NotifyQueuedTrackChanges(Graph(), id, outputStart,
-                                TrackEventCommand::TRACK_EVENT_CREATED,
-                                *segment, aPort->GetSource(), aTrack->GetID());
-  }
   segment->AppendNullData(outputStart);
   StreamTracks::Track* track =
       &mTracks.AddTrack(id, outputStart, segment.forget());
   STREAM_LOG(LogLevel::Debug, ("TrackUnionStream %p added track %d for input "
                                "stream %p track %d, start ticks %lld",
                                this, track->GetID(), aPort->GetSource(),
                                aTrack->GetID(), (long long)outputStart));
 
@@ -259,26 +246,16 @@ uint32_t TrackUnionStream::AddTrack(Medi
 }
 
 void TrackUnionStream::EndTrack(uint32_t aIndex) {
   StreamTracks::Track* outputTrack =
       mTracks.FindTrack(mTrackMap[aIndex].mOutputTrackID);
   if (!outputTrack || outputTrack->IsEnded()) return;
   STREAM_LOG(LogLevel::Debug, ("TrackUnionStream %p ending track %d", this,
                                outputTrack->GetID()));
-  for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-    MediaStreamListener* l = mListeners[j];
-    StreamTime offset = outputTrack->GetSegment()->GetDuration();
-    nsAutoPtr<MediaSegment> segment;
-    segment = outputTrack->GetSegment()->CreateEmptyClone();
-    l->NotifyQueuedTrackChanges(Graph(), outputTrack->GetID(), offset,
-                                TrackEventCommand::TRACK_EVENT_ENDED, *segment,
-                                mTrackMap[aIndex].mInputPort->GetSource(),
-                                mTrackMap[aIndex].mInputTrackID);
-  }
   outputTrack->SetEnded();
 }
 
 void TrackUnionStream::CopyTrackData(StreamTracks::Track* aInputTrack,
                                      uint32_t aMapIndex, GraphTime aFrom,
                                      GraphTime aTo,
                                      bool* aOutputTrackFinished) {
   TrackMapEntry* map = &mTrackMap[aMapIndex];
@@ -335,26 +312,16 @@ void TrackUnionStream::CopyTrackData(Str
         StreamTime inputStart =
             source->GraphTimeToStreamTimeWithBlocking(interval.mStart);
         segment->AppendSlice(*aInputTrack->GetSegment(),
                              std::min(inputTrackEndPoint, inputStart),
                              std::min(inputTrackEndPoint, inputEnd));
       }
     }
     ApplyTrackDisabling(outputTrack->GetID(), segment);
-    for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-      MediaStreamListener* l = mListeners[j];
-      // Separate Audio and Video.
-      if (segment->GetType() == MediaSegment::AUDIO) {
-        l->NotifyQueuedAudioData(Graph(), outputTrack->GetID(), outputStart,
-                                 *static_cast<AudioSegment*>(segment),
-                                 map->mInputPort->GetSource(),
-                                 map->mInputTrackID);
-      }
-    }
     for (TrackBound<MediaStreamTrackListener>& b : mTrackListeners) {
       if (b.mTrackID != outputTrack->GetID()) {
         continue;
       }
       b.mListener->NotifyQueuedChanges(Graph(), outputStart, *segment);
     }
     outputTrack->GetSegment()->AppendFrom(segment);
   }
--- a/dom/media/imagecapture/CaptureTask.cpp
+++ b/dom/media/imagecapture/CaptureTask.cpp
@@ -15,17 +15,17 @@
 
 namespace mozilla {
 
 class CaptureTask::MediaStreamEventListener : public MediaStreamTrackListener {
  public:
   explicit MediaStreamEventListener(CaptureTask* aCaptureTask)
       : mCaptureTask(aCaptureTask){};
 
-  // MediaStreamListener methods.
+  // MediaStreamTrackListener methods.
   void NotifyEnded() override {
     if (!mCaptureTask->mImageGrabbedOrTrackEnd) {
       mCaptureTask->PostTrackEndEvent();
     }
   }
 
  private:
   CaptureTask* mCaptureTask;
--- a/dom/media/webaudio/AudioNodeStream.cpp
+++ b/dom/media/webaudio/AudioNodeStream.cpp
@@ -566,23 +566,16 @@ void AudioNodeStream::AdvanceOutputSegme
   mTracks.AdvanceKnownTracksTime(STREAM_TIME_MAX);
 
   AudioSegment* segment = track->Get<AudioSegment>();
 
   AudioChunk copyChunk = *mLastChunks[0].AsMutableChunk();
   AudioSegment tmpSegment;
   tmpSegment.AppendAndConsumeChunk(&copyChunk);
 
-  for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-    MediaStreamListener* l = mListeners[j];
-    // Notify MediaStreamListeners.
-    l->NotifyQueuedTrackChanges(Graph(), AUDIO_TRACK, segment->GetDuration(),
-                                TrackEventCommand::TRACK_EVENT_NONE,
-                                tmpSegment);
-  }
   for (TrackBound<MediaStreamTrackListener>& b : mTrackListeners) {
     // Notify MediaStreamTrackListeners.
     if (b.mTrackID != AUDIO_TRACK) {
       continue;
     }
     b.mListener->NotifyQueuedChanges(Graph(), segment->GetDuration(),
                                      tmpSegment);
   }
@@ -592,24 +585,16 @@ void AudioNodeStream::AdvanceOutputSegme
   } else {
     segment->AppendFrom(&tmpSegment);
   }
 }
 
 void AudioNodeStream::FinishOutput() {
   StreamTracks::Track* track = EnsureTrack(AUDIO_TRACK);
   track->SetEnded();
-
-  for (uint32_t j = 0; j < mListeners.Length(); ++j) {
-    MediaStreamListener* l = mListeners[j];
-    AudioSegment emptySegment;
-    l->NotifyQueuedTrackChanges(Graph(), AUDIO_TRACK, track->GetEnd(),
-                                TrackEventCommand::TRACK_EVENT_ENDED,
-                                emptySegment);
-  }
 }
 
 void AudioNodeStream::AddInput(MediaInputPort* aPort) {
   ProcessedMediaStream::AddInput(aPort);
   AudioNodeStream* ns = aPort->GetSource()->AsAudioNodeStream();
   // Streams that are not AudioNodeStreams are considered active.
   if (!ns || (ns->mIsActive && !ns->IsAudioParamStream())) {
     IncrementActiveInputCount();