diff --git a/content/html/content/src/HTMLMediaElement.cpp b/content/html/content/src/HTMLMediaElement.cpp
index 0beaa9bfed36..4d210a7bb35d 100755
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -2843,6 +2843,8 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
GetSrcMediaStream()->AddVideoOutput(container);
}
+ // Note: we must call DisconnectTrackListListeners(...) before dropping
+ // mSrcStream
mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks());
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
@@ -2859,6 +2861,8 @@ void HTMLMediaElement::EndSrcMediaStreamPlayback()
if (stream) {
stream->RemoveListener(mSrcStreamListener);
}
+ mSrcStream->DisconnectTrackListListeners(AudioTracks(), VideoTracks());
+
// Kill its reference to this element
mSrcStreamListener->Forget();
mSrcStreamListener = nullptr;
diff --git a/content/media/DOMMediaStream.cpp b/content/media/DOMMediaStream.cpp
index b6fcace53396..206859df9407 100644
--- a/content/media/DOMMediaStream.cpp
+++ b/content/media/DOMMediaStream.cpp
@@ -452,6 +452,19 @@ DOMMediaStream::ConstructMediaTracks(AudioTrackList* aAudioTrackList,
}
}
+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)
{
diff --git a/content/media/DOMMediaStream.h b/content/media/DOMMediaStream.h
index 07aa74379cc2..8160746d157e 100644
--- a/content/media/DOMMediaStream.h
+++ b/content/media/DOMMediaStream.h
@@ -242,6 +242,12 @@ public:
void ConstructMediaTracks(AudioTrackList* aAudioTrackList,
VideoTrackList* aVideoTrackList);
+ /**
+ * MUST call this before the AudioTrackList or VideoTrackList go away
+ */
+ void DisconnectTrackListListeners(const AudioTrackList* aAudioTrackList,
+ const VideoTrackList* aVideoTrackList);
+
virtual void NotifyMediaStreamTrackCreated(MediaStreamTrack* aTrack);
virtual void NotifyMediaStreamTrackEnded(MediaStreamTrack* aTrack);
diff --git a/content/media/MediaTrackList.h b/content/media/MediaTrackList.h
index 1ee16e01a54c..ba2c2411567f 100644
--- a/content/media/MediaTrackList.h
+++ b/content/media/MediaTrackList.h
@@ -10,6 +10,8 @@
#include "mozilla/DOMEventTargetHelper.h"
namespace mozilla {
+class DOMMediaStream;
+
namespace dom {
class HTMLMediaElement;
@@ -28,6 +30,8 @@ class MediaTrackList;
class MediaTrackListListener
{
public:
+ friend class mozilla::DOMMediaStream;
+
explicit MediaTrackListListener(MediaTrackList* aMediaTrackList)
: mMediaTrackList(aMediaTrackList) {};