Bug 1309516 part 4 - always notify LoadedMetadataEvent before decoding first frame;r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Fri, 14 Oct 2016 17:26:24 +0800
changeset 428003 4aef6ba2516f0d05927d4b9b5f23b426131cc7ac
parent 428002 cb9924bcc2c1d2a820b7b942c89feb861be85569
child 428004 4de4162cce1bb37a5ab14c0506428be9b7e698ff
push id33202
push userbmo:kaku@mozilla.com
push dateFri, 21 Oct 2016 11:11:30 +0000
reviewersjwwang
bugs1309516
milestone52.0a1
Bug 1309516 part 4 - always notify LoadedMetadataEvent before decoding first frame;r?jwwang MozReview-Commit-ID: EwSJLjjLBaJ
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -305,60 +305,40 @@ private:
     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()) {
-      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();
-    }
+    MOZ_ASSERT(mMaster->mDuration.Ref().isSome());
+
+    mMaster->EnqueueLoadedMetadataEvent();
 
     if (mPendingDormant) {
       // No need to store mQueuedSeek because we are at position 0.
       SetState(DECODER_STATE_DORMANT);
       return;
     }
 
-    if (waitingForCDM) {
+    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(DECODER_STATE_WAIT_FOR_CDM);
       return;
     }
 
     SetState(DECODER_STATE_DECODING_FIRSTFRAME);
   }
@@ -1250,17 +1230,16 @@ 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),
@@ -2661,21 +2640,16 @@ 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
@@ -703,24 +703,16 @@ 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