Bug 1536766 - Follow the video clock when audio ends early in DecodedStream. r=jya
☠☠ backed out by 41f1dcbe9caa ☠ ☠
authorAndreas Pehrson <apehrson@mozilla.com>
Thu, 18 Apr 2019 15:23:22 +0000
changeset 470097 6386ed1b7d741daadea35af8389f58f8df0376b3
parent 470096 ab27d9f5902a6c6896dd16c89f8b05de474d6ff7
child 470098 000260ba28de8b30791c72a6871d5879b92fe59d
push id112843
push useraiakab@mozilla.com
push dateFri, 19 Apr 2019 09:50:22 +0000
treeherdermozilla-inbound@c06f27cbfe40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1536766
milestone68.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 1536766 - Follow the video clock when audio ends early in DecodedStream. r=jya Differential Revision: https://phabricator.services.mozilla.com/D27260
dom/media/mediasink/DecodedStream.cpp
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -60,48 +60,67 @@ class DecodedStreamGraphListener {
       MozPromiseHolder<DecodedStream::EndedPromise>&& aAudioEndedHolder,
       TrackID aVideoTrackID,
       MozPromiseHolder<DecodedStream::EndedPromise>&& aVideoEndedHolder,
       AbstractThread* aMainThread)
       : mAudioTrackListener(IsTrackIDExplicit(aAudioTrackID)
                                 ? MakeRefPtr<DecodedStreamTrackListener>(
                                       this, aStream, aAudioTrackID)
                                 : nullptr),
-        mAudioTrackID(aAudioTrackID),
         mAudioEndedHolder(std::move(aAudioEndedHolder)),
         mVideoTrackListener(IsTrackIDExplicit(aVideoTrackID)
                                 ? MakeRefPtr<DecodedStreamTrackListener>(
                                       this, aStream, aVideoTrackID)
                                 : nullptr),
-        mVideoTrackID(aVideoTrackID),
         mVideoEndedHolder(std::move(aVideoEndedHolder)),
         mStream(aStream),
+        mAudioTrackID(aAudioTrackID),
+        mVideoTrackID(aVideoTrackID),
         mAbstractMainThread(aMainThread) {
     MOZ_ASSERT(NS_IsMainThread());
     if (mAudioTrackListener) {
       mStream->AddTrackListener(mAudioTrackListener, mAudioTrackID);
     } else {
+      mAudioEnded = true;
       mAudioEndedHolder.ResolveIfExists(true, __func__);
     }
 
     if (mVideoTrackListener) {
       mStream->AddTrackListener(mVideoTrackListener, mVideoTrackID);
     } else {
+      mVideoEnded = true;
       mVideoEndedHolder.ResolveIfExists(true, __func__);
     }
   }
 
   void NotifyOutput(TrackID aTrackID, StreamTime aCurrentTrackTime) {
-    if (aTrackID != mAudioTrackID && mAudioTrackID != TRACK_NONE) {
-      // Only audio playout drives the clock forward, if present.
+    if (aTrackID != mAudioTrackID && mAudioTrackID != TRACK_NONE &&
+        !mAudioEnded) {
+      // Only audio playout drives the clock forward, if present and live.
       return;
     }
+    MOZ_ASSERT_IF(aTrackID == mAudioTrackID, !mAudioEnded);
+    MOZ_ASSERT_IF(aTrackID == mVideoTrackID, !mVideoEnded);
     mOnOutput.Notify(mStream->StreamTimeToMicroseconds(aCurrentTrackTime));
   }
 
+  void NotifyEnded(TrackID aTrackID) {
+    if (aTrackID == mAudioTrackID) {
+      mAudioEnded = true;
+    } else if (aTrackID == mVideoTrackID) {
+      mVideoEnded = true;
+    } else {
+      MOZ_CRASH("Unexpected TrackID");
+    }
+    mStream->Graph()->DispatchToMainThreadStableState(
+        NewRunnableMethod<mozilla::TrackID>(
+            "DecodedStreamGraphListener::DoNotifyTrackEnded", this,
+            &DecodedStreamGraphListener::DoNotifyTrackEnded, aTrackID));
+  }
+
   TrackID AudioTrackID() const { return mAudioTrackID; }
 
   TrackID VideoTrackID() const { return mVideoTrackID; }
 
   void DoNotifyTrackEnded(TrackID aTrackID) {
     MOZ_ASSERT(NS_IsMainThread());
     if (aTrackID == mAudioTrackID) {
       mAudioEndedHolder.ResolveIfExists(true, __func__);
@@ -137,41 +156,43 @@ class DecodedStreamGraphListener {
     MOZ_ASSERT(mAudioEndedHolder.IsEmpty());
     MOZ_ASSERT(mVideoEndedHolder.IsEmpty());
   }
 
   MediaEventProducer<int64_t> mOnOutput;
 
   // Main thread only.
   RefPtr<DecodedStreamTrackListener> mAudioTrackListener;
-  const TrackID mAudioTrackID;
   MozPromiseHolder<DecodedStream::EndedPromise> mAudioEndedHolder;
   RefPtr<DecodedStreamTrackListener> mVideoTrackListener;
-  const TrackID mVideoTrackID;
   MozPromiseHolder<DecodedStream::EndedPromise> mVideoEndedHolder;
 
+  // Graph thread only.
+  bool mAudioEnded = false;
+  bool mVideoEnded = false;
+
+  // Any thread.
   const RefPtr<SourceMediaStream> mStream;
+  const TrackID mAudioTrackID;
+  const TrackID mVideoTrackID;
   const RefPtr<AbstractThread> mAbstractMainThread;
 };
 
 DecodedStreamTrackListener::DecodedStreamTrackListener(
     DecodedStreamGraphListener* aGraphListener, SourceMediaStream* aStream,
     mozilla::TrackID aTrackID)
     : mGraphListener(aGraphListener), mStream(aStream), mTrackID(aTrackID) {}
 
 void DecodedStreamTrackListener::NotifyOutput(MediaStreamGraph* aGraph,
                                               StreamTime aCurrentTrackTime) {
   mGraphListener->NotifyOutput(mTrackID, aCurrentTrackTime);
 }
 
 void DecodedStreamTrackListener::NotifyEnded() {
-  mStream->Graph()->DispatchToMainThreadStableState(
-      NewRunnableMethod<mozilla::TrackID>(
-          "DecodedStreamGraphListener::DoNotifyTrackEnded", mGraphListener,
-          &DecodedStreamGraphListener::DoNotifyTrackEnded, mTrackID));
+  mGraphListener->NotifyEnded(mTrackID);
 }
 
 /*
  * All MediaStream-related data is protected by the decoder's monitor.
  * We have at most one DecodedStreamDaata per MediaDecoder. Its stream
  * is used as the input for each ProcessedMediaStream created by calls to
  * captureStream(UntilEnded). Seeking creates a new source stream, as does
  * replaying after the input as ended. In the latter case, the new source is