Commit graph

41 commits

Author SHA1 Message Date
Ali Mohammad Pur
5e1499d104 Everywhere: Rename {Deprecated => Byte}String
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).

This commit is auto-generated:
  $ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
    Meta Ports Ladybird Tests Kernel)
  $ perl -pie 's/\bDeprecatedString\b/ByteString/g;
    s/deprecated_string/byte_string/g' $xs
  $ clang-format --style=file -i \
    $(git diff --name-only | grep \.cpp\|\.h)
  $ gn format $(git ls-files '*.gn' '*.gni')
2023-12-17 18:25:10 +03:30
kleines Filmröllchen
062e0db46c LibCore: Make MappedFile OwnPtr-based
Since it will become a stream in a little bit, it should behave like all
non-trivial stream classes, who are not primarily intended to have
shared ownership to make closing behavior more predictable. Across all
uses of MappedFile, there is only one use case of shared mapped files in
LibVideo, which now uses the thin SharedMappedFile wrapper.
2023-09-27 03:22:56 +02:00
Timothy Flynn
c911781c21 Everywhere: Remove needless trailing semi-colons after functions
This is a new option in clang-format-16.
2023-07-08 10:32:56 +01:00
Zaggy1024
1789905d4a LibVideo/PlaybackManager: Don't crash when demuxer seek throws an error
`seek_demuxer_to_most_recent_keyframe()` wasn't correctly returning in
cases where an error was thrown by the demuxer. To avoid this, the
function now returns the error, and the playback state handler must act
on it instead, allowing it to exit the seeking state early.
2023-06-25 20:35:37 -04:00
kleines Filmröllchen
213025f210 AK: Rename Time to Duration
That's what this class really is; in fact that's what the first line of
the comment says it is.

This commit does not rename the main files, since those will contain
other time-related classes in a little bit.
2023-05-24 23:18:07 +02:00
Zaggy1024
e31f696ee6 LibVideo/PlaybackManager: Use a function to start the internal timer
In addition, this renames the internal timer to better suit its new
purpose since the playback state handlers were added. Not only is it
used to time frame presentations, but also to poll the queue when
seeking or buffering.
2023-05-23 05:17:48 -06:00
Zaggy1024
71d70df34f LibVideo/PlaybackManager: Decode frames off the main thread
Running decoding on the main thread can cause frames to be delayed due
to the presentation timer waiting for a decode to finish. If a frame
takes too long to decode, this delay can be quite visible. Therefore,
decoding has been moved to a separate thread, with frames sent to the
main thread through a thread-safe queue.

This results in frame times going from being late by up to 16ms to a
very consistent ~1-2ms.
2023-05-23 05:17:48 -06:00
Zaggy1024
eae7422ebc LibVideo: Fallibly construct playback manager fields 2023-05-23 05:17:48 -06:00
Caoimhe
465fa3460f LibVideo: Add PlaybackManager::from_mapped_file
This allows us to create a PlaybackManager from a file which has already
been mapped, instead of passing a file name.

This means that anyone who uses `PlaybackManager` can now use LibFSAC :)
2023-05-14 15:56:49 -06:00
Timothy Flynn
374a24d84c LibVideo: Remove hook to override LibVideo's playback timers
This was added to allow Ladybird to override the timers with Qt timers.
2023-04-25 18:02:22 +02:00
Timothy Flynn
f8f35fdaad LibVideo: Remove hook to notify clients upon reaching end of the stream
This reverts commit 33047b38ec.

This use case is now satisfied with on_playback_state_change and getting
the playback state from the PlaybackManager.
2023-04-17 01:16:04 +02:00
Zaggy1024
e391f18e9e LibVideo: Remove Starting playback state in favor of Seeking to zero 2023-04-14 12:05:52 +01:00
Zaggy1024
dc049e36cf LibVideo: Add a method to get the playback state from PlaybackManager 2023-04-14 12:05:52 +01:00
Timothy Flynn
33047b38ec LibVideo: Add a hook to notify clients upon reaching end of the stream 2023-04-11 19:27:55 +02:00
Timothy Flynn
7132047c92 LibVideo: Add a forwarding header
And change some non-plain structs to classes for consistency.
2023-04-09 23:55:05 +02:00
Timothy Flynn
918ed5c920 LibVideo: Add a getter for the PlaybackManager's selected track 2023-04-09 23:55:05 +02:00
Timothy Flynn
519b79abde LibVideo: Add a factory to create a PlaybackManager from in-memory data
The demuxer already has such a factory, so this just exposes the same
factory in the PlaybackManager.
2023-04-09 23:55:05 +02:00
Timothy Flynn
3591a13e85 LibVideo+VideoPlayer: Convert playback event handler to callbacks
To pass events from LibVideo's PlaybackManager to interested parties, we
currently dispatch Core::Event objects that outside callers listen for.
Dispatching events in this manner rely on a Core::EventLoop. In order to
use PlaybackManager from LibWeb, change this mechanism to instead use a
set of callbacks to inform callers of events.
2023-04-09 23:55:05 +02:00
Timothy Flynn
0f2b863c01 LibVideo: Initialize primitive member variables in PlaybackManager
Using uninitialized primitives is undefined behavior. In this case, all
videos would autoplay on Serenity, but not play at all on Lagom, due to
some m_playing booleans being uninitialized.
2023-04-09 23:55:05 +02:00
Zaggy1024
4f26b35640 LibVideo: Create Resuming handler for seek/buffer handlers to inherit
This allows the logic for keeping track of whether to resume to the
paused or the playing state when exiting these states. The new
StartingStateHandler also uses the class, since it can also be paused
and unpaused while waiting for samples.

