Bug 1685399 - part3 : use actual invisible state to determine if we should suspend decoding. r=padenot

There is no need for decoder to use both "document visibility" and "element's layout visibility" to determine if we should suspend decoding.

That can simply be done by checking `HTMLMediaElement::IsActuallyInvisible()`.

Differential Revision: https://phabricator.services.mozilla.com/D101108
This commit is contained in:
alwu
2021-01-14 19:54:42 +00:00
parent 2cbc778a00
commit 23c6726a98
3 changed files with 25 additions and 52 deletions

View File

@@ -7506,7 +7506,7 @@ void HTMLMediaElement::GetEMEInfo(dom::EMEDebugInfo& aInfo) {
void HTMLMediaElement::NotifyDecoderActivityChanges() const { void HTMLMediaElement::NotifyDecoderActivityChanges() const {
if (mDecoder) { if (mDecoder) {
mDecoder->NotifyOwnerActivityChanged(!IsHidden(), mVisibilityState, mDecoder->NotifyOwnerActivityChanged(IsActuallyInvisible(),
IsInComposedDoc()); IsInComposedDoc());
} }
} }

View File

@@ -26,7 +26,6 @@
#include "mozilla/StaticPrefs_media.h" #include "mozilla/StaticPrefs_media.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "Visibility.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
@@ -198,13 +197,11 @@ void MediaDecoder::InitStatics() {
NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter) NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
void MediaDecoder::NotifyOwnerActivityChanged(bool aIsDocumentVisible, void MediaDecoder::NotifyOwnerActivityChanged(bool aIsOwnerInvisible,
Visibility aElementVisibility, bool aIsOwnerConnected) {
bool aIsElementInTree) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown()); MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
SetElementVisibility(aIsDocumentVisible, aElementVisibility, SetElementVisibility(aIsOwnerInvisible, aIsOwnerConnected);
aIsElementInTree);
NotifyCompositor(); NotifyCompositor();
} }
@@ -294,9 +291,8 @@ MediaDecoder::MediaDecoder(MediaDecoderInit& aInit)
mVideoFrameContainer(aInit.mOwner->GetVideoFrameContainer()), mVideoFrameContainer(aInit.mOwner->GetVideoFrameContainer()),
mMinimizePreroll(aInit.mMinimizePreroll), mMinimizePreroll(aInit.mMinimizePreroll),
mFiredMetadataLoaded(false), mFiredMetadataLoaded(false),
mIsDocumentVisible(false), mIsOwnerInvisible(false),
mElementVisibility(Visibility::Untracked), mIsOwnerConnected(false),
mIsElementInTree(false),
mForcedHidden(false), mForcedHidden(false),
mHasSuspendTaint(aInit.mHasSuspendTaint), mHasSuspendTaint(aInit.mHasSuspendTaint),
mPlaybackRate(aInit.mPlaybackRate), mPlaybackRate(aInit.mPlaybackRate),
@@ -963,13 +959,11 @@ void MediaDecoder::NotifyCompositor() {
} }
} }
void MediaDecoder::SetElementVisibility(bool aIsDocumentVisible, void MediaDecoder::SetElementVisibility(bool aIsOwnerInvisible,
Visibility aElementVisibility, bool aIsOwnerConnected) {
bool aIsElementInTree) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
mIsDocumentVisible = aIsDocumentVisible; mIsOwnerInvisible = aIsOwnerInvisible;
mElementVisibility = aElementVisibility; mIsOwnerConnected = aIsOwnerConnected;
mIsElementInTree = aIsElementInTree;
UpdateVideoDecodeMode(); UpdateVideoDecodeMode();
} }
@@ -1018,8 +1012,8 @@ void MediaDecoder::UpdateVideoDecodeMode() {
return; return;
} }
// Don't suspend elements that is not in tree. // Don't suspend elements that is not in a connected tree.
if (!mIsElementInTree) { if (!mIsOwnerConnected) {
LOG("UpdateVideoDecodeMode(), set Normal because the element is not in " LOG("UpdateVideoDecodeMode(), set Normal because the element is not in "
"tree."); "tree.");
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal); mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
@@ -1042,27 +1036,12 @@ void MediaDecoder::UpdateVideoDecodeMode() {
return; return;
} }
// If the element is in-tree with UNTRACKED visibility, that means the element if (mIsOwnerInvisible) {
// is not close enough to the viewport so we have not start to update its LOG("UpdateVideoDecodeMode(), set Suspend because of invisible element.");
// visibility. In this case, it's equals to invisible.
if (mIsElementInTree && mElementVisibility == Visibility::Untracked) {
LOG("UpdateVideoDecodeMode(), set Suspend because element hasn't be "
"updated visibility state.");
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Suspend); 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
// itself is visible.
if (mIsDocumentVisible &&
mElementVisibility == Visibility::ApproximatelyVisible) {
LOG("UpdateVideoDecodeMode(), set Normal because the element visible.");
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
} else { } else {
LOG("UpdateVideoDecodeMode(), set Suspend because the element is not " LOG("UpdateVideoDecodeMode(), set Normal because of visible element.");
"visible."); mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Suspend);
} }
} }

View File

@@ -50,8 +50,6 @@ class MediaDecoderStateMachine;
struct MediaPlaybackEvent; struct MediaPlaybackEvent;
struct SharedDummyTrack; struct SharedDummyTrack;
enum class Visibility : uint8_t;
struct MOZ_STACK_CLASS MediaDecoderInit { struct MOZ_STACK_CLASS MediaDecoderInit {
MediaDecoderOwner* const mOwner; MediaDecoderOwner* const mOwner;
const double mVolume; const double mVolume;
@@ -141,9 +139,8 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
virtual void Play(); virtual void Play();
// Notify activity of the decoder owner is changed. // Notify activity of the decoder owner is changed.
virtual void NotifyOwnerActivityChanged(bool aIsDocumentVisible, virtual void NotifyOwnerActivityChanged(bool aIsOwnerInvisible,
Visibility aElementVisibility, bool aIsOwnerConnected);
bool aIsElementInTree);
// Pause video playback. // Pause video playback.
virtual void Pause(); virtual void Pause();
@@ -307,9 +304,8 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
bool CanPlayThrough(); bool CanPlayThrough();
// Called from HTMLMediaElement when owner document activity changes // Called from HTMLMediaElement when owner document activity changes
virtual void SetElementVisibility(bool aIsDocumentVisible, virtual void SetElementVisibility(bool aIsOwnerInvisible,
Visibility aElementVisibility, bool aIsOwnerConnected);
bool aIsElementInTree);
// Force override the visible state to hidden. // Force override the visible state to hidden.
// Called from HTMLMediaElement when testing of video decode suspend from // Called from HTMLMediaElement when testing of video decode suspend from
@@ -569,14 +565,12 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
// only be accessed from main thread. // only be accessed from main thread.
UniquePtr<MediaInfo> mInfo; UniquePtr<MediaInfo> mInfo;
// Tracks the visibility status of owner element's document. // True if the owner element is actually visible to users.
bool mIsDocumentVisible; bool mIsOwnerInvisible;
// Tracks the visibility status of owner element. // True if the owner element is connected to a document tree.
Visibility mElementVisibility; // https://dom.spec.whatwg.org/#connected
bool mIsOwnerConnected;
// Tracks the owner is in-tree or not.
bool mIsElementInTree;
// If true, forces the decoder to be considered hidden. // If true, forces the decoder to be considered hidden.
bool mForcedHidden; bool mForcedHidden;