LibWeb: Implement the buffered attribute on SourceBuffer

This is used to detect what data is still needed to maintain or resume
playback based on the current playback position. This is the last piece
that was preventing YouTube MSE from working.
This commit is contained in:
Zaggy1024
2026-03-27 02:13:29 -05:00
committed by Gregory Bertilson
parent 51c3f7c41e
commit 459578c280
Notes: github-actions[bot] 2026-04-01 07:55:56 +00:00
6 changed files with 62 additions and 5 deletions

View File

@@ -575,4 +575,38 @@ void SourceBufferProcessor::clear_reached_end_of_stream()
track_buffer->demuxer().clear_reached_end_of_stream();
}
// https://w3c.github.io/media-source/#dom-sourcebuffer-buffered
Media::TimeRanges SourceBufferProcessor::buffered_ranges() const
{
// 2. Let highest end time be the largest track buffer ranges end time across all the track buffers
// managed by this SourceBuffer object.
AK::Duration highest_end_time;
for (auto const& [track_id, track_buffer] : m_track_buffers) {
auto end_time = track_buffer->demuxer().track_buffer_ranges().highest_end_time();
highest_end_time = max(highest_end_time, end_time);
}
// 3. Let intersection ranges equal a TimeRanges object containing a single range from 0 to highest end time.
Media::TimeRanges intersection;
if (highest_end_time > AK::Duration::zero())
intersection.add_range(AK::Duration::zero(), highest_end_time);
// 4. For each audio and video track buffer managed by this SourceBuffer, run the following steps:
for (auto const& [track_id, track_buffer] : m_track_buffers) {
// 1. Let track ranges equal the track buffer ranges for the current track buffer.
auto track_ranges = track_buffer->demuxer().track_buffer_ranges();
// 2. If readyState is "ended", then set the end time on the last range in track ranges to
// highest end time.
// FIXME: Check readyState from the parent MediaSource.
// 3. Let new intersection ranges equal the intersection between the intersection ranges and
// the track ranges.
// 4. Replace the ranges in intersection ranges with the new intersection ranges.
intersection = intersection.intersection(track_ranges);
}
return intersection;
}
}