Bug 1498440 - part3 : remove time-adjustment related codes in ReaderProxy. r=jya
authoralwu <alwu@mozilla.com>
Mon, 05 Nov 2018 22:04:12 +0000
changeset 444494 c67e483b4ab49df78d2bae3b889275284d919a44
parent 444493 f47b8fef7cc7f1c4c21bb7ebea49b02e9a92ce10
child 444495 2e61ba5a50f21511c80536cf6c4f7ebde528fc78
push id34996
push userrgurzau@mozilla.com
push dateTue, 06 Nov 2018 09:53:23 +0000
treeherdermozilla-central@e160f0a60e4f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1498440
milestone65.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 1498440 - part3 : remove time-adjustment related codes in ReaderProxy. r=jya Differential Revision: https://phabricator.services.mozilla.com/D9188
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/ReaderProxy.cpp
dom/media/ReaderProxy.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -396,17 +396,17 @@ public:
   {
     if (mMaster->IsPlaying()) {
       mMaster->StopPlayback();
     }
 
     // Calculate the position to seek to when exiting dormant.
     auto t = mMaster->mMediaSink->IsStarted()
       ? mMaster->GetClock() : mMaster->GetMediaTime();
-    Reader()->AdjustByLooping(t);
+    mMaster->AdjustByLooping(t);
     mPendingSeek.mTarget.emplace(t, SeekTarget::Accurate);
     // SeekJob asserts |mTarget.IsValid() == !mPromise.IsEmpty()| so we
     // need to create the promise even it is not used at all.
     // The promise may be used when coming out of DormantState into
     // SeekingState.
     RefPtr<MediaDecoder::SeekPromise> x =
       mPendingSeek.mPromise.Ensure(__func__);
 
@@ -870,16 +870,20 @@ public:
 
   void HandleEndOfAudio() override
   {
     // The data time in the audio queue is assumed to be increased linearly,
     // so we need to add the last ending time as the offset to correct the
     // audio data time in the next round when seamless looping is enabled.
     mAudioLoopingOffset = mMaster->mDecodedAudioEndTime;
 
+    if (mMaster->mAudioDecodedDuration.isNothing()) {
+      mMaster->mAudioDecodedDuration.emplace(mMaster->mDecodedAudioEndTime);
+    }
+
     SLOG("received EOS when seamless looping, starts seeking");
     Reader()->ResetDecode(TrackInfo::kAudioTrack);
     Reader()->Seek(SeekTarget(media::TimeUnit::Zero(), SeekTarget::Accurate))
       ->Then(OwnerThread(), __func__,
               [this] () -> void {
                 mAudioSeekRequest.Complete();
                 SLOG("seeking completed, start to request first sample, "
                      "queueing audio task - queued=%zu, decoder-queued=%zu",
@@ -2074,17 +2078,17 @@ public:
     // StopPlayback in order to reset the IsPlaying() state so audio
     // is restarted correctly.
     mMaster->StopPlayback();
 
     if (!mSentPlaybackEndedEvent) {
       auto clockTime =
         std::max(mMaster->AudioEndTime(), mMaster->VideoEndTime());
       // Correct the time over the end once looping was turned on.
-      Reader()->AdjustByLooping(clockTime);
+      mMaster->AdjustByLooping(clockTime);
       if (mMaster->mDuration.Ref()->IsInfinite()) {
         // We have a finite duration when playback reaches the end.
         mMaster->mDuration = Some(clockTime);
         DDLOGEX(mMaster,
                 DDLogCategory::Property,
                 "duration_us",
                 mMaster->mDuration.Ref()->ToMicroseconds());
       }
@@ -3691,17 +3695,17 @@ MediaDecoderStateMachine::UpdatePlayback
   // This ensures that if we're running off the system clock, we don't
   // advance the clock to after the media end time.
   if (VideoEndTime() > TimeUnit::Zero() || AudioEndTime() > TimeUnit::Zero()) {
 
     auto clockTime = GetClock();
 
     // Once looping was turned on, the time is probably larger than the duration
     // of the media track, so the time over the end should be corrected.
-    mReader->AdjustByLooping(clockTime);
+    AdjustByLooping(clockTime);
     bool loopback = clockTime < GetMediaTime() && mLooping;
 
     // Skip frames up to the frame at the playback position, and figure out
     // the time remaining until it's time to display the next frame and drop
     // the current frame.
     NS_ASSERTION(clockTime >= TimeUnit::Zero(), "Should have positive clock time.");
 
     // These will be non -1 if we've displayed a video frame, or played an audio
@@ -4196,16 +4200,25 @@ MediaDecoderStateMachine::CancelSuspendT
       mVideoDecodeSuspendTimer.IsScheduled() ? 'T' : 'F');
   MOZ_ASSERT(OnTaskQueue());
   if (mVideoDecodeSuspendTimer.IsScheduled()) {
     mOnPlaybackEvent.Notify(MediaPlaybackEvent::CancelVideoSuspendTimer);
   }
   mVideoDecodeSuspendTimer.Reset();
 }
 
+void
+MediaDecoderStateMachine::AdjustByLooping(media::TimeUnit& aTime) const
+{
+  MOZ_ASSERT(OnTaskQueue());
+  if (mAudioDecodedDuration.isSome() && mAudioDecodedDuration.ref().IsPositive()) {
+    aTime = aTime % mAudioDecodedDuration.ref().ToMicroseconds();
+  }
+}
+
 } // namespace mozilla
 
 // avoid redefined macro in unified build
 #undef LOG
 #undef LOGV
 #undef LOGW
 #undef LOGE
 #undef SLOGW
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -709,16 +709,21 @@ private:
   MediaEventProducer<DecoderDoctorEvent> mOnDecoderDoctorEvent;
 
   MediaEventProducer<NextFrameStatus> mOnNextFrameStatus;
 
   const bool mIsMSE;
 
   bool mSeamlessLoopingAllowed;
 
+  // If media was in looping and had reached to the end before, then we need
+  // to adjust sample time from clock time to media time.
+  void AdjustByLooping(media::TimeUnit& aTime) const;
+  Maybe<media::TimeUnit> mAudioDecodedDuration;
+
   // Current playback position in the stream in bytes.
   int64_t mPlaybackOffset = 0;
 
 private:
   // The buffered range. Mirrored from the decoder thread.
   Mirror<media::TimeIntervals> mBuffered;
 
   // The current play state, mirrored from the main thread.
--- a/dom/media/ReaderProxy.cpp
+++ b/dom/media/ReaderProxy.cpp
@@ -14,18 +14,16 @@ namespace mozilla {
 ReaderProxy::ReaderProxy(AbstractThread* aOwnerThread,
                          MediaFormatReader* aReader)
   : mOwnerThread(aOwnerThread)
   , mReader(aReader)
   , mWatchManager(this, aReader->OwnerThread())
   , mDuration(aReader->OwnerThread(),
               media::NullableTimeUnit(),
               "ReaderProxy::mDuration (Mirror)")
-  , mSeamlessLoopingBlocked(false)
-  , mSeamlessLoopingEnabled(false)
 {
   // Must support either heuristic buffering or WaitForData().
   MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
              mReader->IsWaitForDataSupported());
 }
 
 ReaderProxy::~ReaderProxy()
 {}
@@ -53,79 +51,37 @@ ReaderProxy::ReadMetadata()
            &ReaderProxy::OnMetadataNotRead);
 }
 
 RefPtr<ReaderProxy::AudioDataPromise>
 ReaderProxy::OnAudioDataRequestCompleted(RefPtr<AudioData> aAudio)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
 
-  // Subtract the start time and add the looping-offset time.
-  int64_t offset =
-    StartTime().ToMicroseconds() - mLoopingOffset.ToMicroseconds();
-  aAudio->AdjustForStartTime(offset);
+  aAudio->AdjustForStartTime(StartTime().ToMicroseconds());
   if (aAudio->mTime.IsValid()) {
-    mLastAudioEndTime = aAudio->mTime;
     return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__);
   }
   return AudioDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
                                            __func__);
 }
 
 RefPtr<ReaderProxy::AudioDataPromise>
 ReaderProxy::OnAudioDataRequestFailed(const MediaResult& aError)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-
