Bug 1295884 - Fix video suspend intermittent failures. r?jwwang
On Linux x64 PGO try, HTMLMediaElement was reliably invoking
decoder->NotifyOwnerActivityChanged() after SetVisible(false) was
called. This caused the pending suspend to be cancelled and the test
waits for an event that never arrives.
Fixed by adding 'forced hidden' to MediaDecoder that overrides the
element visibility that comes from HTMLMediaElement.
MozReview-Commit-ID: 5aRhxxZ5cZd
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -793,18 +793,17 @@ HTMLMediaElement::MozDumpDebugInfo()
void
HTMLMediaElement::SetVisible(bool aVisible)
{
if (!mDecoder) {
return;
}
- mDecoder->NotifyOwnerActivityChanged(aVisible);
-
+ mDecoder->SetForcedHidden(!aVisible);
}
already_AddRefed<DOMMediaStream>
HTMLMediaElement::GetSrcObject() const
{
NS_ASSERTION(!mSrcAttrStream || mSrcAttrStream->GetPlaybackStream(),
"MediaStream should have been set up properly");
RefPtr<DOMMediaStream> stream = mSrcAttrStream;
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -503,16 +503,18 @@ MediaDecoder::MediaDecoder(MediaDecoderO
, mFrameStats(new FrameStatistics())
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
, mPlaybackStatistics(new MediaChannelStatistics())
, mPinnedForSeek(false)
, mPausedForPlaybackRateNull(false)
, mMinimizePreroll(false)
, mMediaTracksConstructed(false)
, mFiredMetadataLoaded(false)
+ , mElementVisible(true)
+ , mForcedHidden(false)
, mIsDormant(false)
, mIsHeuristicDormantSupported(
Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
, mHeuristicDormantTimeout(
Preferences::GetInt("media.decoder.heuristic.dormant.timeout",
DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS))
, mIsHeuristicDormant(false)
, INIT_MIRROR(mStateMachineIsShutdown, true)
@@ -1358,17 +1360,26 @@ MediaDecoder::DurationChanged()
Seek(mDuration, SeekTarget::Accurate);
}
}
void
MediaDecoder::SetElementVisibility(bool aIsVisible)
{
MOZ_ASSERT(NS_IsMainThread());
- mIsVisible = aIsVisible;
+ mElementVisible = aIsVisible;
+ mIsVisible = !mForcedHidden && mElementVisible;
+}
+
+void
+MediaDecoder::SetForcedHidden(bool aForcedHidden)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ mForcedHidden = aForcedHidden;
+ SetElementVisibility(mElementVisible);
}
void
MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
{
MOZ_ASSERT(NS_IsMainThread());
if (mPlayState <= PLAY_STATE_LOADING) {
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -373,16 +373,20 @@ private:
virtual bool CanPlayThrough();
void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
// Called from HTMLMediaElement when owner document activity changes
virtual void SetElementVisibility(bool aIsVisible);
+ // Force override the visible state to hidden.
+ // Called from HTMLMediaElement when testing of video decode suspend from mochitests.
+ void SetForcedHidden(bool aForcedHidden);
+
/******
* The following methods must only be called on the main
* thread.
******/
// Change to a new play state. This updates the mState variable and
// notifies any thread blocking on this object's monitor of the
// change. Call on the main thread only.
@@ -698,16 +702,22 @@ protected:
// True if we've already fired metadataloaded.
bool mFiredMetadataLoaded;
// Stores media info, including info of audio tracks and video tracks, should
// only be accessed from main thread.
nsAutoPtr<MediaInfo> mInfo;
+ // Tracks the visiblity status from HTMLMediaElement
+ bool mElementVisible;
+
+ // If true, forces the decoder to be considered hidden.
+ bool mForcedHidden;
+
// True if MediaDecoder is in dormant state.
bool mIsDormant;
// True if heuristic dormant is supported.
const bool mIsHeuristicDormantSupported;
// Timeout ms of heuristic dormant timer.
const int mHeuristicDormantTimeout;