Backed out changeset 804308421d74 (bug 1309516)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 05 Nov 2016 11:00:20 +0100
changeset 321127 2b7cc43dfb60c65243665be25aed8a65b5740508
parent 321126 1e1e71cf9feac94a4626178313022af9a128537f
child 321128 e94d188473d3063b9fdf3b577734b7e12a661a2a
push id30919
push userphilringnalda@gmail.com
push dateSat, 05 Nov 2016 20:28:20 +0000
treeherdermozilla-central@572249b2ffb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1309516
milestone52.0a1
backs out804308421d74db8112f9852636afaca31316324f
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
Backed out changeset 804308421d74 (bug 1309516)
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1291,34 +1291,54 @@ DecodeMetadataState::OnMetadataRead(Meta
   Resource()->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
 
   mMaster->mInfo = Some(aMetadata->mInfo);
   mMaster->mMetadataTags = aMetadata->mTags.forget();
 
   if (Info().mMetadataDuration.isSome()) {
     mMaster->RecomputeDuration();
   } else if (Info().mUnadjustedMetadataEndTime.isSome()) {
-    const TimeUnit unadjusted = Info().mUnadjustedMetadataEndTime.ref();
-    const TimeUnit adjustment = Info().mStartTime;
-    mMaster->mInfo->mMetadataDuration.emplace(unadjusted - adjustment);
-    mMaster->RecomputeDuration();
+    RefPtr<Master> master = mMaster;
+    Reader()->AwaitStartTime()->Then(OwnerThread(), __func__,
+      [master] () {
+        NS_ENSURE_TRUE_VOID(!master->IsShutdown());
+        auto& info = master->mInfo.ref();
+        TimeUnit unadjusted = info.mUnadjustedMetadataEndTime.ref();
+        TimeUnit adjustment = master->mReader->StartTime();
+        info.mMetadataDuration.emplace(unadjusted - adjustment);
+        master->RecomputeDuration();
+      }, [master, this] () {
+        SWARN("Adjusting metadata end time failed");
+      }
+    );
   }
 
   if (mMaster->HasVideo()) {
     SLOG("Video decode isAsync=%d HWAccel=%d videoQueueSize=%d",
          Reader()->IsAsync(),
          Reader()->VideoIsHardwareAccelerated(),
          mMaster->GetAmpleVideoFrames());
   }
 
-  MOZ_ASSERT(mMaster->mDuration.Ref().isSome());
-
-  mMaster->EnqueueLoadedMetadataEvent();
-
-  if (Info().IsEncrypted() && !mMaster->mCDMProxy) {
+  // In general, we wait until we know the duration before notifying the decoder.
+  // However, we notify  unconditionally in this case without waiting for the start
+  // time, since the caller might be waiting on metadataloaded to be fired before
+  // feeding in the CDM, which we need to decode the first frame (and
+  // thus get the metadata). We could fix this if we could compute the start
+  // time by demuxing without necessaring decoding.
+  bool waitingForCDM = Info().IsEncrypted() && !mMaster->mCDMProxy;
+
+  mMaster->mNotifyMetadataBeforeFirstFrame =
+    mMaster->mDuration.Ref().isSome() || waitingForCDM;
+
+  if (mMaster->mNotifyMetadataBeforeFirstFrame) {
+    mMaster->EnqueueLoadedMetadataEvent();
+  }
+
+  if (waitingForCDM) {
     // Metadata parsing was successful but we're still waiting for CDM caps
     // to become available so that we can build the correct decryptor/decoder.
     SetState<WaitForCDMState>(mPendingDormant);
   } else if (mPendingDormant) {
     SetState<DormantState>(SeekJob{});
   } else {
     SetState<DecodingFirstFrameState>(SeekJob{});
   }
@@ -1817,16 +1837,17 @@ MediaDecoderStateMachine::MediaDecoderSt
   mDecodedAudioEndTime(0),
   mDecodedVideoEndTime(0),
   mPlaybackRate(1.0),
   mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
   mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
   mAudioCaptured(false),
   INIT_WATCHABLE(mAudioCompleted, false),
   INIT_WATCHABLE(mVideoCompleted, false),
+  mNotifyMetadataBeforeFirstFrame(false),
   mMinimizePreroll(false),
   mSentLoadedMetadataEvent(false),
   mSentFirstFrameLoadedEvent(false),
   mVideoDecodeSuspended(false),
   mVideoDecodeSuspendTimer(mTaskQueue),
   mOutputStreamManager(new OutputStreamManager()),
   mResource(aDecoder->GetResource()),
   mAudioOffloading(false),
@@ -2947,16 +2968,21 @@ MediaDecoderStateMachine::FinishDecodeFi
 
   DECODER_LOG("Media duration %lld, "
               "transportSeekable=%d, mediaSeekable=%d",
               Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable.Ref());
 
   // Get potentially updated metadata
   mReader->ReadUpdatedMetadata(mInfo.ptr());
 
+  if (!mNotifyMetadataBeforeFirstFrame) {
+    // If we didn't have duration and/or start time before, we should now.
+    EnqueueLoadedMetadataEvent();
+  }
+
   EnqueueFirstFrameLoadedEvent();
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::BeginShutdown()
 {
   return InvokeAsync(OwnerThread(), this, __func__,
                      &MediaDecoderStateMachine::Shutdown);
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -688,16 +688,24 @@ private:
   // the state machine thread. Synchronised via decoder monitor.
   // When data is being sent to a MediaStream, this is true when all data has
   // been written to the MediaStream.
   Watchable<bool> mAudioCompleted;
 
   // True if all video frames are already rendered.
   Watchable<bool> mVideoCompleted;
 
+  // Flag whether we notify metadata before decoding the first frame or after.
+  //
+  // Note that the odd semantics here are designed to replicate the current
+  // behavior where we notify the decoder each time we come out of dormant, but
+  // send suppressed event visibility for those cases. This code can probably be
+  // simplified.
+  bool mNotifyMetadataBeforeFirstFrame;
+
   // True if we should not decode/preroll unnecessary samples, unless we're
   // played. "Prerolling" in this context refers to when we decode and
   // buffer decoded samples in advance of when they're needed for playback.
   // This flag is set for preload=metadata media, and means we won't
   // decode more than the first video frame and first block of audio samples
   // for that media when we startup, or after a seek. When Play() is called,
   // we reset this flag, as we assume the user is playing the media, so
   // prerolling is appropriate then. This flag is used to reduce the overhead