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

  Changed paths:
    M 
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-duration-expected.txt
    M 
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-duration.html
    M LayoutTests/platform/mac/TestExpectations
    M Source/WebCore/Modules/mediasource/MediaSource.cpp
    M Source/WebCore/platform/graphics/avfoundation/AudioVideoRendererAVFObjC.mm
    M 
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h
    M 
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm

  Log Message:
  -----------
  [MSE] mediasource-duration WPT test fails on multi-track content
https://bugs.webkit.org/show_bug.cgi?id=222422
rdar://176599938

Reviewed by Eric Carlson.

Several independent bugs along the duration-truncation seek path caused
the mediasource-duration WPT test to fail on multi-track mp4 content:

1. MediaSource::setDurationInternal lost MediaTime precision when the
   JS-supplied duration equalled the highest buffered end time. The JS
   Number arrives as a MediaTime constructed via createWithDouble (the
   "DoubleValue" form, which holds a raw double). The spec normalisation
   step 4 only swaps to the precise rational highestEndTime when
   newDuration is *strictly less* than it; on equality the imprecise
   DoubleValue won, then propagated through durationChanged ->
   mediaPlayerDurationChanged -> seekInternal as the seek target.
   Eventually SourceBufferPrivate::computeSeekTime saw a DoubleValue
   target and rounded it to MediaTime::DefaultTimeScale (10M), losing
   precision. Use <= so that the precise rational from the buffered
   ranges is picked on equality, and the precise value flows through to
   computeSeekTime where the DoubleValue branch is skipped entirely.

2. AudioVideoRendererAVFObjC::notifyTimeReachedAndStall's boundary
   observer callback fired the WebContent-side callback with `now`
   (currentTime() captured before re-pinning the synchronizer), even
   though it then re-set the synchronizer to the precise timeBoundary
   immediately after. The reported time therefore carried the
   synchronizer's timescale-rounded value rather than the precise
   requested value. Fire callback(timeBoundary) so the value matches
   what the synchronizer was just pinned to.

3. The same boundary observer also called pause() and timeChanged()
   unconditionally. During an in-flight seek (e.g. the seek triggered by
   a duration truncation), pausing mid-seek and firing timeChanged()
   races with the seek's own state transitions and produces
   spec-incorrect event ordering (timeupdate before seeking). Skip both
   calls when seeking() is true and let the seek path drive state
   transitions.

4. The "setting same duration multiple times does not fire duplicate
   durationchange" subtest timed out ~60% of the time in WebKitTestRunner
   because the 'ended' event was never scheduled. Log-traced cause: after
   endOfStream() the boundary observer is programmed at
   stallAtTime = highestEndTime (audio-sample-aligned, longer than the
   video-frame-aligned end). Playback drains naturally - currentTime
   advances to exactly highestEndTime and stops - but
   AVSampleBufferRenderSynchronizer's boundary-time observer does not
   fire in that case. The effectiveRate-changed listener, however, does
   fire when the synchronizer rate drops to 0 at drain. Use that as a
   reliable signal: in MediaPlayerPrivateMediaSourceAVFObjC::
   effectiveRateChanged(), when effectiveRate == 0 and MediaSource is
   in the 'ended' state and MediaSourcePrivate::hasFutureTime(currentTime)
   is false, route a timeChanged() through so
   HTMLMediaElement::mediaPlayerTimeChanged schedules the 'ended' event
   (currentTime == duration at this point, satisfying its now >= dur
   check). The existing 'if (!effectiveRate()) timeChanged()' fallback
   in mediaSourceHasRetrievedAllData() is replaced with the same helper
   for consistency; the isEnded() gate is always true in that context
   (the caller sets m_ended = true before dispatching), making the gate
   explicit and symmetric with the effectiveRateChanged site.

* 
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-duration-expected.txt:
  Three subtests now pass.
* 
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-duration.html:
 The last test was invalid.
It adds data from 0.095 and expect the mediaElement's play promise to be 
resolved ; it can't be as with this starting
gap there's nothing to play. Remove the call to play() it's not required for 
this test.
* LayoutTests/platform/mac/TestExpectations: Drop the flaky/Failure
  expectation that covered these failures.
* Source/WebCore/Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::setDurationInternal):
* Source/WebCore/platform/graphics/avfoundation/AudioVideoRendererAVFObjC.mm:
(WebCore::AudioVideoRendererAVFObjC::notifyTimeReachedAndStall):
* 
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
* 
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::bufferedChanged):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::effectiveRateChanged):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::notifyEndOfMediaIfNeeded):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::mediaSourceHasRetrievedAllData):

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



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

Reply via email to