Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 21a3e6b45c05b297534a0727d2ea6dd87d6e0aa6
https://github.com/WebKit/WebKit/commit/21a3e6b45c05b297534a0727d2ea6dd87d6e0aa6
Author: Jean-Yves Avenard <[email protected]>
Date: 2026-05-17 (Sun, 17 May 2026)
Changed paths:
M
LayoutTests/media/media-source/media-source-remove-decodeorder-crash-expected.txt
M LayoutTests/media/media-source/media-source-remove-decodeorder-crash.html
M Source/WebCore/platform/graphics/TrackBuffer.cpp
M Source/WebCore/platform/graphics/TrackBuffer.h
Log Message:
-----------
[MSE] SourceBuffer.remove() removes one extra sample, and buffered trims
coverage still backed by retained samples
https://bugs.webkit.org/show_bug.cgi?id=314814
rdar://177065364
Reviewed by Eric Carlson.
Two defects along the SourceBuffer.remove() path:
1. Per MSE spec 3.5.9 step 3.3, only coded frames whose starting
timestamp is "greater than or equal to start" should be removed.
TrackBuffer::removeCodedFrames was using
findSampleContainingOrAfterPresentationTime(start), which for
non-divisible samples (video frames) returns the sample whose
presentation range *contains* start - i.e. a sample with PTS <
start - and erased it. Switch to
findSampleStartingOnOrAfterPresentationTime to match the spec
exactly. Divisible samples are still split at start by the prior
divideSampleIfPossibleAtPresentationTime call, and the resulting
"after" piece (whose PTS == start) is then correctly picked up by
findSampleStartingOnOrAfter. Apply the same change in
codedFramesIntervalSize so the eviction-size estimator stays
consistent with the actual remove behaviour.
2. TrackBuffer::removeSamples' neighbour-sample handling already
padded erasedRanges on either side when the adjacent retained
sample left a gap (prevSample.end < erasedStart, or nextSample.PT
> erasedEnd). The symmetric overlap cases were never handled, so
when a retained sample's presentation interval extended into the
erased range - which happens for WebM sub-millisecond overlaps
allowed by contiguousFrameTolerance, and can also be manufactured
by tests via abort()+append - erasedRanges included coverage that
was still backed by a retained sample, and the caller's
intersection trimmed m_buffered accordingly. The old "containing"
remove semantics papered over this in a subsequent remove by
aggressively pulling the overlap sample in; spec-strict remove
does not, so the inconsistency is now observable. Extend the same
neighbour check with overlap branches: if the previous retained
sample ends past erasedStart, clip erasedStart to its end; if the
next retained sample starts before erasedEnd, clip erasedEnd to
its PTS. No extra map scans - reuses the iterators already fetched
for the gap case.
* LayoutTests/media/media-source/media-source-remove-decodeorder-crash.html:
Change remove(1.9, 2) to remove(1, 2). This test doesn't involve
buffered-range math; the original call relied on the old "containing"
removal to erase the [1, 2) sample. Under spec-strict no sample has
PTS in [1.9, 2). remove(1, 2) still drives the decode-order
extraction path (PTS=1 has DTS=2, last in decode order) and produces
the existing expected output.
* Source/WebCore/platform/graphics/TrackBuffer.cpp:
(WebCore::TrackBuffer::removeSamples):
(WebCore::TrackBuffer::removeCodedFrames):
(WebCore::TrackBuffer::codedFramesIntervalSize):
(WebCore::TrackBuffer::tryDivideSampleAtTime):
* Source/WebCore/platform/graphics/TrackBuffer.h:
Canonical link: https://commits.webkit.org/313383@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications