Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 62987e20ab97418bd379d1fddeab9a181c064e3c
      
https://github.com/WebKit/WebKit/commit/62987e20ab97418bd379d1fddeab9a181c064e3c
  Author: Jean-Yves Avenard <[email protected]>
  Date:   2026-05-06 (Wed, 06 May 2026)

  Changed paths:
    M Source/WebCore/platform/graphics/TrackBuffer.cpp
    M Source/WebCore/platform/graphics/TrackBuffer.h
    M Source/WebCore/platform/graphics/avfoundation/AudioVideoRendererAVFObjC.mm
    M Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.h
    M Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.mm

  Log Message:
  -----------
  [MSE][Cocoa] Silence spurious UpcomingPTSExpectation warnings from
AVSampleBufferVideoRenderer on B-frame content
https://bugs.webkit.org/show_bug.cgi?id=314077
rdar://176260662

Reviewed by Jer Noble.

AVSampleBufferVideoRenderer's _enqueueSingleSampleBuffer: compares each
incoming sample's PTS against a floor that WebKit publishes via
-[AVSampleBufferDisplayLayer expectMinimumUpcomingSampleBufferPresentationTime:]
and logs "UpcomingPTSExpectation is enabled, but enqueuePTS:X is smaller
than expectedMinimumUpcomingPTS:Y" whenever a later sample arrives with
a lower PTS. The log is informational only — samples are still accepted
— but on B-frame streams the message fires every frame pair: a 5-minute
Twitch capture produced 6197 lines, burying other signal during stall
investigations.

The floor came from TrackBuffer::minimumEnqueuedPresentationTime(),
recomputed by TrackBuffer::updateMinimumUpcomingPresentationTime() as a
sliding-window minimum over m_decodeQueue. When the parser feeds samples
one at a time (typical Twitch behaviour, and the common case during
post-changeType recovery) the decode queue is near-empty after each pop
and the scan can only see the current sample's own PTS. In decode order
that's a P-frame at the top of a GOP triplet, with two B-frames at lower
PTS arriving next — and the floor we publish is therefore always too
high by the B-frame reorder distance.

Two coordinated changes:

1. TrackBuffer now tracks the max observed reorder depth. On every
    addSample() we count samples in decode order since the most recent
    new-max PTS; the running maximum is stored in
    m_maxObservedReorderDepth, seeded to a conservative default of 3 to
    cover typical IPBB/IPBBB patterns and growing on deeper reorder.
    updateMinimumUpcomingPresentationTime() refuses to publish a value
    until the queue contains at least m_maxObservedReorderDepth + 1
    samples past the head when m_hasOutOfOrderFrames is set — that's the
    point at which the sliding-window scan has actually seen every
    B-frame that could come before the head's PTS. A new
    setInitialReorderDepth(size_t) hook is exposed so a future change
    can seed the depth from the codec config (H.264 max_num_reorder_frames
    / H.265 sps_max_num_reorder_pics); today it is unused and the
    mechanism is purely empirical.

2. Propagate the "no lookahead available" state cleanly down to the
    renderer instead of masking it. AudioVideoRendererAVFObjC::enqueueSample()
    no longer falls back to sample->presentationTime() when the caller
    passes std::nullopt; VideoMediaSampleRenderer::enqueueSample() now
    takes std::optional<MediaTime> and stores the optional in
    m_compressedSampleQueue. decodeNextSampleIfNeeded() only calls
    -expectMinimumUpcomingSampleBufferPresentationTime: when the stored
    optional holds a value. Without a lookahead it falls through and
    keeps decoding, which was the previous unintended behaviour anyway
    (the floor we were publishing was wrong).

Net effect: zero warnings in steady-state Twitch playback, and none
during ad/content transitions once the first handful of samples have
established the reorder depth.

No tests added; manual verification via
log stream --predicate='(process="Safari" or 
process="com.apple.WebKit.GPU.Development")'
with a Twitch session shows the "UpcomingPTSExpectation is enabled"
message count drop from ~6000 / 5 min to near zero.

* Source/WebCore/platform/graphics/TrackBuffer.h:
(WebCore::TrackBuffer::setInitialReorderDepth):
Add setInitialReorderDepth() and the three new members backing the
reorder-depth observation.
* Source/WebCore/platform/graphics/TrackBuffer.cpp:
(WebCore::TrackBuffer::addSample):
Track the running reorder depth alongside m_hasOutOfOrderFrames.
(WebCore::TrackBuffer::updateMinimumUpcomingPresentationTime):
Gate publication on having at least m_maxObservedReorderDepth + 1
samples in the queue when m_hasOutOfOrderFrames is set.
(WebCore::TrackBuffer::clearDecodeQueue):
Reset the observation counters but keep the learned depth.
* Source/WebCore/platform/graphics/avfoundation/AudioVideoRendererAVFObjC.mm:
(WebCore::AudioVideoRendererAVFObjC::enqueueSample):
Pass the std::optional<MediaTime> through instead of substituting the
sample's own PTS.
* Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.h:
Change enqueueSample() signature and m_compressedSampleQueue element
type to carry std::optional<MediaTime>.
* Source/WebCore/platform/graphics/cocoa/VideoMediaSampleRenderer.mm:
(WebCore::VideoMediaSampleRenderer::enqueueSample):
Accept std::optional<MediaTime>.
(WebCore::VideoMediaSampleRenderer::decodeNextSampleIfNeeded):
Only publish a floor when the stored optional is present; fall through
and decode otherwise.

Canonical link: https://commits.webkit.org/312763@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to