Bug 1322799 part 5 - move AccurateSeekTask::Handle{Audio,Video,Not}{Decoded,Waited}(); r?jwwang}
MozReview-Commit-ID: 6ZulbXUFdf8
--- a/dom/media/AccurateSeekTask.cpp
+++ b/dom/media/AccurateSeekTask.cpp
@@ -92,164 +92,41 @@ AccurateSeekTask::CalculateNewCurrentTim
MOZ_ASSERT(false, "AccurateSeekTask doesn't handle other seek types.");
return 0;
}
void
AccurateSeekTask::HandleAudioDecoded(MediaData* aAudio)
{
- AssertOwnerThread();
- MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
-
- RefPtr<MediaData> audio(aAudio);
- MOZ_ASSERT(audio);
-
- // The MDSM::mDecodedAudioEndTime will be updated once the whole SeekTask is
- // resolved.
-
- SAMPLE_LOG("OnAudioDecoded [%lld,%lld]", audio->mTime, audio->GetEndTime());
-
- // Video-only seek doesn't reset audio decoder. There might be pending audio
- // requests when AccurateSeekTask::Seek() begins. We will just store the data
- // without checking |mDiscontinuity| or calling DropAudioUpToSeekTarget().
- if (mTarget.IsVideoOnly()) {
- mSeekedAudioData = audio.forget();
- return;
- }
-
- AdjustFastSeekIfNeeded(audio);
-
- if (mTarget.IsFast()) {
- // Non-precise seek; we can stop the seek at the first sample.
- mSeekedAudioData = audio;
- mDoneAudioSeeking = true;
- } else {
- nsresult rv = DropAudioUpToSeekTarget(audio);
- if (NS_FAILED(rv)) {
- RejectIfExist(rv, __func__);
- return;
- }
- }
-
- if (!mDoneAudioSeeking) {
- RequestAudioData();
- return;
- }
- MaybeFinishSeek();
}
void
AccurateSeekTask::HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart)
{
- AssertOwnerThread();
- MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
-
- RefPtr<MediaData> video(aVideo);
- MOZ_ASSERT(video);
-
- // The MDSM::mDecodedVideoEndTime will be updated once the whole SeekTask is
- // resolved.
-
- SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", video->mTime, video->GetEndTime());
-
- AdjustFastSeekIfNeeded(video);
-
- if (mTarget.IsFast()) {
- // Non-precise seek. We can stop the seek at the first sample.
- mSeekedVideoData = video;
- mDoneVideoSeeking = true;
- } else {
- nsresult rv = DropVideoUpToSeekTarget(video.get());
- if (NS_FAILED(rv)) {
- RejectIfExist(rv, __func__);
- return;
- }
- }
-
- if (!mDoneVideoSeeking) {
- RequestVideoData();
- return;
- }
- MaybeFinishSeek();
}
void
AccurateSeekTask::HandleNotDecoded(MediaData::Type aType, const MediaResult& aError)
{
- AssertOwnerThread();
- MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
-
- SAMPLE_LOG("OnNotDecoded type=%d reason=%u", aType, aError.Code());
-
- // Ignore pending requests from video-only seek.
- if (aType == MediaData::AUDIO_DATA && mTarget.IsVideoOnly()) {
- return;
- }
-
- // If the decoder is waiting for data, we tell it to call us back when the
- // data arrives.
- if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
- mReader->WaitForData(aType);
- return;
- }
-
- if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
- if (aType == MediaData::AUDIO_DATA) {
- RequestAudioData();
- } else {
- RequestVideoData();
- }
- return;
- }
-
- if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
- if (aType == MediaData::AUDIO_DATA) {
- mIsAudioQueueFinished = true;
- mDoneAudioSeeking = true;
- } else {
- mIsVideoQueueFinished = true;
- mDoneVideoSeeking = true;
- if (mFirstVideoFrameAfterSeek) {
- // Hit the end of stream. Move mFirstVideoFrameAfterSeek into
- // mSeekedVideoData so we have something to display after seeking.
- mSeekedVideoData = mFirstVideoFrameAfterSeek.forget();
- }
- }
- MaybeFinishSeek();
- return;
- }
-
- // This is a decode error, delegate to the generic error path.
- RejectIfExist(aError, __func__);
}
void
AccurateSeekTask::HandleAudioWaited(MediaData::Type aType)
{
- AssertOwnerThread();
-
- // Ignore pending requests from video-only seek.
- if (mTarget.IsVideoOnly()) {
- return;
- }
- RequestAudioData();
}
void
AccurateSeekTask::HandleVideoWaited(MediaData::Type aType)
{
- AssertOwnerThread();
- RequestVideoData();
}
void
AccurateSeekTask::HandleNotWaited(const WaitForDataRejectValue& aRejection)
{
- AssertOwnerThread();
}
RefPtr<AccurateSeekTask::SeekTaskPromise>
AccurateSeekTask::Seek(const media::TimeUnit& aDuration)
{
AssertOwnerThread();
return mSeekTaskPromise.Ensure(__func__);
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -81,16 +81,17 @@ using namespace mozilla::media;
#define DECODER_WARN(x, ...) NS_WARNING(nsPrintfCString(FMT(x, ##__VA_ARGS__)).get())
#define DUMP_LOG(x, ...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, nullptr, -1)
// Used by StateObject and its sub-classes
#define SFMT(x, ...) "Decoder=%p state=%s " x, mMaster->mDecoderID, ToStateStr(GetState()), ##__VA_ARGS__
#define SLOG(x, ...) MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, (SFMT(x, ##__VA_ARGS__)))
#define SWARN(x, ...) NS_WARNING(nsPrintfCString(SFMT(x, ##__VA_ARGS__)).get())
#define SDUMP(x, ...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(SFMT(x, ##__VA_ARGS__)).get(), nullptr, nullptr, -1)
+#define SSAMPLELOG(x, ...) MOZ_LOG(gMediaSampleLog, LogLevel::Debug, (SFMT(x, ##__VA_ARGS__)))
// Certain constants get stored as member variables and then adjusted by various
// scale factors on a per-decoder basis. We want to make sure to avoid using these
// constants directly, so we put them in a namespace.
namespace detail {
// If audio queue has less than this many usecs of decoded audio, we won't risk
// trying to decode the video, we'll skip decoding video up to the next
@@ -884,16 +885,161 @@ public:
void Exit() override
{
SeekingState::Exit();
// Disconnect MediaDecoderReaderWrapper.
mSeekRequest.DisconnectIfExists();
}
+ void HandleAudioDecoded(MediaData* aAudio) override
+ {
+ MOZ_ASSERT(mSeekTaskRequest.Exists(), "Seek shouldn't be finished");
+
+ RefPtr<MediaData> audio(aAudio);
+ MOZ_ASSERT(audio);
+
+ // The MDSM::mDecodedAudioEndTime will be updated once the whole SeekTask is
+ // resolved.
+
+ SSAMPLELOG("HandleAudioDecoded [%lld,%lld]", audio->mTime, audio->GetEndTime());
+
+ // Video-only seek doesn't reset audio decoder. There might be pending audio
+ // requests when AccurateSeekTask::Seek() begins. We will just store the data
+ // without checking |mDiscontinuity| or calling DropAudioUpToSeekTarget().
+ if (mTask->mTarget.IsVideoOnly()) {
+ mTask->mSeekedAudioData = audio.forget();
+ return;
+ }
+
+ mTask->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);
+ if (NS_FAILED(rv)) {
+ mTask->RejectIfExist(rv, __func__);
+ return;
+ }
+ }
+
+ if (!mTask->mDoneAudioSeeking) {
+ RequestAudioData();
+ return;
+ }
+ mTask->MaybeFinishSeek();
+ }
+
+ void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override
+ {
+ MOZ_ASSERT(mSeekTaskRequest.Exists(), "Seek shouldn't be finished");
+
+ RefPtr<MediaData> video(aVideo);
+ MOZ_ASSERT(video);
+
+ // The MDSM::mDecodedVideoEndTime will be updated once the whole SeekTask is
+ // resolved.
+
+ SSAMPLELOG("HandleVideoDecoded [%lld,%lld]", video->mTime, video->GetEndTime());
+
+ mTask->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());
+ if (NS_FAILED(rv)) {
+ mTask->RejectIfExist(rv, __func__);
+ return;
+ }
+ }
+
+ if (!mTask->mDoneVideoSeeking) {
+ RequestVideoData();
+ return;
+ }
+ mTask->MaybeFinishSeek();
+ }
+
+ void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) override
+ {
+ MOZ_ASSERT(mSeekTaskRequest.Exists(), "Seek shouldn't be finished");
+
+ SSAMPLELOG("OnNotDecoded type=%d reason=%u", aType, aError.Code());
+
+ // Ignore pending requests from video-only seek.
+ if (aType == MediaData::AUDIO_DATA && mTask->mTarget.IsVideoOnly()) {
+ return;
+ }
+
+ // If the decoder is waiting for data, we tell it to call us back when the
+ // data arrives.
+ if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
+ Reader()->WaitForData(aType);
+ return;
+ }
+
+ if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
+ if (aType == MediaData::AUDIO_DATA) {
+ RequestAudioData();
+ } else {
+ RequestVideoData();
+ }
+ return;
+ }
+
+ if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
+ if (aType == MediaData::AUDIO_DATA) {
+ mTask->mIsAudioQueueFinished = true;
+ mTask->mDoneAudioSeeking = true;
+ } else {
+ mTask->mIsVideoQueueFinished = true;
+ mTask->mDoneVideoSeeking = true;
+ if (mTask->mFirstVideoFrameAfterSeek) {
+ // Hit the end of stream. Move mFirstVideoFrameAfterSeek into
+ // mSeekedVideoData so we have something to display after seeking.
+ mTask->mSeekedVideoData = mTask->mFirstVideoFrameAfterSeek.forget();
+ }
+ }
+ mTask->MaybeFinishSeek();
+ return;
+ }
+
+ // This is a decode error, delegate to the generic error path.
+ mTask->RejectIfExist(aError, __func__);
+ }
+
+ void HandleAudioWaited(MediaData::Type aType) override
+ {
+ MOZ_ASSERT(mSeekTaskRequest.Exists(), "Seek shouldn't be finished");
+
+ // Ignore pending requests from video-only seek.
+ if (mTask->mTarget.IsVideoOnly()) {
+ return;
+ }
+ RequestAudioData();
+ }
+
+ void HandleVideoWaited(MediaData::Type aType) override
+ {
+ MOZ_ASSERT(mSeekTaskRequest.Exists(), "Seek shouldn't be finished");
+
+ RequestVideoData();
+ }
+
+ void HandleNotWaited(const WaitForDataRejectValue& aRejection) override
+ {
+ MOZ_ASSERT(mSeekTaskRequest.Exists(), "Seek shouldn't be finished");
+ }
+
private:
void CreateSeekTask() override
{
mSeekTask = new AccurateSeekTask(
mMaster->mDecoderID, OwnerThread(), Reader(), mSeekJob.mTarget,
Info(), mMaster->Duration(), mMaster->GetMediaTime());
mTask = static_cast<AccurateSeekTask*>(mSeekTask.get());