Bug 1322799 part 7 - move AccurateSeekTask::Drop{Audio,Video}UpToSeekTarget(); r?jwwang
MozReview-Commit-ID: 8i3yLFqXfJL
--- 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);