Use the demux_set_ts_offset() added in the previous commit to base each
timeline segment to use timestamps according to its relative position
within the overall timeline. As a consequence we don't need to care
about these timestamps anymore, and everything becomes simpler.
(Another minor but delicious nugget of sanity.)
Most of this is explained in the DOCS additions.
This gives us slightly more sanity, because there is less interaction
between the various parts. The goal is getting rid of the video_offset
entirely.
The simplification extends to the user API. In particular, we don't need
to fix missing parts in the API, such as the lack for a seek command
that seeks relatively to the start time. All these things are now
transparent.
(If someone really wants to know the real timestamps/start time, new
properties would have to be added.)
Get rid of get_past_frame_durations(), which was a bit too messy. Add
a past_frames array, which contains the same information in a more
reasonable way. This also means that we can get the exact current and
past frame durations without going through awful stuff. (The main
problem is that vo_pts_history contains future frames as well, which is
needed for frame backstepping etc., but gets in the way here.)
Also disable the automatic disabling of display-sync if the frame
duration changes, and extend the frame durations allowed for display
sync. To allow arbitrarily high durations, vo.c needs to be changed
to pause and potentially redraw OSD while showing a single frame, so
they're still limited.
In an attempt to deal with VFR, calculate the overall speed using the
average FPS. The frame scheduling itself does not use the average FPS,
but the duration of the current frame. This does not work too well,
but provides a good base for further improvements.
Where this commit actually helps a lot is dealing with rounded
timestamps, e.g. if the container framerate is wrong or unknown, or
if the muxer wrote incorrectly rounded timestamps. While the rounding
errors apparently can't be get rid of completely in the general case,
this is still much better than e.g. disabling display-sync completely
just because some frame durations go out of bounds.
The stop command didn't always stop. In this case, opening a HLS URL and
then sending "stop" during loading would actually make it fallback to
parsing it as a playlist, and then continued to play the playlist items.
(This corner case makes several unfortunate factors come together to
produce this really odd behavior.)
Another issue is that the "stop" was not always explicitly set. This
could be a problem when sending several commands at once. Only the
"quit" command should have priority over the "stop" command, so this is
still checked.
This was in sub/, because the code used to be specific to subtitles. It
was extended to automatically load external audio files too, and moving
the file and renaming it was long overdue.
The previous commit was incomplete (and I didn't notice due to a broken
test procedure).
The annoying part is that actually creating the VO was separate; redo
this and merge the code for this into handle_force_window() as well.
This will also make implementing proper reaction to runtime option
changes easier. (Only the part for actually listening to option changes
is missing.)
This is a bad hack; the correct way to handle this would be implementing
profiles differently, and then listen to option changes and act on them
dynamically.
If this mode is enabled, the player tries to strictly synchronize video
to display refresh. It will adjust playback speed to match the display,
so if you play 23.976 fps video on a 24 Hz screen, playback speed is
increased by approximately 1/1000. Audio wll be resampled to keep up
with playback.
This is different from the default sync mode, which will sync video to
audio, with the consequence that video might skip or repeat a frame once
in a while to make video keep up with audio.
This is still unpolished. There are some major problems as well; in
particular, mkv VFR files won't work well. The reason is that Matroska
is terrible and rounds timestamps to milliseconds. This makes it rather
hard to guess the framerate of a section of video that is playing. We
could probably fix this by just accepting jittery timestamps (instead
of explicitly disabling the sync code in this case), but I'm not ready
to accept such a solution yet.
Another issue is that we are extremely reliant on OS video and audio
APIs working in an expected manner, which of course is not too often
the case. Consequently, the new sync mode is a bit fragile.
For video sync, we want separate playback speed controls for user-
requested speed and the "correction" speed for video timing. Further, we
use this separation to make sure only a resampler is inserted if
playback speed is only changed for video sync correction.
As of this commit, this is basically inactive code. It's just
preparation for the video sync code (the following commit).
Additionally to taking the average, this tries to use the demuxer FPS to
eliminate jitter, and applies some other heuristics to check if the
result is sane.
This code will also be used for the display sync code (it will actually
make use of the require_exact parameter).
(The value of doing this over keeping the simpler demux_mkv hack is
somewhat questionable. But at least it allows us to deal with other
container formats that use jittery timestamps, such as mp4 remuxed
from mkv.)
Instead of opening a stream and then a demuxer, do both at once with
demux_open_url().
This requires some awkward additions to demuxer_params, because there
are some weird features associated with opening the main file. E.g. the
relatively useless --stream-capture features requires enabling capturing
on the stream before the demuxer is opened, but on the other hand
shouldn't be done on secondary files like external subtitles.
Also relatively bad: since demux_open_url() returns just a demuxer
pointer or NULL, additional error reporting is done via demuxer_params.
Still, at least conceptually, it's ok, and simpler than before.
Nobody wanted to restore this, so it gets the boot.
If anyone still wants to volunteer to restore menu support, this would
be welcome. (I might even try it myself if I feel masochistic and like
wasting a lot of time for nothing.) But if it does get restored, it
should be done differently. There were many stupid things about how it
was done. For example, it somehow tried to pull mp_nav_events through
all the layers (including needing to "buffer" them in the demuxer),
which was needlessly complicated. It could be done simpler.
This code was already inactive, so this commit actually changes nothing.
Also keep in mind that normal DVD/BD playback still works.
This is a real pain: if a quit command is received, it's set to PT_QUIT.
And then other code could overwrite it, making it not quit. The annoying
bit is that stop_play is written and read in many places. Just not
overwriting it unconditionally seems to be the best course of action.
For the sake of removing the separate stream/demuxer loading code.
This could probably be reimplemented in some other way, but I have no
DVB hardware for testing. The most preferred way would be making DVB to
not quit, and just rerun the stream selection.
The final goal is making opening the demuxer and opening the stream the
same operation.
Stream dumping is a rather uninteresting feature, but has a small
number of vocal users, and it's easy to keep.
At least Matroska files have a "forced" flag (in addition to the
"default" flag). Export this flag. Treat it almost like the default
flag, but with slightly higher priority.
Adding an external audio track before loading the main file didn't work
right. For one, mp_switch_track() assumes it is called after the main
file is loaded. (The difference is that decoders are only initialized
once the main file is loaded, and we avoid doing this before that for
whatever reason.)
To avoid further messiness, just allow mp_switch_track() to be called at
any time. Also make it do what mp_mark_user_track_selection() did, since
the latter requires current_track to be set. (One could probably simply
allow current_track to be set at this point, but it'd interfere with
default track selection anyway and thus would be pointless.)
Fixes#1984.
mp_find_config_file() will print the filename lookup and its result in
verbose mode. This is wanted, but gets inconvenient when it is done for
every playlist entry (for resuming).
Lookup the watch_later subdir only once and cache the result instead.
This drops the logic for loading the resume file from other locations,
which should generally be unnecessary, though might lead to confusion if
the user has mixed old and new config paths (which the user shouldn't).
Also add a mp_find_user_config_file() function for a more
straightforward and reliable way to get actual local configpaths,
instead of possibly global and unwritable locations.
Also, for symmetry, check the resume option in mp_load_playback_resume()
just like mp_check_playlist_resume() does.
Should help with debugging, and might be slightly more userfriendly.
Note that this is called manually in multiple entry-points, instead of
the functions doing the actual work (like mp_remove_track()). This is
done so that exiting the player or calling the sub_reload command won't
print redundant in-between states.
This could make the player crash on exit if the "sub_reload" command was
used successfully. the reason was that the mpctx->sources array could
have dangling pointers to the unloaded demuxers.
Also fix a memory leak by actually always freeing the per-stream
subtitle decoders (which are a hack to make ordered chapters behave
better).
It was possible to make the player play local files by putting rar://
links into remote playlists, and some other potentially unsafe things.
Redo the handling of it. Now the rar-redirector (the thing in
demux_playlist.c) sets disable_safety, which makes the player open any
playlist entries returned. This is fine, because it redirects to the
same file anyway (just with different selection/interpretation of the
contents). On the other hand, rar:// itself is now considered fully
unsafe, which means that it is ignored if found in normal playlists.
Commit f54220d9 attempted to improve this, but it got worse. Now there
was a crash when ytdl_hook.lua added external tracks. This happened
because close_unused_demuxers() assumed that sources[0] was the main
demuxer (so that it didn't close it). This assumption failed, because
the ytdl script can add external tracks before the main file is loaded.
The easy fix would have been to check for master_demuxer, and not i==0.
But instead give up on the old idea, make some stricter assumptions how
demuxers and external tracks map, and simplify the code.
Do timeline building (scanning & opening reference files for ordered
chapters, and more) in a thread. As a result, this process can actually
be stopped without having to kill the player.
This is pretty simple: just reuse the demuxer opening thread. We have
to give up on the idea that open_demux_reentrant() is reusable, though.
(Althoughthe timeline readers still need some fixes before they react to
the quit request.)
These functions do blocking work on a separate thread, but wait until
they return. So they are not async or non-blocking. But they do react to
user-input and client API accesses, which makes them reentrant.
Includes some logic for not starting the demuxer thread for fully read
subtitles. (Well, the cache will still waste _lots_ of resources, and
the cache always has to be created, because we don't know whether it'll
be needed _before_ opening the file.)
See #1597.
Instead of accessing MPContext in player/timeline/*, create a separate
context struct, which the timeline loaders fill out. It turns out that
there's not much in the way too big MPContext that these need to access.
One major PITA is managing (and closing) the set of open demuxers. The
problem is that we need a list of all demuxers to make sure no unneeded
streams are enabled.
This adds a callback to the demuxer_desc struct, with the intention of
leaving to to the demuxer to call the right loader, instead of
explicitly checking the demuxer type and dispatching manually in common
code. I also considered making the timeline part of the demuxer state,
but decided against: it's too much of a mess wrt. memory management and
threading, and also doesn't make it clear who owns the child demuxers.
With the struct timeline decoupled from the demuxer state, it's at least
somewhat clear that the child demuxers are independent from the "main"
demuxer.
The actual changes to player/timeline/* are separated in the following
commits, because they're quite verbose. Some artifacts will be removed
later as soon as there's only 1 timeline loading mechanism.
Also effects some other cases.
The real reason for this is for keeping track of which demuxers can be
closed (see following commit). Since I don't want to use reference
counting for this, some sort of simplistic mark-and-sweep is done to
determine whether a demuxer is still needed.