Bug 1309516 part 4 - always notify LoadedMetadataEvent before decoding first frame;r=jwwang
☠☠ backed out by fb72036436f9 ☠ ☠
authorKaku Kuo <kaku@mozilla.com>
Sun, 16 Oct 2016 21:49:07 +0800
changeset 320047 35d6e08883d65abd421ca0a2998b940fda7df965
parent 320046 e39be827b2200e44f51bbbf12de370ee71ed07cb
child 320048 a154fa107dd382275c79602102a278523c0987c2
push id20749
push userryanvm@gmail.com
push dateSat, 29 Oct 2016 13:21:21 +0000
treeherderfx-team@1b170b39ed6b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1309516
milestone52.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
@@ -1247,54 +1247,34 @@ 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()) {
-    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>(mPendingDormant);
   } else if (mPendingDormant) {
     SetState<DormantState>(SeekJob{});
   } else {
     SetState<DecodingFirstFrameState>(SeekJob{});
   }
@@ -1778,17 +1758,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),
@@ -2928,21 +2907,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
@@ -691,24 +691,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