Move the command line parsing and some other things to the common init
routine shared between command line player and client API. This means
they're using almost exactly the same code now.
The main intended side effect is that the client API will load mpv.conf;
though still only if config loading is enabled.
(The cplayer still avoids creating an extra thread, passes a command
line, and prints an exit status to the terminal. It also has some
different defaults.)
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.
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.
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.
These commands are counterparts of sub_add/sub_remove/sub_reload which
work for external audio file.
Signed-off-by: wm4 <wm4@nowhere>
(minor simplification)
mpctx->audio_delay always has the same value as opts->audio_delay. (This
was not the case a long time ago, when the audio-delay property didn't
actually write to opts->audio_delay. I think.)
This is for the ordered chapters case only. In theory this could have
resulted in initial audio, video or subs missing, although it didn't
happen in practice (because no streams were selected, thus the demuxer
thread didn't actually try to read anything). It's still better to make
this explicit.
Also, timeline_set_part() can be private to loadfile.c.
Most of this is explained in the code comments. This change should
improve performance with vapoursynth, especially if concurrent requests
are used.
This should change nothing if vf_vapoursynth is not in the filter chain,
since non-threaded filters obviously can not asynchronously finish
filtering of frames.
This attempts to increase user-friendliness by excluding useless tags.
It should be especially helpful with mp4 files, because the FFmpeg mp4
demuxer adds tons of completely useless information to the metadata.
Fixes#1403.
Until now, these options took effect only at program start. This could
be confusing when e.g. doing "mpv list.m3u --shuffle". Make them always
take effect when a playlist is loaded either via a playlist file, or
with the "loadlist" command.
The code in the demuxer etc. was changed to update all metadata/tags at
once, instead of changing each metadata field. As a consequence,
printing of the tags to the terminal was also changed to print
everything on each change.
Some users didn't like this. Add a very primitive way to avoid printing
fields with the same value again if metadata is marked as changed. This
is not always correct (could print unchanged fields anyway), but usually
works.
(In general, a rather roundabout way to reflect a changed title with ICY
streaming...)
Fixes#813 (let's call it a "policy change").
This adds API to libmpv that lets host applications use the mpv opengl
renderer. This is a more flexible (and possibly more portable) option to
foreign window embedding (via --wid).
This assumes that methods like context sharing and multithreaded OpenGL
rendering are infeasible, and that a way is needed to integrate it with
an application that uses a single thread to render everything.
Add an example that does this with QtQuick/qml. The example is
relatively lazy, but still shows how relatively simple the integration
is. The FBO indirection could probably be avoided, but would require
more work (and would probably lead to worse QtQuick integration, because
it would have to ignore transformations like rotation).
Because this makes mpv directly use the host application's OpenGL
context, there is no platform specific code involved in mpv, except
for hw decoding interop.
main.qml is derived from some Qt example.
The following things are still missing:
- a way to do better video timing
- expose GL renderer options, allow changing them at runtime
- support for color equalizer controls
- support for screenshots
There were complaints that a chapter seek past the last chapter was
quitting the player. Change the behavior to what is expected: the last
frame.
If no chapters are available, this still does nothing.
It feels strange that seeking past EOF with --keep-open actually leaves
the player at a random position. You can't even unpause, because the
demuxer is in the EOF state, and what you see on screen is just what was
around before the seek.
Improve this by attempting to seek to the last video frame if EOF
happens. We explicitly don't do this if EOF was reached normally to
increase robustness (if the VO got a frame since the last seek, it
obviously means we had normal playback before EOF).
If an error happens when trying to find the last frame (such as not
actually finding a last frame because e.g. the demuxer misbehaves), this
will probably turn your CPU into a heater. There is no logic to prevent
reinitiating the last-frame search if the last-frame search reached EOF.
(Pausing usually prevents that EOF is reached again after a successful
last-frame search.)
Fixes#819.
libass won't use embedded fonts, unless ass_set_fonts() (called by
mp_ass_configure_fonts()) is called. However, we call this function when
the ASS_Renderer is initialized, which is long before the .ass file is
actually loaded. (I'm not sure why it tries to keep 1 ASS_Renderer, but
it always did this.)
Fix by calling mp_ass_configure_fonts() after loading them. This also
means this function will be called multiple times - hopefully this is
harmless (it will reinit fontconfig every time, though).
While we're at it, also initialize the ASS_Renderer lazily.
Fixes#1244.
Instead of defining a separate data structure in the core.
For some odd reason, demux_chapter exported the chapter time in
nano-seconds. Change that to the usual timestamps (rename the field
to make any code relying on this to fail compilation), and also remove
the unused chapter end time.
If you played e.g. an audio-only file and something bad happened that
interrupted playback, the exit message could say "No files played".
This was awkward, so show a different message in this case.
Also overhaul how the exit status is reported in order to make this
easier. This includes things such as not reporting a playback error
when loading playlists (playlists contain no video or audio, which
was considered an error).
Not sure if I'm happy with this, but for now it seems like a slight
improvement.
Use the codepath that is normally used for DVD/BD title switching and
DVB channel switching. Removes some extra artifacts from the client API:
now MPV_EVENT_END_FILE will never be called on reloads (and neither is
MPV_EVENT_START_FILE).
No development activity (or even any sign of life) for almost a year.
A replacement based on youtube-dl will probably be provided before the
next mpv release. Ask on the IRC channel if you want to test.
Simplify the Lua check too: libquvi linking against a different Lua
version than mpv was a frequent issue, but with libquvi gone, no
direct dependency uses Lua, and such a clash is rather unlikely.
The player was supposed to exit playback if both video and audio failed
to initialize (or if one of the streams was not selected when the other
stream failed). This didn't work; for one this check was missing from
one of the failure paths. And more importantly, both checked the
current_track array incorrectly.
Fix these issues, and move the failure handling code into a common
function.
CC: @mpv-player/stable
Apparently using the stream index is the best way to refer to the same
streams across multiple FFmpeg-using programs, even if the stream index
itself is rarely meaningful in any way.
For Matroska, there are some possible problems, depending how FFmpeg
actually adds streams. Normally they seem to match though.
A vague idea to get something similar what libquvi did.
Undocumented because it might change a lot, or even be removed. To give
an idea what it does, a Lua script could do the following:
-- type ID priority
mp.commandv("hook_add", "on_load", 0, 0)
mp.register_script_message("hook_run", function(param, param2)
-- param is "0", the user-chosen ID from the hook_add command
-- param2 is the magic value that has to be passed to finish
-- the hook
mp.resume_all()
-- do something, maybe set options that are reset on end:
mp.set_property("file-local-options/name", "value")
-- or change the URL that's being opened:
local url = mp.get_property("stream-open-filename")
mp.set_property("stream-open-filename", url .. ".png")
-- let the player (or the next script) continue
mp.commandv("hook_ack", param2)
end)
This reverts commit 45c8b97efb.
Some else complained (github issue #1163).
The feature requested in #1148 will be implemented differently in
the following commit.
After @frau's split of macosx_events from macosx_application, `is_cplayer' is
not needed anymore. At the moment only global events such as Media Keys and
Apple Remote work, because the VO-level ones were hardcoded to be disabled.
(that will be fix in a later commit ).
Now any action that stops playback of a file (even playlist navigation)
will save the position. Normal EOF is of course excluded from this, as
well as commands that just reload the current file.
The option name is now slightly off, although you could argue what the
word "quit" means.
Fixes#1148 (or at least this is how I understood it).
Run opening the stream and opening the demuxer in a separate thread.
This should remove the last code paths in which the player can normally
get blocked on network.
When the stream is opened, the player will still react to input and so
on. Commands to abort opening can also be handled properly, instead of
using some of the old hacks in input.c. The only thing the user can
really do is aborting loading by navigating the playlist or quitting.
Whether playback abort works depends on the stream implementation; with
normal network, this will depend on what libavformat (via "interrupt"
callback) does.
Some pain is caused by DVD/BD/DVB. These want to reload the demuxer
sometimes. DVB wants it in order to discard old, inactive streams.
DVD/BD for the same reason, and also for reloading stream languages
and similar metadata. This means the stream and the demuxer have to
be loaded separately.
One minor detail is that we now need to copy all global options. This
wasn't really needed before, because the options were accessed on
opening only, but since opening is now on a separate thread, this
obviously becomes a necessity.
Also recreate ASS_Library on every file played. This means we can move
the code out of main.c as well.
Recreating the ASS_Library object has no disadvantages, because it
literally stores only the message callback, the (per-file) font
attachment as byte arrays, and the set of style overrides. Hopefully
this thing can be removed from the libass API entirely at some point.
The only reason why the player core creates the ASS_Renderer, instead
of the subtitle renderer, is because we want to cache the loaded fonts
across ordered chapter transitions, so this probably still has to stay
around for now.
Each subsystem (or similar thing) had an INITIALIZED_ flag assigned. The
main use of this was that you could pass a bitmask of these flags to
uninit_player(). Except in some situations where you wanted to
uninitialize nearly everything, this wasn't really useful. Moreover, it
was quite annoying that subsystems had most of the code in a specific
file, but the uninit code in loadfile.c (because that's where
uninit_player() was implemented).
Simplify all this. Remove the flags; e.g. instead of testing for the
INITIALIZED_AO flag, test whether mpctx->ao is set. Move uninit code
to separate functions, e.g. uninit_audio_out().
This would play some silence in case video was slower than audio. If
framedropping is already enabled, there's no other way to keep A/V
sync, short of changing audio playback speed (which would give worse
results). The --audiodrop option inserted silence if there was more
than 500ms desync.
This worked somewhat, but I think it was a silly idea after all. Whether
the playback experience is really bad or slightly worse doesn't really
matter. There also was a subtle bug with PTS handling, that apparently
caused A/V desync anyway at ridiculous playback speeds.
Just remove this feature; nobody is going to use it anyway.
Eliminate the remains of the OSD message stack. Another simplification
comes from the fact that we do not need to care about time going
backwards (we always use a monotonic time source, and wrapping time
values are practically impossible). What this code was pretty trivial,
and by now unnecessarily roundabout.
Merge get_osd_msg() into update_osd_msg(), and add_osd_msg() into
set_osd_msg_va().
There's no need to update OSD messages and the terminal status if nobody
is going to see it. Since the player doesn't block on video display
anymore, this update happens to often and probably burns slightly more
CPU than necessary. (OSD redrawing is handled separately, so it's just
mostly useless text processing and such.)
Change it so that it's updated only on every video frame or all 50ms
(whatever comes first).
For VO OSD, we could in theory try to lock to the OSD redraw heuristic
or the display refresh rate, but that's more complicated and doesn't
work for the terminal status.
Be less annoying, print the actual OSD level instead of something
meaningless, but still clear the OSD if OSD level 0 (no OSD) is set.
Remove the special handling for terminal OSD, that was just dumb.
Probably not many user-visible changes. One notable change is that the
terminal OSD code for OSD bar fallback handling is removed with no
replacement. Instead, terminal OSD gets the same text message as normal
OSD. For volume, this is ok, because the text message is reasonable.
Other properties will look worse, but could be adjusted, and there are
in fact no other such properties that would be useful in audio-only
mode.
The fallback message for seeking falls away as well, but that message
was useless anyway - the terminal status line provides all information
anyway.
I believe the show_property_osd() code is now much easier to follow.