The pause/play actions on the handlers inheriting from the resuming
handler will also now notify the owner that the state has changed so
that it can change icons, etc.
2023-02-12 18:47:56 +01:00
Zaggy1024
a6b938b407 LibVideo/VideoPlayer: Dispatch state change events and update play icon
The PlaybackStateChangeEvent wasn't connected up anymore, so the player
wouldn't change icons when stopping playback due to reaching the end of
the stream or encountering an error.
2023-02-12 18:47:56 +01:00
Zaggy1024
789bc99b8d LibVideo: Add StartingStateHandler to prepare the first frames of video
This new state handler will retrieve and display the first frame, while
ensuring that playback can start as soon as possible by buffering two
frames on top of the first frame for the PlayingStateHandler to set its
next frame timer by.
2023-02-12 18:47:56 +01:00
Zaggy1024
5da0c6f916 LibVideo: Delay playback errors by their sample timestamps when we can
If we encounter an error in the video decoder, we can set a timestamp
for the error item in the queue so that it will display the error only
when the frame that caused the error would have been displayed.
2023-02-12 18:47:56 +01:00
Zaggy1024
2a228e8a6e LibVideo: Deduplicate logic for dispatching video frame queue items
Previously we had dispatch_decoder_error and on_decoder_error serving
the same function, with one not handling the end of stream properly.

There is also a new function to dispatch either an error or a frame to
the owner of this playback manager, so that PlaybackStateHandlers don't
have to duplicate this logic.
2023-02-12 18:47:56 +01:00
Timothy Flynn
4a916cd379 Everywhere: Remove needless copies of Error / ErrorOr instances
Either take the underlying objects with release_* methods or move() the
instances around.
2023-02-10 09:08:52 +00:00
Zaggy1024
b0db56cd39 VideoPlayer/LibVideo: Seek accurately when scrolling in the seek bar
Fast seeking does not work correctly when seeking in small increments,
so it is necessary to use accurate seeking when using certain actions.

The PlaybackManager has been changed to accept the seek mode as a
parameter to `seek_to_timestamp` to facilitate this. This now means
that it no longer has to track a seek mode preference.
2023-02-08 21:52:42 +01:00
Zaggy1024
3bfef8bfe0 LibVideo: Pass the current sample to demuxers to lazily seek better
In cases where the PlaybackManager's earliest buffered or displayed
sample is closer to the seek target than the demuxer's chosen keyframe,
we don't want to seek at all. To enable this, demuxers now receive an
optional parameter with the earliest timestamp that the caller can
still access.

The demuxer in turn returns an optional to indicate when a seek was not
needed, which allows PlaybackManager to avoid clearing its queue and
re-decoding frames.
2023-02-08 21:52:42 +01:00
Zaggy1024
275d57eb6f LibVideo/PlaybackManager: Organize playback states into virtual classes
Storing playback states in virtual classes allows the behavior to be
much more clearly written. Each `PlaybackStateHandler` subclass can
implement some event-handling functions to model their behavior, and
has functions to change its parent PlaybackManager's state to any other
state.

This will allow expanding the functionality of playback in the future,
for example to allow skipping a single frame forward/backward.
2023-02-08 21:52:42 +01:00
Zaggy1024
a4c7672802 LibVideo: Rename Status -> State in PlaybackStatusChangeEvent class
A bit of a bikeshed, but status sounds more like a result of an action,
and state sounds more accurate to what the `PlaybackManager` does.

The previous and current state fields of the `PlaybackStateChangeEvent`
are now removed, since they were unused (for now).

