Bug 1346116 part 2 - consider a video is in-tree or not in the suspend-video-decoding policy; r?jwwang
We never suspend videos that is NOT in-tree because we found that, according to the Telemetry data, most (>70%) videos
which are used as the argument of drawImage() are not in-tree. So, by preventing suspending not-in-tree videos, we should
be able to alleviate the pain of not able to resume video decoders synchronously.
MozReview-Commit-ID: 8eqs0pHZLIt
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -7399,17 +7399,18 @@ HTMLMediaElement::GetEMEInfo(nsString& a
aEMEInfo.Append(sessionsInfo);
}
void
HTMLMediaElement::NotifyDecoderActivityChanges() const
{
if (mDecoder) {
mDecoder->NotifyOwnerActivityChanged(!IsHidden(),
- mVisibilityState == Visibility::APPROXIMATELY_VISIBLE);
+ mVisibilityState == Visibility::APPROXIMATELY_VISIBLE,
+ IsInUncomposedDoc());
}
}
bool HasDebuggerPrivilege(JSContext* aCx, JSObject* aObj)
{
return nsContentUtils::CallerHasPermission(aCx,
NS_LITERAL_STRING("debugger"));
}
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -293,21 +293,22 @@ MediaDecoder::ResourceCallback::NotifyBy
self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
}
});
mAbstractMainThread->Dispatch(r.forget());
}
void
MediaDecoder::NotifyOwnerActivityChanged(bool aIsDocumentVisible,
- bool aIsElementVisible)
+ bool aIsElementVisible,
+ bool aIsElementInTree)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
- SetElementVisibility(aIsDocumentVisible, aIsElementVisible);
+ SetElementVisibility(aIsDocumentVisible, aIsElementVisible, aIsElementInTree);
NotifyCompositor();
}
void
MediaDecoder::Pause()
{
MOZ_ASSERT(NS_IsMainThread());
@@ -392,16 +393,17 @@ MediaDecoder::MediaDecoder(MediaDecoderO
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
, mPlaybackStatistics(new MediaChannelStatistics())
, mPinnedForSeek(false)
, mMinimizePreroll(false)
, mMediaTracksConstructed(false)
, mFiredMetadataLoaded(false)
, mIsDocumentVisible(false)
, mIsElementVisible(false)
+ , mIsElementInTree(false)
, mForcedHidden(false)
, mHasSuspendTaint(false)
, INIT_MIRROR(mStateMachineIsShutdown, true)
, INIT_MIRROR(mBuffered, TimeIntervals())
, INIT_MIRROR(mNextFrameStatus, MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE)
, INIT_MIRROR(mCurrentPosition, 0)
, INIT_MIRROR(mStateMachineDuration, NullableTimeUnit())
, INIT_MIRROR(mPlaybackPosition, 0)
@@ -1303,21 +1305,23 @@ MediaDecoder::NotifyCompositor()
if (layerManager) {
RefPtr<KnowsCompositor> knowsCompositor = layerManager->AsShadowForwarder();
mCompositorUpdatedEvent.Notify(knowsCompositor);
}
}
void
MediaDecoder::SetElementVisibility(bool aIsDocumentVisible,
- bool aIsElementVisible)
+ bool aIsElementVisible,
+ bool aIsElementInTree)
{
MOZ_ASSERT(NS_IsMainThread());
mIsDocumentVisible = aIsDocumentVisible;
mIsElementVisible = aIsElementVisible;
+ mIsElementInTree = aIsElementInTree;
UpdateVideoDecodeMode();
}
void
MediaDecoder::SetForcedHidden(bool aForcedHidden)
{
MOZ_ASSERT(NS_IsMainThread());
mForcedHidden = aForcedHidden;
@@ -1341,16 +1345,22 @@ MediaDecoder::UpdateVideoDecodeMode()
}
// If mHasSuspendTaint is set, never suspend the video decoder.
if (mHasSuspendTaint) {
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
return;
}
+ // Don't suspend elements that is not in tree.
+ if (!mIsElementInTree) {
+ mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
+ return;
+ }
+
// If mForcedHidden is set, suspend the video decoder anyway.
if (mForcedHidden) {
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Suspend);
return;
}
// Otherwise, depends on the owner's visibility state.
// A element is visible only if its document is visible and the element
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -185,17 +185,18 @@ public:
nsresult InitializeStateMachine();
// Start playback of a video. 'Load' must have previously been
// called.
virtual nsresult Play();
// Notify activity of the decoder owner is changed.
virtual void NotifyOwnerActivityChanged(bool aIsDocumentVisible,
- bool aIsElementVisible);
+ bool aIsElementVisible,
+ bool aIsElementInTree);
// Pause video playback.
virtual void Pause();
// Adjust the speed of the playback, optionally with pitch correction,
virtual void SetVolume(double aVolume);
virtual void SetPlaybackRate(double aPlaybackRate);
void SetPreservesPitch(bool aPreservesPitch);
@@ -368,17 +369,18 @@ private:
// to buffer, given the current download and playback rates.
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 aIsDocumentVisible,
- bool aIsElementVisible);
+ bool aIsElementVisible,
+ bool aIsElementInTree);
// Force override the visible state to hidden.
// Called from HTMLMediaElement when testing of video decode suspend from mochitests.
void SetForcedHidden(bool aForcedHidden);
// Mark the decoder as tainted, meaning suspend-video-decoder is disabled.
void SetSuspendTaint(bool aTaint);
@@ -716,19 +718,22 @@ protected:
// Stores media info, including info of audio tracks and video tracks, should
// only be accessed from main thread.
nsAutoPtr<MediaInfo> mInfo;
// Tracks the visibility status of owner element's document.
bool mIsDocumentVisible;
- // Tracks the visibliity status of owner element.
+ // Tracks the visibility status of owner element.
bool mIsElementVisible;
+ // Tracks the owner is in-tree or not.
+ bool mIsElementInTree;
+
// If true, forces the decoder to be considered hidden.
bool mForcedHidden;
// True if the decoder has a suspend taint - meaning suspend-video-decoder is
// disabled.
bool mHasSuspendTaint;
// A listener to receive metadata updates from MDSM.