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

  Changed paths:
    A 
LayoutTests/media/media-source/media-source-append-bframe-orphan-post-reset-expected.txt
    A 
LayoutTests/media/media-source/media-source-append-bframe-orphan-post-reset.html
    A 
LayoutTests/media/media-source/media-source-append-overlapping-equal-decode-key-expected.txt
    A 
LayoutTests/media/media-source/media-source-append-overlapping-equal-decode-key.html
    A 
LayoutTests/media/media-source/media-source-append-pt-collision-tail-expected.txt
    A LayoutTests/media/media-source/media-source-append-pt-collision-tail.html
    A 
LayoutTests/media/media-source/media-source-coded-frame-group-reset-overlapping-sample-orphan-expected.txt
    A 
LayoutTests/media/media-source/media-source-coded-frame-group-reset-overlapping-sample-orphan.html
    A 
LayoutTests/media/media-source/media-source-pt-collision-cleanup-expected.txt
    A LayoutTests/media/media-source/media-source-pt-collision-cleanup.html
    M LayoutTests/media/media-source/media-source-video-playback-quality.html
    M LayoutTests/platform/glib/TestExpectations
    M Source/WebCore/platform/graphics/SourceBufferPrivate.cpp
    M Source/WebCore/platform/graphics/TrackBuffer.cpp

  Log Message:
  -----------
  [MSE] processMediaSample: close Coded Frame Processing spec gaps proposed in 
w3c/media-source#374 and #375
https://bugs.webkit.org/show_bug.cgi?id=314723
rdar://176971800

Reviewed by OOPs

The "Coded Frame Processing" algorithm in the MSE spec has two cleanup
gaps when an incoming coded frame arrives mid-stream. Each is tracked
as a proposed spec amendment:

  - w3c/media-source#374 (SAP Type 2 decode-shadowed orphans).
    Non-sync coded frames whose decode timestamp is strictly greater
    than the incoming frame's decode timestamp and whose presentation
    timestamp is less than the incoming frame's survive every existing
    cleanup step. They decode after the incoming random access point
    but present before it, and no random access point remains at or
    before their presentation timestamps once the incoming one takes
    over. They become unreachable on seek.

  - w3c/media-source#375 (presentation-timestamp coincidence).
    Coded frames whose presentation timestamp coincides (exactly, or
    within 1 microsecond) with the incoming frame's can coexist in the
    track buffer with the incoming frame, producing downstream
    ambiguity in algorithms that refer to "the coded frame in track
    buffer with a presentation interval that contains t".

Place the #375 amendment between step 1.13 ("overlap check") and step
1.14 ("Remove existing coded frames in track buffer"):

    Look up the presentation-order range
        [incoming.pts - 1us, incoming.pts + 1us)
    via findSamplesBetweenPresentationTimes (O(log n)) and add every
    sample it yields to erasedSamples. Runs unconditionally: a mid-
    stream PT collision can reach "Add the coded frame" with all other
    cleanup steps no-opping, so #375's lookup must not be gated on
    erasedSamples being non-empty.

Place the #374 amendment inside step 1.15's existing "Remove all
possible decoding dependencies" block, after the main dependent sweep:

    Call findSamplesBetweenDecodeKeys(incomingDecodeKey,
    erasedSamples.decodeOrder().begin()->first) and, for each returned
    sample, insert into dependentSamples if it is non-sync and its
    presentation timestamp is less than the incoming frame's.

    Using erasedSamples.begin()->first as the upper bound is safe:
    samples in [erasedSamples.begin(), nextSyncIter) are already
    scheduled for removal by the step 1.15 main sweep immediately
    above (dependentSamples.insert(firstDecodeIter, nextSyncIter)),
    so #374 only needs to cover the gap [incomingDecodeKey,
    erasedSamples.begin()). The amendment filed on #374 includes an
    optimization note permitting implementations to bound the scan
    short of the next random access point; this bound satisfies the
    note, and the predicate (non-sync AND pts < incoming.pts) keeps
    sync frames and samples with pts >= incoming.pts preserved.

Remove the samplesWithHigherDecodeTimes cleanup previously located
inside step 1.15's dependent sweep: its responsibilities are now
covered by #375 (equal-key collision, equal-PT collision) and by the

Simplify the step-1.14 B-frame cascade's DTS re-key guard. The
three-predicate condition

    nextSampleInDecodeOrderRef->presentationTime() < sample->presentationTime()
    && nextSyncSample != trackBuffer.samples().decodeOrder().begin()
    && trackBuffer.samples().decodeOrder().size() > 0

collapses to its semantic predicate

    nextSampleInDecodeOrderRef->presentationTime() < sample->presentationTime()

because size() > 0 is implied by the earlier early-break on
nextSampleInDecodeOrder == decodeOrder().end(), and nextSyncSample
can never equal begin() because findSyncSampleAfterDecodeIterator
pre-increments its argument before scanning (SampleMap.cpp:
std::find_if(++currentSampleDTS, end(), ...)). The invariant is
documented inline.

* 
LayoutTests/media/media-source/media-source-append-bframe-orphan-post-reset-expected.txt:
 Added.
* 
LayoutTests/media/media-source/media-source-append-bframe-orphan-post-reset.html:
 Added.
  Real-MP4 regression guard for #374. Seg 1 is a B-frame GOP anchored
  past t=1s (so seg 2's non-zero DTS avoids
  Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp's
  extendToTheBeginning hack, which fires on DTS==0 && PTS>0 && sync);
  seg 2's single sync at DTS=1.000 PTS=1.075 lands inside an existing
  B-frame's presentation interval. With the new passes: the legitimate
  next-GOP I-frame at (1.050, 1.100) is preserved (pts > incoming.pts);
  the orphan B-frame at (1.150, 1.025) is evicted (pts < incoming.pts,
  non-sync); final buffered length = 3.

* 
LayoutTests/media/media-source/media-source-append-overlapping-equal-decode-key-expected.txt:
 Added.
* 
LayoutTests/media/media-source/media-source-append-overlapping-equal-decode-key.html:
 Added.
  Real-MP4 regression guard for #375. Seg 2 is split into two appends
  with independent baseDecodeTime so the setup samples push highestPT
  past 200, leaving the #375 presentation-timestamp collision cleanup
  as the only code path that can evict the existing sample at DTS=200
  when seg 2B's incoming sync at DTS=200 is processed. The sample in
  the buffer at DTS=0.200 must carry seg 2B's duration (120), not
  seg 1's (100).

* 
LayoutTests/media/media-source/media-source-coded-frame-group-reset-overlapping-sample-orphan-expected.txt:
 Added.
* 
LayoutTests/media/media-source/media-source-coded-frame-group-reset-overlapping-sample-orphan.html:
 Added.
  Step 1.6 + step 1.14 cascade DTS re-key-decline + fallthrough-erase
  coverage. Timestamps shifted past t=1s so seg 2's DTS is non-zero,
  avoiding the GStreamer extendToTheBeginning hack. Seg 1 is a single
  sync at baseDecodeTime=1100 dur=100; seg 2 is a single sync at
  baseDecodeTime=1000 dur=50 CTO=150 (PTS=1150 inside seg 1's interval
  [1100, 1200)). Cascade's DTS re-key declines because the candidate
  safeDecodeTime lands past the incoming frame's duration window, and
  the fallthrough addRange erases the overlapping seg 1 sample.
  Buffered collapses to [1.15, 1.2].

* LayoutTests/media/media-source/media-source-video-playback-quality.html: the 
test actually exposed bug #375
it added two samples with the same key pts/dts and would have been silently 
dropped upon adding to the SampleMap.
* LayoutTests/platform/glib/TestExpectations:
* Source/WebCore/platform/graphics/SourceBufferPrivate.cpp:
(WebCore::SourceBufferPrivate::processMediaSample):
  Inserted the #375 unconditional pass between step 1.13 and step 1.14;
  inserted the #374 bounded pass inside step 1.15's dependent sweep;
  removed the obsolete samplesWithHigherDecodeTimes block; simplified
  the B-frame cascade's DTS re-key guard.

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



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

Reply via email to