Bug 220660 - PiP video subtitles stop updating when Safari is backgrounded
Summary: PiP video subtitles stop updating when Safari is backgrounded
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Peng Liu
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-01-15 09:58 PST by Peng Liu
Modified: 2021-01-21 22:11 PST (History)
15 users (show)

See Also:


Attachments
Patch (5.09 KB, patch)
2021-01-15 10:17 PST, Peng Liu
no flags Details | Formatted Diff | Diff
Only prevent suspending rendering when a video with visible text tracks is in PiP (11.81 KB, patch)
2021-01-15 16:18 PST, Peng Liu
no flags Details | Formatted Diff | Diff
Only unfreeze the layer tree when we need to update text track representation (15.10 KB, patch)
2021-01-19 17:44 PST, Peng Liu
no flags Details | Formatted Diff | Diff
Patch (7.38 KB, patch)
2021-01-20 20:17 PST, Peng Liu
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (7.42 KB, patch)
2021-01-20 20:24 PST, Peng Liu
darin: review+
Details | Formatted Diff | Diff
Patch for landing (7.45 KB, patch)
2021-01-21 20:02 PST, Peng Liu
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Peng Liu 2021-01-15 09:58:34 PST
PiP video subtitles stop updating when Safari is backgrounded
Comment 1 Peng Liu 2021-01-15 09:59:16 PST
<rdar://problem/70864713>
Comment 2 Peng Liu 2021-01-15 10:17:28 PST
Created attachment 417714 [details]
Patch
Comment 3 Darin Adler 2021-01-15 16:05:01 PST
Comment on attachment 417714 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=417714&action=review

> Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:219
> +    return m_isRenderingSuspended && !m_webPage.videoFullscreenManager().hasVideo();

This code is a little bit mysterious, not obvious. Hard to understand this is about PIP and why it’s correct. There’s not even a why comment!

And worse, we have no regression test for this, so someone could break it and commit the change without ever knowing it.

That’s bad combination: seems like we may be unable to keep this working and might make the same kind of mistake again in the future.
Comment 4 Peng Liu 2021-01-15 16:18:55 PST
Created attachment 417746 [details]
Only prevent suspending rendering when a video with visible text tracks is in PiP
Comment 5 Peng Liu 2021-01-15 16:29:37 PST
Comment on attachment 417714 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=417714&action=review

>> Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:219
>> +    return m_isRenderingSuspended && !m_webPage.videoFullscreenManager().hasVideo();
> 
> This code is a little bit mysterious, not obvious. Hard to understand this is about PIP and why it’s correct. There’s not even a why comment!
> 
> And worse, we have no regression test for this, so someone could break it and commit the change without ever knowing it.
> 
> That’s bad combination: seems like we may be unable to keep this working and might make the same kind of mistake again in the future.

