Bug 1284399. Part 1 - add GetSeekTarget() to remove direct access to mSeekJob. r=kaku draft
authorJW Wang <jwwang@mozilla.com>
Thu, 30 Jun 2016 13:37:20 +0800
changeset 386925 af1a96c78fbdab64f24ed4f39ac0becdc74aba0f
parent 386893 04821a70c739a00d12e12df651c0989441e22728
child 386926 2f5ea74f31e95cca4e5e7371f05154e6245b612a
push id22850
push userjwwang@mozilla.com
push dateWed, 13 Jul 2016 02:19:16 +0000
reviewerskaku
bugs1284399
milestone50.0a1
Bug 1284399. Part 1 - add GetSeekTarget() to remove direct access to mSeekJob. r=kaku MozReview-Commit-ID: 60wIW9gHYKt
dom/media/AccurateSeekTask.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/NextFrameSeekTask.cpp
dom/media/SeekTask.cpp
dom/media/SeekTask.h
--- a/dom/media/AccurateSeekTask.cpp
+++ b/dom/media/AccurateSeekTask.cpp
@@ -47,18 +47,17 @@ AccurateSeekTask::AccurateSeekTask(const
   , mAudioRate(aInfo.mAudio.mRate)
   , mDoneAudioSeeking(!aInfo.HasAudio() || mSeekJob.mTarget.IsVideoOnly())
   , mDoneVideoSeeking(!aInfo.HasVideo())
 {
   AssertOwnerThread();
 
   // Bound the seek time to be inside the media range.
   NS_ASSERTION(aEnd.ToMicroseconds() != -1, "Should know end time by now");
-  mSeekJob.mTarget.SetTime(
-    std::max(media::TimeUnit(), std::min(mSeekJob.mTarget.GetTime(), aEnd)));
+  mTarget.SetTime(std::max(media::TimeUnit(), std::min(mTarget.GetTime(), aEnd)));
 
   // Configure MediaDecoderReaderWrapper.
   SetCallbacks();
 }
 
 AccurateSeekTask::~AccurateSeekTask()
 {
   AssertOwnerThread();
@@ -91,17 +90,17 @@ AccurateSeekTask::NeedToResetMDSM() cons
 }
 
 RefPtr<AccurateSeekTask::SeekTaskPromise>
 AccurateSeekTask::Seek(const media::TimeUnit& aDuration)
 {
   AssertOwnerThread();
 
   // Do the seek.
-  mSeekRequest.Begin(mReader->Seek(mSeekJob.mTarget, aDuration)
+  mSeekRequest.Begin(mReader->Seek(mTarget, aDuration)
     ->Then(OwnerThread(), __func__, this,
            &AccurateSeekTask::OnSeekResolved, &AccurateSeekTask::OnSeekRejected));
 
   return mSeekTaskPromise.Ensure(__func__);
 }
 
 void
 AccurateSeekTask::RequestAudioData()
@@ -124,53 +123,53 @@ AccurateSeekTask::RequestVideoData()
 }
 
 nsresult
 AccurateSeekTask::DropAudioUpToSeekTarget(MediaData* aSample)
 {
   AssertOwnerThread();
 
   RefPtr<AudioData> audio(aSample->As<AudioData>());
-  MOZ_ASSERT(audio && mSeekJob.Exists() && mSeekJob.mTarget.IsAccurate());
+  MOZ_ASSERT(audio && mSeekJob.Exists() && mTarget.IsAccurate());
 
   CheckedInt64 sampleDuration = FramesToUsecs(audio->mFrames, mAudioRate);
   if (!sampleDuration.isValid()) {
     return NS_ERROR_FAILURE;
   }
 
-  if (audio->mTime + sampleDuration.value() <= mSeekJob.mTarget.GetTime().ToMicroseconds()) {
+  if (audio->mTime + sampleDuration.value() <= mTarget.GetTime().ToMicroseconds()) {
     // Our seek target lies after the frames in this AudioData. Don't
     // push it onto the audio queue, and keep decoding forwards.
     return NS_OK;
   }
 
-  if (audio->mTime > mSeekJob.mTarget.GetTime().ToMicroseconds()) {
+  if (audio->mTime > mTarget.GetTime().ToMicroseconds()) {
     // The seek target doesn't lie in the audio block just after the last
     // audio frames we've seen which were before the seek target. This
     // could have been the first audio data we've seen after seek, i.e. the
     // seek terminated after the seek target in the audio stream. Just
     // abort the audio decode-to-target, the state machine will play
     // silence to cover the gap. Typically this happens in poorly muxed
     // files.
     DECODER_WARN("Audio not synced after seek, maybe a poorly muxed file?");
     mSeekedAudioData = audio;
     mDoneAudioSeeking = true;
     return NS_OK;
   }
 
   // The seek target lies somewhere in this AudioData's frames, strip off
   // any frames which lie before the seek target, so we'll begin playback
   // exactly at the seek target.
-  NS_ASSERTION(mSeekJob.mTarget.GetTime().ToMicroseconds() >= audio->mTime,
+  NS_ASSERTION(mTarget.GetTime().ToMicroseconds() >= audio->mTime,
                "Target must at or be after data start.");
-  NS_ASSERTION(mSeekJob.mTarget.GetTime().ToMicroseconds() < audio->mTime + sampleDuration.value(),
+  NS_ASSERTION(mTarget.GetTime().ToMicroseconds() < audio->mTime + sampleDuration.value(),
                "Data must end after target.");
 
   CheckedInt64 framesToPrune =
-    UsecsToFrames(mSeekJob.mTarget.GetTime().ToMicroseconds() - audio->mTime, mAudioRate);
+    UsecsToFrames(mTarget.GetTime().ToMicroseconds() - audio->mTime, mAudioRate);
   if (!framesToPrune.isValid()) {
     return NS_ERROR_FAILURE;
   }
   if (framesToPrune.value() > audio->mFrames) {
     // We've messed up somehow. Don't try to trim frames, the |frames|
     // variable below will overflow.
     DECODER_WARN("Can't prune more frames that we have!");
     return NS_ERROR_FAILURE;
@@ -185,17 +184,17 @@ AccurateSeekTask::DropAudioUpToSeekTarge
   memcpy(audioData.get(),
          audio->mAudioData.get() + (framesToPrune.value() * channels),
          frames * channels * sizeof(AudioDataValue));
   CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
   if (!duration.isValid()) {
     return NS_ERROR_FAILURE;
   }
   RefPtr<AudioData> data(new AudioData(audio->mOffset,
-                                       mSeekJob.mTarget.GetTime().ToMicroseconds(),
+                                       mTarget.GetTime().ToMicroseconds(),
                                        duration.value(),
                                        frames,
                                        Move(audioData),
                                        channels,
                                        audio->mRate));
   MOZ_ASSERT(!mSeekedAudioData, "Should be the 1st sample after seeking");
   mSeekedAudioData = data;
   mDoneAudioSeeking = true;
@@ -208,17 +207,17 @@ AccurateSeekTask::DropVideoUpToSeekTarge
 {
   AssertOwnerThread();
 
   RefPtr<VideoData> video(aSample->As<VideoData>());
   MOZ_ASSERT(video);
   DECODER_LOG("DropVideoUpToSeekTarget() frame [%lld, %lld]",
               video->mTime, video->GetEndTime());
   MOZ_ASSERT(mSeekJob.Exists());
-  const int64_t target = mSeekJob.mTarget.GetTime().ToMicroseconds();
+  const int64_t target = mTarget.GetTime().ToMicroseconds();
 
   // If the frame end time is less than the seek target, we won't want
   // to display this frame after the seek, so discard it.
   if (target >= video->GetEndTime()) {
     DECODER_LOG("DropVideoUpToSeekTarget() pop video frame [%lld, %lld] target=%lld",
                 video->mTime, video->GetEndTime(), target);
     mFirstVideoFrameAfterSeek = video;
   } else {
@@ -276,26 +275,26 @@ AccurateSeekTask::OnSeekRejected(nsresul
   MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
   RejectIfExist(__func__);
 }
 
 void
 AccurateSeekTask::AdjustFastSeekIfNeeded(MediaData* aSample)
 {
   AssertOwnerThread();
-  if (mSeekJob.mTarget.IsFast() &&
-      mSeekJob.mTarget.GetTime() > mCurrentTimeBeforeSeek &&
+  if (mTarget.IsFast() &&
+      mTarget.GetTime() > mCurrentTimeBeforeSeek &&
       aSample->mTime < mCurrentTimeBeforeSeek.ToMicroseconds()) {
     // We are doing a fastSeek, but we ended up *before* the previous
     // playback position. This is surprising UX, so switch to an accurate
     // seek and decode to the seek target. This is not conformant to the
     // spec, fastSeek should always be fast, but until we get the time to
     // change all Readers to seek to the keyframe after the currentTime
     // in this case, we'll just decode forward. Bug 1026330.
-    mSeekJob.mTarget.SetType(SeekTarget::Accurate);
+    mTarget.SetType(SeekTarget::Accurate);
   }
 }
 
 void
 AccurateSeekTask::OnAudioDecoded(MediaData* aAudioSample)
 {
   AssertOwnerThread();
   MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
@@ -319,17 +318,17 @@ AccurateSeekTask::OnAudioDecoded(MediaDa
 
   if (mFirstAudioSample) {
     mFirstAudioSample = false;
     MOZ_ASSERT(audio->mDiscontinuity);
   }
 
   AdjustFastSeekIfNeeded(audio);
 
-  if (mSeekJob.mTarget.IsFast()) {
+  if (mTarget.IsFast()) {
     // Non-precise seek; we can stop the seek at the first sample.
     mSeekedAudioData = audio;
     mDoneAudioSeeking = true;
   } else if (NS_FAILED(DropAudioUpToSeekTarget(audio))) {
     RejectIfExist(__func__);
     return;
   }
 
@@ -410,17 +409,17 @@ AccurateSeekTask::OnVideoDecoded(MediaDa
 
   if (mFirstVideoSample) {
     mFirstVideoSample = false;
     MOZ_ASSERT(video->mDiscontinuity);
   }
 
   AdjustFastSeekIfNeeded(video);
 
-  if (mSeekJob.mTarget.IsFast()) {
+  if (mTarget.IsFast()) {
     // Non-precise seek. We can stop the seek at the first sample.
     mSeekedVideoData = video;
     mDoneVideoSeeking = true;
   } else if (NS_FAILED(DropVideoUpToSeekTarget(video.get()))) {
     RejectIfExist(__func__);
     return;
   }
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1166,18 +1166,18 @@ MediaDecoderStateMachine::SetDormant(boo
     if (mState == DECODER_STATE_SEEKING) {
       if (mQueuedSeek.Exists()) {
         // Keep latest seek target
       } else if (mSeekTask && mSeekTask->Exists()) {
         // Because both audio and video decoders are going to be reset in this
         // method later, we treat a VideoOnly seek task as a normal Accurate
         // seek task so that while it is resumed, both audio and video playback
         // are handled.
-        if (mSeekTask->GetSeekJob().mTarget.IsVideoOnly()) {
-          mSeekTask->GetSeekJob().mTarget.SetType(SeekTarget::Accurate);
+        if (mSeekTask->GetSeekTarget().IsVideoOnly()) {
+          mSeekTask->GetSeekTarget().SetType(SeekTarget::Accurate);
         }
         mQueuedSeek = Move(mSeekTask->GetSeekJob());
         mSeekTaskRequest.DisconnectIfExists();
       } else {
         mQueuedSeek.mTarget = SeekTarget(mCurrentPosition,
                                          SeekTarget::Accurate,
                                          MediaDecoderEventVisibility::Suppressed);
         // XXXbholley - Nobody is listening to this promise. Do we need to pass it
@@ -1653,19 +1653,19 @@ MediaDecoderStateMachine::InitiateSeek(S
   } else {
     MOZ_DIAGNOSTIC_ASSERT(false, "Cannot handle this seek task.");
   }
 
   // Stop playback now to ensure that while we're outside the monitor
   // dispatching SeekingStarted, playback doesn't advance and mess with
   // mCurrentPosition that we've setting to seekTime here.
   StopPlayback();
-  UpdatePlaybackPositionInternal(mSeekTask->GetSeekJob().mTarget.GetTime().ToMicroseconds());
-
-  mOnSeekingStart.Notify(mSeekTask->GetSeekJob().mTarget.mEventVisibility);
+  UpdatePlaybackPositionInternal(mSeekTask->GetSeekTarget().GetTime().ToMicroseconds());
+
+  mOnSeekingStart.Notify(mSeekTask->GetSeekTarget().mEventVisibility);
 
   // Reset our state machine and decoding pipeline before seeking.
   if (mSeekTask->NeedToResetMDSM()) { Reset(); }
 
   // Do the seek.
   mSeekTaskRequest.Begin(mSeekTask->Seek(Duration())
     ->Then(OwnerThread(), __func__, this,
            &MediaDecoderStateMachine::OnSeekTaskResolved,
@@ -2141,17 +2141,17 @@ MediaDecoderStateMachine::FinishDecodeFi
 }
 
 void
 MediaDecoderStateMachine::SeekCompleted()
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(mState == DECODER_STATE_SEEKING);
 
-  int64_t seekTime = mSeekTask->GetSeekJob().mTarget.GetTime().ToMicroseconds();
+  int64_t seekTime = mSeekTask->GetSeekTarget().GetTime().ToMicroseconds();
   int64_t newCurrentTime = seekTime;
 
   // Setup timestamp state.
   RefPtr<MediaData> video = VideoQueue().PeekFront();
   if (seekTime == Duration().ToMicroseconds()) {
     newCurrentTime = seekTime;
   } else if (HasAudio()) {
     RefPtr<MediaData> audio = AudioQueue().PeekFront();
--- a/dom/media/NextFrameSeekTask.cpp
+++ b/dom/media/NextFrameSeekTask.cpp
@@ -151,17 +151,17 @@ NextFrameSeekTask::IsVideoSeekComplete()
 
 void
 NextFrameSeekTask::MaybeFinishSeek()
 {
   AssertOwnerThread();
   if (IsAudioSeekComplete() && IsVideoSeekComplete()) {
     UpdateSeekTargetTime();
 
-    auto time = mSeekJob.mTarget.GetTime().ToMicroseconds();
+    auto time = mTarget.GetTime().ToMicroseconds();
     DiscardFrames(mAudioQueue, [time] (int64_t aSampleTime) {
       return aSampleTime < time;
     });
 
     Resolve(__func__); // Call to MDSM::SeekCompleted();
   }
 }
 
@@ -328,19 +328,19 @@ NextFrameSeekTask::CancelCallbacks()
 
 void
 NextFrameSeekTask::UpdateSeekTargetTime()
 {
   AssertOwnerThread();
 
   RefPtr<MediaData> data = mVideoQueue.PeekFront();
   if (data) {
-    mSeekJob.mTarget.SetTime(TimeUnit::FromMicroseconds(data->mTime));
+    mTarget.SetTime(TimeUnit::FromMicroseconds(data->mTime));
   } else if (mSeekedVideoData) {
-    mSeekJob.mTarget.SetTime(TimeUnit::FromMicroseconds(mSeekedVideoData->mTime));
+    mTarget.SetTime(TimeUnit::FromMicroseconds(mSeekedVideoData->mTime));
   } else if (mIsVideoQueueFinished || mVideoQueue.AtEndOfStream()) {
-    mSeekJob.mTarget.SetTime(mDuration);
+    mTarget.SetTime(mDuration);
   } else {
     MOZ_ASSERT(false, "No data!");
   }
 }
 } // namespace media
 } // namespace mozilla
--- a/dom/media/SeekTask.cpp
+++ b/dom/media/SeekTask.cpp
@@ -13,16 +13,17 @@ namespace mozilla {
 SeekTask::SeekTask(const void* aDecoderID,
                    AbstractThread* aThread,
                    MediaDecoderReaderWrapper* aReader,
                    SeekJob&& aSeekJob)
   : mDecoderID(aDecoderID)
   , mOwnerThread(aThread)
   , mReader(aReader)
   , mSeekJob(Move(aSeekJob))
+  , mTarget(mSeekJob.mTarget)
   , mIsDiscarded(false)
   , mIsAudioQueueFinished(false)
   , mIsVideoQueueFinished(false)
   , mNeedToStopPrerollingAudio(false)
   , mNeedToStopPrerollingVideo(false)
 {
   AssertOwnerThread();
 }
@@ -78,16 +79,23 @@ SeekTask::OwnerThread() const
 
 SeekJob&
 SeekTask::GetSeekJob()
 {
   AssertOwnerThread();
   return mSeekJob;
 }
 
+SeekTarget&
+SeekTask::GetSeekTarget()
+{
+  AssertOwnerThread();
+  return mTarget;
+}
+
 bool
 SeekTask::Exists() const
 {
   AssertOwnerThread();
 
   // mSeekTaskPromise communicates SeekTask and MDSM;
   // mSeekJob communicates MDSM and MediaDecoder;
   // Either one exists means the current seek task has yet finished.
--- a/dom/media/SeekTask.h
+++ b/dom/media/SeekTask.h
@@ -53,16 +53,18 @@ public:
   virtual void Discard() = 0;
 
   virtual RefPtr<SeekTaskPromise> Seek(const media::TimeUnit& aDuration) = 0;
 
   virtual bool NeedToResetMDSM() const = 0;
 
   SeekJob& GetSeekJob();
 
+  SeekTarget& GetSeekTarget();
+
   bool Exists() const;
 
 protected:
   SeekTask(const void* aDecoderID,
            AbstractThread* aThread,
            MediaDecoderReaderWrapper* aReader,
            SeekJob&& aSeekJob);
 
@@ -82,16 +84,17 @@ protected:
   const void* mDecoderID; // For logging.
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReaderWrapper> mReader;
 
   /*
    * Internal state.
    */
   SeekJob mSeekJob;
+  SeekTarget& mTarget;
   MozPromiseHolder<SeekTaskPromise> mSeekTaskPromise;
   bool mIsDiscarded;
 
   /*
    * Information which are going to be returned to MDSM.
    */
   RefPtr<MediaData> mSeekedAudioData;
   RefPtr<MediaData> mSeekedVideoData;