Commit Graph

21 Commits

Author SHA1 Message Date
Zaggy1024
a05da1b7d0 LibMedia: Make Matroska::SampleIterator movable again
It seems that at some point it became non-movable, causing some
warnings where we were trying to avoid unnecessary copies.
2026-02-06 13:28:09 +01: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
75231e63b1 LibMedia: Only pass Demuxer to the data providers
...and abstract away the stream/cursor blocking/aborting functionality
so that demuxers can implement or ignore those methods as they see fit.

This is a step towards implementing a wrapper demuxer for MSE streams.
2026-01-30 10:02:00 -06:00
Zaggy1024
a5153d05e7 LibMedia: Avoid unnecessary stream RefPtr copies in Matroska::Reader 2026-01-29 05:22:27 -06:00
Zaggy1024
f0d7d1d5f5 LibMedia: Track Matroska master element ends with position()
We don't actually need a Vector stack of bytes read for each element
we're reading out of a Matroska file, we already have the C++ stack
in which we can store the start and end of the master elements we're
reading.

This fixes an issue where seeks while parsing master elements would not
increment m_octets_read, so the master element could continue reading
further than intended.

This could cause a BlockGroup followed by a SimpleBlock to read as if
the BlockGroup contained the SimpleBlock, meaning that SampleIterator
would skip the SimpleBlock.

A test is added to ensure this doesn't regress again.
2026-01-28 14:48:03 -06:00
Aliaksandr Kalenik
4261d73781 LibMedia: Remove m_stream_cursor from Matroska::Reader
Pass the Streamer through parsing methods during initialization instead
of storing the cursor as a member. This makes Reader effectively
read-only after construction, improving thread safety since the cursor
is no longer shared state.
2026-01-07 00:13:32 +01:00
Zaggy1024
b77980b4cc LibMedia: Move Matroska's get_frames method to SampleIterator
This ensures that we're using the reader for the particular thread that
the block was read from, avoiding any race conditions between seeks and
reads across threads.
2026-01-07 00:13:32 +01:00
Zaggy1024
5da08f59b0 LibMedia: Remove a function declaration from Matroska::SampleIterator
This was unused.
2026-01-07 00:13:32 +01:00
Zaggy1024
0170111bb5 LibMedia: Stop lazily parsing data in Matroska::Reader
This wasn't really gaining us anything in practice, and it makes it
harder to make sample iterators thread-safe.
2026-01-07 00:13:32 +01:00
Zaggy1024
5aa5beed26 LibMedia: Avoid copying Matroska block data when seeking
We only need to get the frames from a block when requested by the
demuxer, so factor that out into a function that it can call when it is
outputting frames.
2026-01-05 17:53:24 -06:00
Zaggy1024
72a5581f7b LibMedia: Seek Matroska cue-less tracks using the first track's cues
Defaulting to cues from the first track allows us to skip to any point
in a file without having to read and skip all the clusters/blocks up to
that point. This is a prerequisite to using range requests to seek in
large video files.

In order to ensure that this remains correct in cases where the first
track's cues point to a cluster containing blocks in the seeked track
with later timestamps than the seek target, the original logic is used
to start from the first block and iteratively find the closest keyframe
to the target timestamp.

In cases where the timestamp falls after the selected cue point, we
also use the iterative seeking to skip to the last keyframe that
precedes the target timestamp, which will often allow us to skip
decoding many audio blocks, since most audio codecs only store
independently-decodable blocks.
2026-01-05 17:53:24 -06:00
Zaggy1024
ea25881185 LibMedia: Reduce the size of cue points in Matroska::Reader
In the map from track to vector of cue points, we were storing
positions for each track that was included in the cues. Instead, only
store the position of the track to which the vector is assigned in the
map.
2026-01-05 17:53:24 -06:00
Zaggy1024
1e773942b1 LibMedia: Try to use FFmpeg for all formats other than Matroska
By sniffing specifically for MP4 and WebM, we were precluding
PlaybackManager from playing any other formats. Instead, use
MatroskaDemuxer if the media has a `matroska` or `webm` EBML doctype,
and fall back to FFmpeg for all others.

We'll need to limit the containers that FFmpeg is able to open at some
point, but for now, this allows us to play the formats we could before.
2025-12-18 17:28:14 -06:00
Aliaksandr Kalenik
f2498f1b9e LibMedia: Add MP4 and WebM media type sniffing
When media data is fully buffered, we can just try Matroska first and
fall back to FFmpeg. With incremental fetching, that approach becomes
wasteful: we may repeatedly attempt demuxer construction before enough
bytes are available, and FFmpeg in particular tends to produce noisy
logs while probing partial input.

Add lightweight container sniffing for WebM and MP4 that operates on
`IncrementallyPopulatedStream::Cursor`,
`prepare_playback_from_media_data()` now blocks until there is enough
data to decide the container type, then constructs the appropriate
demuxer directly instead of probing both.

Co-authored-by: Zaggy1024 <Zaggy1024@gmail.com>
2025-12-16 02:42:48 -06:00
Aliaksandr Kalenik
c5d8cb5c47 LibMedia: Change demuxers to use IncrementallyPopulatedStream as input
Refactor the FFmpeg and Matroska demuxers to consume data through
`IncrementallyPopulatedStream::Cursor` instead of a pointer to fully
buffered.

This change establishes a new rule: each track must be initialized with
its own cursor. Data providers now explicitly create a per-track context
via `Demuxer::create_context_for_track(track, cursor)`, and own pointer
to that cursor. In the upcoming changes, holding the cursor in the
provider would allow to signal "cancel blocking reads" so an
in-flight seek can fail immediately when a newer seek request arrives.
2025-12-16 02:42:48 -06:00
Aliaksandr Kalenik
d754a569e0 LibMedia: Delete from_file() and from_mapped_file() in MatroskaDemuxer
These calls were only used in tests where we could read the whole file
into memory and use `from_data()`.
2025-12-10 11:38:13 -06:00
Zaggy1024
31c751ee92 LibMedia: Handle buggy FFmpeg WebM muxing in Matroska::Reader 2025-11-21 11:02:44 +01:00
Zaggy1024
b59f0501b8 LibMedia: Use String instead of ByteString in Matroska::Document 2025-11-21 11:02:44 +01:00
ayeteadoe
8150fb4cbb LibMedia: Enable EXPLICIT_SYMBOL_EXPORT 2025-08-24 12:58:27 -06:00
Pavel Shliak
b60cb699a9 LibMedia: Clean up #include directives
This change aims to improve the speed of incremental builds.
2024-11-21 14:08:33 +01:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00