Commit Graph

8 Commits

Author SHA1 Message Date
Zaggy1024
512ed03e78 LibMedia: Gracefully fall back to video-only playback when audio fails
Hook up a callback in AudioMixingSink to notify PlaybackManager if the
output fails to be initialized. Then, when that happens, swap out the
time provider for GenericTimeProvider and continue without audio.

Fixes #8071
2026-03-21 23:11:47 -05:00
Zaggy1024
17726f76e5 LibMedia: Skip DisplayingVideoSink::update() if the provider is null
We could hit a VERIFY in RefPtr if there was a seek in flight while the
PlaybackManager was being destroyed, since finishing a seek would run
DisplayingVideoSink::resume_updates() which would then check if there
is a new frame to display.
2026-01-30 16:58:38 +01:00
Zaggy1024
f9081fbde6 LibMedia: Dispose future media data and flush decoders when idle
In order to free up memory when a video is paused for an extended
period, we add a new Suspended state to PlaybackManager which tells the
data providers to suspend. The data providers will handle this signal
by disposing of their entire decoded data queue and flushing their
decoder.

When initially creating a PlaybackManager, and when resuming to a
paused state, the delay before suspension will be much lower than when
pausing from any other state. This is intended to prevent media
elements from consuming memory for long when decoding the first frame
for display, as well as to allow the data providers to suspend much
more quickly after a seek while paused.

Currently, resuming playback doesn't display much of a delay on my
MacBook, though that may change once we completely tear down the
decoder in the suspended state. It may also be exacerbated by using
hardware decoders due more complex decoder initialization.
2026-01-26 15:49:07 -06:00
Zaggy1024
e6dbcccb99 LibGfx+LibMedia: Send video frames to Skia as subsampled YUV
This saves us from having our own color conversion code, which was
taking up a fair amount of time in VideoDataProvider. With this change,
we should be able to play high resolution videos without interruptions
on machines where the CPU can keep up with decoding.

In order to make this change, ImmutableBitmap is now able to be
constructed with YUV data instead of an RBG bitmap. It holds onto a
YUVData instance that stores the buffers of image data, since Skia
itself doesn't take ownership of them.

In order to support greater than 8 bits of color depth, we normalize
the 10- or 12-bit color values into a 16-bit range.
2026-01-22 19:44:36 +01: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
Zaggy1024
a87ea9d096 LibMedia: Have the sinks start the data providers
This will allow us to start the audio data providers after their sample
specification conversion is set up in a future commit.
2025-12-13 08:58:26 +01:00
Zaggy1024
ccf4b3f6e9 LibMedia: Implement media seeking
This implementation allows:
- Accurate seeking to an exact timestamp
- Seeking to the keyframe before a timestamp
- Seeking to the keyframe after a timestamp
These three options will be used to satisfy the playback position
selection in the media element's seeking steps.
2025-10-27 17:28:49 -07:00
Zaggy1024
7e238cd724 LibMedia: Add separate classes managing decoding and displaying video
These are unused in this commit, but will later be used to output video
via PlaybackManager, or to decode video directly to some consumer.
2025-10-27 17:28:49 -07:00