-  if (mSeamlessLoopingBlocked || !mSeamlessLoopingEnabled ||
-      aError.Code() != NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
-    return AudioDataPromise::CreateAndReject(aError, __func__);
-  }
-
-  // The data time in the audio queue is assumed to be increased linearly,
-  // so we need to add the last ending time as the offset to correct the
-  // audio data time in the next round when seamless looping is enabled.
-  mLoopingOffset = mLastAudioEndTime;
-
-  // Save the duration of the audio track if it hasn't been set.
-  if (!mAudioDuration.IsValid()) {
-    mAudioDuration = mLastAudioEndTime;
-  }
-
-  // For seamless looping, the demuxer is sought to the beginning and then
-  // keep requesting decoded data in advance, upon receiving EOS.
-  // The MDSM will not be aware of the EOS and keep receiving decoded data
-  // as usual while looping is on.
-  RefPtr<ReaderProxy> self = this;
-  RefPtr<MediaFormatReader> reader = mReader;
-  ResetDecode(TrackInfo::kAudioTrack);
-  return SeekInternal(SeekTarget(media::TimeUnit::Zero(), SeekTarget::Accurate))
-    ->Then(mReader->OwnerThread(),
-           __func__,
-           [reader]() { return reader->RequestAudioData(); },
-           [](const SeekRejectValue& aReject) {
-             return AudioDataPromise::CreateAndReject(aReject.mError, __func__);
-           })
-    ->Then(mOwnerThread,
-           __func__,
-           [self](RefPtr<AudioData> aAudio) {
-             return self->OnAudioDataRequestCompleted(aAudio.forget());
-           },
-           [](const MediaResult& aError) {
-             return AudioDataPromise::CreateAndReject(aError, __func__);
-           });
+  return AudioDataPromise::CreateAndReject(aError, __func__);
 }
 
 RefPtr<ReaderProxy::AudioDataPromise>
 ReaderProxy::RequestAudioData()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mShutdown);
 
