Bug 1309516 part 4 - always notify LoadedMetadataEvent before decoding first frame;r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Sun, 16 Oct 2016 21:49:07 +0800
changeset 441570 102aee5bf2b29e6525754820bedd37d7f50e8e6f
parent 441569 02deeaeed28497934f0c4e7dfffe89b839c480d3
child 441571 a8d6235762b015f83d8784936bf8e847c35ab265
push id36449
push userbmo:kaku@mozilla.com
push dateSat, 19 Nov 2016 07:05:35 +0000
reviewersjwwang
bugs1309516
milestone53.0a1
Bug 1309516 part 4 - always notify LoadedMetadataEvent before decoding first frame;r?jwwang MozReview-Commit-ID: 4VcmELgvAjC
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1248,54 +1248,34 @@ DecodeMetadataState::OnMetadataRead(Meta
   mMaster->mInfo = Some(aMetadata->mInfo);
   mMaster->mMetadataTags = aMetadata->mTags.forget();
   mMaster->mMediaSeekable = Info().mMediaSeekable;
   mMaster->mMediaSeekableOnlyInBufferedRanges = Info().mMediaSeekableOnlyInBufferedRanges;
 
   if (Info().mMetadataDuration.isSome()) {
     mMaster->RecomputeDuration();
   } else if (Info().mUnadjustedMetadataEndTime.isSome()) {
-    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");
-      }
-    );
+    const TimeUnit unadjusted = Info().mUnadjustedMetadataEndTime.ref();
+    const TimeUnit adjustment = Info().mStartTime;
+    mMaster->mInfo->mMetadataDuration.emplace(unadjusted - adjustment);
+    mMaster->RecomputeDuration();
   }
 
   if (mMaster->HasVideo()) {
     SLOG("Video decode isAsync=%d HWAccel=%d videoQueueSize=%d",
          Reader()->IsAsync(),
          Reader()->VideoIsHardwareAccelerated(),
          mMaster->GetAmpleVideoFrames());
   }
 
-  // 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) {
+  MOZ_ASSERT(mMaster->mDuration.Ref().isSome());
+
+  mMaster->EnqueueLoadedMetadataEvent();
+
+  if (Info().IsEncrypted() && !mMaster->mCDMProxy) {
     // 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>();
   } else {
     SetState<DecodingFirstFrameState>(SeekJob{});
   }
 }
 
@@ -1694,17 +1674,16 @@ MediaDecoderStateMachine::MediaDecoderSt
   mFragmentEndTime(-1),
   mReader(new MediaDecoderReaderWrapper(mTaskQueue, aReader)),
   mDecodedAudioEndTime(0),
   mDecodedVideoEndTime(0),
   mPlaybackRate(1.0),
   mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
   mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
   mAudioCaptured(false),
-  mNotifyMetadataBeforeFirstFrame(false),
   mMinimizePreroll(false),
   mSentLoadedMetadataEvent(false),
   mSentFirstFrameLoadedEvent(false),
   mVideoDecodeSuspended(false),
   mVideoDecodeSuspendTimer(mTaskQueue),
   mOutputStreamManager(new OutputStreamManager()),
   mResource(aDecoder->GetResource()),
   mAudioOffloading(false),
@@ -2813,21 +2792,16 @@ MediaDecoderStateMachine::FinishDecodeFi
 
   DECODER_LOG("Media duration %lld, "
               "transportSeekable=%d, mediaSeekable=%d",
               Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable);
 
   // 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
@@ -680,24 +680,16 @@ private:
   bool mAudioCaptured;
 
   // True if all audio frames are already rendered.
   bool mAudioCompleted = false;
 
   // True if all video frames are already rendered.
   bool mVideoCompleted = false;
 
-  // 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