Bug 1703603 - Handle HTMLMediaElement playing MediaSource when using mozCaptureStreamUntilEnded. r=bryce
authorPaul Adenot <paul@paul.cx>
Wed, 02 Jun 2021 14:20:40 +0000
changeset 581722 9ab1bb831b50bc4012153f51a75389995abebc1d
parent 581721 e0b5df171b002bd828bf054295b2a3e2da1e7ec6
child 581723 3ddb254cdb74205aacb019f8f1ba33816c270378
push id144207
push userpadenot@mozilla.com
push dateWed, 02 Jun 2021 15:37:06 +0000
treeherderautoland@3ddb254cdb74 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbryce
bugs1703603
milestone91.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 1703603 - Handle HTMLMediaElement playing MediaSource when using mozCaptureStreamUntilEnded. r=bryce This means keeping a reference to the MediaSource object in the MediaStream to ensure it's being kept alive for the duration of the playback. Differential Revision: https://phabricator.services.mozilla.com/D112607
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1173,23 +1173,26 @@ void ImplCycleCollectionTraverse(nsCycle
                                  const char* aName, uint32_t aFlags) {
   ImplCycleCollectionTraverse(aCallback, aField.mStream, "mStream", aFlags);
   ImplCycleCollectionTraverse(aCallback, aField.mLiveTracks, "mLiveTracks",
                               aFlags);
   ImplCycleCollectionTraverse(aCallback, aField.mFinishWhenEndedLoadingSrc,
                               "mFinishWhenEndedLoadingSrc", aFlags);
   ImplCycleCollectionTraverse(aCallback, aField.mFinishWhenEndedAttrStream,
                               "mFinishWhenEndedAttrStream", aFlags);
+  ImplCycleCollectionTraverse(aCallback, aField.mFinishWhenEndedMediaSource,
+                              "mFinishWhenEndedMediaSource", aFlags);
 }
 
 void ImplCycleCollectionUnlink(HTMLMediaElement::OutputMediaStream& aField) {
   ImplCycleCollectionUnlink(aField.mStream);
   ImplCycleCollectionUnlink(aField.mLiveTracks);
   ImplCycleCollectionUnlink(aField.mFinishWhenEndedLoadingSrc);
   ImplCycleCollectionUnlink(aField.mFinishWhenEndedAttrStream);
+  ImplCycleCollectionUnlink(aField.mFinishWhenEndedMediaSource);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLMediaElement::MediaElementTrackSource,
                          MediaStreamTrackSource)
 NS_IMPL_RELEASE_INHERITED(HTMLMediaElement::MediaElementTrackSource,
                           MediaStreamTrackSource)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
     HTMLMediaElement::MediaElementTrackSource)
@@ -3635,39 +3638,46 @@ void HTMLMediaElement::UpdateOutputTrack
 
   // Then update finish-when-ended output streams as needed.
   for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
     if (!mOutputStreams[i].mFinishWhenEnded) {
       continue;
     }
 
     if (!mOutputStreams[i].mFinishWhenEndedLoadingSrc &&
-        !mOutputStreams[i].mFinishWhenEndedAttrStream) {
+        !mOutputStreams[i].mFinishWhenEndedAttrStream &&
+        !mOutputStreams[i].mFinishWhenEndedMediaSource) {
       // This finish-when-ended stream has not seen any source loaded yet.
       // Update the loading src if it's time.
       if (!IsPlaybackEnded()) {
         if (mLoadingSrc) {
           mOutputStreams[i].mFinishWhenEndedLoadingSrc = mLoadingSrc;
         } else if (mSrcAttrStream) {
           mOutputStreams[i].mFinishWhenEndedAttrStream = mSrcAttrStream;
+        } else if (mSrcMediaSource) {
+          mOutputStreams[i].mFinishWhenEndedMediaSource = mSrcMediaSource;
         }
       }
       continue;
     }
 
     // Discard finish-when-ended output streams with a loading src set as
     // needed.
     if (!IsPlaybackEnded() &&
         mLoadingSrc == mOutputStreams[i].mFinishWhenEndedLoadingSrc) {
       continue;
     }
     if (!IsPlaybackEnded() &&
         mSrcAttrStream == mOutputStreams[i].mFinishWhenEndedAttrStream) {
       continue;
     }
+    if (!IsPlaybackEnded() &&
+        mSrcMediaSource == mOutputStreams[i].mFinishWhenEndedMediaSource) {
+      continue;
+    }
     LOG(LogLevel::Debug,
         ("Playback ended or source changed. Discarding stream %p",
          mOutputStreams[i].mStream.get()));
     mOutputStreams.RemoveElementAt(i);
     if (mOutputStreams.IsEmpty()) {
       mTracksCaptured = nullptr;
       // mTracksCaptured is one of the Watchables triggering this method.
       // Unsetting it here means we'll run through this method again very soon.
@@ -3804,18 +3814,22 @@ already_AddRefed<DOMMediaStream> HTMLMed
     // UpdateOutputTrackSources will set the current src when it becomes
     // available later.
     if (mLoadingSrc) {
       out->mFinishWhenEndedLoadingSrc = mLoadingSrc;
     }
     if (mSrcAttrStream) {
       out->mFinishWhenEndedAttrStream = mSrcAttrStream;
     }
+    if (mSrcMediaSource) {
+      out->mFinishWhenEndedMediaSource = mSrcMediaSource;
+    }
     MOZ_ASSERT(out->mFinishWhenEndedLoadingSrc ||
-               out->mFinishWhenEndedAttrStream);
+               out->mFinishWhenEndedAttrStream ||
+               out->mFinishWhenEndedMediaSource);
   }
 
   if (aStreamCaptureType == StreamCaptureType::CAPTURE_AUDIO) {
     if (mSrcStream) {
       // We don't support applying volume and mute to the captured stream, when
       // capturing a MediaStream.
       ReportToConsole(nsIScriptError::errorFlag,
                       "MediaElementAudioCaptureOfMediaStreamError");
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -130,21 +130,23 @@ class HTMLMediaElement : public nsGeneri
                       bool aFinishWhenEnded);
     ~OutputMediaStream();
 
     RefPtr<DOMMediaStream> mStream;
     nsTArray<RefPtr<MediaStreamTrack>> mLiveTracks;
     const bool mCapturingAudioOnly;
     const bool mFinishWhenEnded;
     // If mFinishWhenEnded is true, this is the URI of the first resource
-    // mStream got tracks for, if not a MediaStream.
+    // mStream got tracks for.
     nsCOMPtr<nsIURI> mFinishWhenEndedLoadingSrc;
     // If mFinishWhenEnded is true, this is the first MediaStream mStream got
-    // tracks for, if not a resource.
+    // tracks for.
     RefPtr<DOMMediaStream> mFinishWhenEndedAttrStream;
+    // If mFinishWhenEnded is true, this is the MediaSource being played.
+    RefPtr<MediaSource> mFinishWhenEndedMediaSource;
   };
 
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   CORSMode GetCORSMode() { return mCORSMode; }
 
   explicit HTMLMediaElement(
       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);