Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 2b092c252762a5a9a301b99d25b300b450cc28c5
https://github.com/WebKit/WebKit/commit/2b092c252762a5a9a301b99d25b300b450cc28c5
Author: Jean-Yves Avenard <[email protected]>
Date: 2026-05-15 (Fri, 15 May 2026)
Changed paths:
M Source/WebCore/platform/graphics/avfoundation/AudioVideoRendererAVFObjC.mm
M Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.h
M Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.mm
M Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.cpp
M Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.h
M
Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.messages.in
M Source/WebKit/WebProcess/GPU/media/AudioVideoRendererRemote.cpp
M Source/WebKit/WebProcess/GPU/media/AudioVideoRendererRemote.h
M
Source/WebKit/WebProcess/GPU/media/AudioVideoRendererRemoteMessageReceiver.messages.in
M Source/WebKit/WebProcess/GPU/media/RemoteAudioVideoRendererState.h
M
Source/WebKit/WebProcess/GPU/media/RemoteAudioVideoRendererState.serialization.in
Log Message:
-----------
Reduce power cost of VideoPlaybackQualityMetrics
https://bugs.webkit.org/show_bug.cgi?id=314796
rdar://176487081
Reviewed by Jer Noble.
On the protected-content path — where no WebCoreDecompressionSession is
in use — VideoMediaSampleRenderer's four per-metric accessors each issued
a separate [renderer videoPerformanceMetrics] synchronous XPC, and the
GPU-side RemoteAudioVideoRendererProxyManager eagerly bundled the resulting
VideoPlaybackQualityMetrics into every RemoteAudioVideoRendererState push
back to WebContent. Each such push therefore fanned into four XPCs, and
they fired on every state-carrying event plus the 250ms periodic StateUpdate,
even when no script was asking for the metrics. Plain MSE / WebM playback
services these accessors from in-process atomics and was unaffected.
Consolidate the fetch into a single [renderer videoPerformanceMetrics]
call and move metrics delivery to a pull model matching
MediaPlayerPrivateRemote / RemoteMediaPlayerProxy:
1. VideoMediaSampleRenderer exposes videoPlaybackQualityMetrics() that
builds the full struct from one videoPerformanceMetrics read (or
from the internal decompression-session counters when applicable).
The four per-metric getters are removed; AudioVideoRendererAVFObjC
delegates to the new single-call method.
2. RemoteAudioVideoRendererState no longer carries a metrics payload.
stateFor() returns only timeUpdateData + paused, so on the
protected-content path the frequent state pushes no longer XPC
into mediaserverd.
3. AudioVideoRendererRemote::videoPlaybackQualityMetrics() now
estimates client query cadence and forwards it to the GPU via a new
SetVideoPlaybackMetricsUpdateInterval IPC, mirroring
MediaPlayerPrivateRemote::updateVideoPlaybackMetricsUpdateInterval.
The interval seeds at 1s on the first query and retunes when the
observed delta drifts by more than 250ms, clamped to a 250ms floor
so rapid bursts of queries cannot drive the GPU into a sub-ms push
cadence. If the client stops polling for more than 30s,
updateCacheState tells the GPU to stop pushing (interval=0); the
next query re-seeds. The method returns the last cached struct
pushed from the GPU.
4. RemoteAudioVideoRendererProxyManager piggybacks metrics collection
on its existing setTimeObserver tick (every
remoteAudioVideoRendererUpdateInterval), matching the structure of
RemoteMediaPlayerProxy::maybeUpdateCachedVideoMetrics. Each tick
calls maybeUpdateCachedVideoMetrics(), which early-returns while
the renderer is paused, when no interval has been negotiated, or
when the scheduled nextPlaybackQualityMetricsUpdateTime has not
elapsed yet. When it does fire, updateCachedVideoMetrics() reads
[renderer videoPerformanceMetrics] once, sends
UpdatePlaybackQualityMetrics to the WebContent, and anchors the
next tick at now + interval. SetVideoPlaybackMetricsUpdateInterval
primes the cache immediately and anchors the first next-tick at
now + interval - 0.25s (metricsAdvanceUpdate) so the GPU refreshes
just before the client's expected next query. No dedicated
RunLoop::Timer is needed: the time observer naturally stops firing
when media time stops advancing, so paused / stalled playback
incurs no additional wake-ups.
Debug logging is added on both sides to trace query cadence, interval
retuning, and the metrics values flowing over the new IPC.
[renderer videoPerformanceMetrics] performs a sync XP dispatch and is
called from the main thread, blocking it until completion. A future
update could run this operation on the AVSampleBufferDisplayLayer's
AVSampleBufferVideoRenderer in a secondary WorkQueue. But as this
commit only affects protected content which occurs on the main thread,
additional work is required.
* Source/WebCore/platform/graphics/avfoundation/AudioVideoRendererAVFObjC.mm:
(WebCore::AudioVideoRendererAVFObjC::videoPlaybackQualityMetrics): Delegate
to VideoMediaSampleRenderer's single-call method.
* Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.h:
* Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.mm:
(WebCore::VideoMediaSampleRenderer::videoPlaybackQualityMetrics): New.
Builds the full VideoPlaybackQualityMetrics from one videoPerformanceMetrics
read (or internal counters on the decompression-session path). The four
per-metric accessors are removed.
* Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.cpp:
* Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.h:
(WebKit::RemoteAudioVideoRendererProxyManager::create): Call
maybeUpdateCachedVideoMetrics from the existing setTimeObserver tick
so metrics refresh on the same cadence that already drives the state
pushes.
(WebKit::RemoteAudioVideoRendererProxyManager::stateFor): Drop the
metrics fetch; return only timeUpdateData and paused.
(WebKit::RemoteAudioVideoRendererProxyManager::setVideoPlaybackMetricsUpdateInterval):
New IPC handler. Pushes current metrics immediately, stores the interval
on the RendererContext, and anchors nextPlaybackQualityMetricsUpdateTime
with the 250ms metricsAdvanceUpdate nudge so the first refresh lands
just before the client's next expected query.
(WebKit::RemoteAudioVideoRendererProxyManager::maybeUpdateCachedVideoMetrics):
New. Gate-check for the time-observer callsite: skips while the renderer
is paused, when no interval is negotiated, or when the scheduled update
time has not yet elapsed.
(WebKit::RemoteAudioVideoRendererProxyManager::updateCachedVideoMetrics):
Fetches metrics in a single call, sends UpdatePlaybackQualityMetrics to
the WebContent, and advances nextPlaybackQualityMetricsUpdateTime by
the current interval.
*
Source/WebKit/GPUProcess/media/RemoteAudioVideoRendererProxyManager.messages.in:
Declare SetVideoPlaybackMetricsUpdateInterval.
* Source/WebKit/WebProcess/GPU/media/AudioVideoRendererRemote.cpp:
* Source/WebKit/WebProcess/GPU/media/AudioVideoRendererRemote.h:
(WebKit::AudioVideoRendererRemote::videoPlaybackQualityMetrics): Estimate
client query cadence, clamp retunes to a 250ms floor, and send
SetVideoPlaybackMetricsUpdateInterval when the interval changes. Returns
the cached struct from the GPU.
(WebKit::AudioVideoRendererRemote::updateVideoPlaybackMetricsUpdateInterval):
New. Dispatches the interval IPC on queueSingleton().
(WebKit::AudioVideoRendererRemote::updateCacheState): No longer copies
videoPlaybackQualityMetrics out of the state struct. Auto-disables GPU
metrics pushes (interval=0) when the client has not queried for 30s,
mirroring MediaPlayerPrivateRemote::updateCachedState.
(WebKit::AudioVideoRendererRemote::MessageReceiver::updatePlaybackQualityMetrics):
New receiver for the GPU-pushed metrics. Stores into m_cachedState.
*
Source/WebKit/WebProcess/GPU/media/AudioVideoRendererRemoteMessageReceiver.messages.in:
Declare UpdatePlaybackQualityMetrics.
* Source/WebKit/WebProcess/GPU/media/RemoteAudioVideoRendererState.h:
*
Source/WebKit/WebProcess/GPU/media/RemoteAudioVideoRendererState.serialization.in:
Remove the videoPlaybackQualityMetrics field.
Canonical link: https://commits.webkit.org/313304@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications