Skip to content
Permalink
Browse files
[GPU Process] MSE videos are unable to AirPlay
https://bugs.webkit.org/show_bug.cgi?id=222956
rdar://72798835

When a user picks an device from the AirPlay menu, WebKit fires a
'webkitcurrentplaybacktargetiswirelesschanged' event at the <video> element and
sets `video.webkitCurrentPlaybackTargetIsWireless` to true so script in the page
is aware that the user wants to use AirPlay. AirPlay requires a <video> element to
be backed by a url that an AppleTV can load and play, so this is also a signal for
a page's script to change the <video> source if it is currently backed by a source
that is incompatible with AirPlay, e.g. MSE, MediaStream, data:. If the current media engine
does not support AirPlay (`m_player->canPlayToWirelessPlaybackTarget()` returns false)
by the next runloop, HTMLMediaElement fires `webkitcurrentplaybacktargetiswirelesschanged`
again and sets `video.webkitCurrentPlaybackTargetIsWireless` to false to signal
that AirPlay is not active.

When media is played in the GPU Process, one turn of the runloop isn't long enough
for the new media engine to be set up, configured, and have the new state pushed
back to the web process, so HTMLMediaElement will now wait for up to 500ms for
`m_player->canPlayToWirelessPlaybackTarget()` to return true.

Reviewed by Jer Noble.

Tested manually, this requires and AppleTV to test.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::checkPlaybackTargetCompatablity):
(WebCore::HTMLMediaElement::setIsPlayingToWirelessTarget):
* html/HTMLMediaElement.h:


Canonical link: https://commits.webkit.org/235096@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@274175 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
eric-carlson committed Mar 9, 2021
1 parent 83ae5d0 commit eda1af80e3a78c28d78b20b9cbcfbcf91f7d9e57
Showing 3 changed files with 44 additions and 8 deletions.
@@ -1,3 +1,35 @@
2021-03-09 Eric Carlson <eric.carlson@apple.com>

[GPU Process] MSE videos are unable to AirPlay
https://bugs.webkit.org/show_bug.cgi?id=222956
rdar://72798835

When a user picks an device from the AirPlay menu, WebKit fires a
'webkitcurrentplaybacktargetiswirelesschanged' event at the <video> element and
sets `video.webkitCurrentPlaybackTargetIsWireless` to true so script in the page
is aware that the user wants to use AirPlay. AirPlay requires a <video> element to
be backed by a url that an AppleTV can load and play, so this is also a signal for
a page's script to change the <video> source if it is currently backed by a source
that is incompatible with AirPlay, e.g. MSE, MediaStream, data:. If the current media engine
does not support AirPlay (`m_player->canPlayToWirelessPlaybackTarget()` returns false)
by the next runloop, HTMLMediaElement fires `webkitcurrentplaybacktargetiswirelesschanged`
again and sets `video.webkitCurrentPlaybackTargetIsWireless` to false to signal
that AirPlay is not active.

When media is played in the GPU Process, one turn of the runloop isn't long enough
for the new media engine to be set up, configured, and have the new state pushed
back to the web process, so HTMLMediaElement will now wait for up to 500ms for
`m_player->canPlayToWirelessPlaybackTarget()` to return true.

Reviewed by Jer Noble.

Tested manually, this requires and AppleTV to test.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::checkPlaybackTargetCompatablity):
(WebCore::HTMLMediaElement::setIsPlayingToWirelessTarget):
* html/HTMLMediaElement.h:

2021-03-09 Manuel Rego Casasnovas <rego@igalia.com>

[selectors] Move :focus-viisble & :focus-within flags from Node to UserActionElementSet
@@ -966,11 +966,8 @@ void HTMLMediaElement::scheduleCheckPlaybackTargetCompatability()
if (m_checkPlaybackTargetCompatablityTask.hasPendingTask())
return;

auto logSiteIdentifier = LOGIDENTIFIER;
ALWAYS_LOG(logSiteIdentifier, "task scheduled");
m_checkPlaybackTargetCompatablityTask.scheduleTask([this, logSiteIdentifier] {
UNUSED_PARAM(logSiteIdentifier);
ALWAYS_LOG(logSiteIdentifier, "lambda(), task fired");
ALWAYS_LOG(LOGIDENTIFIER);
m_checkPlaybackTargetCompatablityTask.scheduleTask([this] {
checkPlaybackTargetCompatablity();
});
}
@@ -979,7 +976,14 @@ void HTMLMediaElement::checkPlaybackTargetCompatablity()
{
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
if (m_isPlayingToWirelessTarget && !m_player->canPlayToWirelessPlaybackTarget()) {
ALWAYS_LOG(LOGIDENTIFIER, "calling setShouldPlayToPlaybackTarget(false)");
static const Seconds maxIntervalForWirelessPlaybackPlayerUpdate { 500_ms };
Seconds delta = MonotonicTime::now() - m_currentPlaybackTargetIsWirelessEventFiredTime;
if (delta < maxIntervalForWirelessPlaybackPlayerUpdate) {
scheduleCheckPlaybackTargetCompatability();
return;
}

ERROR_LOG(LOGIDENTIFIER, "player incompatible after ", delta.value(), ", calling setShouldPlayToPlaybackTarget(false)");
m_failedToPlayToWirelessTarget = true;
m_player->setShouldPlayToPlaybackTarget(false);
}
@@ -5750,10 +5754,8 @@ void HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(bool is
void HTMLMediaElement::setIsPlayingToWirelessTarget(bool isPlayingToWirelessTarget)
{
auto logSiteIdentifier = LOGIDENTIFIER;
ALWAYS_LOG(logSiteIdentifier, isPlayingToWirelessTarget);
m_playbackTargetIsWirelessQueue.enqueueTask([this, isPlayingToWirelessTarget, logSiteIdentifier] {
UNUSED_PARAM(logSiteIdentifier);
ALWAYS_LOG(logSiteIdentifier, "lambda(), task fired");

if (isPlayingToWirelessTarget == m_isPlayingToWirelessTarget)
return;
@@ -5768,6 +5770,7 @@ void HTMLMediaElement::setIsPlayingToWirelessTarget(bool isPlayingToWirelessTarg
updateSleepDisabling();

m_failedToPlayToWirelessTarget = false;
m_currentPlaybackTargetIsWirelessEventFiredTime = MonotonicTime::now();
scheduleCheckPlaybackTargetCompatability();

if (!isContextStopped())
@@ -1173,6 +1173,7 @@ class HTMLMediaElement

#if ENABLE(WIRELESS_PLAYBACK_TARGET)
MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying };
MonotonicTime m_currentPlaybackTargetIsWirelessEventFiredTime;
bool m_hasPlaybackTargetAvailabilityListeners { false };
bool m_failedToPlayToWirelessTarget { false };
#endif

0 comments on commit eda1af8

Please sign in to comment.