Bug 1077274: Clean up tracklists r=jib a=dveditz
authorRandell Jesup <rjesup@jesup.org>
Fri, 03 Oct 2014 16:20:10 -0400
changeset 216927 f0253d7268bb
parent 216926 7b2887bd78a0
child 216928 bbf1c4e2ddce
push id3972
push userrjesup@wgate.com
push date2014-10-03 21:32 +0000
treeherdermozilla-beta@f0253d7268bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjib, dveditz
bugs1077274
milestone33.0
Bug 1077274: Clean up tracklists r=jib a=dveditz
content/html/content/src/HTMLMediaElement.cpp
content/media/DOMMediaStream.cpp
content/media/DOMMediaStream.h
content/media/MediaTrackList.h
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -2831,16 +2831,18 @@ void HTMLMediaElement::SetupSrcMediaStre
   ChangeDelayLoadStatus(false);
   GetSrcMediaStream()->AddAudioOutput(this);
   GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume));
   VideoFrameContainer* container = GetVideoFrameContainer();
   if (container) {
     GetSrcMediaStream()->AddVideoOutput(container);
   }
 
+  // Note: we must call DisconnectTrackListListeners(...)  before dropping
+  // mSrcStream
   mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks());
 
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
   DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
   DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
   DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
   AddRemoveSelfReference();
@@ -2849,16 +2851,18 @@ void HTMLMediaElement::SetupSrcMediaStre
 }
 
 void HTMLMediaElement::EndSrcMediaStreamPlayback()
 {
   MediaStream* stream = GetSrcMediaStream();
   if (stream) {
     stream->RemoveListener(mSrcStreamListener);
   }
+  mSrcStream->DisconnectTrackListListeners(AudioTracks(), VideoTracks());
+
   // Kill its reference to this element
   mSrcStreamListener->Forget();
   mSrcStreamListener = nullptr;
   if (stream) {
     stream->RemoveAudioOutput(this);
   }
   VideoFrameContainer* container = GetVideoFrameContainer();
   if (container) {
--- a/content/media/DOMMediaStream.cpp
+++ b/content/media/DOMMediaStream.cpp
@@ -438,16 +438,29 @@ DOMMediaStream::ConstructMediaTracks(Aud
     // enable, the one that is listed first in the element's videoTracks object
     // must be selected.
     int index = firstEnabledVideo >= 0 ? firstEnabledVideo : 0;
     (*aVideoTrackList)[index]->SetEnabledInternal(true, MediaTrack::FIRE_NO_EVENTS);
   }
 }
 
 void
+DOMMediaStream::DisconnectTrackListListeners(const AudioTrackList* aAudioTrackList,
+                                             const VideoTrackList* aVideoTrackList)
+{
+  for (auto i = mMediaTrackListListeners.Length(); i > 0; ) { // unsigned!
+    --i; // 0 ... Length()-1 range
+    if (mMediaTrackListListeners[i].mMediaTrackList == aAudioTrackList ||
+        mMediaTrackListListeners[i].mMediaTrackList == aVideoTrackList) {
+      mMediaTrackListListeners.RemoveElementAt(i);
+    }
+  }
+}
+
+void
 DOMMediaStream::NotifyMediaStreamTrackCreated(MediaStreamTrack* aTrack)
 {
   for (uint32_t i = 0; i < mMediaTrackListListeners.Length(); ++i) {
     if (AudioStreamTrack* t = aTrack->AsAudioStreamTrack()) {
       nsRefPtr<AudioTrack> track = CreateAudioTrack(t);
       mMediaTrackListListeners[i].NotifyMediaTrackCreated(track);
     } else if (VideoStreamTrack* t = aTrack->AsVideoStreamTrack()) {
       nsRefPtr<VideoTrack> track = CreateVideoTrack(t);
--- a/content/media/DOMMediaStream.h
+++ b/content/media/DOMMediaStream.h
@@ -220,16 +220,22 @@ public:
   /**
    * If loading and playing a MediaStream in a media element, for each
    * MediaStreamTrack in the MediaStream, create a corresponding AudioTrack or
    * VideoTrack during the phase of resource fetching.
    */
   void ConstructMediaTracks(AudioTrackList* aAudioTrackList,
                             VideoTrackList* aVideoTrackList);
 
+  /**
+   * MUST call this before the AudioTrackList or VideoTrackList go away
+   */
+  void DisconnectTrackListListeners(const AudioTrackList* aAudioTrackList,
+                                    const VideoTrackList* aVideoTrackList);
+
   void NotifyMediaStreamTrackCreated(MediaStreamTrack* aTrack);
 
   void NotifyMediaStreamTrackEnded(MediaStreamTrack* aTrack);
 
 protected:
   virtual ~DOMMediaStream();
 
   void Destroy();
--- a/content/media/MediaTrackList.h
+++ b/content/media/MediaTrackList.h
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_MediaTrackList_h
 #define mozilla_dom_MediaTrackList_h
 
 #include "mozilla/DOMEventTargetHelper.h"
 
 namespace mozilla {
+class DOMMediaStream;
+
 namespace dom {
 
 class HTMLMediaElement;
 class MediaTrack;
 class AudioTrackList;
 class VideoTrackList;
 class AudioTrack;
 class VideoTrack;
@@ -23,16 +25,18 @@ class MediaTrackList;
 /**
  * This is for the media resource to notify its audio track and video track,
  * when a media-resource-specific track has ended, or whether it has enabled or
  * not. All notification methods are called from the main thread.
  */
 class MediaTrackListListener
 {
 public:
+  friend class mozilla::DOMMediaStream;
+
   MediaTrackListListener(MediaTrackList* aMediaTrackList)
     : mMediaTrackList(aMediaTrackList) {};
 
   ~MediaTrackListListener()
   {
     mMediaTrackList = nullptr;
   };