Bug 208252 - [Media in GPU process] Implement the video fullscreen and Picture-in-Picture support
Summary: [Media in GPU process] Implement the video fullscreen and Picture-in-Picture ...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: WebKit Nightly Build
Hardware: iPhone / iPad Unspecified
: P2 Normal
Assignee: Peng Liu
URL:
Keywords: InRadar
Depends on:
Blocks: 205123
  Show dependency treegraph
 
Reported: 2020-02-26 11:20 PST by Peng Liu
Modified: 2020-02-29 00:27 PST (History)
13 users (show)

See Also:


Attachments
WIP Patch (31.39 KB, patch)
2020-02-26 12:06 PST, Peng Liu
no flags Details | Formatted Diff | Diff
WIP patch - rebased (31.41 KB, patch)
2020-02-26 15:26 PST, Peng Liu
no flags Details | Formatted Diff | Diff
Patch (46.34 KB, patch)
2020-02-28 15:59 PST, Peng Liu
simon.fraser: review+
Details | Formatted Diff | Diff
Patch for landing (47.75 KB, patch)
2020-02-28 17:35 PST, Peng Liu
no flags Details | Formatted Diff | Diff
Patch for landing (fix unified build failures) (48.67 KB, patch)
2020-02-28 20:31 PST, Peng Liu
no flags Details | Formatted Diff | Diff
Patch for landing (48.66 KB, patch)
2020-02-28 21:50 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 2020-02-26 11:20:22 PST
The video fullscreen and Picture-in-Picture on iOS and the Picture-in-Picture on Mac use a container layer (a CALayer created by VideoFullscreenManager) to host the video layer (created by MediaPlayerPrivate) in fullscreen/PiP modes. Both the layers are in the Web process so they can interact directly.

However, after we enable the GPU process to run the MediaPlayerPrivate, the container layer and the video layer cannot interact directly because they are in different processes. We have to add a pair of remote layer and hosting context to connect them.
Comment 1 Radar WebKit Bug Importer 2020-02-26 11:20:54 PST
<rdar://problem/59813445>
Comment 2 Peng Liu 2020-02-26 12:06:11 PST
Created attachment 391766 [details]
WIP Patch
Comment 3 Peng Liu 2020-02-26 15:26:27 PST
Created attachment 391789 [details]
WIP patch - rebased
Comment 4 Eric Carlson 2020-02-27 06:31:32 PST
Comment on attachment 391789 [details]
WIP patch - rebased

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

> Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:1088
> +    return adoptNS([[CALayer alloc] init]);

Nit: rather than duplicating this code in each MPP, you could put it in VideoLayerManagerObjC since all three use it. You also might want to layer name to help when debugging the layer tree.

> Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in:67
> +#if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
> +    EnterFullscreen() -> () Async
> +    ExitFullscreen() -> () Async
> +#endif

Nit: Why make this macOS/iOS only even if it won't work for other ports yet?

> Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp:593
> +    return m_videoFullscreenLayer;

Many <video> and *all* <audio> elements never enter fullscreen, so you should probably create m_videoFullscreenLayer here rather than in prepareForPlayback.

> Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp:604
> +    if (!videoFullscreenLayer) {
> +        connection().sendWithAsyncReply(Messages::RemoteMediaPlayerProxy::ExitFullscreen(), WTFMove(completionHandler), m_id);
> +        return;
> +    }
> +        
> +    ASSERT(videoFullscreenLayer == m_videoFullscreenLayer.get());
> +    connection().sendWithAsyncReply(Messages::RemoteMediaPlayerProxy::EnterFullscreen(), WTFMove(completionHandler), m_id);

It seems a bit strange to have setVideoFullscreenLayer call enterFullscreen and exitFullscreen in the web process, and to have enterFullscreen and exitFullscreen call setVideoFullscreenLayer in the GPU process.

> Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm:276
> +#ifndef NDEBUG

Why only do this in Debug builds?
Comment 5 Peng Liu 2020-02-27 15:24:14 PST
Comment on attachment 391789 [details]
WIP patch - rebased

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

>> Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:1088
>> +    return adoptNS([[CALayer alloc] init]);
> 
> Nit: rather than duplicating this code in each MPP, you could put it in VideoLayerManagerObjC since all three use it. You also might want to layer name to help when debugging the layer tree.

This is a great suggestion. But it will lead to a lot of changes. We had better do that in a refactoring. I filed a bug for it.
https://bugs.webkit.org/show_bug.cgi?id=208342

>> Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in:67
>> +#endif
> 
> Nit: Why make this macOS/iOS only even if it won't work for other ports yet?

Let's enable it for all ports with the media in GPU Process feature support.

>> Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp:593
>> +    return m_videoFullscreenLayer;
> 
> Many <video> and *all* <audio> elements never enter fullscreen, so you should probably create m_videoFullscreenLayer here rather than in prepareForPlayback.

You are right! Let's create m_videoFullscreenLayer in createVideoFullscreenLayer() instead of prepareForPlayback(). An even better fix will delay the creation of m_fullscreenLayerHostingContext and the corresponding CALayer in RemoteMediaPlayerProxy (in the GPU Process) as well. But that will require MediaPlayerPrivateRemote::createVideoFullscreenLayer() to create the layer asynchronously. I plan do that in https://bugs.webkit.org/show_bug.cgi?id=208342.

>> Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp:604
>> +    connection().sendWithAsyncReply(Messages::RemoteMediaPlayerProxy::EnterFullscreen(), WTFMove(completionHandler), m_id);
> 
> It seems a bit strange to have setVideoFullscreenLayer call enterFullscreen and exitFullscreen in the web process, and to have enterFullscreen and exitFullscreen call setVideoFullscreenLayer in the GPU process.

This will be fixed in the refactoring.
https://bugs.webkit.org/show_bug.cgi?id=208342

>> Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm:276
>> +#ifndef NDEBUG
> 
> Why only do this in Debug builds?

Will enable it always.
Comment 6 Peng Liu 2020-02-28 15:59:24 PST
Created attachment 392028 [details]
Patch
Comment 7 Simon Fraser (smfr) 2020-02-28 16:15:36 PST
Comment on attachment 392028 [details]
Patch

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

> Source/WebCore/html/HTMLMediaElement.h:182
> +    RetainPtr<PlatformLayer> createVideoFullscreenLayer();

Should this really create a new one every time?

What is the "video fullscreen layer"? Is it the layer with the video in it, the layer that goes fullscreen, or something else?

> Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp:508
> +    m_inlineLayerHostingContext->setRootLayer(m_player->platformLayer());

LayerHostingContext takes a CALayer*. You should really be in a .mm file if you're calling this code. RemoteMediaPlayerProxy.cpp doesn't sound Cocoa-specific.

> Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:51
> +    [videoFullscreenLayer setName:@"Web video fullscreen manager layer (remote)"];

That's a lot of words.

Why "videoFullscreenLayer" if it's really "videoFullscreenRemoteManagerLayer"?

> Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:52
> +    [videoFullscreenLayer setPosition:CGPointMake(0, 0)];

CGPointZero.

Maybe set the anchor point too because this won't be top-left aligned if it has non-zero size.

> Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:53
> +    [videoFullscreenLayer setBackgroundColor:cachedCGColor(WebCore::Color::transparent)];

This shouldn't be necessary.

> Source/WebKit/WebProcess/GPU/media/cocoa/MediaPlayerPrivateRemoteCocoa.mm:37
> +#if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))

We should have an ENABLE_ or something for this combination. Why doesn't iOS just define ENABLE_VIDEO_PRESENTATION_MODE ?
Comment 8 Peng Liu 2020-02-28 17:22:30 PST
Comment on attachment 392028 [details]
Patch

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

>> Source/WebCore/html/HTMLMediaElement.h:182
>> +    RetainPtr<PlatformLayer> createVideoFullscreenLayer();
> 
> Should this really create a new one every time?
> 
> What is the "video fullscreen layer"? Is it the layer with the video in it, the layer that goes fullscreen, or something else?

When we run MediaPlayerPrivate* in the Web process, yes, a new layer will be created every time. That’s also the behavior before this patch and it will be changed in https://bugs.webkit.org/show_bug.cgi?id=208342.
When we run MediaPlayerPrivate* in the GPU process, no, we will create the layer in the first time when the function is called and reuse it in the future.

The "video fullscreen layer" is a container layer to embed the real video content layer. It is used in both video fullscreen and PiP scenarios.

>> Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp:508
>> +    m_inlineLayerHostingContext->setRootLayer(m_player->platformLayer());
> 
> LayerHostingContext takes a CALayer*. You should really be in a .mm file if you're calling this code. RemoteMediaPlayerProxy.cpp doesn't sound Cocoa-specific.

Right. Let's move it to RemoteMediaPlayerProxyCocoa.mm. The same to other functions related to LayerHostingContext.

>> Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:51
>> +    [videoFullscreenLayer setName:@"Web video fullscreen manager layer (remote)"];
> 
> That's a lot of words.
> 
> Why "videoFullscreenLayer" if it's really "videoFullscreenRemoteManagerLayer"?

Agree.
We use the name "videoFullscreenLayer" in all other places except here (setName). I will change the name here as well as the name in VideoFullscreenManager.

>> Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:52
>> +    [videoFullscreenLayer setPosition:CGPointMake(0, 0)];
> 
> CGPointZero.
> 
> Maybe set the anchor point too because this won't be top-left aligned if it has non-zero size.

Fixed.
Will try to set the anchor point later because we may need to change the anchor point of the corresponding layer in the web process as well.

>> Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:53
>> +    [videoFullscreenLayer setBackgroundColor:cachedCGColor(WebCore::Color::transparent)];
> 
> This shouldn't be necessary.

Removed.

>> Source/WebKit/WebProcess/GPU/media/cocoa/MediaPlayerPrivateRemoteCocoa.mm:37
>> +#if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
> 
> We should have an ENABLE_ or something for this combination. Why doesn't iOS just define ENABLE_VIDEO_PRESENTATION_MODE ?

Good question! But I would like to keep it in the current way. Maybe fix it in another patch later.
Comment 9 Peng Liu 2020-02-28 17:35:18 PST
Created attachment 392039 [details]
Patch for landing
Comment 10 Peng Liu 2020-02-28 20:31:07 PST
Created attachment 392045 [details]
Patch for landing (fix unified build failures)
Comment 11 WebKit Commit Bot 2020-02-28 21:45:45 PST
Comment on attachment 392045 [details]
Patch for landing (fix unified build failures)

Rejecting attachment 392045 [details] from commit-queue.

Failed to run "['/Volumes/Data/EWS/WebKit/Tools/Scripts/webkit-patch', '--status-host=webkit-queues.webkit.org', '--bot-id=webkit-cq-03', 'validate-changelog', '--check-oops', '--non-interactive', 392045, '--port=mac']" exit_code: 1 cwd: /Volumes/Data/EWS/WebKit

ChangeLog entry in Source/WebCore/ChangeLog contains OOPS!.

Full output: https://webkit-queues.webkit.org/results/13330939
Comment 12 Peng Liu 2020-02-28 21:50:18 PST
Created attachment 392047 [details]
Patch for landing
Comment 13 WebKit Commit Bot 2020-02-28 23:21:54 PST
Comment on attachment 392047 [details]
Patch for landing

Clearing flags on attachment: 392047

Committed r257680: <https://trac.webkit.org/changeset/257680>