Bug 1322799 part 7 - move AccurateSeekTask::Drop{Audio,Video}UpToSeekTarget(); r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Fri, 09 Dec 2016 13:20:10 -1000
changeset 449369 3006aa6e219412bb7363b5fa12790fe107ca144a
parent 449368 5c354288bb00e7cb9ecfd892ff670a398e5e2404
child 449370 180a3c47a5345c18b28ad57edc904fba502acee3
push id38552
push userbmo:kaku@mozilla.com
push dateWed, 14 Dec 2016 02:51:42 +0000
reviewersjwwang
bugs1322799
milestone53.0a1
Bug 1322799 part 7 - move AccurateSeekTask::Drop{Audio,Video}UpToSeekTarget(); r?jwwang MozReview-Commit-ID: 8i3yLFqXfJL
dom/media/AccurateSeekTask.cpp
dom/media/AccurateSeekTask.h
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/AccurateSeekTask.cpp
+++ b/dom/media/AccurateSeekTask.cpp
@@ -127,134 +127,16 @@ AccurateSeekTask::HandleNotWaited(const 
 RefPtr<AccurateSeekTask::SeekTaskPromise>
 AccurateSeekTask::Seek(const media::TimeUnit& aDuration)
 {
   AssertOwnerThread();
 
   return mSeekTaskPromise.Ensure(__func__);
 }
 
-nsresult
-AccurateSeekTask::DropAudioUpToSeekTarget(MediaData* aSample)
-{
-  AssertOwnerThread();
-
-  RefPtr<AudioData> audio(aSample->As<AudioData>());
-  MOZ_ASSERT(audio && mTarget.IsAccurate());
-
-  CheckedInt64 sampleDuration = FramesToUsecs(audio->mFrames, mAudioRate);
-  if (!sampleDuration.isValid()) {
-    return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
-  }
-
-  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 > 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(mTarget.GetTime().ToMicroseconds() >= audio->mTime,
-               "Target must at or be after data start.");
-  NS_ASSERTION(mTarget.GetTime().ToMicroseconds() < audio->mTime + sampleDuration.value(),
-               "Data must end after target.");
-
-  CheckedInt64 framesToPrune =
-    UsecsToFrames(mTarget.GetTime().ToMicroseconds() - audio->mTime, mAudioRate);
-  if (!framesToPrune.isValid()) {
-    return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
-  }
-  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;
-  }
-  uint32_t frames = audio->mFrames - static_cast<uint32_t>(framesToPrune.value());
-  uint32_t channels = audio->mChannels;
-  AlignedAudioBuffer audioData(frames * channels);
-  if (!audioData) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  memcpy(audioData.get(),
-         audio->mAudioData.get() + (framesToPrune.value() * channels),
-         frames * channels * sizeof(AudioDataValue));
-  CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
-  if (!duration.isValid()) {
-    return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
-  }
-  RefPtr<AudioData> data(new AudioData(audio->mOffset,
-                                       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;
-
-  return NS_OK;
-}
-
-nsresult
-AccurateSeekTask::DropVideoUpToSeekTarget(MediaData* aSample)
-{
-  AssertOwnerThread();
-
-  RefPtr<VideoData> video(aSample->As<VideoData>());
-  MOZ_ASSERT(video);
-  DECODER_LOG("DropVideoUpToSeekTarget() frame [%lld, %lld]",
-              video->mTime, video->GetEndTime());
-  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 {
-    if (target >= video->mTime && video->GetEndTime() >= target) {
-      // The seek target lies inside this frame's time slice. Adjust the frame's
-      // start time to match the seek target. We do this by replacing the
-      // first frame with a shallow copy which has the new timestamp.
-      RefPtr<VideoData> temp = VideoData::ShallowCopyUpdateTimestamp(video.get(), target);
-      video = temp;
-    }
-    mFirstVideoFrameAfterSeek = nullptr;
-
-    DECODER_LOG("DropVideoUpToSeekTarget() found video frame [%lld, %lld] containing target=%lld",
-                video->mTime, video->GetEndTime(), target);
-
-    MOZ_ASSERT(!mSeekedVideoData, "Should be the 1st sample after seeking");
-    mSeekedVideoData = video;
-    mDoneVideoSeeking = true;
-  }
-
-  return NS_OK;
-}
-
 void
 AccurateSeekTask::MaybeFinishSeek()
 {
   AssertOwnerThread();
   if (mDoneAudioSeeking && mDoneVideoSeeking) {
     Resolve(__func__); // Call to MDSM::SeekCompleted();
   }
 }
--- a/dom/media/AccurateSeekTask.h
+++ b/dom/media/AccurateSeekTask.h
@@ -38,20 +38,16 @@ public:
   void HandleAudioWaited(MediaData::Type aType) override;
 
   void HandleVideoWaited(MediaData::Type aType) override;
 
   void HandleNotWaited(const WaitForDataRejectValue& aRejection) override;
 
   ~AccurateSeekTask();
 
-  nsresult DropAudioUpToSeekTarget(MediaData* aSample);
-
-  nsresult DropVideoUpToSeekTarget(MediaData* aSample);
-
   void MaybeFinishSeek();
 
   /*
    * Internal state.
    */
   const media::TimeUnit mCurrentTimeBeforeSeek;
   const uint32_t mAudioRate;  // Audio sample rate.
   bool mDoneAudioSeeking;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -912,17 +912,17 @@ public:
 
     AdjustFastSeekIfNeeded(audio);
 
     if (mTask->mTarget.IsFast()) {
       // Non-precise seek; we can stop the seek at the first sample.
       mTask->mSeekedAudioData = audio;
       mTask->mDoneAudioSeeking = true;
     } else {
-      nsresult rv = mTask->DropAudioUpToSeekTarget(audio);
+      nsresult rv = DropAudioUpToSeekTarget(audio);
       if (NS_FAILED(rv)) {
         mTask->RejectIfExist(rv, __func__);
         return;
       }
     }
 
     if (!mTask->mDoneAudioSeeking) {
       RequestAudioData();
@@ -945,17 +945,17 @@ public:
 
     AdjustFastSeekIfNeeded(video);
 
     if (mTask->mTarget.IsFast()) {
       // Non-precise seek. We can stop the seek at the first sample.
       mTask->mSeekedVideoData = video;
       mTask->mDoneVideoSeeking = true;
     } else {
-      nsresult rv = mTask->DropVideoUpToSeekTarget(video.get());
+      nsresult rv = DropVideoUpToSeekTarget(video.get());
       if (NS_FAILED(rv)) {
         mTask->RejectIfExist(rv, __func__);
         return;
       }
     }
 
     if (!mTask->mDoneVideoSeeking) {
       RequestVideoData();
@@ -1128,16 +1128,128 @@ private:
       // 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.
       mTask->mTarget.SetType(SeekTarget::Accurate);
     }
   }
 
+  nsresult DropAudioUpToSeekTarget(MediaData* aSample)
+  {
+    RefPtr<AudioData> audio(aSample->As<AudioData>());
+    MOZ_ASSERT(audio && mTask->mTarget.IsAccurate());
+
+    CheckedInt64 sampleDuration = FramesToUsecs(audio->mFrames, mTask->mAudioRate);
+    if (!sampleDuration.isValid()) {
+      return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+    }
+
+    if (audio->mTime + sampleDuration.value() <= mTask->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 > mTask->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.
+      SWARN("Audio not synced after seek, maybe a poorly muxed file?");
+      mTask->mSeekedAudioData = audio;
+      mTask->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(mTask->mTarget.GetTime().ToMicroseconds() >= audio->mTime,
+                 "Target must at or be after data start.");
+    NS_ASSERTION(mTask->mTarget.GetTime().ToMicroseconds() < audio->mTime + sampleDuration.value(),
+                 "Data must end after target.");
+
+    CheckedInt64 framesToPrune =
+      UsecsToFrames(mTask->mTarget.GetTime().ToMicroseconds() - audio->mTime, mTask->mAudioRate);
+    if (!framesToPrune.isValid()) {
+      return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+    }
+    if (framesToPrune.value() > audio->mFrames) {
+      // We've messed up somehow. Don't try to trim frames, the |frames|
+      // variable below will overflow.
+      SWARN("Can't prune more frames that we have!");
+      return NS_ERROR_FAILURE;
+    }
+    uint32_t frames = audio->mFrames - static_cast<uint32_t>(framesToPrune.value());
+    uint32_t channels = audio->mChannels;
+    AlignedAudioBuffer audioData(frames * channels);
+    if (!audioData) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    memcpy(audioData.get(),
+           audio->mAudioData.get() + (framesToPrune.value() * channels),
+           frames * channels * sizeof(AudioDataValue));
+    CheckedInt64 duration = FramesToUsecs(frames, mTask->mAudioRate);
+    if (!duration.isValid()) {
+      return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+    }
+    RefPtr<AudioData> data(new AudioData(audio->mOffset,
+                                         mTask->mTarget.GetTime().ToMicroseconds(),
+                                         duration.value(),
+                                         frames,
+                                         Move(audioData),
+                                         channels,
+                                         audio->mRate));
+    MOZ_ASSERT(!mTask->mSeekedAudioData, "Should be the 1st sample after seeking");
+    mTask->mSeekedAudioData = data;
+    mTask->mDoneAudioSeeking = true;
+
+    return NS_OK;
+  }
+
+  nsresult DropVideoUpToSeekTarget(MediaData* aSample)
+  {
+    RefPtr<VideoData> video(aSample->As<VideoData>());
+    MOZ_ASSERT(video);
+    SLOG("DropVideoUpToSeekTarget() frame [%lld, %lld]",
+         video->mTime, video->GetEndTime());
+    const int64_t target = mTask->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()) {
+      SLOG("DropVideoUpToSeekTarget() pop video frame [%lld, %lld] target=%lld",
+           video->mTime, video->GetEndTime(), target);
+      mTask->mFirstVideoFrameAfterSeek = video;
+    } else {
+      if (target >= video->mTime && video->GetEndTime() >= target) {
+        // The seek target lies inside this frame's time slice. Adjust the frame's
+        // start time to match the seek target. We do this by replacing the
+        // first frame with a shallow copy which has the new timestamp.
+        RefPtr<VideoData> temp = VideoData::ShallowCopyUpdateTimestamp(video.get(), target);
+        video = temp;
+      }
+      mTask->mFirstVideoFrameAfterSeek = nullptr;
+
+      SLOG("DropVideoUpToSeekTarget() found video frame [%lld, %lld] containing target=%lld",
+                  video->mTime, video->GetEndTime(), target);
+
+      MOZ_ASSERT(!mTask->mSeekedVideoData, "Should be the 1st sample after seeking");
+      mTask->mSeekedVideoData = video;
+      mTask->mDoneVideoSeeking = true;
+    }
+
+    return NS_OK;
+  }
+
   void OnSeekTaskResolved(const SeekTaskResolveValue& aValue)
   {
     mSeekTaskRequest.Complete();
 
     if (aValue.mSeekedAudioData) {
       mMaster->Push(aValue.mSeekedAudioData);
       mMaster->mDecodedAudioEndTime = std::max(
         aValue.mSeekedAudioData->GetEndTime(), mMaster->mDecodedAudioEndTime);