Bug 1447563 - Clear direct track listeners from TrackUnionStream during shutdown. r?padenot draft
authorAndreas Pehrson <pehrsons@mozilla.com>
Mon, 26 Mar 2018 19:20:44 +0200
changeset 772631 a6557b6a8efe9d5e740dc60830bd14e6d3e2f21e
parent 772570 5d1f48fe3b58348d2568d374c1f4eed1766d4a1c
push id103996
push userbmo:apehrson@mozilla.com
push dateMon, 26 Mar 2018 17:22:54 +0000
reviewerspadenot
bugs1447563
milestone61.0a1
Bug 1447563 - Clear direct track listeners from TrackUnionStream during shutdown. r?padenot MozReview-Commit-ID: 9PbpQpOaIIh
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/TrackUnionStream.cpp
dom/media/TrackUnionStream.h
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -2042,19 +2042,17 @@ MediaStream::RemoveAllListenersImpl()
   mListeners.Clear();
 
   auto trackListeners(mTrackListeners);
   for (auto& l : trackListeners) {
     l.mListener->NotifyRemoved();
   }
   mTrackListeners.Clear();
 
-  if (SourceMediaStream* source = AsSourceStream()) {
-    source->RemoveAllDirectListeners();
-  }
+  RemoveAllDirectListenersImpl();
 
   auto videoOutputs(mVideoOutputs);
   for (auto& l : videoOutputs) {
     l.mListener->NotifyRemoved();
   }
   mVideoOutputs.Clear();
 }
 
@@ -3267,17 +3265,17 @@ SourceMediaStream::EndAllTrackAndFinish(
     data->mCommands |= TrackEventCommand::TRACK_EVENT_ENDED;
   }
   mPendingTracks.Clear();
   FinishPendingWithLockHeld();
   // we will call NotifyEvent() to let GetUserMedia know
 }
 
 void
-SourceMediaStream::RemoveAllDirectListeners()
+SourceMediaStream::RemoveAllDirectListenersImpl()
 {
   GraphImpl()->AssertOnGraphThreadOrNotRunning();
 
   auto directListeners(mDirectTrackListeners);
   for (auto& l : directListeners) {
     l.mListener->NotifyDirectListenerUninstalled();
   }
   mDirectTrackListeners.Clear();
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -423,16 +423,22 @@ public:
     return !mAudioOutputs.IsEmpty();
   }
   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(already_AddRefed<MediaStreamTrackListener> aListener,
                                     TrackID aTrackID);
   virtual void RemoveTrackListenerImpl(MediaStreamTrackListener* aListener,
                                        TrackID aTrackID);
   virtual void AddDirectTrackListenerImpl(already_AddRefed<DirectMediaStreamTrackListener> aListener,
                                           TrackID aTrackID);
   virtual void RemoveDirectTrackListenerImpl(DirectMediaStreamTrackListener* aListener,
@@ -796,28 +802,24 @@ public:
   // Overriding allows us to ensure mMutex is locked while changing the track enable status
   void
   ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment,
                       MediaSegment* aRawSegment = nullptr) override {
     mMutex.AssertCurrentThreadOwns();
     MediaStream::ApplyTrackDisabling(aTrackID, aSegment, aRawSegment);
   }
 
+  void RemoveAllDirectListenersImpl() override;
+
   /**
    * End all tracks and Finish() this stream.  Used to voluntarily revoke access
    * to a LocalMediaStream.
    */
   void EndAllTrackAndFinish();
 
-  /**
-   * Removes all direct listeners and signals to them that they have been
-   * uninstalled.
-   */
-  void RemoveAllDirectListeners();
-
   void RegisterForAudioMixing();
 
   /**
    * Returns true if this SourceMediaStream contains at least one audio track
    * that is in pending state.
    * This is thread safe, and takes the SourceMediaStream mutex.
    */
   bool HasPendingAudioTrack();
--- a/dom/media/TrackUnionStream.cpp
+++ b/dom/media/TrackUnionStream.cpp
@@ -476,9 +476,29 @@ TrackUnionStream::RemoveDirectTrackListe
     TrackBound<DirectMediaStreamTrackListener>& bound =
       mPendingDirectTrackListeners[i];
     if (bound.mListener == aListener && bound.mTrackID == aTrackID) {
       mPendingDirectTrackListeners.RemoveElementAt(i);
       return;
     }
   }
 }
+
+void TrackUnionStream::RemoveAllDirectListenersImpl()
+{
+  for (TrackMapEntry& entry : mTrackMap) {
+    nsTArray<RefPtr<DirectMediaStreamTrackListener>>
+      listeners(entry.mOwnedDirectListeners);
+    for (const auto& listener : listeners) {
+      RemoveDirectTrackListenerImpl(listener, entry.mOutputTrackID);
+    }
+    MOZ_DIAGNOSTIC_ASSERT(entry.mOwnedDirectListeners.IsEmpty());
+  }
+
+  nsTArray<TrackBound<DirectMediaStreamTrackListener>>
+    boundListeners(mPendingDirectTrackListeners);
+  for (const auto& binding : boundListeners) {
+    RemoveDirectTrackListenerImpl(binding.mListener, binding.mTrackID);
+  }
+  MOZ_DIAGNOSTIC_ASSERT(mPendingDirectTrackListeners.IsEmpty());
+}
+
 } // namespace mozilla
--- a/dom/media/TrackUnionStream.h
+++ b/dom/media/TrackUnionStream.h
@@ -69,16 +69,17 @@ protected:
   void CopyTrackData(StreamTracks::Track* aInputTrack,
                      uint32_t aMapIndex, GraphTime aFrom, GraphTime aTo,
                      bool* aOutputTrackFinished);
 
   void AddDirectTrackListenerImpl(already_AddRefed<DirectMediaStreamTrackListener> aListener,
                                   TrackID aTrackID) override;
   void RemoveDirectTrackListenerImpl(DirectMediaStreamTrackListener* aListener,
                                      TrackID aTrackID) override;
+  void RemoveAllDirectListenersImpl() override;
 
   nsTArray<TrackMapEntry> mTrackMap;
 
   // The next available TrackID, starting at 1 and progressing upwards.
   // All TrackIDs in [1, mNextAvailableTrackID) have implicitly been used.
   TrackID mNextAvailableTrackID;
 
   // Sorted array of used TrackIDs that require manual tracking.