Bug 1361756 - don't reset decoders when entering dormant.
Resetting decoders somehow cause the WebM demuxer to seek and initiate
network download which is blocked by the site for invisible media elements.
See comment 5 for how this blocks playback.
We work around this issue by not resetting decoders when entering dormant
since we will reset them anyway during seeking when exiting dormant.
This change is a workaround for this bug though. However it is also an
improvement for the dormant state in general since it removes unnecessary
works to improve performance.
MozReview-Commit-ID: KtbpQlrO8J
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -486,19 +486,24 @@ public:
auto t = mMaster->mMediaSink->IsStarted()
? mMaster->GetClock() : mMaster->GetMediaTime();
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.
RefPtr<MediaDecoder::SeekPromise> x =
mPendingSeek.mPromise.Ensure(__func__);
- mMaster->ResetDecode();
- mMaster->StopMediaSink();
- mMaster->mReader->ReleaseResources();
+ // No need to call ResetDecode() and StopMediaSink() here.
+ // We will do them during seeking when exiting dormant.
+
+ // Ignore WAIT_FOR_DATA since we won't decode in dormant.
+ mMaster->mAudioWaitRequest.DisconnectIfExists();
+ mMaster->mVideoWaitRequest.DisconnectIfExists();
+
+ MaybeReleaseResources();
}
void Exit() override
{
// mPendingSeek is either moved when exiting dormant or
// should be rejected here before transition to SHUTDOWN.
mPendingSeek.RejectIfExists(__func__);
}
@@ -515,17 +520,60 @@ public:
void HandleResumeVideoDecoding(const TimeUnit&) override
{
// Do nothing since we won't resume decoding until exiting dormant.
}
void HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) override;
+ void HandleAudioDecoded(AudioData*) override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleVideoDecoded(VideoData*, TimeStamp) override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleWaitingForAudio() override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleWaitingForVideo() override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleAudioCanceled() override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleVideoCanceled() override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleEndOfAudio() override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleEndOfVideo() override
+ {
+ MaybeReleaseResources();
+ }
+
private:
+ void MaybeReleaseResources()
+ {
+ if (!mMaster->mAudioDataRequest.Exists() &&
+ !mMaster->mVideoDataRequest.Exists()) {
+ // Release decoders only when they are idle. Otherwise it might cause
+ // decode error later when resetting decoders during seeking.
+ mMaster->mReader->ReleaseResources();
+ }
+ }
+
SeekJob mPendingSeek;
};
/**
* Purpose: decode the 1st audio and video frames to fire the 'loadeddata' event.
*
* Transition to:
* SHUTDOWN if any decode error.