(Draft) Backport fixes for player suspend#1682
Open
vivienne-w wants to merge 4 commits into
Open
Conversation
c44060e to
b6c49e1
Compare
…ertion crash https://bugs.webkit.org/show_bug.cgi?id=285850 Reviewed by Philippe Normand. WebKit pauses muted videos when scrolling to save resources. However, when running in Debug, an assertion was failing inside MediaPlayerPrivateGStreamer::paused() in the GStreamer ports: > ASSERTION FAILED: pipeline and player states are not synchronized After some debugging, I found two problems that were causing the assertion to fail: (1) MediaPlayerPrivateGStreamerMSE::updateStates() didn't account for this behavior, which could trigger unexpected state changes. The patch adds it to the `shouldBePlaying` check. (2) The assertion checks m_isPipelinePlaying against the actual state of the pipeline. However, the code setting the pipeline to PAUSED when scrolling away (see setVisibleInViewport()) didn't update this field. Normally you use setPipelineState() instead which updates this field. As drive-by fixes this patch also adds new logs and renames two fields to have more useful names. * m_isVisibleInViewport is negated and renamed m_isPausedByViewport, reflecting its actual meaning (`m_isVisibleInViewport` was often true while the HTMLMediaElement was not visible in the viewport. * m_isVisible is renamed to m_pageIsVisible to both match other code and to reflect its actual meaning. This patch adds back media-source-muted-scroll-and-seek-crash.html from 276798@main, which can be used to test the crash does not happen. Note however the same caveat from back then applies: > Currently, part of the code to trigger the crash isn't executed > due to WEBKIT_GST_ALLOW_PLAYBACK_OF_INVISIBLE_VIDEOS=1 being set in the test driver in > Tools/Scripts/webkitpy/port/glib.py (264017@main), which needs to be commented manually. > We should find a way to add a test preference for this code path to be enabled. * LayoutTests/media/media-source/media-source-muted-scroll-and-seek-crash.html: Added. * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::paused const): (WebCore::MediaPlayerPrivateGStreamer::changePipelineState): (WebCore::MediaPlayerPrivateGStreamer::setVisibleInViewport): (WebCore::MediaPlayerPrivateGStreamer::paint): * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: * Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: (WebCore::MediaPlayerPrivateGStreamerMSE::updateStates): Canonical link: https://commits.webkit.org/288906@main
…ewport https://bugs.webkit.org/show_bug.cgi?id=287162 Reviewed by Philippe Normand. This is a follow-up of the cleanups discussed in WebKit/WebKit#39765. This patch combines m_isPausedByViewport and m_invisiblePlayerState into one single field and renames it to m_stateToRestoreWhenVisible. The field is set to VOID_PENDING when we're not paused by viewport. Additionally, safeguards have been added to setVisibleInViewport() to prevent the suspension code from accidentally running more than once. * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::changePipelineState): (WebCore::MediaPlayerPrivateGStreamer::setVisibleInViewport): (WebCore::MediaPlayerPrivateGStreamer::paint): * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: (WebCore::MediaPlayerPrivateGStreamer::isPausedByViewport): * Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: (WebCore::MediaPlayerPrivateGStreamerMSE::updateStates): Canonical link: https://commits.webkit.org/289997@main
https://bugs.webkit.org/show_bug.cgi?id=315755 Reviewed by NOBODY (OOPS!). When the player is both muted and invisible, we try to suspend it (by just pausing the playback pipeline), to save on resources. However so far this is happens quite inconsistently, with multiple issues: First, suspends are tied too much to visibility changes - (un)muting can't suspend/resume, so this refactors them out into `managePlayerSuspend()`, and also renames the relevant variables/methods to reflect that they're about suspends, not player visibility. Second, we are currently not able to suspend the player if it's already muted and hidden at creation: Either we ignore it because we don't have a pipeline yet, or because it's in NULL. In this scenario, we would also not yet have a target state to resume to, until e.g. a play() request later on, so we need reintroduce a separate boolean flag (m_isSuspended) to make sure we know to delay that state change until we resume. Finally, `m_isMuted` is currently updated inconsistently, and in some scenarios only from a notify::mute callback. This presents a race condition, if we try to suspend after muting the player, but read m_isMuted before the callback updates it. To avoid this, `isMuted()` now directly checks with the pipeline so we have a single source of truth. Only `notifyPlayerOfMute()` still uses the flag to avoid sending redundant notifications. * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::play): (WebCore::MediaPlayerPrivateGStreamer::changePipelineState): Clear saved state if a change < PLAYING is requested; so a sequence like (suspend -> play() -> pause() -> unsuspend) doesn't end up in the wrong state. (WebCore::MediaPlayerPrivateGStreamer::isMuted const): (WebCore::MediaPlayerPrivateGStreamer::setMuted): Also check here if we need to suspend. (WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin): After creating the pipeline, also check here if we need to suspend. (WebCore::MediaPlayerPrivateGStreamer::setViewportVisibility): (WebCore::MediaPlayerPrivateGStreamer::managePlayerSuspend): Added. Handles suspending/resuming the pipeline when needed. (WebCore::MediaPlayerPrivateGStreamer::paint): * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: (WebCore::MediaPlayerPrivateGStreamer::isSuspended const): (WebCore::MediaPlayerPrivateGStreamer::isPausedByViewport const): Deleted. * Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: (WebCore::MediaPlayerPrivateGStreamerMSE::updateStates): Go forward with the state change even when suspended; changePipelineState() needs to save the new target state
b6c49e1 to
6fb77b7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This backports my fixes for player suspends, plus a prerequisite patch we dont yet have in 2.46
6fb77b7