-  mSeamlessLoopingBlocked = false;
   return InvokeAsync(mReader->OwnerThread(),
                      mReader.get(),
                      __func__,
                      &MediaFormatReader::RequestAudioData)
     ->Then(mOwnerThread,
            __func__,
            this,
            &ReaderProxy::OnAudioDataRequestCompleted,
@@ -133,17 +89,16 @@ ReaderProxy::RequestAudioData()
 }
 
 RefPtr<ReaderProxy::VideoDataPromise>
 ReaderProxy::RequestVideoData(const media::TimeUnit& aTimeThreshold)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mShutdown);
 
-  mSeamlessLoopingBlocked = false;
   const auto threshold = aTimeThreshold > media::TimeUnit::Zero()
                          ? aTimeThreshold + StartTime()
                          : aTimeThreshold;
 
   int64_t startTime = StartTime().ToMicroseconds();
   return InvokeAsync(mReader->OwnerThread(),
                      mReader.get(),
                      __func__,
@@ -163,21 +118,16 @@ ReaderProxy::RequestVideoData(const medi
              return VideoDataPromise::CreateAndReject(aError, __func__);
            });
 }
 
 RefPtr<ReaderProxy::SeekPromise>
 ReaderProxy::Seek(const SeekTarget& aTarget)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-  mSeamlessLoopingBlocked = true;
-  // Reset the members for seamless looping if the seek is triggered outside.
-  mLoopingOffset = media::TimeUnit::Zero();
-  mLastAudioEndTime = media::TimeUnit::Zero();
-  mAudioDuration = media::TimeUnit::Invalid();
   return SeekInternal(aTarget);
 }
 
 RefPtr<ReaderProxy::SeekPromise>
 ReaderProxy::SeekInternal(const SeekTarget& aTarget)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   SeekTarget adjustedTarget = aTarget;
@@ -295,27 +245,9 @@ ReaderProxy::SetCanonicalDuration(
       mDuration.Connect(canonical);
       mWatchManager.Watch(mDuration, &ReaderProxy::UpdateDuration);
     });
   nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   Unused << rv;
 }
 
-void
-ReaderProxy::SetSeamlessLoopingEnabled(bool aEnabled)
-{
-  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-  mSeamlessLoopingEnabled = aEnabled;
-}
-
-void
-ReaderProxy::AdjustByLooping(media::TimeUnit& aTime)
-{
-  MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-  MOZ_ASSERT(!mShutdown);
-  MOZ_ASSERT(!mSeamlessLoopingEnabled || !mSeamlessLoopingBlocked);
-  if (mAudioDuration.IsValid() && mAudioDuration.IsPositive()) {
-    aTime = aTime % mAudioDuration.ToMicroseconds();
-  }
-}
-
 } // namespace mozilla
--- a/dom/media/ReaderProxy.h
+++ b/dom/media/ReaderProxy.h
@@ -79,20 +79,16 @@ public:
 
   void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); }
 
   void SetVideoBlankDecode(bool aIsBlankDecode);
 
   void SetCanonicalDuration(
     AbstractCanonical<media::NullableTimeUnit>* aCanonical);
 
-  void SetSeamlessLoopingEnabled(bool aEnabled);
-
-  void AdjustByLooping(media::TimeUnit& aTime);
-
 private:
   ~ReaderProxy();
   RefPtr<MetadataPromise> OnMetadataRead(MetadataHolder&& aMetadata);
   RefPtr<MetadataPromise> OnMetadataNotRead(const MediaResult& aError);
   void UpdateDuration();
   RefPtr<SeekPromise> SeekInternal(const SeekTarget& aTarget);
 
   RefPtr<ReaderProxy::AudioDataPromise> OnAudioDataRequestCompleted(
@@ -106,25 +102,13 @@ private:
   bool mShutdown = false;
   Maybe<media::TimeUnit> mStartTime;
 
   // State-watching manager.
   WatchManager<ReaderProxy> mWatchManager;
 
   // Duration, mirrored from the state machine task queue.
   Mirror<media::NullableTimeUnit> mDuration;
-
-  // The total duration of audio looping in previous rounds.
-  media::TimeUnit mLoopingOffset = media::TimeUnit::Zero();
-  // To keep tracking the latest time of decoded audio data.
-  media::TimeUnit mLastAudioEndTime = media::TimeUnit::Zero();
-  // The duration of the audio track.
-  media::TimeUnit mAudioDuration = media::TimeUnit::Invalid();
-
-  // To prevent seamless looping while seeking.
-  bool mSeamlessLoopingBlocked;
-  // Indicates whether we should loop the media.
-  bool mSeamlessLoopingEnabled;
 };
 
 } // namespace mozilla
 
 #endif // ReaderProxy_h_