Sorry, I forgot to remove the "r?" flag when we are discussing the patch on slack. :-(

Agree! A regression test is needed. But the issue happens when the browser is in the background and a video with text tracks is playing in picture-in-picture. We are not able to test it on iOS before fixing bug 203724.
Comment 6 Peng Liu 2021-01-19 17:44:37 PST
Created attachment 417933 [details]
Only unfreeze the layer tree when we need to update text track representation
Comment 7 Peng Liu 2021-01-20 20:17:06 PST
Created attachment 418017 [details]
Patch
Comment 8 Peng Liu 2021-01-20 20:24:33 PST
Created attachment 418018 [details]
Patch
Comment 9 Eric Carlson 2021-01-21 11:19:13 PST
Comment on attachment 418018 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=418018&action=review

> Source/WebKit/WebProcess/WebPage/WebPage.cpp:2650
> +    if (m_layerTreeFreezeReasons.hasExactlyOneBitSet() && m_layerTreeFreezeReasons.contains(LayerTreeFreezeReason::BackgroundApplication) && m_videoFullscreenManager && m_videoFullscreenManager->videoInPictureInPicture()) {

Nit: `m_videoFullscreenManager` will be NULL most of the time, so you might want to check it first to short circuit the rest of the tests.
Comment 10 Peng Liu 2021-01-21 11:59:23 PST
Comment on attachment 418018 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=418018&action=review

>> Source/WebKit/WebProcess/WebPage/WebPage.cpp:2650
>> +    if (m_layerTreeFreezeReasons.hasExactlyOneBitSet() && m_layerTreeFreezeReasons.contains(LayerTreeFreezeReason::BackgroundApplication) && m_videoFullscreenManager && m_videoFullscreenManager->videoInPictureInPicture()) {
> 
> Nit: `m_videoFullscreenManager` will be NULL most of the time, so you might want to check it first to short circuit the rest of the tests.

Good point! Thanks!
Comment 11 Darin Adler 2021-01-21 15:42:23 PST
Comment on attachment 418018 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=418018&action=review

> Source/WebKit/ChangeLog:11
> +        Subtitles in the picture-in-picture window will stop updating when the browser is
> +        in the background because we freeze the layer tree when a browser is in the background.
> +        This patch fixes this issue by avoiding freezing the layer tree if a video is playing
> +        in picture-in-picture when the browser is in the background.

Can we construct a regression test?

> Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h:121
> +    bool videoInPictureInPicture() const;

This sounds like a function that would return a "video", not a function that would return a boolean answer to a question.

Given the comment you wrote above, it seems that this function’s name should be hasVideoPlayingInPictureInPicture().

> Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm:274
> +    if (mode == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
> +        m_videoElementInPictureInPicture = makeWeakPtr(videoElement);

Seems like an omission that if the mode is something else, we don’t null out m_videoElementInPictureInPicture. Do we have an iron clad guarantee it will be null in that case? Could we maybe just set to null? Or is there some chance that we can have a PiP lingering while we start some other full-screen, perhaps on a different element?
Comment 12 Peng Liu 2021-01-21 20:00:09 PST
Comment on attachment 418018 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=418018&action=review

>> Source/WebKit/ChangeLog:11
>> +        in picture-in-picture when the browser is in the background.
> 
> Can we construct a regression test?

I have to manually test this patch because we cannot automatically test picture-in-picture features on iOS now.
We plan to add regression tests for video fullscreen and picture-in-picture with the XCTest framework in WebKit.

>>> Source/WebKit/WebProcess/WebPage/WebPage.cpp:2650
>>> +    if (m_layerTreeFreezeReasons.hasExactlyOneBitSet() && m_layerTreeFreezeReasons.contains(LayerTreeFreezeReason::BackgroundApplication) && m_videoFullscreenManager && m_videoFullscreenManager->videoInPictureInPicture()) {
>> 
>> Nit: `m_videoFullscreenManager` will be NULL most of the time, so you might want to check it first to short circuit the rest of the tests.
> 
> Good point! Thanks!

Fixed.

>> Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h:121
>> +    bool videoInPictureInPicture() const;
> 
> This sounds like a function that would return a "video", not a function that would return a boolean answer to a question.
> 
> Given the comment you wrote above, it seems that this function’s name should be hasVideoPlayingInPictureInPicture().

Agree! Fixed.

>> Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm:274
>> +        m_videoElementInPictureInPicture = makeWeakPtr(videoElement);
> 
> Seems like an omission that if the mode is something else, we don’t null out m_videoElementInPictureInPicture. Do we have an iron clad guarantee it will be null in that case? Could we maybe just set to null? Or is there some chance that we can have a PiP lingering while we start some other full-screen, perhaps on a different element?

The behavior is intended.

More than one video elements can be in fullscreen (sounds strange though), but only one video can be in picture-in-picture. And it is possible that one video is in picture-in-picture while another video is in fullscreen.

When a video is in picture-in-picture and another video tries to enter picture-in-picture, the current video in picture-in-picture will exit picture-in-picture while the new video enters picture-in-picture.

This patch works in those cases.
Comment 13 Peng Liu 2021-01-21 20:02:53 PST
Created attachment 418105 [details]
Patch for landing
Comment 14 EWS 2021-01-21 22:11:27 PST
Committed r271737: <https://trac.webkit.org/changeset/271737>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 418105 [details].