This is a lead-up to the refactoring of VideoPlaybackManager to make
that diff more legible.
2023-02-08 21:52:42 +01:00
Sam Atkins
5cc4b37bf3 LibVideo: Remove declarations for non-existent methods 2023-01-27 20:33:18 +00:00
Sam Atkins
e181b1cb82 Userland: Use Core::Timer::create_foo() factory functions where possible 2023-01-12 11:25:51 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Zaggy1024
fd3ffd88ce LibVideo: Add a fast seeking mode to seek only to keyframes
Now that we're able to find the nearest keyframe, we can have a fast
seeking mode that only seeks to keyframes, so that it doesn't have to
also decode inter frames until it reaches the timestamp.

The default is still accurate seeking, so that the entire seeking
implementation can be tested.
2022-11-25 23:28:39 +01:00
Zaggy1024
5c2cede2c9 LibVideo: Implement accurate seeking to inter frames in PlaybackManager
This implements the PlaybackManager portion of seeking, so that it can
seek to any frame in the video by dropping all preceding frames until
it reaches the seek point.

MatroskaDemuxer currently will only seek to the start of the video.
That means that every seek has to drop all the frames until it comes
across the target timestamp.
2022-11-25 23:28:39 +01:00
Zaggy1024
9a9fe08449 LibVideo: Rewrite the video frame present function to be more readable
The PlaybackManager::update_presented_frame function was getting out of
hand and adding seeking was making it illegible. This rewrites it to be
(hopefully) quite a bit more readable, and adds a few comments to help
future readers of the code.

In addition, some helpful debugging prints were added that should help
debug any future issues with the player.
2022-11-25 23:28:39 +01:00
Zaggy1024
f31621b3f2 VideoPlayer/LibVideo: Implement the UI functionality for seeking
With these changes, the seek bar can be used, but only to seek to the
start of the file. Seeking to anywhere else in the file will cause an
error in the demuxer.

The timestamp label that was previously invisible now has its text set
according to either the playback or seek slider's position.
2022-11-25 23:28:39 +01:00
Zaggy1024
9cf7e8c5aa LibVideo: Reorganize demuxer file hierarchy and rename Matroska files
As new demuxers are added, this will get quite full of files, so it'll
be good to have a separate folder for these.

To avoid too many chained namespaces, the Containers subdirectory is
not also a namespace, but the Matroska folder is for the sake of
separating the multiple classes for parsed information entering the
Video namespace.
2022-11-25 23:28:39 +01:00
Zaggy1024
87aed17a46 VideoPlayer: Make PlaybackManager use OwnPtr
VideoPlayerWidget was keeping a reference to PlaybackManager when
changing files, so the old and new managers would both send frames to
be presented at the same time, causing it to flicker back and forth
between the two videos. However, PlaybackManager no longer relies on
event bubbling to pass events to its parent. By changing it to send
events directly to an Object, it can avoid being ref counted, so that
it will get destroyed with its containing object and stop sending
events.
2022-11-14 10:05:56 +00:00
Zaggy1024
72ed286e16 LibVideo: Allow the VP9 decoder to queue multiple frames
Frames will now be queued for retrieval by the user of the decoder.
When the end of the current queue is reached, a DecoderError of
category NeedsMoreInput will be emitted, allowing the caller to react
by displaying what was previously retrieved for sending more samples.
2022-11-12 10:17:27 -07:00
Zaggy1024
18a6a1dd10 LibVideo: Handle corrupted video errors without spamming dialogs
No longer will the video player explode with error dialogs that then
lock the user out of closing them.

To avoid issues where the playback state becomes invalid when an error
occurs, I've made all decoder errors pass through the frame queue.
This way, when a video is corrupted, there should be no chance that the
playback state becomes invalid due to setting the state to Corrupted
in the event handler while a presentation event is still pending.
Or at least I think that was what caused some issues I was seeing :^)

This system should be a lot more robust if any future errors need to be
handled.
2022-11-10 12:32:55 +03:30
Zaggy1024
353e1c2b4d LibVideo: Add PlaybackManager to load and decode videos
This file will be the basis for abstracting away the out-of-thread or
later out-of-process decoding from applications displaying videos. For
now, the demuxer is hardcoded to be MatroskaParser, since that is all
we support so far. The demuxer should later be selected based on the
file header.

The playback and decoding are currently all done on one thread using
timers. The design of the code is such that adding threading should
be trivial, at least based on an earlier version of the code. For now,
though, it's better that this runs in one thread, as the multithreaded
approach causes the Video Player to lock up permanently after a few
frames are decoded.
2022-10-31 14:47:13 +01:00