Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: cc6a6a6dd0da3f3c3f7c96cc77a6ffe859a1a178
https://github.com/WebKit/WebKit/commit/cc6a6a6dd0da3f3c3f7c96cc77a6ffe859a1a178
Author: Jean-Yves Avenard <[email protected]>
Date: 2026-07-07 (Tue, 07 Jul 2026)
Changed paths:
M
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-remove-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html
M LayoutTests/platform/glib/TestExpectations
M LayoutTests/platform/mac/TestExpectations
M Source/WebCore/SourcesCocoa.txt
M Source/WebCore/WebCore.xcodeproj/project.pbxproj
M Source/WebCore/platform/graphics/SourceBufferPrivate.cpp
M Source/WebCore/platform/graphics/SourceBufferPrivate.h
M
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h
M
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm
M Source/WebCore/platform/graphics/cocoa/ISOBMFFPreParser.cpp
M Source/WebCore/platform/graphics/cocoa/ISOBMFFPreParser.h
A Source/WebCore/platform/graphics/cocoa/ISOBMFFTrackInfoParser.cpp
A Source/WebCore/platform/graphics/cocoa/ISOBMFFTrackInfoParser.h
M Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
A Tools/TestWebKitAPI/Tests/WebCore/cocoa/ISOBMFFTrackInfoParserTests.cpp
Log Message:
-----------
[MSE][Cocoa]
imported/w3c/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html
is a permanent failure
https://bugs.webkit.org/show_bug.cgi?id=316870
rdar://179296547
Reviewed by Youenn Fablet.
The WPT mediasource-sequencemode-append-buffer.html test exercises three
SourceBuffer.mode = "sequence" scenarios using an asset whose video track
carries an empty edit list. Three independent issues — two engine bugs and
one test-side bug — combined to make all three subtests fail on AVFoundation
baswe MSE ; this commit addresses each.
Problems
--------
1. Empty fMP4 edit list not applied to video PTS.
The asset's video track has an `edts/elst` whose first entry is an
empty edit (media_time = -1, segment_duration = 0.095 s in movie
timescale). AVStreamDataParser does not honour empty edits in fMP4, so
the CMSampleBuffers it emits have PTS = raw mdat PTS, missing the
elst-prescribed 0.095s presentation shift. The test's segmentInfo
bakes in the post-shift timestamps, so the engine and the test data
disagreed by exactly that amount.
2. Frames submitted to coded-frame processing in parser-arrival order.
MSE Coded Frame Processing step 1.3 sets `timestampOffset =
group_start_timestamp - presentation_timestamp` on the first sample to
enter the loop. For multi-track segments the only spec-coherent choice
for that "first" sample is the cross-track minimum-PTS sample — any
other choice makes samples of one track land before
group_start_timestamp. SourceBufferPrivate was iterating
m_pendingSamples in parser-arrival order, so step 1.3 fired on
whichever track AVStreamDataParser happened to emit first. Once
problem 1 was fixed, that mismatch became visible: for media[1] step
1.3 fired on video (PTS 0.896666) when audio (PTS 0.882358) should
have driven it. The same problem reappeared on sequence-mode
discontinuity (step 1.6 retries step 1.3 on the discontinuity-
triggering sample) when chaining a second segment.
A similar workaround is implemented by Firefox.
3. Third subtest's expected post-EOS buffered range was unsatisfiable.
The third subtest appends media[1] then media[0] in sequence mode and
asserted the post-EOS buffered range to be a single contiguous range.
With a single per-segment `timestampOffset` (per spec) and media[0]'s
tracks not aligned at the same start (`timev` = 0.095, `timea` = 0 for
this asset), placing media[0] adjacent to media[1] inevitably
introduces a per-track gap inside the unified buffered range of width
`media[0].timev − media[0].timea`. Firefox and Chrome both fail this
subtest too — Firefox with the identical two-range output WebKit
produces, Chrome with a different `timestampOffset` value — so no
production engine satisfies the expected single-range output for this
asset shape.
Solutions
---------
1. A new ISOBMFFTrackInfoParser walks the moov bytes (captured by the
existing ISOBMFFPreParser before they are forwarded to
AVStreamDataParser) and extracts any per-track empty edit.
SourceBufferParserAVFObjC then offsets each emitted sample's PTS and
DTS by that duration via MediaSampleAVFObjC::offsetTimestampsBy()
before delivering the sample to the client.
2. Before iterating samples in processPendingMediaSamples, do a bounded
look-ahead per track (16 frames for video — the H.264/H.265 max
reorder window — 1 for non-video tracks) to identify the cross-track-
min-PTS sample and its position in the batch. When that sample isn't
already at position 0, drain priority-track samples in
[0, priorityIndex] in a first pass; a second pass then iterates the
remaining samples in arrival order, skipping the entries pass 1
already processed. The samples vector itself is not mutated.
3. In the imported WPT test, compute the expected post-EOS buffered
string from segmentInfo, accounting for media[0]'s per-track head
delta when it is non-zero (giving a two-range expected) and falling
back to the original single-range string when it is zero. To be
upstreamed to WPT.
Add API tests, covered by existing tests.
*
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-remove-expected.txt:
*
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html:
* LayoutTests/platform/glib/TestExpectations:
* LayoutTests/platform/mac/TestExpectations: Remove the
mediasource-sequencemode-append-buffer.html Skip entry.
Mark mediasource-getvideoplaybackquality.html as Failing due to bug 316898.
* Source/WebCore/SourcesCocoa.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
Register the new ISOBMFFTrackInfoParser source files.
* Source/WebCore/platform/graphics/SourceBufferPrivate.cpp:
(WebCore::SourceBufferPrivate::findPrioritySample const):
(WebCore::SourceBufferPrivate::processNewMediaSamples):
(WebCore::SourceBufferPrivate::processPendingMediaSamples):
Bounded per-track look-ahead identifies the cross-track-min-PTS
priority sample; a two-pass iteration drains priority-track samples
first, then the rest, without mutating m_pendingSamples.
* Source/WebCore/platform/graphics/SourceBufferPrivate.h:
*
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h:
*
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm:
(WebCore::makePreParserIfNeeded):
(WebCore::SourceBufferParserAVFObjC::SourceBufferParserAVFObjC):
(WebCore::SourceBufferParserAVFObjC::resetParserState): Clear the map.
(WebCore::SourceBufferParserAVFObjC::didProvideMediaDataForTrackID):
Apply the offset to each sample before delivering it.
(WebCore::SourceBufferParserAVFObjC::setEmptyEditOffsetsFromInitSegment):
Receive per-track empty-edit offsets from the pre-parser callback and
stash them in a per-track map.
* Source/WebCore/platform/graphics/cocoa/ISOBMFFPreParser.cpp:
(WebCore::ISOBMFFPreParser::ISOBMFFPreParser):
(WebCore::ISOBMFFPreParser::reset):
(WebCore::ISOBMFFPreParser::appendData):
Take an optional TrackInfoCallback; buffer moov body bytes during the
segment scan and run the walker once the body is complete.
* Source/WebCore/platform/graphics/cocoa/ISOBMFFPreParser.h:
(WebCore::ISOBMFFPreParser::ISOBMFFPreParser):
* Source/WebCore/platform/graphics/cocoa/ISOBMFFTrackInfoParser.cpp:
(WebCore::FourCC):
(WebCore::readNextChildBox):
(WebCore::forEachChildBox):
(WebCore::readFullBoxVersion):
(WebCore::readMvhdTimescale):
(WebCore::readTkhdTrackID):
(WebCore::readElstEntry0EmptyEditDuration):
(WebCore::findEmptyEditDurationInEdts):
(WebCore::parseTrak):
(WebCore::ISOBMFFTrackInfoParser::parseMoovBody):
New BitReader-based walker returning each track's empty-edit duration.
* Source/WebCore/platform/graphics/cocoa/ISOBMFFTrackInfoParser.h:
* Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Tests/WebCore/cocoa/ISOBMFFTrackInfoParserTests.cpp:
Added.
(TestWebKitAPI::appendBE32):
(TestWebKitAPI::appendBE64):
(TestWebKitAPI::makeBox):
(TestWebKitAPI::makeMvhd):
(TestWebKitAPI::makeTkhd):
(TestWebKitAPI::makeElstV0):
(TestWebKitAPI::makeElstV1):
(TestWebKitAPI::makeEdts):
(TestWebKitAPI::makeTrak):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, EmptyInputReturnsNothing)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, SingleTrackEmptyEditVersion0)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, SingleTrackEmptyEditVersion1)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, NonEmptyEditIsIgnored)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, TrackWithoutEditListIsOmitted)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, TrackIDZeroIsRejected)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, MissingMvhdReturnsNothing)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser,
OversizedEmptyEditDurationIsRejected)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, TruncatedChildBoxDoesNotCrash)):
(TestWebKitAPI::TEST(ISOBMFFTrackInfoParser, MultipleEmptyEditTracks)):
Canonical link: https://commits.webkit.org/316626@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications