Commit graph

19 commits

Author SHA1 Message Date
Zaggy1024
8576527d8a LibMedia: Actually adjust incremental stream's request positions
This was unintentionally clobbering the prior modification to the
request position. Requesting data slightly earlier in the file is
intended to ensure that we have data if the demuxer decides to seek
backwards.
2026-05-28 10:30:20 -05:00
Zaggy1024
fea33aa02f LibMedia+Tests: Add a method to remove data from incremental streams
This will later be used to test updating of buffered time ranges when
data is removed. It will also be needed when data eviction is
implemented.
2026-05-28 10:30:20 -05:00
Zaggy1024
617f50813a LibMedia: Ensure that overlapped incremental stream chunks are merged
Returning early if an added chunk didn't overlap the previous one could
result in overlapping chunks or 0-byte gaps if a chunk was after but
within the new one. Instead, fall through to allow the merging to
continue as normal.

Also, make the joining condition check if the new chunk spans multiple
existing chunks to merge/remove those.
2026-05-28 10:30:20 -05:00
Zaggy1024
c4514c27ab LibMedia: Add a method to get the available bytes from a MediaStream
This will be used to determine the buffered time ranges.
2026-05-28 10:30:20 -05:00
Zaggy1024
f62af69dcd LibMedia: Allow MediaStreamCursor to never block on missing data
This is necessary to allow the main thread to read out frames to
determine the buffered ranges, without affecting the request position
of an IncrementallyPopulatedStream or causing a deadlock waiting for
data to come in.
2026-05-28 10:30:20 -05:00
Zaggy1024
0c830caade LibMedia: Avoid crashing in tests appending data to incremental streams
We would ignore whether the callback/event loop had been set up for the
stream. Tests appending enough data for it to start a new request after
the new data would cause a crash.
2026-05-28 10:30:20 -05:00
Zaggy1024
a286f30663 LibMedia: Qualify AK::SeekMode to differentiate from Media::SeekMode 2026-05-13 02:05:35 -05:00
R-Goc
02bb892d7a LibThreading/LibSync: Split out sync primitives
This commit splits out synchronization primitives from LibThreading into
LibSync. This is because LibThreading depends on LibCore, while LibCore
needs the synchronization primitives from LibThreading. This worked
while they were header only, but when I tried to add an implementation
file it ran into the circular dependency. To abstract away the pthread
implementation using cpp files is necessary so the synchronization
primitives were moved to a separate library.
2026-05-08 18:58:35 -05:00
antoniospg
0a89e76775 LibMedia: Fix wrong comparison to check if chunk covers new one 2026-05-08 17:51:28 -05:00
Zaggy1024
b223b3edf0 LibMedia: Allow clearing incremental streams' data request callbacks 2026-02-18 13:13:32 -06:00
Zaggy1024
af45418fbf Everywhere: Rename IncrementallyPopulatedStream::reached_end_of_body
This needs to be called even if we haven't reached the end of the body,
so let's call it close() instead.
2026-02-18 13:13:32 -06:00
Zaggy1024
972438c4d7 LibMedia: Abstract the interface of IncrementallyPopulatedStream
The way that other classes interact with IncrementallyPopulatedStream
is now through a virtual interface MediaStream and MediaStreamCursor.
This way, we can have simpler implementations of reading media data
that will not require an RB tree and synchronization.
2026-01-30 10:02:00 -06:00
Zaggy1024
4482f91827 LibMedia: Wake IncrementallyPopulatedStream upon adding a new chunk
In the early exit for adding a new chunk to m_chunks when no chunk
exists before this one, we were not previously waking any cursors that
may be waiting for this data. This would not generally be an issue when
data is coming in in small chunks, since a second chunk will cause it
to wake, but a test case which only appended one chunk exposed this
bug.
2026-01-29 18:06:02 -06:00
Zaggy1024
1b06792e8f LibMedia+LibWeb: Use range requests to fulfill media data
This makes media playback able to start without having to wait for data
to sequentially download, especially when seeking the media to a
timestamp residing in data that hasn't loaded yet.

Initially, the HTMLMediaElement will request the file without range a
range request. Then, if the IncrementallyPopulatedStream finds that it
needs data that is not yet available, it will decide whether to wait
for that data to be received through the current request, or start a
new request that is closer to the required data.

In this commit, it assumes that the server will support range requests.
2026-01-29 05:22:27 -06:00
Zaggy1024
f06105bf3d LibMedia+Meta: Add IncrementallyPopulatedStream::create_from_data
Data will be copied when added to the stream anyway, so callers should
be able to pass ReadonlyBytes instead of ByteBuffer&&.
2026-01-29 05:22:27 -06:00
Aliaksandr Kalenik
7bc5016868 LibMedia: Add IncrementallyPopulatedStream::set_expected_size()
Store the response's `Content-Length` (when available) as an "expected
size" on `IncrementallyPopulatedStream`.

This allows `IncrementallyPopulatedStream::size()` to return a
meaningful total length early, instead of blocking until EOF. That's
important for the FFmpeg MP4 demuxer, which queries the stream size
immediately after initialization.

Additionally, use the expected size to pre-reserve the underlying
`ByteBuffer` capacity, avoiding repeated reallocations as chunks are
appended.
2025-12-16 02:42:48 -06:00
Aliaksandr Kalenik
3a56e9580a LibMedia: Add "buffering" playback state
`IncrementallyPopulatedStream::Cursor` now tracks whether it's currently
blocked inside a wait for more bytes, allowing higher layers to
distinguish "no frames yet" from "decoder is idle".

Enter buffering when `DisplayingVideoSink` runs out of frames and the
associated `VideoDataProvider` is blocked waiting for data to arrive.
Exit buffering once decoding refills the frame queue.

For now, buffering behaves like paused, but it gives us an explicit
state to hook UI into.
2025-12-16 02:42:48 -06:00
Aliaksandr Kalenik
21e8ece013 LibMedia: Abort blocking reads for ongoing seek if it's replaced
When a seek is requested while a previous seek is still blocked waiting
for not yet available bytes, we want to abandon the old request
immediately and start processing the new one.
2025-12-16 02:42:48 -06:00
Aliaksandr Kalenik
c659cba240 LibMedia: Introduce IncrementallyPopulatedStream
...a shared byte stream that can be appended to as network data arrives.

The stream supports creating multiple independent `Cursor`s, each with
its own read position. This matches our demuxing needs, where different
audio/video tracks may read from the same underlying data concurrently.

`Cursor::read_into()` and `Cursor::seek()` block until the requested
range is available (or the stream is closed). This is intentional: the
FFmpeg `avio_alloc_context()` read callback cannot reliably surface
`EAGAIN` without putting the demuxer into an error state that
requires recovery via seeking, so we instead wait until we can satisfy
the read.
2025-12-16 02:42:48 -06:00