Compare commits

...
1326 Commits
Author SHA1 Message Date
sfan5 091aa96c4d Release 0.31.0 2019-12-28 12:07:07 +01:00
wm4 499a41ea35 DOCS/tech-overview.txt: some more blabla
This file is only complete once it contains the entire mpv source code
in English form.
2019-12-28 10:09:28 +01:00
wm4 025e77eaf1 audio: react to --ao and --audio-buffer runtime changes
Before this commit, runtime changes were only applied if something else
caused audio to be reinitialized. Now setting them reinitializes audio
explicitly.
2019-12-27 17:56:22 +01:00
wm4 0c0c373844 m_option: fix runtime changing of --audio-channels
This option type, used by --audio-channels, had a completely broken
m_option_type.equal implementation, and thus reacted incorrectly to
runtime option changes.

Broken since commit b16cea750f.
2019-12-27 17:44:33 +01:00
wm4 2a7e17fe4e DOCS/tech-overview.txt: add lots of irrelevant blabla
Thought it might be useful to document some of these things, instead of
explaining them over and over again. But I can guarantee that nobody
will ever read all this. (Independent of its quality and completeness.)
2019-12-27 17:09:47 +01:00
der richter 1caa653f2d cocoa-cb: force redraw when screen or size changes
in certain circumstances the video was not redrawn even when the size
or the backing scale factor changed. this could lead to a lower
resolution output than intended.

now it redraws the video when screen properties or the window size
changes.
2019-12-24 21:51:24 +01:00
der richter d9e13f42b8 cocoa-cb: implement hidpi scale reporting 2019-12-24 21:51:24 +01:00
wm4 8e9644761a console: add a basic help command
It's not really great. But I think it's good enough to save someone
who's lost. Most importantly, it should become obvious _what_ the
console expects (input commands), and how to exit it.

Would be nice if we could show some documentation, or give a link to
documentation, but that's out of scope and/or not easy.

I considered implementing the "help" command as builtin command in
command.c. On the other hand, this could not show console.lua specific
help, so I implemented it in console.lua. The ad-hoc command parsing
(that sort-of mirrors mpv input command syntax) for the "help" command
is probably the worst part of this.
2019-12-24 16:08:04 +01:00
wm4 1d2fcb9227 console: do not strip leading spaces
As suggested by TheAMM and avih.
2019-12-24 16:04:00 +01:00
wm4 029bb593e7 command: extend command-list output
Add some very basic information about arguments.
2019-12-24 16:03:16 +01:00
wm4 b6d7d246fe manpage: fix example in --hwdec section 2019-12-24 16:02:49 +01:00
wm4 b9084dfd47 stats: do not use "tick" event
It's deprecated. The new solution works almost exactly the same way
(since the still existing internal tick event triggers vsync-jitter
change command), though as far as API usage goes, it's somewhat
questionable. (The comment is meant to discourage anyone trying to copy
the idea for external scripts.)
2019-12-24 16:02:24 +01:00
Niklas Haas f868052872 build: force bootstrap.py to use python3
The script fails running successfully with python2.
2019-12-24 12:22:36 +01:00
wm4 2636bbbf33 osc: redraw on visibility option runtime changes
This affects behavior when using the "del" default key binding.
Sometimes, setting visibility to always did not draw it correctly. This
probably fixes it.
2019-12-24 09:50:08 +01:00
wm4 67650446b5 vd_lavc: remove hwdec-by-default special case for RPI 2019-12-24 09:24:56 +01:00
wm4 380f01567d vd_lavc: more hwdec autoselect nonsense
Add an "auto-safe" mode, mostly triggered by Ubuntu's nonsense to force
hwdec=vaapi in the global config file in their mpv package. But to be
honest it's probably something more people want.

This is implemented as explicit whitelist. On Windows, HEVC/Intel is
sometimes broken, but it's still whitelisted, and in theory we'd need a
detailed whitelist of device names etc. (like for example browsers tend
to do). On OSX, videotoolbox is a pretty bad choice, but unfortunately
the only one, so it's whitelisted too. There may be a larger number of
hwdec wrappers that work anyway, and I'm for example ignoring Android.
2019-12-24 09:24:22 +01:00
der richter e7add205d8 build: fix build with disabled swift and Media Player
when swift is disabled some headers are not included. one of them is the
options/options.h header that is needed for the vo_sub_opts struct. we
include it to fix the build without swift.

the second problem is the build time check for the macOS 10.12.2
features or more specific the Media Player support. since it is a swift
feature we can not use it when swift is disabled. add a separate
Media Player check that also depends on swift and use that new
preprocessor variable as a build time check instead.

Fixes #7282
2019-12-23 23:44:20 +01:00
Avi Halachmi (:avih) 9f2fda7d85 js: support mp.create_osd_overlay (match 07287262)
The legacy mp.set_osd_ass(...) is still supported (but also still
undocumented) as a wrapper for the new mp.create_osd_overlay(...).
2019-12-23 17:52:34 +02:00
Avi Halachmi (:avih) 5a74bf5f95 js: batch key bindings updates (match 96932fe7)
Implemented using one-time idle observer (i.e. setTimeout), to avoid
additional function call(back) every time the event loop enters idle.

The lua mp.flush_key_bindings() is also available, also undocumented.
2019-12-23 17:52:34 +02:00
Nicolas F 7ed70f925b osc: add option to disable santa hat
A minority of users have expressed a dislike of hats, calling them
"cancer [that] don't belong in software" describing the people who add
them as "shitty circlejerks" and "chucklefuck."

While I personally disagree with those opinions, it's probably easier
to let them have it their way. For that reason this adds the option
`greenandgrumpy` to the osc, which allows users to disable the hat.
2019-12-23 16:38:41 +01:00
wm4 091ee9d770 lua: fix guard against division by 0
This was incorrectly converted from the original C code. Change it to
what the original code used.
2019-12-23 16:10:06 +01:00
wm4 d951a7f021 lua: fix passing non-integers to mp.set_osd_ass()
libass uses integers for PlayResX/Y, so the osd-overlay command also
does. Lua (pre-5.3) does not have an integer type, but the command
interface makes a difference anyway. If you pass a Lua number with a
fractional part to an integer parameter (using mp.command_native()), it
will result in an error and complain about incompatible types.

I think that's fine, but since this behavior extends to
mp.set_osd_ass(), this is a compatibility problem.

Fix this by explicitly coercing the resolution parameters to integer
numbers.
2019-12-23 13:23:10 +01:00
wm4 86d24b069b osc: set an arbitrary high Z-order
The main reason for this is just to make show the OSC always above
console.lua, instead of a random order.

(And this is also the only reason osc.lua was changed to the new API.
The old API could have been extended, but lets not.)
2019-12-23 12:06:33 +01:00
wm4 490b3ba007 osc: use new overlay API
This tries to avoid the update() call if nothing changed. This brings it
more into line with the old code (the osd-overlay command simply does
not skip the update if nothing changed). I don't know whether this
matters; most likely not. Normally, code should try to avoid redundant
updates on its own, so it's not the job of the command. However, for the
OSC we simply want to reduce the differences.
2019-12-23 11:48:16 +01:00
wm4 0728726251 client API, lua: add new API for setting OSD overlays
Lua scripting has an undocumented mp.set_osd_ass() function, which is
used by osc.lua and console.lua. Apparently, 3rd party scripts also use
this. It's probably time to make this a public API.

The Lua implementation just bypassed the libmpv API. To make it usable
by any type of client, turn it into a command, "osd-overlay".

There's already a "overlay-add". Ignore it (although the manpage admits
guiltiness). I don't really want to deal with that old command. Its main
problem is that it uses global IDs, while I'd like to avoid that scripts
mess with each others overlays (whether that is accidentally or
intentionally). Maybe "overlay-add" can eventually be merged into
"osd-overlay", but I'm too lazy to do that now.

Scripting now uses the commands. There is a helper to manage OSD
overlays. The helper is very "thin"; I only want to force script authors
to use the ID allocation, which may help with putting multiple scripts
into a single .lua file without causing conflicts (basically, avoiding
singletons within a script's environment). The old set_osd_ass() is
emulated with the new API.

The JS scripting wrapper also provides a set_osd_ass() function, which
calls internal mpv API. Comment that part (to keep it compiling), but
I'm leaving it to @avih to finish the change.
2019-12-23 11:44:24 +01:00
wm4 96932fe77c lua: batch-update key bindings
Lua scripting implements key bindings by defining an input section with
all the bindings in it. Every add_key_binding() call ran a mpv command
to update this section. This caused a lot of spam at debug log levels.

Reduce the spam and more it efficient by batching updates into a single
mpv command when the script becomes inactive. This is pretty simple,
because there's already the concept of idle handlers.

This requires that the script actually goes to sleep, which might not
happen in various extremely bogus corner cases, such as polling the mpv
message queue with active waiting. Just don't do that.
2019-12-23 11:17:01 +01:00
wm4 346c651de3 manpage: document that --vo=xv breaks "boxvideo"
(OK, maybe a bit redundant, since vo=xv breaks a lot of stuff.)
2019-12-23 11:11:24 +01:00
wm4 36da3325a3 demux: stop setting dummy stream on demux_close_stream()
Demuxers can call demux_close_stream() to close the underlying stream if
it's not needed anymore. (Useful to release "heavy" resources like FDs
and sockets. Plus merely keeping a file open can have visible side
effects such as inability to unmount a filesystem or, on Windows, to do
anything with the file.)

Until now, this set demuxer->stream to a dummy stream, because most code
used to assume that the stream field is non-NULL. But this requirement
disappeared (in some cases, the stream field is already NULL), so stop
doing that. demux_lavf.c, one of the demuxers which calls this function,
still had some of this, though.
2019-12-23 11:09:42 +01:00
wm4 af6652004d stream_concat, stream_memory: more stream_origin stuff
Make concat streams use the "worst" origin of its parts, which may or
may not be what makes sense. stream_memory has no natural way to do
this, so just add a vague comment.
2019-12-23 11:03:44 +01:00
wm4 ba45b67370 bstr: remove unused bstr_splitlines() function 2019-12-23 11:01:56 +01:00
wm4 cd09ea92be demux_mf: use stream API to open list files
mf:// has an obscure feature that lets you pass a list of filenames
separated by newlines. Who knows whether anyone is using that. It opened
these listfiles with fopen(), so the recent stream origin bullshit
doesn't operate on it. Fix this by using the mpv internal stream API
instead. Unfortunately there is no fgets(), so write an ad-hoc one. (An
implementation of line reading via "stream" is still in demux_playlist,
but it's better to keep it quarantined there.)
2019-12-23 11:01:29 +01:00
TheAMM 6d93e4cb22 osc: display Santa hat for idle logo in December
During the 12th month (checked during script initialization), draw a Santa hat
on top of the idle message's logo.
Slightly refactors and optimizes the drawing process as well: reorder original
logo layers and remove redundant holes in them, use a shared line prefix
to clear the style and set start position.

Signed-off-by: wm4 <wm4@nowhere>
2019-12-23 01:45:34 +01:00
wm4 0eabc6614a client API: deprecate tick event
This is conceptually outdated and should not exist. This affects Lua
scripting and JSON IPC too.
2019-12-22 14:37:28 +01:00
Avi Halachmi (:avih) b670838b3d js: read_options: on_update: don't re-read the config file
Now that 00af718a made the lua read_options behavior much more similar
to the js behavior, the main difference was that lua does not re-read
the config file at on_update (but it does re-apply its stored content)
while js did re-read it.

Now the js on_update also does not re-read the config file and instead
applies its stored original content.

This is slightly hacky by adding an undocumented optional 4th argument
to read_options which allows overriding the config file content.
2019-12-22 14:51:13 +02:00
wm4 3267bcd210 console: reduce border size
This looks better if the ASS canvas size is used to scale according to
HiDPI factor (instead of font size).
2019-12-22 12:52:36 +01:00
wm4 b899504862 osc: use video margins only if OSC is visible
Looks awkward otherwise. This means that even if boxvideo is enabled,
nothing gets "boxed" if the OSC is set to auto-hide.
2019-12-22 12:50:29 +01:00
wm4 6bf1a83057 osc: cleanup boxvideo margin handling
Make sure it gets properly reinitialized when needed. This is especially
useful now that the OSC reacts to runtime option changes, which can
change the layout too.

This may call set_property_number() on the margin properties more often
now, but since redundant option changes are ignored now, this shouldn't
have any too bad effects.
2019-12-22 12:44:26 +01:00
wm4 12843dcea1 osc: full reinit on runtime option changes
Fuck it, just let's just reinit everything.

On a side note, the changelist parameter provided by read_options()
(here "list") is now unused. But it's not hard to provide and might be
useful for other stuff. So don't remove it from the generic
read_options() code.
2019-12-22 12:32:50 +01:00
wm4 00af718a9e lua: change runtime option change behavior
As described in the manpage changes. This makes more sense than the
previous approach, where options could "unexpectedly" stick. Although
this is still a somewhat arbitrary policy (ask many people and you'd get
a number of different expectations on what should happen), I think that
it reflects what mpv's builtin stuff does.

All the copying is annoying, but let's just hope nobody is stupid enough
to change these properties per video frame or something equally
ridiculous.
2019-12-22 12:30:53 +01:00
wm4 9e15e3ad8f demux: remove debug abort()
WHAT THE FUCK

Fixes: #7279
2019-12-22 04:57:18 +01:00
Niklas Haas 2a70140ba8 vo_gpu: vulkan: set allow_suboptimal when possible
This was added in libplacebo v1.29.0 and allows making resizes slightly
smoother for clients that already handle resize events (such as mpv).
2019-12-22 03:55:07 +01:00
Nicolas F 93a6308bb7 video/out/x11: add fs-screen fallback
Apparently there are two different options for controlling which
screen an mpv window goes onto: --fs-screen and --screen. The former
explicitly only controls which screen a fullscreened window goes onto,
but does not appear to actually care about this option at runtime for
X11, so pressing f will always fullscreen to the screen mpv is currently
on. This means the option is of questionable usefulness for starters.

Making it worse, if you use --screen=1 --fs, mpv will actually fullscreen
on screen 0, because --fs-screen isn't set. Instead of doing that, fall
back to whatever --screen is set to.
2019-12-22 02:33:48 +01:00
Abdullah Alansari e6bdd94cb2 command: fix confusing displayed aspect-ratio
For example, when a user switches the aspect-ratio display `16:9`
instead of `1.778` and `Original` instead of `-1.000`.
2019-12-22 02:32:50 +01:00
Avi Halachmi (:avih) 71ddb22b39 js: read_options: support on_update (match 478a321d)
This is a bit different than the lua code: on script-opts change it
simply re-applies the conf-file and script-opts to the options object,
and if this results in any changed value at options then on_update is
called with the changelist as argument.

This allows a value to revert back to the conf-file value if the
matching script-opts key had a different value and then got deleted.
It also guarantees to call back whenever the options object is
modified, which the lua code doesn't do (e.g. if the caller changed
a value and the observer changed it back - it won't detect a change).
2019-12-21 14:57:10 +02:00
wm4 05fb6f906d osc: cosmetics: remove some excessive whitespace 2019-12-20 14:25:56 +01:00
wm4 b439588172 osc: react to script-opts runtime changes
With special attention to changing osc-visibility. Untested, although
osc-visibility works (it's pretty much equivalent to the key binding, so
there is not much interesting going on).

Somewhat inspired by code posted by github user CogentRedTester.

Fixes: #4513
2019-12-20 14:24:36 +01:00
wm4 478a321dcc lua: add a helper for runtime script option changes
A script can use this to easily get runtime updates. (Even if
script-opts is sort of clunky.)
2019-12-20 14:21:16 +01:00
wm4 db1e28f175 osc: rearrange hidetimeout/visibiltiy handling
The way how this modifies and backups/restores user option values is a
bit of a problem for runtime option changing.

Clean this up a little. Now cycling the visibility updates the user
option value, but always to "valid" values (unlike hidetimeout used to
be used). If the user option value is changed externally (enabled by a
later commit), it'll be cleanly overwritten.
2019-12-20 13:44:59 +01:00
wm4 70c5401952 osc: move windowcontrols option code to the right place
There doesn't seem to be a reason why it was where it was. It should be
in validate_user_opts(), which will be important for runtime changing
too.
2019-12-20 13:21:49 +01:00
wm4 7338e3d8fe manpage: add osc and console default keys to keyboard control section
Although they were not undocumented, they were hidden away in the
respective manpage sections. It's a good idea to add them to the main
keyboard bindings overview too. stats.lua also did this.
2019-12-20 13:00:39 +01:00
wm4 05cd4c9e08 console: use hidpi scale reporting
I decided to factor this into the user's scale option (instead of
somehow using it as default if the user has not specified it), because
it makes the option handling simpler, and won't break things like
per-screen DPI if the user only wants to scale the console font by a
factor.
2019-12-20 13:00:39 +01:00
wm4 ac474631c1 x11: implement hidpi scale reporting
(X11 does not support different per-screen DPI (or only via hacks), so
this is pretty simple. If other backends are going to implement this,
then they should send VO_EVENT_WIN_STATE if the DPI for the mpv window
changes by moving it to another screen or such.)
2019-12-20 13:00:39 +01:00
wm4 8e620c8e76 command: add property returning hidpi scale 2019-12-20 13:00:39 +01:00
wm4 8448fe0b62 demux: add an option to control tag charset
Fucking gross that you need this in almost-2020.

Fixes: #7255
2019-12-20 13:00:39 +01:00
wm4 0e98b2ad8e edl: accept arbitrary paths
Until now, .edl files accepted only "simple" filenames, i.e. no relative
or absolute paths, no URLs. Now that the origin bullshit is a bit
cleaned up and enforced in the EDL code, there's absolutely no reason to
keep this.

The new code behaves somewhat similar to playlists. (Although playlists
are special because they're not truly recursively opened.)
2019-12-20 13:00:39 +01:00
wm4 1cb9e7efb8 stream, demux: redo origin policy thing
mpv has a very weak and very annoying policy that determines whether a
playlist should be used or not. For example, if you play a remote
playlist, you usually don't want it to be able to read local filesystem
entries. (Although for a media player the impact is small I guess.)

It's weak and annoying as in that it does not prevent certain cases
which could be interpreted as bad in some cases, such as allowing
playlists on the local filesystem to reference remote URLs. It probably
barely makes sense, but we just want to exclude some other "definitely
not a good idea" things, all while playlists generally just work, so
whatever.

The policy is:
- from the command line anything is played
- local playlists can reference anything except "unsafe" streams
  ("unsafe" means special stream inputs like libavfilter graphs)
- remote playlists can reference only remote URLs
- things like "memory://" and archives are "transparent" to this

This commit does... something. It replaces the weird stream flags with a
slightly clearer "origin" value, which is now consequently passed down
and used everywhere. It fixes some deviations from the described policy.

I wanted to force archives to reference only content within them, but
this would probably have been more complicated (or required different
abstractions), and I'm too lazy to figure it out, so archives are now
"transparent" (playlists within archives behave the same outside).

There may be a lot of bugs in this.

This is unfortunately a very noisy commit because:
- every stream open call now needs to pass the origin
- so does every demuxer open call (=> params param. gets mandatory)
- most stream were changed to provide the "origin" value
- the origin value needed to be passed along in a lot of places
- I was too lazy to split the commit

Fixes: #7274
2019-12-20 13:00:39 +01:00
wm4 572c32abbe libarchive: prefix entry names in archive URLs with '/'
This has the advantage that playlists within the archive will work as
expected, because demux_playlist will correctly join the archive base
URL and entry name. Before this change, it could skip before the "|",
resulting in a broken URL.
2019-12-20 08:35:08 +01:00
wm4 505cab9c15 osc: fix a comment 2019-12-20 00:53:42 +01:00
wm4 99cc13e3d1 osc: fade out if paused and mouse position is outside of OSC
This broke with the recent changes since tick() is not called regularly
anymore in paused mode. Add an explicit timer for this.
2019-12-19 22:43:22 +01:00
wm4 69fb2ddbc7 osc: fix crash when toggling visibility
The previous osc.lua related commit removed this function, and trying to
call it crashed the OSC. Just remove the call.
2019-12-19 22:10:09 +01:00
Avi Halachmi (:avih) 3460a7b696 js: support shared script properties (match 7e4819e7) 2019-12-19 16:23:19 +02:00
Avi Halachmi (:avih) 4fc5cd32d0 js: require: allow custom module search paths via mp.module_paths 2019-12-19 16:23:19 +02:00
Avi Halachmi (:avih) 3d2e30d764 DOCS: js: minor update for modules/require 2019-12-19 16:23:19 +02:00
wm4 c4ae7d8203 osc: don't run update_margins() every frame
This is something recent that also caused per frame log spam, because it
tried to update the margins every frame.
2019-12-19 12:53:37 +01:00
wm4 3ed96cca88 command: reduce OSC/stats log spam
For some inexplicable reason, the OSC runs the expand-text command a
_lot_. This command is logged at the log file default log level, so the
log file can quickly fill up with these messages. It directly violates
the mpv logging policy: per-frame (or similarly common) log messages
should not be enabled by default for the log file.

stats.lua uses the show-text command for some reason (instead of
creating its own OSD layer).

Explicitly reduce the log level for expand-text and some other commands.
Also reduce the log level for commands triggered by mouse movement.

The previous commit also contributed some to reduce log spam.

Fixes: #4771
2019-12-19 12:52:13 +01:00
wm4 48f906249e osc: use property notifications and a timer instead of "tick" events
Traditionally, the OSC used mpv's "tick" event, which was approximately
sent once per video frame. It didn't try to track any other state, and
just updated everything.

This is sort of a problem in many corner cases and non-corner cases. For
example, it would eat CPU in the paused state (probably to some degree
also the mpv core's fault), or would waste power or even throw errors
("event queue overflows") on high FPS video.

Change this to not using the tick event. Instead, react to a number of
property change events. Rate-limit actual redrawing with a timer; the
next update cannot happen sooner than the hardcoded 30ms OSC frame
duration. This has also the effect that multiple successive updates are
(mostly) coalesced.

This means the OSC won't eat your CPU when the player is fucking paused.
(It'll still update if e.g. the cache is growing, though.) There is some
potential for bugs whenever it uses properties that are not explicitly
observed. (In theory we could easily change this to a reactive concept
to avoid such things, but whatever.)
2019-12-19 12:41:01 +01:00
wm4 ce9d2c9f8e client API: remove comment about error status
mpv_event_property (for property observation) actually never sets an
error status. You cannot distinguish between unavailable properties and
properties which returned an error. Not sure if it ever did.
2019-12-19 11:21:30 +01:00
wm4 b054abe7fc manpage: lua: mention what happens on unavailable properties
Kind of as big one if the user unexpectedly gets nil instead of a value.
2019-12-19 11:19:15 +01:00
wm4 2c5cb2c53f client API: rewrite property observation (again)
I intend to rewrite this code approximately every 2 months.

Last time, I did this in commit d66eb93e5d (and 065c307e8e and
b2006eeb74). It was intended to remove the roundabout synchronous
thread "ping pong" when observing properties. At first, the original
async. code was replaced with some nice mostly synchronous code. But
then an async. code path had to be added for vo_libmpv, and finally the
sync. code was dropped because it broke in other obscure cases (like the
Objective-C Cocoa backend).

Try again. This time, update properties entirely on the main thread.
Updates get batched out on every playloop iteration. (At first I wanted
it to make it every time the player goes to sleep, but that might starve
API clients if the playloop get saturated.) One nice thing is that
clients only get woken up once all changed events have been sent, which
might reduce overhead.

While this sounds simple, it's not. The main problem is that reading
properties must not block the client API, i.e. no client API locks can
be held while reading the property. Maybe eventually we can avoid this
requirement, but currently it's just a fact. This means we have to
iterate over all clients and then over all properties (of each client),
all while releasing all locks when updating a property. Solve this by
rechecking on each iteration whether the list changed, and if so,
aborting the iteration and redo it "next time".

High risk change, expect bugs such as crashes and missing property
updates.
2019-12-19 11:11:51 +01:00
wm4 f719b63840 options: fix incorrect deprecation message
Passing multiple items to a key/value option is OK, only for -add
suffixed options it's deprecated.
2019-12-19 01:17:01 +01:00
wm4 7142214243 options: fix UB/crash in key/values parser
keyvalue_list_find_key() was called on a "partially" constructed list,
because the terminating NULL was added only later. Didn't I say this
code is cursed?

Fixes: #7273
2019-12-18 18:44:21 +01:00
wm4 09ea3a424f console: adjust position to OSC
See previous commit.
2019-12-18 09:04:15 +01:00
wm4 4787eb594a osc: make margins available
This is for console.lua (see next commit). The idea is that console.lua
can adjust its offset to the bottom of the window by the height of the
OSC.

If the OSC is not set to permanently visible, export no margins, because
it would look weird to move the console depending on the mouse movement.
2019-12-18 09:03:32 +01:00
wm4 7e4819e705 command, lua: add a way to share data between scripts
Very primitive and dumb, but fulfils its purpose for the next commits.

I chose this specific implementation because it has the lowest footprint
in command.c, without resorting to crazy hacks such as sending messages
between scripts (which would be hard to coordinate especially on
startup).
2019-12-18 08:58:49 +01:00
wm4 6ab013cbdd command: make change-list work with pure properties too
Until now, it only worked on options. Useful for the next commit.
2019-12-18 07:50:48 +01:00
wm4 11d35b72a6 x11: fix X property out of bounds memory reads
The size overflow check was inverted: instead of allowing reading only
the first dst_size bytes of the property, it allowed copying past the
property buffer (as returned by xlib). xlib doesn't return the size of
the buffer in bytes, so it has to be computed and checked manually.

Wouldn't it be great if C allowed me to write the overflow check in a
readable way, so it doesn't trick me into writing dumb security bugs?

Relying on X security is even dumber than creating a X security bug,
though, so this was not a real problem. But I found that one specific
call tried to read more than what the property provided, so reduce that.

Also, len*ib obviously can't overflow, so there's an additional layer of
dumb to this whole thing.

While we're at dumb things, why the hell does xlib use "long" for 32 bit
types. It's a god damn pain.
2019-12-18 07:12:53 +01:00
wm4 5f74ed5828 options: deprecate -del for list options
I never liked that these used integer indexes. -remove should have
existed from the start. This deprecation is yet another empty threat,
though.
2019-12-18 06:57:24 +01:00
wm4 9b9307ea9f options: fix filter list comparison (again)
This was completely broken: it compared the first item of the filter
list only. Apparently I forgot that this is a list. This probably broke
aspects of runtime filter changing probably since commit  b16cea750f.

Fix this, and remove some redundant code from obj_settings_equals().
Which is not the same as m_obj_settings_equal(), so rename it to make
confusing them harder. (obj_setting_match() has these very weird label
semantics that should probably just be killed. Or not.)
2019-12-18 06:49:48 +01:00
wm4 0a1588d39b options: add -remove action to list options
Actually I wanted this for key/value lists only, but add it to the
others for consistency too. (For vf/af it barely makes even sense, but
anyway.)
2019-12-18 06:31:39 +01:00
wm4 8bdedf9062 options: make keys in key/value lists unique
I don't even know anymore whether this was intended or not. Certain use
cases for the "-o" options might require this. These options are for
passing general FFmpeg options. These are translated to av_opt_set()
calls, which may or may not accumulate the option values on multiple
calls with the same option name (how should I know?).

Anyway, it seems crazy to allow non-unique keys, so make them unique.

The ad-hoc nature of the option code makes this wonderfully complicated
(when I wrote that this code is cursed, I meant it). In combination with
lazy testing, it probably means there are lots of bugs here.
2019-12-18 06:03:39 +01:00
wm4 d3e3bd4307 options: increase consistency between list options and document them
Whenever I deal with this, I have to look at the code to make sense of
this. And beyond that, there are some strange inconsistencies. (I think
this code is cursed. It always was, and maybe always will be.)

Although the manpage claimed that using multiple items for -add etc. is
deprecated, string list options didn't warn against it. So add the
warning, and add something in the changelog (even though nobody will
ever read this).

The manpage mentioned --vf-append, but this didn't even exist. So add
it, I guess. We encourage using -append for the other option types, so
for consistency, it should work on filter options. (And I already
tricked me into believing it existed when I mentioned it in the
manpage.)

Make the "operations" table separate for all option types, and mention
the option type on every single of the top-level list options.
2019-12-18 05:32:02 +01:00
wm4 bd96b97170 vd_lavc: add gross workaround for nvdec/libavcodec broken API issue
libavcodec's nvdec wrapper can return invalid frames, that do not have
any data fields set. This is not allowed by the API, but why would they
follow their own API?

Add a workaround to specifically detect this situation. In practice,
this should fall back to software decoding if it happens too often in a
row. (But single errors are still tolerated, because I don't know why.)

Untested due to lack of hardware from the regrettable graphics company.

Better do this here than deal with the moronic project we unfortunately
depend on.

See: #7185
2019-12-18 01:56:50 +01:00
wm4 06c9c38199 f_lavfi: add gross workaround for af_dynaudnorm bug
Better do this here than deal with the moronic project we unfortunately
depend on.

The workaround is generic; unknown whether it works correctly with
multi-input/output filters or filter graphs. It assumes that if all
inputs are EOF, and all outputs are EAGAIN, the bug happened.

This is pretty tricky, because anything could happen. Any time some form
of progress is made, the got_eagain state needs to be reset, because the
filter pad's state could have changed.
2019-12-18 01:44:20 +01:00
der richter 0b9bc6f180 cocoa-cb: report fullscreen state for legacy fullscreen
report the fs screen state when the fullscreen is externally triggered
for the legacy fullscreen.
2019-12-17 23:48:13 +01:00
wm4 2a4d7c4aa8 command, vo: remove old option change notification mechanisms
These all have been replaced recently.

There was a leftover in window.swift. It couldn't have done anything
useful in the current state of the code, so drop these lines.
2019-12-17 23:18:17 +01:00
wm4 13dff3073d client API: remove some dead code
This was for the "suspend" API, which has been removed (turned into
stubs) a long time ago.
2019-12-17 23:11:15 +01:00
wm4 e75d28effd command: slightly simplify input-ipc-server change detection/init
The generic change detection now handles this just as well.

The way how this function is manually called at init is slightly gross.
Make that part slightly more explicit to hopefully avoid confusion.
2019-12-17 23:06:10 +01:00
Jan Ekström df7d5a1689 video/w32_common: follow updates to the border option instead of VOCTRL_BORDER 2019-12-18 00:02:49 +02:00
Jan Ekström 6554db47ab video/w32_common: follow updates to the ontop option instead of VOCTRL_ONTOP 2019-12-18 00:02:49 +02:00
Jan Ekström ee75908134 video/w32_common: move minimized state signaling to where it happens
WM_SIZE is the message we receive from which we can infer if we got
minimized or not.
2019-12-18 00:02:49 +02:00
Jan Ekström 8200304768 video/w32_common: switch full screening to options cache
* Instead of following VOCTRL_FULLSCREEN, check for option changes.
* Instead of signaling VO_EVENT_FULLSCREEN_STATE, update the cached
  option structure and have it propagated to the origin.

Additionally, gets rid of all the straight usage of the VO options
structure.

Done in a similar style to the Wayland common file, where in case
of reading the value, the "payload" from cache is utilized.
2019-12-18 00:02:49 +02:00
wm4 0bf0efd6d3 demux_edl: fix reusing segment source files
EDL files can have multiple segments taken from the same source file. In
this case, the source file is supposed to be opened only once. This
stopped working, and it created a new demuxer instance for every single
segment entry. This made it slow and made it use much more memory than
needed.

This was because it tried to iterate over the array of source files, but
the array count (num_parts) was only set to a non-0 value later. Fix
this by maintaining the count correctly.

In addition, the actual code for checking whether a source can be reused
(in open_source()) regressed and stopped working correctly. d->stream
could be NULL. Use demuxer.filename instead; I'm not entirely sure
whether this is always correct, but fortunately we have a distributed
almost-AI driven test suite (called "users") which will probably find
and report such cases.

Probably broke with commit a09396ee60 or something close, but didn't
check closer.

Fixes: #7267
2019-12-17 01:57:42 +01:00
wm4 65e9139764 x11: fix --hidpi-window-scale=no on hidpi screens
In this combination, the [current-]window-scale properties still
incorrectly applied scaling.

For some reason, vo_calc_window_geometry2() handled this option
(basically ignored the dpi_scale parameter passed to it), but since the
DPI compensation for window-scale is implemented in x11_common.c, we
need to check and honor this option here too. (What a mess.)
2019-12-16 21:45:46 +01:00
wm4 5d9aa72f25 msg: fix "terminal-default" logging mode
console.lua uses "terminal-default" logging, which is supposed to return
all messages logged to the terminal to the API. Internally, this is
translated to MP_LOG_BUFFER_MSGL_TERM, which is MSGL_MAX+1, because it's
not an actual log level (blame C for not having proper sum types or
something).

Unfortunately, this unintentionally raised the internal log level to
MSGL_MAX+1. It still functioned as intended, because log messages were
simply filtered at a "later" point. But it led to every message being
formatted even if not needed. More importantly, it made mp_msg_test()
pointless (code calls this to avoid logging in "expensive" cases and if
the messages would just get discarded). Also, this broke libplacebo
logging, because the code to map the log messages did not expect a level
higher than MSGL_MAX (mp_msg_level() returned MSGL_MAX+1 too).

Fix this by not letting the dummy level value be used as log level.
Messages at terminal log level will always make it to the inner log
message dispatcher function (i.e. mp_msg_va() will call
write_msg_to_buffers()), so log buffers which use the dummy log level
don't need to adjust the actual log level at all.
2019-12-16 21:31:54 +01:00
wm4 d07b7f068d command: change "window-scale" property behavior
This is similar to the "edition" change.

I considered making this go through deprecation, but didn't have a good
idea how to do that. Maybe it's fine, because this is pretty obscure.
But it might break some API users/scripts (it certainly broke
stats.lua), and all I have to say is sorry for that.
2019-12-16 02:32:17 +01:00
wm4 9800855895 x11: scale window-scale by DPI
"window-scale" is 1.0 by default; however, x11 implicitly set that to
2.0 on hidpi screens. This made the default 2.0, which was inconsistent
with the option. The "window-scale" property jumped from 1.0 to 2.0 when
a window was created.

Avoid this by factoring the DPI into the window-scale. This makes the
UNFS_WINDOW_SIZE return a virtual size; since this value is used for the
window-scale property only, this is fine and has no further
consequences. (Originally, this was possibly meant to be used for other
purposes, but I'm perfectly fine with redoing this again should that
ever happen.)

This changes user-visible behavior, and it's as if setting window-scale
multiplies its argument by 2 suddenly. Hopefully no user will get angry.
2019-12-16 02:22:51 +01:00
wm4 1d482e42cb command: remove unnecessary mute property implementation
This only added the CONSTRICTED_TYPE thing, but it works correctly
without.
2019-12-16 01:54:06 +01:00
wm4 de0f9b9f2d m_option: clamp integer before adding a value
This is for the previous commit, and should affect behavior with the
special M_PROPERTY_GET_CONSTRICTED_TYPE mechanism only. The effect is
that cycling the "edition" property, if the option is set to "auto",
will change to the second edition instead of the first.

Normally, option values must always be within their range, so this
should not affect anything else. M_PROPERTY_GET_CONSTRICTED_TYPE is
sort-of fine with this kind of behavior.

If this affects any other M_PROPERTY_GET_CONSTRICTED_TYPE users
neqatively, I will revert the change.
2019-12-16 01:52:52 +01:00
wm4 aa5f234b43 command: change "edition" property behavior
See manpage/changelog changes.

The purpose of this change is to removes another case of inconsistent
property behavior. At first I wanted to make this go through deprecation
before making a technically incompatible change, but then I considered
this feature too obscure as that anyone would care.
2019-12-16 01:47:06 +01:00
wm4 76a92fd30b player: avoid underrun wakeup loop
The VO underrun detection (just a weak heuristic) added in commit f26dfb
flagged the underrun state every time it was checked, and since the
check happened in every playloop iteration, this caused the playloop to
wake up itself on every iteration. It burned an entire core while in
this state.

Fix this by flagging this condition only once (as it should be), and
requiring that a frame is displayed to trigger it again. This makes it
work similar as the audio underrun check.

The bug report referenced below says --demuxer-thread=no avoided this.
This is because the demuxer layer doesn't do proper underrun reporting
if the reader thread is disabled.

Fixes: #7259
2019-12-16 01:15:43 +01:00
wm4 31eb2f9f33 build: downgrade EGL requirement from 1.5 to 1.4
With the previous commit, there's no need for 1.5 anymore. And in fact,
it's just too dangerous to rely on 1.5 because of all the EGL craziness.
For example, you might get a 1.5 EGL system library, but a driver might
still give you 1.4 at runtime. If you assume that you can call 1.5
functions, you will probably get random crashes in this case. What a
cursed API. (The same problem exists with EGL 1.3, but fortunately
nothing seems to use that anymore. We can just ignore that problem.)
2019-12-16 00:37:18 +01:00
wm4 e1586585b4 vo_gpu: opengl: make it work with EGL 1.4
This tries to deal with the crazy EGL situation. The summary is:

- using eglGetDisplay() with multiple windowing platforms doesn't really
  work, but Mesa had an awful hack for it
- this hack can be disabled at build time, and some distros sometimes
  accidentally or intentionally do so
- Mesa will probably eventually disable it by default
- we switched to eglGetPlatformDisplay(), but this requires EGL 1.5
- the very regrettable graphics company (also known as Nvidia) ships
  drivers (for old hardware I think) that are EGL 1.4 only
- that means even though we "require" EGL 1.5 and link against it, the
  runtime EGL may be 1.4
- trying to run mpv there crashes in the dynamic linker
- so we have to go through some more awful compatibility hacks

This commit tries to do it "properly", but using EGL 1.4 as base. The
plaform selection mechanism is a messy extension there, which got
elevated to core API in 1.5 (but OF COURSE in incompatible ways).

I'm not sure whether the EGL 1.5 code path (by parsing the EGL_VERSION)
is really needed, but if you ask me, it feels slightly saner not to rely
on an EGL 1.4 kludge forever. But maybe this is just an instance of
self-harm, since they will most likely never drop or not provide this
API.

Also, unlike before, we actually check the extension string for the
individual platform extensions, because who knows, some EGL
implementations might curse us if we pass unknown platform parameters.
(But actually, the more I think about this, the more bullshit it is.)

X11 and Wayland were the only ones trying to call eglGetPlatformDisplay,
so they're the only ones which are adjusted in this commit.

Unfortunately, correct function of this commit is unconfirmed. It's
possible that it crashes with the old drivers mentioned above.

Why didn't they solve it like this:

struct native_display {
    int platform_type;
    void *native_display;
};

Could have kept eglGetDisplay() without all the obnoxious extension BS.
2019-12-16 00:25:51 +01:00
wm4 4ae43a1c40 vd_lavc: fix broken assert()
This assert() sometimes triggered (and still triggers) with lavc API
bugs. It tries to check that at least 1 plane is set to a non-NULL
value. Obviously, a valid frame returned by successful decoding should
never have it.

The problem is that some hwdecs use integer surface IDs cast to a
pointer. Recently, it happened that newer Intel drivers started using
surface ID 0 under certain circumstances (for unknown reasons), which
triggers this assert.

Just get rid of it.

For the sake of #7185, add an assert() specifically for nvdec. That
failure needs to be further analyzed, is probably a FFmpeg bug, and
without this assert() would just crash somewhere further down the video
chain.

Fixes: #7261
2019-12-15 23:40:11 +01:00
wm4 2c6d42e704 vo_gpu: x11egl: log EGL config ID
Somewhat useful for debugging.
2019-12-15 23:33:23 +01:00
wm4 8e08a2ec97 vd_lavc: simplify decode return error checking
This code checked AVFrame.buf[0] instead of the decode return code to
see whether a frame was decoded. This is sort of suspicious; while I
think that the lavc API actually guarantees it, it's not intuitive
anyway. In addition, the code was unnecessarily roundabout.

Replace it with a proper error code check. Remove the other error return
(that was, or should have been, redundant before). The no-frame path is
now cleanly separated. Add an assert on the frame-returned path; if this
fails, lavc violated its own API.
2019-12-15 22:26:39 +01:00
der richter a32db637b5 mac: replace old event tap for media key support with MediaPlayer
the old event tap has several problems, like no proper priority support
or having to set accessibility permissions for mpv or the terminal.

it is now replaced by the new MediaPlayer which has proper priority
support and isn't as greedy as previously. this only includes Media Key
support and not any of the other features included in the MediaPlayer
framework, like proper Now Playing data (only set dummy data for now).
this is only available on macOS 10.12.2 and higher.

also removes some unnecessary redefines.

Fixes #6389
2019-12-15 20:07:31 +01:00
der richter 8a6ee7fe94 mac: remove Apple Remote support
the Apple Remote has long been deprecated and abandoned by Apple.
current macs don't come with support for it anymore. support might be
re-added with the next commit.
2019-12-15 20:07:31 +01:00
der richter 1eb6cbd093 cocoa-cb: fix freeing of macos_opts config group
using the MPContext as ta parent was a bad idea and shouldn't be done in
any circumstances there because it only supposed to be for internal
usage. this had the undesired effect that the options group was freed
but still used since the MPContext is freed afterwards.

instead manually free options group.
2019-12-15 20:07:11 +01:00
der richter f21a980e37 cocoa-cb: update and add more options to use new options handling
this updates and add the maximized, minimized, keepaspect and ontop
options to use the new options handling
2019-12-15 20:07:11 +01:00
der richter c8cc203735 cocoa-cb: use m_config_cache and new VOCTRL for option handling
this removes the direct access of the mp_vo_opts stuct via the vo struct
and replaces it with the m_config_cache usage. this updates the
fullscreen and window-minimized property via m_config_cache_write_opt
instead of the old mechanism via VOCTRL and event flagging. also use the
new VOCTRL_VO_OPTS_CHANGED event for fullscreen and border changes.
2019-12-15 20:07:11 +01:00
wm4 e5676a67ee DOCS/contribute.md: fix a typo 2019-12-15 16:33:58 +01:00
wm4 0de881fa72 DOCS/contribute.md: should -> must
People somehow think "should" makes things optional, even though the
wording was merely trying to account for the exception of the rule. I
guess this means programming documents should sound like we're running a
police state (which is also the ultimate outcome of all technological
development, if you weren't aware).

See: #7248
2019-12-15 14:58:51 +01:00
Philip Sequeira a6cb92c74a zsh completion: fix handling of aliases that are listed without --
Pretty sure they used to all have --, but I guess it was changed at some
point. More incentive to do this completion stuff in a more structured
way.
2019-12-15 14:17:00 +01:00
Philip Sequeira 0198bc13a1 zsh completion: use actual POSIX-compatible regex for whitespace
\s and \S aren't actually part of the spec, but it seems glibc supports
them anyway so I didn't notice when originally testing. This fixes the
script on Apple's libc and probably others that adhere more closely to
the spec.

The most direct replacement for \s would have been [[:space:]], but we
only expect to see spaces and tabs, so might as well just do that. Also
could have used [[:blank:]], which is basically a locale-aware version
of [ \t], but mpv isn't going to output anything but ASCII spaces and
tabs, so let's avoid unnecessary complexity and stick with the ASCII
literals.
2019-12-15 14:17:00 +01:00
Philip Sequeira a921c0628e zsh completion: actually make pcre optional
It was supposed to be optional already, but I misunderstood how the
re_match_pcre option worked. If it's set, it will try to use PCRE
matching whether it's available or not (and blow up if it's not). So,
first try to load the module it'll use, and only set the option if that
works.

Fixes #7240.
2019-12-15 14:17:00 +01:00
Down Thomas 698a6a2747 osxbundle: simplify process_libraries() to eliminate leafs()
Instead of traversing across leafs() which can lead to an infinite
loop issue with cross-linked libraries, use the dictionary
(libs_dict) created by libraries() to create a set (libs_set) of
every unique library. Every value in libs_dict is also a key in
libs_dict, so every unique library linked to mpv will be a key in
libs_dict. Use set() on libs_dict to return a set of the keys from
libs_dict, and remove binary from the set so that a duplicate of
the binary is not added to the libs directory.

Iterate over libs_set to bundle dylibs while using the libs_dict
to determine which install_names to change.
2019-12-15 12:33:25 +01:00
wm4 2dbe33ce83 DOCS: mention that mpv doesn't build with MSVC
And troll Microsoft slightly while we're at it. But is it trolling if
it's the truth?

The level of C99 support in MSVC is probably a bit better than most
people think, but it's by far not adequate. We need a bit of either C11
or GNU extensions too, and rely on some MinGW helpers (that look like
they're provided by MS, except they're not).
2019-12-14 16:05:54 +01:00
wm4 aab0116e7d player: fix an outdated comment
The client API doesn't use input_ctx anymore, and the "wakeup" flag is
gone (if it even existed at all).
2019-12-14 14:18:40 +01:00
wm4 1f1d2d5f49 player: move point at which queued seeks are applied
Do it after decoding etc., but before waiting for input. This seems to
make more sense, because whether a queued seek can be applied depends on
the playback state. So it sounds like a good idea to apply the seek
first thing, but it's a bad idea to go to sleep if there's still a
queued seek pending (that couldn't be processed earlier).

Also add an empty line before mp_wait_events(); it doesn't really have
to do with the filter bullshit.
2019-12-14 14:18:10 +01:00
wm4 57fbc9cd76 player: make repeated hr-seeks past EOF trigger EOF as expected
If you have a normal file with audio and video, and keep "spamming"
forward hr-seeks, the player just kept showing the last video frame
instead of exiting or playing the next file. This started happening
since commit 6bcda94cb. Although not a bug per se, it was odd, and very
user-noticable.

The main problem was that the pending seek command was processed before
the EOF was "noticed". Processing the command reset everything, so the
player did not terminate playback, but repeated the seek.

This commit restores the old behavior.

For one, it makes video return the correct status (video.c). The
parameter is a bit ugly, but better than duplicating the logic or having
another MPContext field. (As a minor detail, setting r=VD_EOF makes sure
have_new_frame() returns true, rather than going through another
iteration or whatever the hell will happen instead, which would clobber
logical_eof.)

Another thing is making the seek logic actually wait until the seek
outcome has been determined if audio is also active. Audio needs to wait
for video in order to get the video seek target position. (Which in turn
is because hr-seek still "snaps" to video frames. You can't seek in
between two frames, so audio can't just use the seek target, but always
has to wait on the timestamp of the video frame. This has other
disadvantages and is a misdesign, but not something I'll fix today.)

In theory, this might make hr-seeks less responsive, because it needs to
fully decode/filter the audio too, but in practice most time is spent on
video, which had to be fully decoded before this change. (In general,
hr-seek could probably just show a random frame when a queued hr-seek
overrides the current hr-seek, which would probably lead to a better
user experience, but that's out of scope.)

Fixes: #7206
2019-12-14 14:17:16 +01:00
wm4 23c5965d47 player: cosmetically restructure a small function
No actual functional changes. Just preparation for the next commit, to
reduce its diff.
2019-12-14 14:15:57 +01:00
wm4 ad2cda343b player: add comment to clarify FFmpeg ABI handling
Don't patch it out.
2019-12-13 13:22:46 +01:00
Philip Langdale 2a0a595e37 osc: set the wrap style for the title shown with window controls
I missed adding this when defining the style used for the video
title in the window control bar. The default behaviour is to wrap,
but we want to cut the title off when we run out of space.
2019-12-12 13:12:16 -08:00
wm4 19bd69e5e3 cocoa_common: remove deprecated VOCTRLs/VO_EVENTs
See commit 4e4252f916 and the following as an example how this would
have to be done if done properly.

Since I'm unable to test on OSX, and nobody is interested in fixing this
code (including myself, actually), just remove the deprecated
definitions to make sure the code still builds. This will break runtime
switching of fullscreen, ontop, border. (The way the minimized state is
reported was also deprecated, but commit 40c2f2eeb0 already broke it
anyway.)
2019-12-12 19:56:03 +01:00
wm4 22e4aac9fa wayland: remove unnecessary VO_EVENT_FULLSCREEN_STATE
This is needed and used only for VOCTRL_GET_FULLSCREEN, which the
wayland code got rid of.
2019-12-12 14:47:52 +01:00
wm4 aee413d246 manpage: fix --vulkan-async-compute default value
Seems like this was silently changed to enabled by default on the change
to libplacebo, without adjusting the manpage. Fix the documented
default.

Also add a comment about Nvidia; see referenced issue.

Fixes: #7245
2019-12-12 12:46:59 +01:00
wm4 cc746c9508 vo_gpu: x11egl: cleanup EGL correctly
...probably.

The EGL backend had a strange problem: when recreating the window, EGL
surface creation sometimes mysteriously failed. For example, keeping the
"_" key down (cycles video by default) destroys and recreates the window
in rapid succession, which will often enough show the "Could not create
EGL surface!" message.

This was puzzling because due to mpv's architecture, the X11 Window and
even the X11 Display were fully destroyed, the thread on which they ran
was destroyed, and then everything was recreated. There shouldn't have
been any state that could make subsequent EGL initialization fail.

It turns out mpv forgot to free EGLSurfaces in the x11 code. EGL is a
pretty crazy API (full of thread local and global state with weird
lifetime requirements), and for example it seems EGLDisplay cannot be
explicitly released, but apparently implicitly dies when the native
display is closed (at least EGL 1.5 claims eglTerminate() does _not_
invalidate the display, only certain objects linked to it). It appears
that Mesa still referenced at least EGLSurface in some form, and either
some pointer or some X11 ID was dangling, and when it randomly matched
when eglCreateWindowSurface() was called, it failed.

Fix this by calling eglTerminate(), which supposedly destroys (or rather
unreferences) contexts and surfaces created from the display (but
absurdly not the display itself).

Now why can't you just destroy the display? If it's implicitly
invalidated, why can't it just call eglTerminate() implicitly when this
happens? Did Mesa do something wrong when they somehow didn't
automatically remove the dangling object (so I could claim not to be
responsible for the bug)? Who the fuck knows, and I'm too tired to
figure this out (both because it's late, and because I'm tired of this
EGL crap API).

Still not sure if the code is correct now. I think EGL was designed to
maximize implementation and API-use complications. How else could you
possibly come up with something like the EGLDisplay life cycle? Or am I
just making a fuss? Anyway, fuck EGL, fuck computers, fuck technology.

Fixes: #7129
2019-12-12 01:50:05 +01:00
Philip Langdale db3754d8d6 osc: use custom symbols for window controls
I was recently informed that unicode has official symbols for
window controls, and I put together a change to use them, which
worked, as long as a suitable font was installed. However, it's
not that hard to get a normal system that lacks an appropriate
font, and libass wants to print warnings if the symbols aren't
in the default font, which will almost always be true.

So, I gave up and added the symbols to the custom osd font that
we already have. This ensures they are always available, and
that they are aligned consistently on all platforms.

I took the symbols from the `symbola` font, as this has a suitable
licence and the symbols look nice enough.

Symbola Licence:

    Fonts are free for any use; they may be opened, edited,
    modified, regenerated, packaged and redistributed.

Finally, as we now have access to an un-maximize symbol, I added
logic to use it when the window is maximized.
2019-12-11 13:53:10 -08:00
wm4 59cdfe50b2 rpi: destroy fullscreen change handling
Get rid of the legacy VOCTRL (which will be removed later). I'm not sure
what exactly fullscreen was supposed to do (toggling between using the
entire display, and what --geometry forced?), but I don't care, just get
rid of the VOCTRL. PRs to fix regressions caused by this will be
accepted, but personally I don't care since this is excessively fringe
and obscure.
2019-12-11 18:50:37 +01:00
wm4 b6fa63b01e vo_sdl: use new fullscreen change mechanism
Like the other backends. (Looks relatively convoluted, because it only
uses the fullscreen legacy VOCTRL, none of the others.)
2019-12-11 18:47:57 +01:00
wm4 c84460f61f build: add -Wimplicit-fallthrough
This warning seems to be designed well. It doesn't seem to warn on
fallthrough-only case statements, so it's compatible to well written
code.

stream_dvdnav.c had an obscure bug in inactive code, fix it.
stream_dvb.c is the only place where it intentionally falls through, I
guess I'll just leave it alone.
2019-12-11 17:28:47 +01:00
dudemanguy c68251a3a7 wayland: adjust hidden state detection
The wayland backend needs to keep track of whether or not a window is
hidden for presentation time. There is no presentation feedback when a
window is hidden which means we shouldn't be sending information to the
vo_sync_info structure (i.e. just leave it all at -1). This seemed to
work fine, but recent changes to presentation time in one notable
compositor (Sway; it was probably always broken in Weston actually)
changed the presentation time behavior.

For reasons that aren't clear, there is a greater than 16.666ms delay
between the first presentation time event and the second presentation
time event (compositor latency?) when you switch back to an mpv window
after it is hidden for long enough (a few seconds). When using
presentation time, this causes mpv to feed in some bad values in its
vsync timing mechanism thus causing the A/V desync spike as described in
issue #7223.

This solution is not really ideal. It would be better if the
presentation time events received by the compositors did not have the
aforementioned inconsistency. However since this occurs in both Sway and
Weston and clients can't really fight compositors in wayland-world,
here's a reasonable enough workaround. Basically, just add a slight
delay before we start feeding information into the vo_sync_info again.
We already do this when the window is hidden, so it's not a huge leap.

The delay chosen here is arbitrary, and it basically just recycles the
same parameters used to detect if a window is hidden. If
vo_wayland_wait_frame times out 60 times in a row (or whatever your
monitor's refresh rate is), then we assume the window is hidden. This is
a pretty safe assumption; something has to be terribly wrong for you to
miss 60 vblanks in a row while a window is on the screen.

In this case, we basically just do the reverse of that. If mpv receives
60 frame callbacks in a row (or whatever your monitor's refresh rate
is), then it assumes the window is not hidden. Previously, as soon as it
received 1 frame callback it was declared not hidden. Essentially,
there's just 1 second of delay after reshowing a window before the
presentation time statistics are used again. This should be more than
enough time to skip over the weird inconsistent behavior presentation
time behavior and avoid the A/V desync spike.

Fixes #7223
2019-12-10 17:55:43 +00:00
Philip Langdale 59b0fec508 osc: explicitly re-init the osc on a change in border visibility
I had previously wondered whether to do this, but in my testing
with x11 and wayland, the osc was being re-inited on a border
toggle already so I didn't add it.

However, on win32, things are different and there is no re-init
when toggling borders. I belive this is because the active window
size doesn't change in anyway, while on x11/wayland, toggling the
border actually changes the window size - and that trigger a re-init.

So, let's just be explicit and request a re-init when the border
is toggled.
2019-12-09 21:02:17 -08:00
James Ross-Gowan b3b2cc44fa console.lua: add this script
Merged from mpv-repl git repo commit 5ea2bf64f9c239f0326b02. Some
changes were made on top of it:

- Tabs were converted to 4 spaces indentation (plus some manual
  indentation fixes in some places).
- All user-visible mentions of "repl" were renamed to "console".
- The README was converted to a manpage (with heavy changes, some
  additions taken from stats.rst; rossy converted the key bindings
  table to RST).
- The method to change the default key binding was changed.
- Change minor detail about "font" default value setting (not a
  functional change).
- Integrate into the player as builtin script, including an option to
  prevent loading it.

Above changes and commit message done by wm4.

Signed-off-by: wm4 <wm4@nowhere>
2019-12-08 02:46:44 +01:00
Anton Kindestam b2b15d4e6e vo_drm: replace drmModeAddFB usage with drmModeAddFB2
drmModeAddFB is legacy, and might not pick the pixel format you
expect, depending on your driver. Use drmModeAddFB2 which specifies
this explicitly using a fourcc.
2019-12-07 19:23:58 +01:00
Anton Kindestam d5cabf7348 drm: avoid division by 0 in drm_pflip_cb with bad drivers
Seems like some drivers only increment msc every other page flip when
running in interlaced mode (I'm looking at you nouveau). I.e. it seems
to be incremented at the frame rate, rather than the field rate.
Obviously we can't work with this, so shame the driver and bail.

On intel this isn't an issue, as msc is incremented at field rate
there.

This means presentation feedback won't work correctly in interlaced
modes with those drivers, but who in their right mind uses an
interlaced mode these days, anyway?
2019-12-07 18:34:25 +01:00
sfan5 83b742df77 drm_common: fix display FPS estimation for interlaced modes 2019-12-07 16:44:27 +01:00
sfan5 376e57ee7b vo_drm: fix potentially broken capability check
If the capability is available it may still be 0 to signal absence of support.
2019-12-07 16:44:27 +01:00
sfan5 823f52f91f drm_common: log more useful things 2019-12-07 16:44:27 +01:00
wm4 b36e8569a1 lua: make later key bindings always have higher priority
Later calls to mp.add_key_binding() should take priority over previous
calls with the same key. Until now, the order was random (due to using
table pairs() iteration order).

Do this by simply sorting by a counter that is never reset. Since
input.c also gives later bindings priority, this works out.

Calling mp.remove_key_binding() on a newer binding makes an older still
existing binding with the same key active again. New bindings override
older ones, but do not overwrite them. I think these are good semantics
for most use cases.

(Note that the Lua code cannot determine whether two bindings use the
same key. Keys are strings, and two different strings could refer to the
same key. The code does not have access to input.c's key name
normalization, so it cannot compare them.)
2019-12-07 14:53:33 +01:00
wm4 855a4779ae filters: move prefix check from f_lavfi.c to user_filters.c
It's user_filters.c which allows the "lavfi-" prefix to distinguish
libavfilter filters from mpv builtin filters. f_lavfi.c is a layer
below, and strictly passes anything it gets to libavfilter. So the
correct place for this is in user_filters.c, which also has the code for
stripping the prefix in the normal filter instantiation code.
2019-12-07 14:19:11 +01:00
wm4 d90d5ee1a0 vo_gpu: hwdec_vaapi_gl: use gl_check_extension() instead of strstr()
In theory, using strstr() to search for extensions is a bad idea,
because some extension names might be prefixes for other names, so you
could get false positives. gl_check_extension() avoids this case.

It's not clear whether this is really needed; maybe not. Surely the EGL
committee is aware of these practices (many GL clients do this, which is
why it's widely considered bad practice), and would avoid defining new
extension names which contain existing names as sub-strings, but
whatever.
2019-12-07 14:16:30 +01:00
wm4 16b9c4c952 vo_gpu: hwdec_vaapi_gl: do not include eglext.h
Adding an ifdef mess to deal with insufficient system headers is kind of
a mess. It's easier to just provide the definitions manually. This sucks
a bit too, but it's the approach we've been using with OpenGL headers in
general, and I think that worked pretty well.
2019-12-07 14:04:43 +01:00
wm4 3cabd11f9b vo_gpu: hwdec_vaapi_gl: add missing PLANE3 defines as well
On systems whose EGL headers do not define these extensions, the build
still failed due to missing ..._PLANE3_... defines. Although we supplied
missing EGL_LINUX_DMA_BUF_EXT defines manually, the PLANE3 ones are
actually from a separate extension, which explains why they were not
added to the fallback defines in the first place.

Add them, now it builds without the eglext.h include.

See #6838.
2019-12-07 14:01:10 +01:00
wm4 23289a452f command: fix unintended reset of filters
Since the recent option changes (probably b16cea750f), using the "vf"
or "af" commands to change the filter chain did not write the option
value correctly. This led to the option value being reset the next time
an option changed.

This happened because the new option value was not copied to the
m_config_cache's internal storage. So on the next option update, it
looked like the option value changed, because the user-side value was
different from the internal value. It was copied back, which meant the
original option value was reinstated, and the previous "vf"/"af" command
was undone.

Fix this by using the correct way to store the option value. This also
takes care of property change notification (because the function is
specifically separate from m_config_cache_write_opt() to do that), so
remove the old call.

Fixes: #7220
2019-12-06 19:27:45 +01:00
wm4 b0c9f582ad player: loadfile overrides previous stop command
Both the "stop" and "loadfile" commands are asynchronous. "stop" starts
terminating playback, which used to be done in the same playloop
iteration, but now it may take longer, so a "loadfile" command can be
received while this is going on. (Possible that it used to work if the
second command was issued at least in the next playloop iteration.)

Make the "loadfile" override the "stop" mode, so the next file will be
played, instead of quitting or going into idle mode.

Unlike the referenced bug report claims, this has nothing to do with
IPC.

Fixes: #7225
2019-12-06 19:21:14 +01:00
wm4 13fe87f66b build: fix zimg message in configure output
It's useful as software scaler in general, not just that video filter.
2019-12-06 19:16:30 +01:00
ekisu 02d8d4e3ef f_lavfi: mp_lavfi_is_usable: check for "lavfi-" prefix
Without this, adding filters with the prefix would fail, and some
filters that have conflicting names with mpv ones were unusable.
2019-12-06 19:12:57 +01:00
dudemanguy 122bbb9ff4 DOCS: fix wayland-frame-wait offset value range
It actually goes down to -500 not -100.
2019-12-05 14:35:23 -06:00
wm4 000c045aa8 vo: redraw dropped frame if paused between queuing and drawing frame
When frame-stepping with display-sync mode enabled in high framerate
video, the frame was sometimes not redrawn correctly. Only the first OSD
interaction (or something similar) made it visible.

In this case, the core schedules many frames as dropped (because it's
ignorant of pausing/frame-stepping, as in theory the player is _not_
paused during frame-stepping, only at the end of it). There's a race
between the VO rendering the queued frame, and the core calling
vo_set_paused() after it has queued the frame. If the latter happens
first, the existing logic to redraw the previous dropped frame does
things correctly. If the former happens, the frame is not redrawn
automatically, but will be redrawn on the next user input (or if OSD is
enabled, and the pause state change updates it, which leads to an
immediate redraw).

Fix this by never actually dropping a frame in paused mode. The request
by the core to drop it is simply ignored.

Maybe this could be done slightly nicer by updating the pause state with
the VO atomically. Then we wouldn't have the frame drop counter going up
either (it's actually dropped, but then redrawn; but I doubt any user,
or me in a few weeks, would understand this). But I'm not really
interested in polishing this by increasing the complexity of the
frame-step code.
2019-12-04 23:55:42 +01:00
Remita Amine c23b3ac53a README: fix typo 2019-12-04 16:20:40 +01:00
Philip Langdale 353e4efdef osc: rework window control configuration to add auto mode
To aid in discoverability, and to address the most common case
directly, I'm adding an 'auto' mode for the window controls. In
this case, we will show the controls if there is no window border
and hide them if there are borders. This also respects the option
being toggled at runtime.

To ensure that it works in the wayland case, I've also made sure
that the wayland code explicitly forces the option to false if
decoration support is missing.

Based on feedback, I've split the config in two, with one option
for whether controls are active, and one for alignment. These are
new enough that we can get away with ignoring compatibility.
2019-12-04 09:32:25 +08:00
Philip Langdale f8689eff6d osc: ensure that window control show/hide zone is handled dynamically
As preparation for adding the auto mode for window controls, we need
to make sure that the controls can be successfully toggled at runtime,
rather than only being able to configure them once at startup. Right
now, there is a problem with the handling of the show/hide zone for
the window controls.

The previous fix for #7212 was to avoid registering the input mapping
for the window control show/hide zone. If there is no input mapping,
then there is no input, and the zone is a no-op, even if it exists.
But this only happens at startup. After that point, the input mapping
doesn't exist and cannot be turned on.

In this change, I'm switching the approach; we now go back to always
registering the input mapping, and instead, we zero out the show/hide
zone if window controls are disabled, and set its size appropriately
if they are enabled.
2019-12-04 09:32:25 +08:00
dudemanguy 7f300a00e9 wayland: fix cursor behavior on an edge case
This small regression was introduced by #7216. Previously, the wayland
backend used a trick which kept track of the previous fullscreen state
and used that logic for showing the cursor. Since vo_opts now keeps
track of the current fullscreen state, most of this stopped being
neccessary.

However, there was one edge case where the cursor didn't
behave the same: passing a fullscreen flag for the inital window. The
cursor would initially be visible here which is not desirable. This can
be remedied pretty easily by just setting the cursor visiblity to false
if the pointer entry event occurs on fullscreen. The only thing we need
to do is to make sure that the autohide delay isn't completely disabled
(i.e. the cursor is always visible). Hence the need for the previous
commit.
2019-12-04 00:47:05 +00:00
dudemanguy 65a317436d options: move cursor autohiding opts to mp_vo_opts
Certain backends (i.e. wayland) will need to do special things with the
mouse. It makes sense to expose the values of these options to them, so
they can behave correctly.
2019-12-04 00:47:05 +00:00
wm4 fd28be400c sd_lavc: add a hack ontop of another hack to fix completely fucked file
Do what we do best in multimedia: add conflicting hacks on top of other
hacks, that fix a single sample, and may break other ones.

In this case, it only happens if the file is most likely already broken
(subtitle bounding boxes go outside of the subtitle "canvas"), so it's
OK. The file still looks broken (and, in fact, the file is completely
fucking broken), but you can see the subtitles.

But in summary, this is not actually something I should have bothered
about.

I noticed that MPlayer shows the subtitles "correctly", but this is only
because they have a hack that extends subtitles with small resolution to
a larger hardcoded resolution. This hack was removed from mpv, because
it broke some completely legitimate files. As another really funny fact,
MPlayer's default video output (vdpau) appears to display this file
correctly, but only because it handles narrow aspect ratios (that extend
the height instead of the width) incorrectly. It extends the height, but
leaves the video with 1:1 aspect ratio at the top. It seems to repeat
the last video line. (-vo xv and -vo gl show it correctly, i.e.
stretched like mpv, by the way.) For some reason, the sample file at
hand is extended with black, so the subtitles are rendered into a black
area below the video, which is almost reasonable. So, MPlayer may
display this file "correctly", but in fact it only happens to do so
because of 1 hack that breaks legitimate files, and 1 bug. What the
fuck.

Fixes: #7218 (sort of)
2019-12-03 22:33:45 +01:00
wm4 e5b016b7bf player: don't apply weird timestamp tolerance on backstep
Hr-seek has some sort of tolerance against timestamps, where it allows
for up to 5ms deviation. This means it can work only for videos with up
to 200 FPS framerate. There were complains about how it doesn't work
with videos beyond some high fps. (1000 was mentioned, although that
sounds more like it's about the limit that .mkv has.)

I suspect this is because otherwise, it might be hard to hit a timestamp
with --start, which specifies timestamps as integer, and thus will most
likely never represent a timestamp exactly. Another part of the problem
is that mpv uses 64 bit floats for timestamps, so fractional parts are
never represented exactly. (Both the "tolerance" and using floats for
timestamps were things introduced before my time.)

Anyway, in the backstep case, we can be relatively sure that the
timestamp will be exact (as in, the same unmodified value that was
returned by the filter chain), so we can make an exception for that, in
order to fix backstep.

Untested. (For that you have users.)

May help with #7208.
2019-12-03 21:43:32 +01:00
wm4 d60bbd86e3 demux_lavf: export demuxer_id for more formats which have it
See previous commit. libavformat exports this information as AVStream.id
field.

The big problem is that the libavformat field is simply 0 if it's
unknown (i.e. the demuxer never sets it). So it needs to remain a
whitelist. Just add more formats which are known to have a meaningful
ID.

I considered exporting IDs for all formats, and then either leaving the
values as they are, or filtering duplicate values (and choosing
arbitrary but unique different IDs). But then again, I think it's sort
of mpv's job to filter FFmpeg's absurd bullshit API, and it should make
an effort to hide it rather than to reflect it.

See: #7211
2019-12-03 21:15:40 +01:00
wm4 370ed5777c demux: do not make up demuxer_id
The demuxer_id (exported in as "src-id" property) is supposed to be the
native stream ID, as it exists in the file, or -1 if that does not exist
(actually any negative value), or if it is unknown.

Until now, an ID was made up if it was missing. That seems like strange
non-sense, and I can't find the reason why it was done. But it was
probably for convenience by the EDL stuff or so.

Stop doing this. Fortunately, the src-id property was documented as
being unavailable if the ID is not known. Even the code for this was
present, it was just inactive until now. Extend input.rst with some
explanations.

Also fixing 3 other places where negative demuxer_id was ignored or
avoided.
2019-12-03 21:04:53 +01:00
Philip Langdale b6f605285c wayland: update remaining legacy VOCTRL usage to options
The remaining legacy VOCTRLs are for the fullscreen and border
properties. For fullscreen this largely just replacing the private
state field with the vo option but there are small semantic
differences that we need to be careful of.

For the border setting, it's trivial as we don't have external
mechanisms for changing the state, but I also can't test it as
I'm not using a compositor that supports it.
2019-12-02 14:14:09 +00:00
Philip Langdale 193b6fd8dd osc: don't show error if windowcontrols=yes
I always intended for this to be accepted and mean "right" but I
made it show an error for any value that's not explicitly
recognised (while considering all unrecognised values to mean "right").

So let's explicitly recognise "yes".
2019-12-02 11:04:43 +08:00
Dudemanguy 7da15ca9bd osc: don't always set window control keybindings
Only set the window control keybindings if the window control option is
actually enabled. Fixes #7212.
2019-12-01 17:23:02 -06:00
Philip Langdale 61b8e1d436 wayland: update Maximize and Minimize handling to use new options
I wanted to get this done quickly as I introduced the new VOCTRL
behaviour for minimize and maximize and it was immediately made
legacy, so best to purge it before anyone gets confused.

I did not sort out fullscreen as that's more involved and not something
I've educated myself about yet. But I did replace the VOCTRL_FULLSCREEN
usage with the new option change mechanism as that seemed simple
enough.
2019-12-01 09:39:51 +08:00
wm4 78f1629a53 vf_gpu: render subtitles
Pretty annoying affair. The vo_gpu code could of course not trigger
rendering from filters yet, so it needed to be extended. Also, this uses
some icky stuff made for vf_sub (and this was the reason I marked vf_sub
as deprecated), so everything is terrible.
2019-11-30 18:09:31 +01:00
wm4 6a88e7463e build: require at least GL 2.0 headers for GLX
The previous hack for fixing #7201 requires this, but it wasn't checked.
It's easy to check, so do it. (Yes, we could just have required OpenGL
3.2 headers and skipped the earlier fix.)

For #7201.
2019-11-30 17:37:56 +01:00
wm4 cd9fe3a843 m_config: remove change callback before unintialization
We don't want m_config uninitialization to call random change callbacks.
This happens at the end of mp_destroy(), when almost everything else is
already destroyed, and the change callbacks would probably trigger UB
all over the place.

The change callbacks could be trigger by m_config_restore_backups(),
which is just used as a cheap way to free the remaining state. The worst
is that this depends on which options may still have been part of this
"backup" state, which depends on user input.

Probably never a practical problem, since the backup state is most
likely guaranteed to be empty before uninit is performed, but still.
2019-11-30 17:33:29 +01:00
wm4 fa9a1ff0a0 vo_gpu: opengl: add hack for ancient Mesa/GLX
glx.h recursively includes gl.h, and there is no way to prevent this.
Old Mesa defines some GL symbols, but not all which mpv needs. In
particular, one user who was too lazy to update his ancient Ubuntu and
preferred to bother us with obscure bug reports, had Mesa headers which
did not define GL 3.2, so GLsync was not defined.

All in all I still think the idea of providing the GL API definitions
ourselves was a good idea; just GLX should have been isolated better.
But isolating GLX now is too much effort.

Not sure why I'm bothering with this at all.

Fixes: #7201 (unconfirmed)
2019-11-30 13:38:28 +01:00
Philip Langdale 8614cb38d9 osc: ensure the window-controls mouse area is initially zero sized
This is necessary to avoid breaking input behaviour in the 'idle'
state when not playing a video. Otherwise, the mouse area starts off
covering the whole window and blocks normal input.
2019-11-30 19:56:30 +08:00
Avi Halachmi (:avih) b67d124dc0 js: mp.add_key_binding: allow false-y name (match 311cc5b)
This is in addition to the allowed omission of name and/or flags (as
documented).
2019-11-30 12:23:47 +02:00
Avi Halachmi (:avih) abf6b22abd lua: unbreak mp.add_key_binding(key, fn)
Commit 311cc5b6 added the ability use flags while omitting name, but
broke the case where both name and flags are omitted.

Now omitting either name or flags or both works as documented.
2019-11-30 12:06:22 +02:00
Philip Langdale 2750ca597c osc: fix typo wsc_geo -> wc_geo 2019-11-30 09:14:49 +08:00
Philip Langdale 971dbcc21c osc: apply boxvideo margins to the window controls
It seems logical to account for the window controls if `boxvideo`
is in use (which has the effect of reducing the size of the video
so that the osc is not covering the video).
2019-11-30 08:56:29 +08:00
wm4 cb7048700f filters: fix incorrect #if for vf_gpu
This didn't match what is in wscript_build.py. Also, it should work on
non-X11 platforms... probably. (The condition is convoluted and almost
nonsensical, but the offscreen context creation needs to be cleaned up
anyway as soon as other backends, e.g. for win32, are added.)
2019-11-30 01:13:37 +01:00
wm4 0e376150a6 command: remove property change notification from property dispatcher
Properties should handle this themselves. This basically sent redundant
notifications. I found only two places where the "proper" notification
was missing.
2019-11-30 01:07:24 +01:00
wm4 464a045ed8 command: merge two functions
Due to recent changes, it makes no sense anymore to keep them separate.
2019-11-30 00:56:23 +01:00
wm4 56b06907a6 command: remove another unneeded hack
Now that the option-to-property bridge is gone, this is not needed
anymore. It always took the "silent" path.

Also, at least as of before this commit, this didn't correctly print a
warning when accessing a deprecated option as property. This was because
m_config_get_co_raw() was used, which intentionally does not print any
warnings, so switch to the non-raw one. (Affects only options that have
.deprecation_message set.)
2019-11-30 00:50:31 +01:00
wm4 90df6c79c9 vf_gpu: add video filter using vo_gpu's renderer
Probably pretty useless in this form (see: the wall of warnings), but
someone wanted this.

I think this should be useful to perform some automated tests, maybe.

Fixes: #7194
2019-11-29 20:37:11 +01:00
wm4 053297b1ca vo_gpu: opengl: do not free "GL" sub-allocations
This function always expects the GL struct pointer to be a talloc
allocation. So far so bad. But the terrible thing is that _lots_ of code
in mpv didn't quite get this (including the code which introduced the
way it is used this way). For example, in context_glx.c you see this:

struct priv {
    GL gl;
    ...

GL is not a talloc allocation, but since it's at the start of a talloc
allocation, it works anyway. So far so bad. But the really terrible
thing is that mpgl_load_functions2() calls talloc_free_children() on the
GL pointer, which means that all of priv's. This would be unintentional
and could create dangling pointers. And this happens at the about 1
dozen of callers. I'm amazed it didn't broke yet anywhere.

Removing this anti-pattern with making GL "implicitly" a talloc
allocation would be too much effort at this point. So just manually free
the only allocation that the function attached to GL.
2019-11-29 20:23:27 +01:00
wm4 1ccb049d3b osc: fix operation when window controls are disabled
It seems this area is simply not defined when window controls are
disabled, so ipairs() will crash on it.
2019-11-29 16:00:21 +01:00
wm4 3f7556baef x11: implement unminimization
This appears to work with IceWM.
2019-11-29 14:27:27 +01:00
Philip Langdale 2b4c867505 osc: handle deadzone and barmargin for window controls
I missed these due to only testing with my personal osc config.

The deadzone needs to be correctly handled for the window controls,
or they will fail to appear when the mouse is close to or over them.

In the process of doing that, I realised that the controls should
respect the barmargin, if set. This is because the controls should
remain aligned when layout=topbar and as the control bar is top
aligned, it should be equally affected if the user needs to set
the barmargin.

I also fixed a mistake in trying to the use the mpv-osd-symbols font
for the window controls.
2019-11-29 13:56:58 +01:00
wm4 d520258ffb x11: handle maximize/minimize with new option stuff
Should restore full functionality.

The initial state setting is a bit shoddy (instead of setting the
properties before map, we use the WM commands to change it after, so you
will see the normal window state for a moment; the WM commands do not
work on unmapped windows, so fixing this would require more code).
2019-11-29 13:56:58 +01:00
wm4 40c2f2eeb0 command: change window-minimized/window-maximized to options
Unfortunately, this breaks window state reporting for all VOs which
supported it. This can be fixed later (for x11 in the next commit).
2019-11-29 13:56:58 +01:00
wm4 d37e461eab x11: add change notification for --on-all-workspaces
Not particularly important and nobody asked for this, but demonstrates
how such things can be easily done now.
2019-11-29 13:56:58 +01:00
wm4 893f76045f x11: handle some more options with new option stuff 2019-11-29 13:56:58 +01:00
wm4 4e4252f916 x11: use new option stuff to implement fullscreen
- remove VOCTRL_FULLSCREEN and VOCTRL_GET_FULLSCREEN
- have your own m_config_cache for the fullscreen option
  (vo->opts_cache cannot be used because you lose per-option change
  notifications, and it'd be a mess anyway)
- use VOCTRL_VO_OPTS_CHANGED to update it
  (it's used for convenience)
- when updating it, check for the fullscreen option
  (wasn't sure how to do it best; currently, it compares the raw
  option pointers, but this could be changed)
- do not send VO_EVENT_FULLSCREEN_STATE on FS change
- instead write the option on FS change
  (assign in opt. struct + m_config_cache_write_opt)
2019-11-29 13:56:58 +01:00
wm4 b16cea750f player: change m_config to use new option handling mechanisms
Instead of making m_config a special-case, it more or less uses the
underlying m_config_cache/m_config_shadow APIs properly. This makes the
player core a (relatively) equivalent user of the core option API. In
particular, this means that other threads can change core options with
m_config_cache_write_opt() calls (before this commit, this merely led to
diverging option values).

An important change is that before this commit, mpctx->opts contained
the "master copy" of all option data. Now it's just another copy of the
option data, and the shadow copy is considered the master. This is why
whenever mpctx->opts is written, the change needs to be copied to the
master (thus why this commits add a bunch of m_config_notify... calls).

If another thread (e.g. a VO) changes an option, async_change_cb is now
invoked, which funnels the change notification through the player's
layers.

The new self_notification parameter on mp_option_change_callback is so
that m_config_notify... doesn't trigger recursion, and it's used in
cases where the change was already "processed". It's still needed to
trigger libmpv property updates. (I considered using an extra
m_config_cache for that, but it'd only cause problems with no
advantages.)

I think the recent changes actually forgot to send libmpv property
updates in some cases. This should fix this anyway. In some cases,
property updates are reworked, and the potential for bugs should be
lower (probably).

The primary point of this change is to allow external updates, for
example by a VO writing the fullscreen option if the window state is
changed by the window manager (rather than mpv changing it). This is not
used yet, but the following commits will.
2019-11-29 12:49:15 +01:00
wm4 5e2658c981 m_config: make m_config_cache_write_opt() check/return changes
Goes in line with the recent changes to always checking for option value
changes. The player core will use this to determine whether it should
send additional change events.
2019-11-29 12:37:41 +01:00
wm4 1cb085a82e options: get rid of GLOBAL_CONFIG hack
Just an implementation detail that can be cleaned up now. Internally,
m_config maintains a tree of m_sub_options structs, except for the root
it was not defined explicitly. GLOBAL_CONFIG was a hack to get access to
it anyway. Define it explicitly instead.
2019-11-29 12:14:43 +01:00
wm4 5083db91eb m_config: untangle new and old code somewhat
The original MPlayer m_config was essentially only responsible for
handling some command line parsing details, handling profiles, and
file-local options. And then there's the new mpv stuff (that stuff was
regretfully written by me), which is mostly associated with making
things thread-safe (includes things like making it all library-safe,
instead of stuffing all option data into global variables).

This commit tries to separate them some more. For example,
m_config_shadow (the thread-safe thing) now does not need access to
m_config anymore. m_config can hopefully be reduced to handling only the
"old" mplayer-derived mechanisms.
2019-11-29 12:14:43 +01:00
wm4 f73881fa10 m_config: allow writing options through m_config_cache
This will allow any other threads to write to the global option data in
a safe way.

The typical example for this is the fullscreen option, which needs to be
written by VO (or even some other thing running completely separate from
the main thread). We have a complicated and annoying contraption which
gets the value updated on the main thread, and this function will help
get rid of it.

As of this commit, this doesn't really work yet, because he main thread
uses its own weird copy of the option data.
2019-11-29 12:14:43 +01:00
wm4 591494b271 m_config: add fine-grained option reporting mechanism
This adds m_config_cache_get_next_changed() and the change_flags field
in m_config_cache. Both can be used to determine whether specific
options changed (rather than the entire sub-group).

Not sure if I'm very happy with that. The former rather compact
update_options() is now a bit of a mess, because it needs to be
incremental. m_config_cache_get_next_changed() will not be too nice to
use, and change_flags still relies on global "allocation" of change
flags (see UPDATE_* defines in m_option.h). If C weren't such a
primitive language that smells like grandpa, it would be nice to define
per-option change callbacks or so.

This compares options by value to determine whether they have changed.
This makes it slower in theory, but in practice it probably doesn't
matter (options are rarely changed after initialization). The
alternative would have been per-option change counters (wastes too much
memory; not a practical problem but too ugly), or keep all
m_config_caches in a global list and have bitmaps with per-option change
bits (sounds complicated). I guess the current way is OK.

Technically, this changes semantics slightly by ignoring setting an
option to the same value. Technically this wasn't a no-op, although the
effect was almost almost no-op. Some code would actually become cleaner
by ignoring such redundant change events, and them being no-op is
probably also what the user would normally assume.
2019-11-29 12:14:43 +01:00
wm4 1e6c57d4e4 m_config: move stuff around
Create a separate struct for internal fields of m_config_cache, so API
users can't just mess with stuff they shouldn't access.

Move the ts field out of m_config_data, so we don't need unnecessary
atomics in one case.

This is just preparation, and shouldn't change any behavior.
2019-11-29 12:14:43 +01:00
wm4 5b5d163a6a atomic: add mp_atomic_uint64 2019-11-29 12:14:43 +01:00
wm4 0cd612530c m_option: remove an outdated ancient comment
The exact type name (m_obj_list_t) was removed in 2013. I don't think
this stub comment helps much with understanding this complicated thing
anyway (this code is for the --vf/--af options, and makes up almost half
of m_option.c).
2019-11-29 12:14:43 +01:00
wm4 f95cdb2e97 f_output_chain: use m_option_equal()
This is used to detect whether any filters were changed. This code was
essentially ported to m_option.c.

One possible difference is how the old code did name comparison. It did
not actually compare the name (!?!?), so this might change behavior,
hopefully to the better.
2019-11-29 12:14:43 +01:00
wm4 6d82c04dca command: use m_option_equal()
No more converting the option values to a string to compare it.
2019-11-29 12:14:43 +01:00
wm4 63270ff898 m_option: add option comparison
Looks like this will be needed for fine-grained option change
notifications. There are some other parts in the player which implement
parts of this.
2019-11-29 12:14:43 +01:00
Philip Langdale 82735d1287 man/osc: fix typo 2019-11-29 18:21:35 +08:00
Philip Langdale c13d6da4d4 x11: implement minimize and maximize related VOCTRLs
This allows the pseudo client side decorations to be used under x11,
which might be desirable when running in border=no mode.
2019-11-29 18:21:19 +08:00
Philip Langdale a220f08648 osc: implement pseudo client side decorations via OSC
Today, if window decorations are not present, either because they were
disabled, or because the platform doesn't support them
(eg: gnome-shell on wayland), there are no window controls, meaning it
is not possible to minimize/maximize/close a window without knowing
keyboard shortcuts.

While you can imagine various ways of offering client side decorations,
it is attractive to consider using OSC because that is functionality
that we already have.

The main work here is defining a separate input area from the main
OSC box with its own buttons, etc.

While we could probably handle auto-detection based on whether
decorations are present or not, it's manually controlled for now.

The window control logic is mostly disconnected from the OSC itself,
except in the case of the `topbar` layout, where there has to be
coordination so that the controls don't get drawn on top of each other.

I had to do fine-positioning of the buttons based on the font on
my system, so don't be surprised if it looks wrong elsewhere.

You could also argue that window controls should be unscaled, even
if the main OSC box is scaled, but I've not tried to do this.
2019-11-29 16:56:20 +08:00
Philip Langdale 901b3dddb0 wayland: implement minimize and maximize related VOCTRLs
We primarily care about pseudo-decorations for wayland, where
the compositor may not support server-side decorations. So let's
implement the minimize and maximize commands and return the
maximized window state.
2019-11-29 16:56:20 +08:00
Philip Langdale c2bd3b1ecc command: add window-maximized and make window-minimized settable
If we want to implement window pseudo-decorations via OSC, we need a
way to tell the vo to minimize and maximize the window. Today, we have
minimized as a read-only property, and no property for maximized.

Let's made minimized settable and add a maximized property to go with
it. In turn, that requires us to add VOCTRLs for minimizing or
maximizing a window, and an additional WIN_STATE to indicate a
maximized window.
2019-11-29 16:56:20 +08:00
Philip Langdale f3c2f1f6aa wayland: restore window geometry after un-maximize
At least with gnome-shell (I know, I know), the compositor does
not provide the old window size when leaving the maximized state.
Instead, we get a toplevel_config event with a 0x0 size and no
additional states.

Today, we already save the window geometry to restore it when leaving
the fullscreen state, so we just need a small change for it to
kick in for leaving the maximized state. If I read this correctly,
we'll still respect the size passed by a compositor that actually
provides the old size.
2019-11-29 16:56:20 +08:00
Philip Langdale 5e3eb03ecf wayland: make the edge grab zone width user configurable
Rather than hard-coding the edge grab zone width, we can make it
user configurable. It seems worthwhile to have separate configs
for pointer and touch usage as the defaults should be different,
and a user might have both input methods in use.
2019-11-29 16:56:20 +08:00
Philip Langdale 4c179a27c2 wayland: add grab zone for resizing window with mouse
Today, we support resizing wayland windows when we detect a touch
event in a defined grab zone. As part of implementing
pseudo-decorations, we should have equivalent functionality for
mouse input. And if we detect support for actual decorations we
will not activate the grab zone as the decorations will provide this.
2019-11-29 16:56:20 +08:00
wm4 f09570664f DOCS/interface-changes.rst: more details about track property changes
Another subtle thing that should be mentioned. May or may not matter to
someone.
2019-11-27 20:47:43 +01:00
wm4 db3b5c9309 x11_common: don't use vo->opts directly
Use x11->opts instead of vo->opts. This doesn't matter currently, and
x11->opts is actually set to vo->opts. However, there's a chance that
either option access changes, or that the way backends integrate with
struct vo changes. This is just a preemptive change to make this less of
a mess, and it's generally a good idea to reduce accesses to struct vo
anyway.
2019-11-27 20:30:13 +01:00
wm4 7c6570402b options: remove options-to-property bridge
The previous bunch of commits made this unnecessary, so this should be
a purely internal change with no user impact.

This may or may not open the way to future improvements. Even if not,
at least the property/option interaction should now be much less buggy.
2019-11-25 20:29:43 +01:00
wm4 78bb1586d3 command: shuffle around even more crap
Convert some remaining properties to work without the option-to-property
bridge. Behavior shouldn't change (except for the corner case that it
tries to reapply the new state when setting a property, while it used to
ignore redundant sets).

As it is the case with many of these changes, much of the code is not in
its final proper state yet, but is rather a temporary workaround. For
example, these "VO flag" properties should just be fully handled in the
VO backend. (Currently, the config or VO layers don't provide enough
mechanism yet as that all the backends like x11, win32, etc. could be
changed yet, but that's another refactoring mess for another time.)

Now nothing relies on this option-to-property bridge anymore, which
opens the way to even more refactoring, which eventually may result in
tiny improvements for the end user.
2019-11-25 20:29:43 +01:00
wm4 fba7c69b8a command: change vid/aid/sid property behavior slightly
Again in line with the option-to-property bridge changes. As usual, this
causes subtle behavior changes, which may affect some users.
2019-11-25 20:29:43 +01:00
wm4 37ac43847e options: pre-check filter names when using vf/af libavfilter bridge
Until now, using a filter not in mpv's builtin filter list would assume
it's a libavfilter filter. If it wasn't, the option value was still
accepted, but creating the filter simply failed. But since this happens
after option parsing, so the result is confusing.

Improve this slightly by checking filter names. This will reject truly
unknown filters at option parsing time. Unfortunately, this still does
not check filter arguments. This would be much more complex, because
you'd have to create a dummy filter graph and allocate the filter. Maybe
another time.
2019-11-25 20:29:42 +01:00
wm4 13afc2150b command: change af/vf property behavior wrt. filter creation failures
The behavior is slightly different in a messy way. The change is in line
with the option-to-property bridge removal mentioned some commits ago
and thus is deemed necessary.
2019-11-25 01:16:03 +01:00
wm4 f5daae12ff command: remove redundant reinit_filters() call on filter change failure
This attempted to restore the old filter chain if setting a new one at
runtime failed. This is not needed anymore, because changing the filter
chain is done in a "transactional" way now.
2019-11-25 01:05:53 +01:00
wm4 5af9fefff6 f_output_chain: fix possible crash when changing filters
When changing filters at runtime (vf/af commands/properties), this could
crash due to a NULL pointer access. The code for comparing the old and
new option values (to detect changes) was simply buggy.
2019-11-25 01:04:38 +01:00
wm4 d123af34b5 m_config: discourage mp_read_option_raw()
This function is dangerous, because it disables the already basic/week
type checking the option system has at all. I'm tend towards thinking
that all of its uses should be replaced.
2019-11-25 00:52:30 +01:00
wm4 3a2dc8b22e command, options: deprecate old --display-fps behavior
See changelog and manpage changes.

(So much effort to fix an ancient dumb mistake for an option nobody
should use anyway.)
2019-11-25 00:47:53 +01:00
wm4 c26e80d0fd command: shuffle some crap around
This is preparation to get rid of the option-to-property bridge
(mp_on_set_option). This is a pretty insane thing that redirects
accesses to options to properties. It was needed in the ever ongoing
transition from something to... something else.

A good example for the need of this bridge is applying profiles at
runtime. This obviously goes through the config parser, but should also
make all changes effective, for which traditionally the property layer
is used.

There isn't much left that needs this bridge. This commit changes a
bunch of options (which also have a property implementation) to use
option change notifications instead. Many of the properties are still
left, but perform unrelated functions like OSD formatting.

This should be mostly compatible. There may be some subtle behavior
changes. For example, "hwdec" and "record-file" do not check for changes
anymore before applying them, so writing the current value to them
suddenly does something, while it was ignored before.

DVB changes untested, but should work.
2019-11-25 00:26:36 +01:00
wm4 9249887641 manpage: remove audio-file etc. caveat description
These properties actually were removed/replaced, so there is no conflict
with the options of the same name anymore. For example, there is no
"audio-file" property anymore, but you still can set "audio-files" (and
--audio-file simply maps to --audio-files-append).
2019-11-24 22:47:32 +01:00
wm4 e2e6bb496e options: remove deprecated --playlist-pos alias
This causes problems because it has the same name as a property which
behaves differently.
2019-11-24 22:39:47 +01:00
wm4 c1acb1afe1 input: use array instead of linked list for sections
Shouldn't change behavior.
2019-11-23 15:00:48 +01:00
wm4 311cc5b611 lua: make add_key_binding() rotate optional arguments correctly
add_key_binding() makes the name argument optional (in weird Lua
fashion), which did not work if there were additional arguments. So
there is no way to avoid specifying a name while passing a rp argument.
Fix this, declare this way of skipping the argument as deprecated, and
allow passing name=nil as the preferred way to skip the name argument.
2019-11-23 14:40:00 +01:00
wm4 66a46cba89 input: remove potential minor memory leak 2019-11-23 14:14:19 +01:00
Niklas Haas b31f2f6cb9 vo_gpu: fix infinite scaler reinit spam
Handling the window with this function makes no sense, since windows
and kernels are not the same thing and don't share the same option list.

The only reason it's done is to make sure the char* points at the static
string rather than the dynamically allocated one, which we can do
manually in this function. Rewrite a bit for clarity/quality.
2019-11-23 11:46:52 +01:00
wm4 2dc6b27ee7 input: export input.conf comments ot input-bindings property
This is supposed to turn input.conf comments into inline documentation.
Whether this will be useful depends on whether there'll be a script
using this field.

This changes a small aspect of input.conf parsing fundamentally: this
attempts to strip comments/whitespace from the command string, which
will later be used to generate the command when a key binding is
executed. This should not have any negative effects, but there could be
unknown bugs. (For some reason, every command is parsed when input.conf
is parsed, but it still only stores the string for the command. I guess
that saves some minor amount of memory.)
2019-11-23 01:18:49 +01:00
wm4 f379cf0bf8 command, input: add input-bindings property
Read-only information about all bindings. Somewhat hoping someone can
make a nice GUI-like overlay thing for it, which provides information
about mapped keys.
2019-11-23 01:18:49 +01:00
wm4 251069d9ea command: add command-list property 2019-11-23 01:18:49 +01:00
wm4 6e0e39b79f input: change mp_cmd.original from bstr to cstr
No reason to have this as bstr, just makes everything more complex.

Also clear mp_cmd.sender when it's copied. Otherwise it would be a
dangling pointer. Apparently it's never set to non-NULL in this
situation, but this is cleaner anyway.
2019-11-23 01:18:49 +01:00
Aman Gupta dbb5dd7c33 demux_lavf: log packet read errors
Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-11-22 12:56:46 -08:00
wm4 033af5390f input: make MP_INPUT_RELEASE_ALL a pseudo-key
Should be without consequences. I think this is less trouble, because
code frequently wants to add/remove bits for modifiers and key state
from key codes, and with this change you can't accidentally break it by
testing or removing bits from the old -1 value.
2019-11-22 01:19:00 +01:00
wm4 4a90da4e1d msg: show how many messages were dropped
Although repl.lua will probably not use this.
2019-11-22 01:15:08 +01:00
wm4 65a531b8e4 msg: drop old instead of new messages on overflow
It did that because there was no other way. It used a lock-free ring
buffer, which does not support this. Use a "manual" ring buffer with
explicit locks instead, and drop messages from the start.

(We could have continued to use mp_ring, but it was already too late,
and although mp_ring is fine, using it for types other than bytes looked
awkward, and writing a ring buffer yet again seemed nicer. At least it's
not C++, where mp_ring would have been a template, and everything would
have looked like shit soup no matter what.)
2019-11-22 01:15:08 +01:00
wm4 53477ffc4b msg: fix missing wakeup callback in terminal-default log level
In the referenced commit, I forgot about this part, and a client which
tried to use this was actually not woken up when needed.

(Also why the hell does the subject line of that commit say "removed"?)

Fixes: 8c2d73f112
2019-11-22 01:15:08 +01:00
wm4 21f2468d67 input: add text produced by key to script key events
Particularly for "any_unicode" mappings, so they don't have to
special-case keys like '#' and ' ', which are normally mapped to
symbolic names for input.conf reasons. (Though admittedly, this is a
pretty minor thing, since API users could map these manually.)
2019-11-22 01:15:08 +01:00
wm4 eab5457e47 manpage: correct "complex" key binding description
The key is never nil if it's invoked through the normal input path. The
key name could be "" if mp_cmd.key_name==NULL. This should not happen,
but there's no strong guarantee in input.c that it cannot happen, so
whatever.
2019-11-22 01:15:08 +01:00
wm4 a394d9e3ae manpage: improve "complex" key binding list of table entries 2019-11-22 01:15:08 +01:00
wm4 0a6c09b96f input: introduce a pseudo key name that grabs all text input
The intended target for this is the mpv.repl script, which manually
added every single ASCII key as a separate key binding. This provides a
simpler mechanism, that will catch any kind of text input.

Due to its special nature, explicitly do not give a guarantee for
compatibility; thus the warning in input.rst.
2019-11-22 01:15:08 +01:00
wm4 a098e98198 input: fix ineffective mp_msg_test call
This was supposed not to go through key lookup if the message wasn't
going to be output, but for whatever reason the log levels were
mismatched.
2019-11-22 01:15:07 +01:00
Avi Halachmi (:avih) 67fef2b152 js: complex key binding: use key_name like the docs say 2019-11-20 16:55:21 +02:00
Avi Halachmi (:avih) 14971424b9 js: report key name for "complex" key bindings - match b08c8f50 2019-11-20 16:28:49 +02:00
Avi Halachmi (:avih) da13a3b231 lua: complex key binding: use key_name like the docs say 2019-11-20 16:28:49 +02:00
Chris Down e143966a76 player: Optionally validate st_mtime when restoring playback state
I often watch sporting events. On many occasions I get files with the
same filename for each session. For example, for F1 I might have the
following directory structure:

    F1/
        FP1.mkv
        FP2.mkv
        FP3.mkv
        Qualification.mkv
        Race.mkv

Since usually one simply watches one race after the other, I usually
just rsync the new event's files over the old ones, so, for example,
Race.mkv will be replaced from the file for the last event with the file
from the new event.

One problem with this is that I like to use --resume-playback for other
kinds of media, so I have it on by default. That works great for, say, a
movie, but doesn't work so well with this scheme, because you can
trivially forget to pass --no-resume-playback on the command line and
end up 2 hours in, watching spoilers as the race results scroll down the
screen :-)

This patch adds a new option, --resume-playback-check-mtime, which
validates that the file's mtime hasn't changed since the watch_later
configuration was saved. It does this by setting the watch_later
configuration to have the same mtime as the file after it is saved.

Switching back and forth between checking mtime and not checking mtime
works fine, as we only choose whether to compare based on it, but we
update the watch_later configuration mtime regardless of its value.
2019-11-20 15:11:33 +01:00
wm4 1649ba15ab manpage: extend documentation of key names
These things weren't written down anywhere yet.
2019-11-19 23:13:12 +01:00
wm4 b08c8f50b5 lua: report key name for "complex" key bindings
This might make certain use cases less of a mess.
2019-11-19 23:11:05 +01:00
wm4 13815bf251 manpage: deprecate input section commands
These were a bad idea and are obscure. Scripting key mapping support
still uses them, but this is not relevant to scripting authors, because
the mpv provided helper code (defaults.lua) takes care of this. In
addition, the OSC uses a legacy form of this.

Hopefully, this input section stuff can be removed, and replaced by a
simpler mechanism.
2019-11-19 23:09:59 +01:00
Aman Gupta 03fbb57bd9 audio: add ao_audiotrack for android 2019-11-19 12:10:26 -08:00
Aman Gupta 1a006d6f06 misc: add jni helpers 2019-11-19 12:10:26 -08:00
Aman Gupta f93faf26d8 audio: fix minor whitespace issue in out/internal.h 2019-11-19 12:10:26 -08:00
Avi Halachmi (:avih) eb033bc29f js: don't pre-filter log level argument in mp.enable_messages()
Match lua's 8e5642ff
2019-11-19 18:13:39 +02:00
wm4 521535cebe DOCS/contribute.md: some clarifications
Even if nobody ever reads this file.
2019-11-18 18:14:07 +01:00
Michael Forney 78963d1e66 video/out/bitmap_packer: Avoid empty initializer list 2019-11-18 16:50:21 +01:00
Michael Forney 235fabcfae video/out/vo_tct: Use octal escape sequence instead of non-standard \e 2019-11-18 16:50:21 +01:00
Michael Forney bea582f383 video/out/gpu: Remove stray top-level ';' 2019-11-18 16:50:21 +01:00
wm4 8c2d73f112 player: remove mechanisms for better logging with repl.lua
As preparation for making repl.lua part of the core (maybe), add some
mechanisms which are supposed to improve its behavior.

Add a silent mode. Calling mpv_request_log_messages() with the log level
name prefixed with "silent:" will disable logging from the API user's
perspective. But it will keep the log buffer, and record new messages,
without returning them to the user. If logging is enabled again by
requesting the same log level without "silent:" prefix, the buffered log
messages are returned to the user at once. This is not documented,
because it's far too messy and special as that I'd want anyone to rely
on this behavior, but it will be perfectly fine for an internal script.

Another thing is that we record early startup messages. The goal is to
make the repl.lua script show option and config parsing file errors.
This works only with the special "terminal-default" log level.

In addition, reduce the "terminal-default" capacity to only 100 log
messages. If this is going to be enabled by default, it shouldn't use
too much resources.
2019-11-18 00:44:54 +01:00
wm4 8e5642ff68 lua: don't pre-filter log level argument in mp.enable_messages()
This will just make it  not work if mpv_request_log_messages() gets
extended to accept more names. Pass the argument without checking.

To keep the behavior the same (for whatever reasons, probably not
important), still raise an error if the libmpv API function returns an
error that the argument was bad.

(The check_loglevel() function is still used when the script _emits_ log
messages, which is different, and for which there is no API anyway.)
2019-11-18 00:44:54 +01:00
Philip Langdale a714ab0601 vo_gpu: hwdec_cuda: Reduce message level of errors while probing
We should only be printing errors that occur when not probing, to
avoid creating the impression that something is wrong - and errors
during probing isn't a problem.
2019-11-17 09:44:32 -08:00
wm4 78cf974375 options: deprecate --video-sync=display-adrop
A stupid thing that will probably be in the way.
2019-11-17 02:11:45 +01:00
wm4 d92395d205 player: remove some unnecessary coverart special cases
These should not be needed, since video is in EOF mode in this case
anyway.

Not too sure about the video.c case to be honest, well, here goes
nothing.
2019-11-17 02:11:45 +01:00
wm4 4e74320320 video: make track switching work for external images
Until now, this didn't work, since the external image had pts 0; so
enabling video at a later time did nothing, because the image was
discarded. Since hrseek now ends on the last frame (instead of nothing),
reusing the hrseek mechanism solves this, and we don't even need to
treat the cursed coverart case separately.
2019-11-17 02:11:45 +01:00
wm4 42c5867c4e player: remove commented declaration
It was commented almost 2 years ago in a "rewrite everything" commit.
2019-11-17 02:11:45 +01:00
wm4 23414d1d71 audio: log A/V initial sync status 2019-11-17 02:11:45 +01:00
wm4 c7487cebd1 demux_mf: fix backward seeking behavior
If SEEK_FORWARD is set, a demuxer should skip to the next frame if the
timestamp does not fall on the start of a frame. If that flag is not
set, it should always seek to the first frame before the target
timestamp (or the first frame in the file).
2019-11-17 02:11:45 +01:00
wm4 f942071524 video: set EOF status as soon as possible
See what the added code comment says. Normally when this is needed, it's
the cover art case. But this flag is not set when using an external
image. This gives weird seek behavior, because the frame will be
"normally" displayed for its determined duration, and during normal
video playback, the video pts will be used - which is always 0 here.

This should happen only if audio is active. Otherwise, we're more or
less in image viewer mode, where the image should be displayed for a
configured duration.
2019-11-17 02:11:45 +01:00
wm4 6bcda94cbc video: if hr-seek goes past last frame, seek to last frame
This gives much better behavior in general, and is what we want if video
somehow ends earlier than audio.

A common special is using an audio file with an external image file.
This commit makes things like switching aspect ratio work (provided the
demuxer for the image behaves correctly, which currently isn't the case
with demux_mf.c). Since the image file had timestamp 0, it was usually
skipped by hr-seek, and changed properties weren't applied to it at the
start of the filter chain.
2019-11-17 02:11:45 +01:00
wm4 ba6ba32825 f_decoder_wrapper: put coverart through image output logic
This wasn't done, probably regression from one of the last dozen of
times this special code path was touched. This meant coverart images
ignored the user-set aspect ratio completely, and some other things.
2019-11-17 02:11:45 +01:00
Philip Langdale ba370e9599 vo_gpu: context_glx: Add X11 native resource
Surprisingly, we've managed to get this far without context_glx ever
adding the X11 display as a native resource. But with the recent change
to attempt to enable vdpau when using EGL, the hwdec now requires the
display to be added. So let's add it.
2019-11-16 15:35:32 -08:00
Dudemanguy 0d8a6c6984 wayland: use eglGetPlatformDisplay()
See aacc194. The same logic all applies to Wayland. In fact, we already
require EGL 1.5 for wayland anyway, so it's better to do it right.
2019-11-16 14:23:07 -06:00
wm4 aacc1942fb x11: require EGL 1.5 and use eglGetPlatformDisplay()
eglGetPlatform() is a broken API, since it takes a windowing specific
argument, yet is supposed to work for multiple APIs at the same time. On
Linux, it can take both a X11 "Display" and a "wl_display". Obviously
there is no way to specify what kind of display the argument is (it's
just a void*).

Mesa has _eglNativePlatformDetectNativeDisplay, which does funny stuff
to try to guess the display type, including trying to call mincore() to
determine whether the pointer can be accessed at all. I guess this
recently accidentally broke (as a bug), but on the other hand, maybe
it's time to do this properly.

The fix is using eglGetPlaformDisplay(). This requires EGL 1.5, plus
Mesa needs to support the associated platform extension
(EGL_KHR_platform_x11).

Since I see no reasonable way to do this in a compatible way, just
require that EGL 1.5 is available. The problem is that EGL 1.4 seems to
require you to create a display to query EGL version and extension, and
you have a chicken-and-egg problem. It's very stupid. Maybe you could
jump through some more hoops to get something compatible, but fuck that.
Users on "too old" Mesa will fall back to GLX (which we keep around for
a regrettable company known by the name of Nvidia).

I think Wayland and GBM should do the same. They're sufficiently
bleeding-edge that you can expect them to have EGL 1.5. On the other
hand, the cursed RPI code will have to stay with a eglGetDisplay().

Speculative fix for #7154.

(Rant about EGL follows. Actually I deleted it.)
2019-11-16 20:55:03 +01:00
wm4 73c3dc0a7b vo_gpu: sync duplicated condition on peak computation
pass_color_map() (in video_shaders.c) and pass_colormanage() (video.c)
both duplicate the condition on whether to do peak computation. Peak
computation requires a compute shader, so if the duplicated conditions
don't match, video_shaders.c will generate a compute shader, but video.c
will try to run it as fragment shader. This leads to a "blue screen".

This can be reproduced by playing a HDTV video with --target-peak=99.

It's not clear how to fix this. Should pass_tone_map() be only invoked
if mp_trc_is_hdr() == true (what pass_colormanage() uses to decide
whether to enable peak computation), or should pass_colormanage() just
tell pass_color_map() to skip peak computation? Decide for the latter,
as it's more robust.

Even if not correct, at least it gets rid of the blue shit.

Fixes: #7149
2019-11-16 19:02:36 +01:00
wm4 b2006eeb74 client API: remove sync. property notification code again
It's too easy to introduce unintended circular lock dependencies. Just
now we found that the (old) cocoa vo_gpu backend is also affected by
this, because it waits on the Cocoa main thread, which in turn uses
libmpv API for OSX... stuff.

Also fix a missing initial property update after observe.

This leaves me unhappy, because it just leads to a stupid thread ping
pong. Will probably rewrite this later.
2019-11-16 18:33:28 +01:00
wm4 b0d95f6f3c manpage: add section about using mpv from programs and scripts
Give an overview over the various methods. I feel like I've written text
like this over and over again (compatibility.rst and
interface-changes.rst for example duplicate the list of mpv API
abstractions), but such is life in hell.

Use this in particular to strongly suggest not to parse terminal output.
This suggestion got lost or de-emphasized at some point (maybe when
removing MPlayer and "slave mode" references). Some of this text is
still there, but it can be considered "fine print" at best, that nobody
will see. Now we have it in a more prominent place. This is especially
important since MPlayer-style use of mpv still seems to be prevalent,
see for example #7153.
2019-11-16 15:38:05 +01:00
wm4 f57f13ceb0 options: deprecate --input-file
I have no idea why this still exists, since we have --input-ipc-server.
I think there was something about Windows, but the latter option is
implemented even on Windows.
2019-11-16 15:28:18 +01:00
wm4 6bbf44d842 video: take first frame into account in audio-sync mode
It appears commit 4ad68d9452 broke handling the first video
frame duration through roundabout ways (I think because the duration of
the first frame was now available at all in the normal case). The first
frame was cut short, which showed up especially with looping, or if the
file had a low FPS.

This questionable change seems to fix it without breaking any other
known cases => push and call it a day.

The display-sync mode did not have this problem.

Fixes: #7150
2019-11-16 13:47:23 +01:00
wm4 b6413f82b2 demux_lavf: fight ffmpeg API some more and get the timeout set
It sometimes happens that HLS streams freeze because the HTTP server is
not responding for a fragment (or something similar, the exact
circumstances are unknown). The --timeout option didn't affect this,
because it's never set on HLS recursive connections (these download the
fragments, while the main connection likely nothing and just wastes a
TCP socket).

Apply an elaborate hack on top of an existing elaborate hack to somehow
get these options set. Of course this could still break easily, but hey,
it's ffmpeg, it can't not try to fuck you over. I'm so fucking sick of
ffmpeg's API bullshit, especially wrt. HLS.

Of course the change is sort of pointless. For HLS, GET requests should
just aggressively retried (because they're not "streamed", they're just
actual files on a CDN), while normal HTTP connections should probably
not be made this fragile (they could be streamed, i.e. they are backed
by some sort of real time encoder, and block if there is no data yet).
The 1 minute default timeout is too high to save playback if this
happens with HLS.

Vaguely related to #5793.
2019-11-16 13:15:45 +01:00
wm4 8d4e012bfa demux_playlist: fix previous commit
This just froze, due to obvious stupidity (I forgot to deal with all
semantic changes done to the the former stream_skip()).

Fixes: ac7f67b3f2
2019-11-15 12:10:01 +01:00
wm4 9efdb0368e player: enable "pause caching" code for local playback too
There isn't really a need to disable this for local playback. I think
originally I did this because I was afraid the code could mess up or be
annoying on local mode, but that's not really a good argument. I'd
rather test this code in local mode too. In this case, it shouldn't
really happen that it runs out of cache in the first place.
2019-11-14 13:51:47 +01:00
wm4 5a99015acf stream_lavf: set --network-timeout to 60 seconds by default
Until now, we've made FFmpeg use the default network timeout - which is
apparently infinite. I don't know if this was changed at some point,
although it seems likely, as I was sure there was a more useful default.

For most use cases, a smaller timeout is more useful (for example
recording something in the background), so force a timeout of 1 minute.

See: #5793
2019-11-14 13:46:03 +01:00
wm4 ac7f67b3f2 demux_mkv, stream: attempt to improve behavior in unseekable streams
stream_skip() semantics were kind of bad, especially after the recent
change to the stream code. Forward stream_skip() calls could still
trigger a seek and fail, even if it was supposed to actually skip data.
(Maybe the idea that stream_skip() should try to seek is worthless in
the first place.)

Rename it to stream_seek_skip() (takes absolute position now because I
think that's better), and make it always skip if the stream is marked as
forward.

While we're at it, make EOF detection more robust. I guess s->eof
shouldn't exist at all, since it's valid only "sometimes". It should be
removed... but not today. A 1-byte stream_read_peek() call is good to
get the s->eof flag set to a correct value.
2019-11-14 12:59:14 +01:00
dudemanguy dcc3c2eb38 wayland: use hidpi-window-scale option 2019-11-12 01:00:08 +00:00
Philip Sequeira b5894e760d github: ask for build/config.log 2019-11-10 20:59:17 -08:00
Philip Sequeira 85aa9635e0 build: fix compilation conditions for vaapi interop inits
This makes the condition for including each init match the condition for
compiling the file that defines it.

It's possible to e.g. HAVE_GL and HAVE_VAAPI without HAVE_VAAPI_EGL,
which resulted in "undefined reference to `vaapi_gl_init'" with the old
code.
2019-11-10 20:59:17 -08:00
wm4 07fd511e14 options: remove M_SETOPT_RUNTIME
Used to contain flags for "save" setting of options at runtime. Now
there is nothing special needed anymore and it's 0. So drop it
completely, and remove anything that distinguishes between runtime and
initialization time.
2019-11-10 23:53:57 +01:00
wm4 4cae192377 options: remove M_OPT_FIXED
Options marked with this flag were changed to strictly read-only after
initialization (mpv_initialize() in the client API, after option parsing
and config file loading with the CLI player).

This used to be necessary, because there was a single option struct that
could be accessed by multiple threads. For example, --config-dir sets
MPOpts.force_configdir, which was read whenever anything accessed the
mpv config dir (which could be on different threads, e.g. font
initialization tries to lookup fonts.conf from an arbitrary thread).

This isn't needed anymore, because threads now access these in a thread
safe way. In the case of --config-dir, the path is actually just copied
on init.

This M_OPT_FIXED mechanism is thus not strictly needed anymore. It still
prevents writing to some options that cannot take effect at runtime, but
even that can be dropped. In general, all mpv options can be changed any
time at runtime, even if they never take effect, and there's no need to
make an exception for a very low number of options. So just get rid of
it.
2019-11-10 23:49:23 +01:00
wm4 20c9538e32 audio: more alignment nonsense
It's hard to see what FFmpeg does or what its API requires. It looks
like the alignment in our own allocation code might be slightly too
lenient, but who knows. Even if this is not needed, upping the alignment
only wastes memory and doesn't do anything bad.

(Note that the only reason why we have our own code is because FFmpeg
doesn't even provide it as API. API users are forced to recreate this,
even if they have no need for custom allocation!)
2019-11-10 15:30:29 +01:00
wm4 4667b3a182 audio: work around ffmpeg being a piece of shit
The "amultiply" filter crashes in AVX mode on unaligned access if an
audio pointer is unaligned (on 32 or 64 bytes I assume).

A requirement that audio data needs to be aligned isn't documented
anywhere. In our case, the data is still sample- and channel-aligned,
which is completely sane. Sure, you can imagine optimizations which make
some algorithms even faster by requiring higher alignment. But, and this
is a big but, you shouldn't crash api users because you just invented a
new undocumented requirement. And even more importantly, your
user-crashing optimization won't matter because it's just a trivial
algorithm working on audio. You don't need to pretend to be an
optimization devil, and nobody will give you a prize for this. But no,
lets random make API users crash (and then probably blame them for it!)
for something that wouldn't matter at all.

Not to mention that they do "document" some requirements on _video_
data, yet their vf_crop probably can still produce unaligned video
pointers. Oh how hilarious that the same documentation also talks about
libswscale alignment requirements. (This is weird because libswscale is
just one of many, many things which consume video data. Also did you
know that zimg, written in C++ and using intrinsics, i.e. the antithesis
to FFmpeg development, is much faster than libswscale, easier to use,
and produces more correct results, even if you ignore that libswscale
flat out doesn't support some very important features?)

Fucking tired of this bullshit. Can't wait until someone comes up with a
better framework than this... (well let's not write this out).

Fix this by copying instead of adjusting the start pointer when skipping
samples. This makes general operations slower just to fix interoperating
with a single filter. Thank you for your "optimization", FFmpeg. Go die
in a fire.

Didn't check whether this is correct. It probably is? If the frame needs
to be copied (due to COW), and memory allocation fails, it just silently
(or audibly lol) doesn't skip samples, because a never-fail function can
suddenly fail. Well, who cares.

Fixes: #7141
2019-11-10 15:13:25 +01:00
wm4 35de8ea0a8 vo_gpu: yuv alpha is always full range
Probably. It's not like these pixel formats are formally specified -
FFmpeg added them because _some_ file format or decoder supports it, and
while that format/codec may define it precisely, the pixel format is
sort of disconnected and just a FFmpeg thing.

In any case, the yuva sample I had at hand uses the full range the
component data type can provide. The old code used the same "shifted"
range as for Y/U/V components, which must have been wrong.

This will not work correctly for packed YUVA formats, but fortunately
they matter even less.
2019-11-09 23:56:44 +01:00
wm4 05f018b81a github: suggest using as github attachment for log files
It's not that we _want_ the log to be on an external site. We just want
the log, somehow. Probably not pasted inline into the issue text.

Also reword the "we are assholes who really want logs" part of the text.
It's a subtle balance between trying to be nice and being a complete
asshole, but no matter what you do, it will always sound like the
latter, so be direct.
2019-11-09 23:56:44 +01:00
wm4 f762303feb manpage: expand MPV_LEAK_REPORT environment variable description 2019-11-09 23:56:44 +01:00
Timothy DeHerrera cb2d7c1534 README.md: fix dead FAQ link due to syntax error 2019-11-09 13:18:15 +01:00
wm4 94d853d3a3 test: add tests for zimg RGB repacking
This tests the RGB repacker code in zimg, which deserves to be tested
because it's tricky and there will be more formats.

scale_test.c contains some code that can be used to test any scaler. Or
at least that would be great; currently it can only test repacking of
some byte-aligned-component RGB formats. It should be called
repack_test.c, but I'm too lazy to change the filename now.

The idea is that libswscale is used to cross-check the conversions
performed by the zimg wrapper. This is why it's "OK" that scale_test.c
does libswscale calls.

scale_sws.c is the equivalent to scale_zimg.c, and is of course
worthless (because it tests libswscale by comparing the results with
libswscale), but still might help with finding bugs in scale_test.c.

This borrows a sorted list of image formats from test/img_format.c, for
the same reason that file sorts them.

There's a slight possibility that this can be used to test vo_gpu.c too
some times in the future.
2019-11-09 01:55:13 +01:00
wm4 27d88e4a9b test: fix --unittest matching
Hurrr.
2019-11-08 21:22:49 +01:00
wm4 cd8fd4b788 vo_gpu: context_x11egl: check eglGetConfigAttrib() for errors
Not sure why it assumes that it always succeeds (although generally it
won't fail).
2019-11-08 21:22:49 +01:00
wm4 bcfabf40a4 img_format: remove some unneeded alpha flag handling
Don't know what this was for, but the result doesn't change.
2019-11-08 21:22:49 +01:00
wm4 1edb3d061b test: add dumping of img_format metadata
This is fragile enough that it warrants getting "monitored".

This takes the commented test program code from img_format.c, makes it
output to a text file, and then compares it to a "ref" file stored in
git.

Originally, I wanted to do the comparison etc. in a shell or Python
script. But why not do it in C. So mpv calls /usr/bin/diff as a
sub-process now.

This test will start producing different output if FFmpeg adds new pixel
formats or pixel format flags, or if mpv adds new IMGFMT (either aliases
to FFmpeg formats or own formats). That is unavoidable, and requires
manual inspection of the results, and then updating the ref file.

The changes in the non-test code are to guarantee that the format ID
conversion functions only translate between valid IDs.
2019-11-08 21:22:49 +01:00
wm4 a6c8b4efa5 test: merge test_helpers.c and index.c
No need to keep them separate. Originally I thought index.c was only
going to contain the list of tests, but that didn't happen.
2019-11-08 20:34:07 +01:00
wm4 98b38b04c9 player: do not require dummy file arguments to use --unittest
Move the test execution above the point where it checks for an empty
playlist and exits if that's the case.
2019-11-08 14:29:58 +01:00
wm4 3e401bf652 test: make build fail if NDEBUG is defined
Defining NDEBUG via CFLAGS is the canonical way to disable assertions in
C. mpv respects this (and ta.c actually disables some debugging
machinery if it's defined).

But for tests, this is not useful at all. So if --enable-tests is passed
to configure, the user must not define NDEBUG, even if the rest of the
player does not care.

(We could just #undef NDEBUG, but let's not. Tests calling into the rest
of the player might depend on asserts there, or so.)
2019-11-08 14:23:56 +01:00
wm4 3ed9c1c970 test: just always provide a context for all entrypoints 2019-11-08 14:21:40 +01:00
wm4 53b7a10f54 wscript: add --enable-ta-leak-report option
Kind of more convenient because I'm lazy.
2019-11-08 00:43:46 +01:00
wm4 640b8532aa wscript: remove outdated --enable-libaf
This stopped doing anything since how many years?

The only actual effect was that af_rubberband was made GPL only. Now it
is available in LGPL builds too.
2019-11-08 00:40:11 +01:00
wm4 fb56896319 test: make tests part of the mpv binary
Until now, each .c file in test/ was built as separate, self-contained
binary. Each binary could be run to execute the tests it contained.

Change this and make them part of the normal mpv binary. Now the tests
have to be invoked via the --unittest option. Do this for two reasons:

- Tests now run within a "properly" initialized mpv instance, so all
  services are available.
- Possibly simplifying the situation for future build systems.

The first point is the main motivation. The mpv code is entangled with
mp_log and the option system. It feels like a bad idea to duplicate some
of the initialization of this just so you can call code using them.

I'm also getting rid of cmocka. There wouldn't be any problem to keep it
(it's a perfectly sane set of helpers), but NIH calls. I would have had
to aggregate all tests into a CMUnitTest list, and I don't see how I'd
get different types of entry points easily. Probably easily solvable,
but since we made only pretty basic use of this library, NIH-ing this is
actually easier (I needed a list of tests with custom metadata anyway,
so all what was left was reimplement the assert_* helpers).

Unit tests now don't output anything, and if they fail, they'll simply
crash and leave a message that typically requires inspecting the test
code to figure out what went wrong (and probably editing the test code
to get more information). I even merged the various test functions into
single ones. Sucks, but here you go.

chmap_sel.c is merged into chmap.c, because I didn't see the point of
this being separate. json.c drops the print_message() to go along with
the new silent-by-default idea, also there's a memory leak fix unrelated
to the rest of this commit.

The new code is enabled with --enable-tests (--enable-test goes away).
Due to waf's option parser, --enable-test still works, because it's a
unique prefix to --enable-tests.
2019-11-08 00:26:37 +01:00
wm4 17dde8eeb6 msg: try to document purpose of log levels better
(But I bet nobody ever reads this anyway.)
2019-11-07 22:53:13 +01:00
wm4 1c8d2246bf vo_gpu: vdpau actually works under EGL
The use of glXGetCurrentDisplay() restricted this to the GLX backend.
But actually it works under EGL as well. Removing the GLX-specific call
and using the general mpv-internal method to get the X "Display" makes
it work in mpv.

I didn't know this. Nvidia didn't list this as extension in the EGL
context when I still used their GPUs.

Note that this might in theory break use of vdpau in some libmpv clients
using the render API. But only if MPV_RENDER_PARAM_X11_DISPLAY is not
used, and they relied on mpv using glXGetCurrentDisplay(). EGL does not
provide such an API, and hwdec_vaapi.c also uses what hwdec_vdpau.c uses
now. Considering that vaapi is preferable these days, it's not bad at
all if these clients get "broken". They can be easily fixed by passing
the display to mpv correctly.
2019-11-07 22:53:13 +01:00
wm4 17a89e5778 manpage: vdpauglx backend was removed
A while ago. It was 100% useless.
2019-11-07 22:53:13 +01:00
wm4 1ab5d829ce builtin.conf: set minimal --stream-buffer-size
Some stream inputs may have higher latency with higher buffer sizes, for
example network filesystems via normal OS filesystem interface (these
have to wait until the full buffer is read, which means higher latency).
Probably doesn't matter in practice, but why take chances.
2019-11-07 22:53:13 +01:00
wm4 573673e6aa DOCS/contribute.md: add #include order to coding style
Another thing nobody will read, or consciously follow.
2019-11-07 22:53:13 +01:00
wm4 afbddbdf8f DOCS/contribute.md, zimg: remove 2 instances of an extraneous "s" 2019-11-07 22:53:13 +01:00
wm4 19becc8ea9 stats, demux: log byte level stream seeks 2019-11-07 22:53:13 +01:00
wm4 6487abde79 stream: remove unused read_chunk field
It was set, but its value was never used. The stream cache used to use
it, but it was removed. It controlled how much data it tried to read
from the underlying stream at once.

The user can now control the buffer size with --stream-buffer-size,
which achieves a similar effect, because the stream will in the common
case read half of the buffer size at once. In fact, the new default size
is 128KB, i.e. 64KB read size, which is as much as stream_file and
stream_cb requested by default. stream_memory requested more, but it
doesn't matter anyway. Only stream_smb set a larger size with 128KB.
2019-11-07 22:53:13 +01:00
wm4 e5a9b792ec stream: replace STREAM_CTRL_GET_SIZE with a proper entrypoint
This is overlay convoluted as a stream control, and important enough to
warrant "first class" functionality.
2019-11-07 22:53:13 +01:00
wm4 ca75fedaf4 stream_dvdnav: ok, this makes no sense at all
The dvdnav API reads in 2K blocks (dvdnav_get_next_block()). The mpv
wrapper (fill_buffer() in this file) expects that the read size done by
the mpv core is at least 2K for this reason. If not, it returns an
error.

This used to be OK, because there was a thing called section alignment
in the core code. This was removed because the core shouldn't suffer
from optical disc idiosyncrasies. Which means that ever since, it has
been working only by coincidence, or maybe not at all.

Fixing this would require keeping a buffer in the priv struct, and
returning it piece by piece if the core makes smaller reads. I have no
intention of writing such code, so add an error message asking for a
patch. If anyone actually cares about DVD, maybe it'll get fixed.
2019-11-07 22:53:13 +01:00
wm4 6fc0e7e0a0 stream_bluray: remove size getter
This isn't really needed, since it doesn't support byte seeking (only
for avoiding that demux_disc fucks up even more if the nested demux_lavf
tries to seek in the TS).
2019-11-07 22:53:13 +01:00
wm4 d3479018db stream: change buffer argument types from char* to void*
This is slightly better, although not much, and ultimately doesn't
matter.

The public API in stream_cb.h also uses char*, but can't change that.
2019-11-07 22:53:13 +01:00
wm4 f850d82e65 stream: avoid a duplicate condition
stream_read_peek() duplicated what stream_read_more() checks for anyway
(whether the forward buffer is large enough). This can be skipped by
making the stream_read_more() return value more consistent.
2019-11-07 22:53:13 +01:00
wm4 53f17a71f4 stream: fix typos in a comments 2019-11-07 22:53:13 +01:00
wm4 12d1761064 stream: remove eof getter
demux_mkv was the only thing using this, and everything else accessed it
directly. No need to keep the indirection wrapper around.

(Funny how this getter was in the initial commit of MPlayer.)
2019-11-07 22:53:10 +01:00
wm4 8a0929973d vo_gpu: unconditionally clear framebuffer on start of frame
For some reason, the first frame displayed on X11 with amdgpu and OpenGL
will be garbled. This is especially visible if the player starts,
displays a frame, but then still takes a while to properly start
playback.

With --interpolation, the behavior somehow changes (usually gets worse).
I'm not sure what exactly is going on, and the code in video.c is way
too abstruse. Maybe there is some slight possibility that a frame with
uncleared contents gets displayed, which somehow also corrupts another
frame that is displayed immediately after that.

If clear is unconditionally run, this somehow doesn't happen, and you
see a video frame. By any logic this shouldn't happen: a video frame
should always overwrite the background. So I can't exclude that this
isn't some sort of driver bug, or at least very obscure interaction.

Clearing should be practically free anyway, so always do it.

Fixes: #7105
2019-11-06 22:42:44 +01:00
wm4 e8aae688c3 stream: bump default buffer size from 2K to 64K
(Only half of the buffer is actually used in a useful way, see manpage
or commit which added the option.)

Might have some advantages with broken network filesystem drivers.

See: #6802
2019-11-06 21:57:31 +01:00
wm4 b4466cf0d4 stream: remove inline buffer optimization
Was probably worthless, and I can't measure a difference anymore (I used
to be able and it still seemed worth doing so back then).

When the default buffer size is enlarged in the next commit, the inline
buffer probably won't even be useful in theory, because the data will
rarely be on the same page as the other stream fields. It surely makes
the inline buffer seem like a ridiculous micro-optimization. Farewell...
2019-11-06 21:54:41 +01:00
wm4 f37f4de849 stream: turn into a ring buffer, make size configurable
In some corner cases (see #6802), it can be beneficial to use a larger
stream buffer size. Use this as argument to rewrite everything for no
reason.

Turn stream.c itself into a ring buffer, with configurable size. The
latter would have been easily achievable with minimal changes, and the
ring buffer is the hard part. There is no reason to have a ring buffer
at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and
some subtle issues with demux_mkv.c wanting to seek back by small
offsets (the latter was handled with small stream_peek() calls, which
are unneeded now).

In addition, this turns small forward seeks into reads (where data is
simply skipped). Before this commit, only stream_skip() did this (which
also mean that stream_skip() simply calls stream_seek() now).

Replace all stream_peek() calls with something else (usually
stream_read_peek()). The function was a problem, because it returned a
pointer to the internal buffer, which is now a ring buffer with
wrapping. The new function just copies the data into a buffer, and in
some cases requires callers to dynamically allocate memory. (The most
common case, demux_lavf.c, required a separate buffer allocation anyway
due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_*
changes.

I'm not happy with this. There still isn't a good reason why there
should be a ring buffer, that is complex, and most of the time just
wastes half of the available memory. Maybe another rewrite soon.

It also contains bugs; you're an alpha tester now.
2019-11-06 21:36:02 +01:00
wm4 abb089431d common: add a helper to round up to next power of 2
This is something relatively frequently needed, and there must be half a
dozen ad-hoc implementations in mpv. The next commit uses this, the
suspected duplicate implementations are hiding.
2019-11-06 21:35:49 +01:00
wm4 48fc642e0c demux: unconditionally reposition stream to start before opening
The old code made it depend on ->seekable. If it isn't seekable, and
something discarded the data, then it'll just show an error message,
which will at least be somewhat informative. If no data was discarded,
the seek call is always a no-op.

There's a weird "timeline" condition in the old code; this doesn't
matter anymore, because timeline stuff does not pass streams down to
nested demuxers anymore.
2019-11-06 21:35:32 +01:00
wm4 517489814d manpage: update input protocols
tv:// and pvr:// are gone, DVD almost. The former didn't really have any
uses left, except webcams. Provide a replacement example for that.

We don't need a separate section for DVD. If you use DVD, you're on your
own. There's still enough documentation left to puzzle things together
even if you don't read the source code.
2019-11-04 16:24:57 +01:00
wm4 872df1e06f manpage: opengl-cb -> libmpv
This was renamed ages ago. Fix the outdated usage. Except where
opengl-cb was correct.
2019-11-04 16:17:07 +01:00
wm4 f043d73405 manpage: fix global config file path in --hwdec description 2019-11-04 00:48:03 +01:00
wm4 2ff14f92be build: fix strict ABI option
Fixes: #7118
2019-11-04 00:25:12 +01:00
wm4 a4f92cef1a manpage: shovel around --hwdec description (again)
Not like anyone reads it. Although putting all this text before listing
the allowed option values sort of has the intention to discourage users
from using the option at all. Advertise Ctrl+h, which is a decent way of
enabling hardware decoding temporarily.
2019-11-04 00:01:05 +01:00
wm4 bcb18b8847 DOCS/interface-changes.rst: improve entry about sws changes
This was pretty vague. Add some context, and explicitly mention how
these options now affect screenshots.
2019-11-03 23:32:59 +01:00
wm4 98352362ea img_format: remove some unused format flags
They were used at some point, but then fell into disuse. In general,
these old flags are all a bit fuzzy, so it's a good idea to remove them
as much as possible.

The comment about MP_IMGFLAG_PAL isn't true anymore. The old meaning was
deprecated at some point, and the flag was removed from "pseudo
paletted" formats. I think mpv at one point changed its own flag from
AV_PIX_FMT_FLAG_PSEUDOPAL to AV_PIX_FMT_FLAG_PAL, when the former was
deprecated, and it became unnecessary to allocate a palette for
non-paletted formats. (The one who deprecated in FFmpeg was me, if you
wonder.)

MP_IMGFLAG_PLANAR was used in command.c, use a relatively similar flag
as replacement.
2019-11-03 23:18:35 +01:00
wm4 cfd6595386 vo_x11: accept zimg formats
This is slightly helpful for testing, and otherwise useless and without
consequence.

I'm not using the correct output format and using IMGFMT_RGB0 as
placeholder. This doesn't matter currently, as both sws and zimg support
this as output (and support any input for it). I'm doing this because
it's surprisingly tricky to get the correct output format at this point,
without digging deeper into x11 shit or refactoring parts of the VO. I
don't care enough about this.
2019-11-03 22:52:12 +01:00
wm4 a19571679f sws_utils: remove some unnecessary sws bug work around
Seems like this was needed in 2012. The comment indicates the bug was
fixed in ffmpeg git, so it's long gone.
2019-11-03 22:48:49 +01:00
wm4 67e17f1104 vd_lavc: don't keep packets for fallbacks if errors are tolerated
The user can raise the number of tolerated hardware decoding errors. On
the other hand, we have a static limit on packets that are "saved" for
fallback handling (and that's a good idea to avoid unbounded memory
usage). In this case, it could happen that the start of a file was fine
after a fallback, but after that buffered amount of data, it would
suddenly skip.

It's more useful to skip buffering entirely if the number of tolerated
decoding errors exceeds the fixed buffer.

(And also, I'm sure nobody gives a shit about this feature.)
2019-11-02 23:00:49 +01:00
wm4 0e1cfe0c42 vd_lavc: fix prepare_decoding() failure modes
prepare_decoding() returned a bool that was supposed to tell whether
decoding could work, or if something was fucked. After recent changes to
the decoder loop, this did not work anymore, and caused an endless loop.
Redo it, so it makes more sense. avctx being NULL (software fallback
initialization failed) now signals EOF. hwdec_failed needs to be handled
on send_packet() only, where it probably never happens anyway.

(Who was the idiot who made libavcodec have two entrypoints for
decoding? Oh right, it was me. PEBKAC.)
2019-11-02 22:44:39 +01:00
wm4 7bf31c51f2 vd_lavc: mention hw decoding if decoding fails in hwdec mode
Just so the user knows. Provides some context.
2019-11-02 22:38:08 +01:00
wm4 1bb726dedc vd_lavc: simplify fallback handling for full stream hw decoder
Shovel the code around to make the data flow slightly simpler (?). At
least there's only one send_packet function now. The old code had the
problem that send_packet() could be called even if there were queued
packets; due to sending the queued packets in the receive_frame
function, this should not happen anymore (the code checking for this
case in send_packet should normally never be called).

Untested with actual full stream hw decoders (none available here); I
created a test case by making hwaccel decoding fail.
2019-11-02 22:37:14 +01:00
wm4 dab588a4a2 vd_lavc: signal packet consumed in drop-all case
This is just a very special code path. This probably got stuck, now that
the previous commit returned the EAGAIN properly. Untested.
2019-11-02 21:38:19 +01:00
wm4 203fc6fe44 vd_lavc: change incorrect bool return type to int
Forgotten in commit 5d5fdb7. This failed to return the error code
properly. In particular, if the decoder rejected the packet, this was
not properly detected. Normally, this mattered only in specific cases.

Fixes: #7115
2019-11-02 21:35:48 +01:00
wm4 3ae9f671d4 README.md: reduce focus on MPlayer, small improvements
MPlayer isn't all too well-known anymore. It does not make sense to
"advertise" with it (and it actually never did).

The GPU comment needed clarification. I think originally, it was just to
signal that you'll have a bad time with Intel. Make that broader.
2019-11-02 19:15:59 +01:00
wm4 6eb0dc5447 zimg: support subsampled chroma with non-aligned image sizes 2019-11-02 18:49:17 +01:00
wm4 d26c1c6814 zinmg: stop using GBRP for RGB
Instead, use a YUV planar format. It doesn't matter, since we use the
format only internally and for "management" purposes. We're only
interested in the physical layout, not what colorspace FFmpeg "forcibly"
associates with it.

Also get rid of using the old and slightly sketchy mp_imgfmt_find()
function. Yep, the IMGFMT_RGB30 now "constructs" the planar format,
instead of using a pixfmt constant. Slightly inconvenient, tricky, and
fragile, but I like it, so bugger off.

This whole thing gets rid of some of the strange plane permutations that
were needed earlier.
2019-11-02 18:11:02 +01:00
wm4 20c1bd8a5e zimg: correct RGB30 order (probably)
According to the definition of the GL format, and the definition in
img_format.h, and the actual output by vo_gpu, the order of components
was probably wrong. It's exceedingly likely that the vo_drm format (for
which this was originally written) has the same layout, so this was
probably a bug from when the zimg wrapper code was refactored.
2019-11-02 17:52:13 +01:00
wm4 e58e650a97 video: mess with the filte chain to enable zimg IMGFMT_RGB30 output
This was too hardcoded to libswscale. In particular, IMGFMT_RGB30 output
is only possible with the zimg wrapper, so the context needs to be taken
into account (since this depends on the --sws-allow-zimg option
dynamically). This is still slightly risky, because zimg currently will
still fall back to swscale in some cases, such as when it refuses to
initialize the particular color conversion that is requested.
f_autoconvert.c could actually handle this better, but I'm tool fucking
lazy right now, and nobody cares anyway, so go away, OK?
2019-11-02 17:50:32 +01:00
wm4 3e660f6164 vo_gpu: opengl: add support for IMGFMT_RGB30
This integrates it as "special" format, with no alpha component, as the
equivalent IMGFMT_RGB30 isn't meant to contain any.

Nothing can produce this format in the video chain yet, so the next
commits are needed to make this actually work.
2019-11-02 17:46:46 +01:00
Dan Elkouby dfc060f099 ass_mp: reset packer when allocation fails
Sometimes the atlas can get so large that it exceeds the maximum allowed
size for an mp_image. Since the atlas will never shrink naturally, this
breaks subtitles entirely until mpv is restarted. Reset the packer so
that subtitles can rendered properly once the atlas fits again.

This is a partial workaround for #6286.
2019-11-02 14:42:36 +01:00
wm4 985a1cde5a manpage: update --framedrop option
The statement about the display FPS is outdated by several years.
"audio"-sync mode does not use the display FPS anymore, and that it's
X11 only also isn't true anymore.

These modes have separate implementations for audio and display video
sync. modes, so the explanations are separate.

Why the hell are users playing around with this anyway? The explanations
are probably too special to make sense for anyone who doesn't know the
code (and who knows the code doesn't need them anyway), but whatever.
2019-11-02 14:29:24 +01:00
wm4 00838fe0c3 zimg: make --zimg-fast=yes default
This is mostly just because of the odd RGB default gamma issue, which
shouldn't have any real impact. This also sets allow_approximate_gamma,
which I hope is fine for normal use cases.
2019-11-02 02:22:16 +01:00
wm4 c9d685f5d6 zimg: pass through Y plane when repacking nv12
Normally, the Y plane can just be passed directly to zimg, and only the
chroma plane needs to be (de)interleaved. It still needs a copy if the Y
pointer is not aligned, though. (Whether this is actually a problem
depends on the CPU and probably zimg's compiler.)

This requires deciding per plane whether the plane should go through the
repack buffer or not. This logic is active in non-nv12 cases, because
not doing so would require extra code (maybe 2 lines or so).
repack_align is now always called, even if it's planar->planar with all
input aligned, but it won't actually do anything in that case. The
assumption is that zimg won't change behavior if you pass a callback
that does nothing versus passing NULL as callback.
2019-11-02 02:18:24 +01:00
wm4 3b56f82965 zimg: add semi-planar repacker
This is for formats like nv12 (including p010, nv24, etc.). Might be
important for hardware decoding. Previously, this would have forced a
libswscale fallback.

The genericism makes this only slightly more complicated. The main
complication is due to the fact that mixing planar and packed stuff is
insane (thanks, Nvidia).

P010 output will actually happily set any of the 6 bit "padding" LSB,
that are normally supposed to be 0 (for unpadded data there is P016).
Scaling happens with 16 bit precision. Not going to bother adding an
extra packer which zeros them out, or with shifting them in
packing/unpacking. Lets just hope nobody notices.
2019-11-02 01:10:22 +01:00
wm4 c3cee4b9ec img_format: add function to find image format by layout
This is similar to mp_imgfmt_find(), but probably a bit saner. Used by
the next commit. The previous commit is required to map this
unambiguously between all formats.
2019-11-02 01:02:54 +01:00
wm4 bdd1e1e7ec img_format: add mp_regular_imgfmt.forced_csp field
As the code comment says, this is needed to disambiguate FFmpeg formats.
This struct only describes the "physical" layout of a format, while
FFmpeg also attaches part of the colorspace information to the format.
2019-11-02 01:00:32 +01:00
wm4 337ccc50dc img_format: add more explanations to component_pad field
Weird shit. I thought this was a clever way to elegantly handle two
cases at once, but maybe it's just confusing.
2019-11-02 00:55:55 +01:00
wm4 4b3666329e zimg: fix out of bounds memory accesses due to broken zmask
We've set all planes to the same zmask. But for subsampled chroma, the
zmask obviously needs to be smaller. This could lead to out of bounds
memory read and write accesses.

Move the align repacker to a single function, since this is now more
convenient.
2019-11-02 00:48:04 +01:00
wm4 871900f562 github: we want a -v -v log now
--log-file uses debug log level by default. On command line, -v -v will
use debug log level.
2019-11-01 01:56:08 +01:00
wm4 2ce4568018 f_decoder_wrapper: reduce uninit message log level
For vd/ad.
2019-11-01 01:55:06 +01:00
wm4 6cd0978f8a client API: reduce log level of client exiting
See previous commit message.
2019-11-01 01:54:39 +01:00
wm4 5189ea4696 demux: reduce log level for cache index resizing
Now that I probably removed all bugs in this (?), this is uninteresting.
2019-11-01 01:54:12 +01:00
wm4 fdce778605 lua: change config file logging
Make the existing "not found" messages debug only, and add a new verbose
message if a config file was opened. The idea is that logging should
make it apparent whether or not config files are loaded, and it's more
common to use scripts without config files, leading to fewer log
messages in verbose mode.
2019-11-01 01:52:05 +01:00
wm4 02cb44ac8b x11: reduce log level for relatively uninteresting things
Normally nobody cares about the WM detection stuff etc., so log this
only at debug log levels.
2019-11-01 01:40:22 +01:00
wm4 67aa7b0439 demux_mkv: reduce log level of mkvinfo part to debug
demux_mkv has lots of logging that shows information about the file. It
sort of reminds of mkvinfo output. While this is sometimes interesting,
it's too much for verbose mode, and should be in debug log level.
2019-11-01 01:37:09 +01:00
wm4 f7073a5ec9 m_config: log applying profiles 2019-11-01 01:29:44 +01:00
wm4 89ae370d41 m_config: raise log level of setting options to verbose
In 2017, we lowered this to debug level. But I think setting options is
important enough that it should be logged even in verbose, at least
compared to all the other dumb noise.

This might be reduced again if verbose logging becomes much cleaner.
2019-11-01 01:29:30 +01:00
wm4 04b4155582 zimg: add more packers/unpackers
This probably covers all packed formats which have byte-aligned
component, no alpha, and no subsampling. Everything else needs more
imgfmt metadata, or something even more complicated. Alpha is primarily
not supported, because zimg requires a second scaler instance for it,
and handling packing/unpacking with it is an unacceptable mess.
2019-10-31 22:43:58 +01:00
wm4 821320252e m_option: remove an unused function
I think the last real use of this went away in 2014 or so.
2019-10-31 17:42:41 +01:00
wm4 706e708d2f options: make --show-profile without parameters list all profiles 2019-10-31 17:32:57 +01:00
wm4 e96ab5becb manpage: fix another typo 2019-10-31 17:27:17 +01:00
wm4 9e0b0be8ee manpage: update --zimg-scaler default
Forgotten in previous commit.
2019-10-31 17:01:31 +01:00
wm4 a7230dfed0 sws_utils, zimg: destroy vo_x11 and vo_drm performance
Raise swscale and zimg default parameters. This restores screenshot
quality settings (maybe) unset in the commit before. Also expose some
more libswscale and zimg options.

Since these options are also used for VOs like x11 and drm, this will
make x11/drm/etc. much slower. For compensation, provide a profile that
sets the old option values: sw-fast. I'm also enabling zimg here, just
as an experiment.

The core problem is that we have a single set of command line options
which control the settings used for most swscale/zimg uses. This was
done in the previous commit. It cannot differentiate between the VOs,
which need to be realtime and may accept/require lower quality options,
and things like screenshots or vo_image, which can be slower, but should
not sacrifice quality by default.

Should this have two sets of options or something similar to do the
right thing depending on the code which calls libswscale? Maybe. Or
should I just ignore the problem, make it someone else's problem (users
who want to use software conversion VOs), provide a sub-optimal
solution, and call it a day? Definitely, sounds good, pushing to master,
goodbye.
2019-10-31 16:51:12 +01:00
wm4 2c43d2b75a screenshot, vo_image: use global swscale/zimg parameters
Lots of dumb crap to do... something. Instead of adding yet another dumb
helper, just use the main" sws_utils API in both callers. (Which,
unfortunately, has been duplicated for glorious webp screenshots,
despite the fact that webp is crap.)

Good part: can enable zimg for screenshots (as far as needed).
Bad part: uses "default" swscale parameters instead of HQ now.
2019-10-31 15:44:09 +01:00
wm4 835586513d sws_utils: shuffle around some shit
Purpose uncertain. I guess it's slightly better, maybe.

The move of the sws/zimg options from VO opts (vo_opt_list) to the
top-level option list is tricky. VO opts have some helper code in vo.c,
that sends VOCTRL_SET_PANSCAN to the VO on every VO opts change. That's
because updating certain VO options used to be this way (and not just
the panscan option). This isn't needed anymore for sws/zimg options, so
explicitly move them away.
2019-10-31 15:26:03 +01:00
wm4 c10ba5eb8e Use mp_log2() instead of av_log2() 2019-10-31 13:17:18 +01:00
wm4 7510ed6f68 common: add mp_log2()
To be used in the next commit.

According to compiler explorer, __builtin_clz is very widely available,
and it barely makes sense to provide a fallback. clang also eats this
(and identifies at least as GCC 4). Actually, there's doubt that a fast
log2 implementation is needed at all (I guess UTF-8 parsing needs it,
but something UTF-8-specific would probably make it faster than using
log2). So the fallback is just something naive.
2019-10-31 13:16:58 +01:00
wm4 6d92e55502 Replace uses of FFMIN/MAX with MPMIN/MAX
And remove libavutil includes where possible.
2019-10-31 11:24:20 +01:00
wm4 6fdfa7c991 stream_memory: remove trivial ffmpeg dependency 2019-10-31 11:06:44 +01:00
wm4 a5461b29c4 manpage: document stats page 3 2019-10-31 11:06:22 +01:00
wm4 1c984f992f player: simplify --stream-dump code
Not sure why it was so complicated. It avoided allocation data on the
stack and copying it twice, but who cares.
2019-10-31 11:05:55 +01:00
wm4 a267452b00 stream: move stream_read_line to demux_playlist.c
demux_playlist.c is the only remaining user of this. Not sure if it
should stay this way, but for now I'll say yes.
2019-10-31 11:05:48 +01:00
wm4 c6b08d222f stream: stop accessing buffer internals in stream_read_line()
Getting this out of the way in preparation for reworking stream
internals.
2019-10-31 11:05:45 +01:00
Jan Ekström be4996e312 interface-changes: fixup the location of d3d11-output-csp
0.30.0 is already cut, so +1 it is.
2019-10-30 20:02:08 +02:00
Jan Ekström 17ad806993 vo_gpu/opengl: fully initialize FBO when passing it to rendering
Until now, we only properly initialized two values, leaving the
rest be garbage.

Fixes #7104
2019-10-30 15:54:41 +01:00
Jan Ekström fc29620ec8 vo_gpu/d3d11: add support for configuring swap chain color space
By default utilizes the color space of the desktop on which the
swap chain is located. If a specific value is defined, it will be
instead be utilized.

Enables configuration of the PQ color space (BT.2020 primaries,
PQ transfer function) for HDR.

Additionally, signals the swap chain color space to the renderer,
so that the render looks correct without having to specify
target-trc or target-prim manually.

Due to all of the APIs being Win10+ only, will only work starting
with Windows 10.
2019-10-30 02:41:25 +02:00
Jan Ekström 93dd77b38e vo_gpu/d3d11: add helpers for getting names for DXGI formats & CSPs
Additionally, define the few enum values that are currently missing
in mingw-w64 headers.
2019-10-30 02:41:25 +02:00
Jan Ekström 4e712e627c vo_gpu: add and utilize color space information from ra_fbo
This lets us set primaries, transfer function and the target peak
based on what the presenting layer would want us to have.

Now that this mechanism is available, warn if the user has
overridden values such as primaries or transfer function.
2019-10-30 02:41:25 +02:00
Jan Janssen b27836011e osc: calculate osc_geo position after aspect correction
Fixes #7098
2019-10-29 17:09:26 +01:00
Cameron Cawley afe3a5a010 vo_caca: Implement VOCTRL_UPDATE_WINDOW_TITLE 2019-10-29 17:07:41 +01:00
Jan Janssen 00c9a6c237 osc: Unify bottom and topbar code
Among the pointless duplication the right timecode label was given some extra space that wasn't needed.

Fixes: #6904
2019-10-28 17:16:02 +01:00
Cameron Cawley 69f7251f32 manpage: Update information about default mouse bindings 2019-10-28 17:14:49 +01:00
Cameron Cawley c2ab4d22b4 vo_sdl: Acknowledge when the mouse enters or leaves the window 2019-10-28 17:14:49 +01:00
Cameron Cawley 619b466cef input: Add default bindings for MBTN_BACK and MBTN_FORWARD 2019-10-28 17:14:49 +01:00
Cameron Cawley f4c04f5a3c vo_sdl: Improve mouse button input
SDL_BUTTON_X1 and SDL_BUTTON_X2 are now correctly mapped to MP_MBTN_BACK and MP_MBTN_FORWARD.
2019-10-28 17:14:49 +01:00
Cameron Cawley d51e637150 vo_sdl: Support mouse wheel input 2019-10-28 17:14:49 +01:00
sfan5 6f9399327e DOCS/release-policy.md: clarify a few details 2019-10-27 14:06:16 +01:00
James Ross-Gowan 8e50d7a746 vo_gpu: log ra_format.storable with the other flags
This seems to have been missed when the storable flag was added, since
all the other flags were logged here. It can be useful to know if an RA
format is storable, so log it as well.
2019-10-27 00:45:27 +11:00
James Ross-Gowan 888f4e63a4 vo_gpu: d3d11: set the ra_format.storable flag
This flag was added in e2976e662d, but it was only set for Vulkan. In
D3D11 it can be set from info in D3D11_FEATURE_FORMAT_SUPPORT2.
2019-10-27 00:45:27 +11:00
wm4 a908101258 vo_gpu: attempt to fix 0bgr format
Using e.g. --vf=format=0bgr showed obviously wrong colors with --vo=gpu.
The reason is that leading padding wasn't handled correctly.

Try to hack fix it. While the code in copy_image() is somewhat
reasonable, I can't tell what the fuck is going on with that HOOKED
shit. For some reason this HOOKED shit doesn't use copy_image() (???),
or uses it incorrectly. It affects debanding. --deband=no works
correctly. If it's enabled, the crap in hook_prelude() is needed.

I bet there are many more bugs with this. For example, the deband shader
will try to deband the alpha channel if the format abgr is used (because
the correct component order is only established later). This can be
tested by inserting a "color.x = 0;" at the end of the deband shader,
and using --vf=format=rgba vs. abgr.

I cannot comprehend why it doesn't just store explicitly which
components a texture contains, and why it doesn't just read the
components always in an uniform way.

There's a big chance this fix works only by coincidence. This shouldn't
have been so hard either. Time for a complete rewrite?
2019-10-26 00:02:55 +02:00
wm4 d3f8d82279 mp_image: copy closed captions when copying attributes
With hwdec copy modes, mp_image_copy_attributes() is used to transfer
metadata other than the image data when copying the image from the
hardware surface. It didn't copy the closed caption data.

Fix this. This makes closed captions in copy mode work.

Fixes: #6376
2019-10-25 22:38:00 +02:00
wm4 40b557db6a mp_image: move buffer ref assigning to a function
Mostly untested, for the next commit.

There's another case of this in this file (ref_buffer()), but it's too
weird, so ignore it.
2019-10-25 22:36:19 +02:00
wm4 c184e290b0 sdl: prevent concurrent use of SDL in different threads
sdl_gamepad.c and vo_sdl.c both have their own event loops and run in
separate threads. They don't know of each other (and shouldn't). Since
SDL only has one global event loop (why didn't they fix this in SDL2?),
these obviously clash. The actual behavior is relatively subtle, which
event being randomly dispatched to either of the threads.

This is very regrettable. Very.

Work this around. "Fortunately" SDL exposes its global state to some
degree. SDL_WasInit() returns whether a "subsystem" was initialized, and
you could say the one who initialized it owns it. Both SDL_INIT_VIDEO
and SDL_INIT_GAMECONTROLLER implicitly enable SDL_INIT_EVENTS, and the
event loop is indeed the resource that cannot be shared.

Unfortunately, this is still racy, since SDL_InitSubSystem is a second
call, and succeeds if the subsystem is already initialized (increases a
refcount I think). But good enough. Blame SDL for everything.

(I think I made this commit message too long. Nobody cares even.)

Fixes: #7085
2019-10-25 22:17:54 +02:00
wm4 e63091b3cc build: make vo_sdl conflict with cocoa
These are inherently incompatible. As far as I'm aware, SDL must be used
from the main thread on OSX.

(Technically, this condition is wrong: the problem happens on OSX in
general, or more precisely, when SDL uses Cocoa. I didn't find the waf
OSX dependency name after 5 second of searching, so I'm just using
cocoa, without which mpv is useless on OSX anyway.)
2019-10-25 22:02:16 +02:00
wm4 9471077efd vo_sdl: put on do not use stamp
It seems some users try to use it (!). This VO was always an experiment,
and intended for low power devices. Whether this experiment succeeded or
not, it's a rather obscure VO. Recently I've seen a regrettable user,
who seemed to use this only because mpv was built without x11 support
(!). Add this warning, like other fallback VOs have it. (The message was
copied from vo_x11.)
2019-10-25 21:58:51 +02:00
wm4 4a82349900 input: disable gamepad code by default
Enabling this by default probably causes a number of issues, such as
breaking vo_sdl, or reacting to various input devices while the window
is not focused. It's also pretty obscure, or at least new. Disable it by
default.
2019-10-25 21:54:35 +02:00
wm4 52536aaa7b f_decoder_wapper: trust frame return over error code
lavc_process() calls the receive/send callbacks, which mirror
libavcodec's send/receive API. The receive API in particular can return
both a status code and a frame. Normally, libavcodec is pretty explicit
that it can't return both a frame and an error. But the receive callback
does more stuff in addition (vd_lavc does hardware decoding fallbacks
etc.). The previous commit shows an instance where this happened, and
where it leaked a frame in this case.

For robustness, check whether the frame is set first, i.e. trust it over
the status code. Before this, it checked for an EOF status first.

Hopefully is of no consequence otherwise. I made this change after
testing everything (can someone implement a test suite which tests this
exhaustively).
2019-10-25 21:50:10 +02:00
wm4 edc6075fa3 vd_lavc: fix draining with hwdec copy modes
Commit 5d5fdb77e9 changed details of the decoding control flow, and
called it a "high-risk" change. It turns out that this broke with with
hwdec copy mode, where there is some sort of delay queue (supposedly
increases efficiency, but more likely worthless cargo-cult).

It simply used the wrong (basically inverted) condition for the draining
case.

This was the only case that did not work properly. Other tests,
including video/audio decoding errors, software decoding fallbacks,
etc., seemed to work well. Might still not be exhaustive, as there are
so many corner cases.

Also change two error code returns. This don't/shouldn't really matter,
though the second error code led it to return both a frame and
AVERROR_EOF, which is unexpected, and makes lavc_process() leak a frame.
But also see next commit.

Fixes: 5d5fdb77e9
2019-10-25 21:44:49 +02:00
James Ross-Gowan 7384b05433 vo_gpu: d3d11: prevent wraparound in queued frames calc
If expected_sync_pc is greater than submit_count, the unsigned
subtraction will wraparound, which breaks playback. This bug was found
while experimenting with bit-blt model present, but it might be possible
to trigger it with the flip model as well, if there was a dropped frame.
2019-10-26 01:14:01 +11:00
sfan5 ca0177481b Update VERSION 2019-10-25 15:39:16 +02:00
sfan5 51ec2e86e8 Merge branch 'release/0.30' 2019-10-25 15:39:02 +02:00
wm4 8b0ff53b69 sdl_gamepad: fix typo in function name
As pointed out by LaserEyess on IRC.
2019-10-25 15:33:23 +02:00
wm4 49cde32be0 sdl_gamepad: fix function signature
This is semantically different in C.
2019-10-25 15:26:34 +02:00
wm4 50f263990a vo_drm: allow use of zimg 2019-10-25 15:25:49 +02:00
wm4 5e2779b2da client API: copy instead of move old value on async path
In theory, it's better to keep the old value, because that's more
consistent with the logic of using change timestamps. With the current
code, the old value will probably never be used (instead it will fetch a
new value on every change), so this shouldn't make a difference in
practice.
2019-10-25 15:14:05 +02:00
sfan5 3a8abbee2f Release 0.30.0 2019-10-25 15:08:15 +02:00
wm4 89dc74885d manpage: fix --script docs
This doesn't take a ',' separated list. --script is just an alias for
--scripts--append. --scripts accepts a list, but uses the
mplayer-inherited platform-dependent path separator.

Fixes: #5996
2019-10-25 15:06:25 +02:00
wm4 509f6f5a9b command: remove some unused property metadata
Also add an OSD entry for the video aspect.
2019-10-25 15:06:17 +02:00
wm4 f5f285ec3e options: set correct range for --video-aspect-override
It appears this option didn't have min/max enabled for quite a while
(broken while it was still called --aspect).
2019-10-25 15:06:13 +02:00
wm4 3c7e20a0e2 json: write NaN/Infinity float values as strings
JSON doesn't support these for some god-awful reason. (JSON would have
been so much better if it weren't based on JavaScript, the plague of
this world.)

We don't really care whether these specific values "round trip", so we
might as well write them in a standard-compliant way.

Untested. I was too lazy to even run this, but it probably works.

See #6691.
2019-10-25 15:06:08 +02:00
wm4 419c44ccf6 vo_gpu, options: don't return NaN through API
Internally, vo_gpu uses NaN for some options to indicate a default value
that is different depending on the context (e.g. different scalers).
There are 2 problems with this:

1. you couldn't reset the options to their defaults
2. NaN is a damn mess and shouldn't be part of the API

The option parser already rejected NaN explicitly, which is why 1.
didn't work. Regarding 2., JSON might be a good example, and actually
caused a bug report.

Fix this by mapping NaN to the special value "default". I think I'd
prefer other mechanisms (maybe just having every scaler expose separate
options?), but for now this will do. See you in a future commit, which
painfully deprecates this and replaces it with something else.

I refrained from using "no" (my favorite magic value for "unset" etc.)
because then I'd have e.g. make --no-scale-param1 work, which in
addition to a lot of effort looks dumb and nobody will use it.

Here's also an apology for the shitty added test script.

Fixes: #6691
2019-10-25 15:06:04 +02:00
wm4 e67386e50b manpage: fix --script docs
This doesn't take a ',' separated list. --script is just an alias for
--scripts--append. --scripts accepts a list, but uses the
mplayer-inherited platform-dependent path separator.

Fixes: #5996
2019-10-25 13:41:34 +02:00
wm4 d66eb93e5d client API: add async path; fix deadlock for vo_libmpv users
In commit 065c307e8e, I broke everything. It seemed like a nice idea,
but it explicitly broke an assumption vo_libmpv were explicitly allowed
to make: that observing properties does not lock the core. The commit
did just that and locked the core for property updates. This made for
example mpv's own OSX backend freeze (it uses vo_libmpv for convenience
to make up for Apple's incredibly broken OpenGL shit).

I don't want to revert that commit just because vo_libmpv's design is
horrible. So instead add an optional asynchronous path, that is only
used if vo_libmpv is in use (best idea ever?).

Interestingly, this isn't so hard. It adds about 90 lines of code, which
are only run on OSX and libmpv users, so I don't have to care about the
crashes and weird behavior this might cause. It even worked on the first
try except for a quickly fixed memory leak. The code path can be tested
anywhere by just turning the uses_vo_libmpv condition into always true.

The atomic is out of laziness. Saves some thinking how to get around the
locking order.
2019-10-25 01:57:51 +02:00
wm4 767c35c883 command: remove some unused property metadata
Also add an OSD entry for the video aspect.
2019-10-25 00:50:38 +02:00
wm4 223876d92b options: set correct range for --video-aspect-override
It appears this option didn't have min/max enabled for quite a while
(broken while it was still called --aspect).
2019-10-25 00:47:45 +02:00
wm4 7ac622bc5f json: write NaN/Infinity float values as strings
JSON doesn't support these for some god-awful reason. (JSON would have
been so much better if it weren't based on JavaScript, the plague of
this world.)

We don't really care whether these specific values "round trip", so we
might as well write them in a standard-compliant way.

Untested. I was too lazy to even run this, but it probably works.

See #6691.
2019-10-25 00:30:04 +02:00
wm4 77f309c94f vo_gpu, options: don't return NaN through API
Internally, vo_gpu uses NaN for some options to indicate a default value
that is different depending on the context (e.g. different scalers).
There are 2 problems with this:

1. you couldn't reset the options to their defaults
2. NaN is a damn mess and shouldn't be part of the API

The option parser already rejected NaN explicitly, which is why 1.
didn't work. Regarding 2., JSON might be a good example, and actually
caused a bug report.

Fix this by mapping NaN to the special value "default". I think I'd
prefer other mechanisms (maybe just having every scaler expose separate
options?), but for now this will do. See you in a future commit, which
painfully deprecates this and replaces it with something else.

I refrained from using "no" (my favorite magic value for "unset" etc.)
because then I'd have e.g. make --no-scale-param1 work, which in
addition to a lot of effort looks dumb and nobody will use it.

Here's also an apology for the shitty added test script.

Fixes: #6691
2019-10-25 00:25:05 +02:00
wm4 b0827b4dc4 client API: avoid lost wakeups
The commit linked below added temporary unlocking to update_prop(),
which is indirectly called by mpv_wait_event(). If an unlock happens,
and no property change event is returned, we must re-poll the event
queue. Rechecking the state on unlocks is basically a standard
requirement for code using condition variables.

Untested beyond a simple test.

Fixes: 065c307e8e
2019-10-24 19:12:36 +02:00
wm4 5d5fdb77e9 ad_lavc, vd_lavc: return full error codes to shared decoder loop
ad_lavc and vd_lavc use the lavc_process() helper to translate the
FFmpeg push/pull API to the internal filter API (which completely
mismatch, even though I'm responsible for both, just fucking kill me).

This interface was "slightly" too tight. It returned only a bool
indicating "progress", which was not enough to handle some cases (see
following commit).

While we're at it, move all state into a struct. This is only a single
bool, but we get the chance to add more if needed.

This fixes mpv falling asleep if decoding returns an error during
draining. If decoding fails when we already sent EOF, the state machine
stopped making progress. This left mpv just sitting around and doing
nothing.

A test case can be created with: echo $RANDOM >> image.png

This makes libavformat read a proper packet plus a packet of garbage.
libavcodec will decode a frame, and then return an error code. The
lavc_process() wrapper could not deal with this, because there was no
way to differentiate between "retry" and "send new packet". Normally, it
would send a new packet, so decoding would make progress anyway. If
there was "progress", we couldn't just retry, because it'd retry
forever.

This is made worse by the fact that it tries to decode at least two
frames before starting display, meaning it will "sit around and do
nothing" before the picture is displayed.

Change it so that on error return, "receiving" a frame is retried. This
will make it return the EOF, so everything works properly.

This is a high-risk change, because all these funny bullshit exceptions
for hardware decoding are in the way, and I didn't retest them. For
example, if hardware decoding is enabled, it keeps a list of packets,
that are fed into the decoder again if hardware decoding fails, and a
software fallback is performed. Another case of horrifying accidental
complexity.

Fixes: #6618
2019-10-24 18:50:28 +02:00
wm4 065c307e8e client API: simplify (?) property change notification generation
Property change notification works by having the mpv core wake up all
clients observing a property when the property potentially changes. The
clients then read the property's value, and determine if there was an
actual change. (The latter part depends what the property returned for
the previous change notification, so it depends on the client, and
cannot be generated by the core itself.)

Until now, reading the property value was done in a pseudo-async way by
queuing a callback back to the core, running it there, and then waking
up the client thread again. I cannot comprehend why this was done in
such a complicated, fragile way. Maybe it's a leftover from times when
client.c had to do this (in short, because properties could access
vo_opengl, which has thread-local state).

One past idea was to make the implementation of true async properties
easier (for which you would need such a state machine anyway). But they
don't exist yet, and I doubt the current mess would be really helpful
when actually implementing them.

Simplify this, and run the update in the client's thread directly. In
addition to the fundamental change, many roundabout things can be
removed as a consequence.

Unfortunately, I noticed that lock order issues force you to release
ctx->lock before doing so, which makes things more complex due to
possible concurrent mpv_unobserve_property() calls. Solve this by
removing properties lazily, which means you may have to do multiple
mpv_wait_event() calls before the property entry is actually destroyed.
This should not matter in practice, and does not affect the semantics.
It could also cause "leaks" by observing/unobserving properties in a
loop, without ever calling mpv_wait_event(). Just don't do this, duh.

(I considered making this dependent on whether the previous
mpv_wait_event() call returned the property being removed, but a
separate code path seemed too complicated. I also considered copying the
name and property data when returning a MPV_EVENT_PROPERTY_CHANGE, but
actually this doesn't solve the problem of update_prop() being
interrupted by mpv_unobserve_property(); there are ways around it, but I
just said no.)

This was made using the cowboy coding software engineering methodology.
If you find any bugs, keep them yourself.
2019-10-24 17:51:36 +02:00
wm4 922be71101 client API: move a function
May reduce the diff of the next commit.
2019-10-24 16:48:32 +02:00
wm4 436bf04d5f client API: remove unused global event mask
Apparently this was only added and used for cache update stuff, which
was changed in commit 8dbc93a94c. Now it's unused, messy, ugly, and
is in the way, so get rid of it.
2019-10-24 16:27:24 +02:00
wm4 962a9fa981 lua: actually unobserve properties in mp.unobserve_property()
Not doing this looked like a memory leak.

This looks like an oversight in the commit that added it: a94020e25b,
possible brain damage?

Fixes: #6823
2019-10-24 16:27:05 +02:00
wm4 bc2058fcd4 demux_mkv: add V_MPEG4/MS/V3 mapping
Fixes: #6547
2019-10-24 13:52:09 +02:00
wm4 8721ac50fb msg: always use terminal control codes for status line
Before this commit, the status line used terminal control codes only if
stderr was a terminal. I'm not sure why this was done, and git blame
tracks it back to a huge commit by me, which changed all of the terminal
handling.

A user complained, so just stop treating this specially for no reason.

Fixes: #6617
2019-10-24 13:52:09 +02:00
wm4 a935109235 ytdl_hook: --vid=no should not ignore --ytdl-format in config file
Do this only if ytdl-format was not set at all.

Fixes: #6636
2019-10-24 13:52:09 +02:00
wm4 14eefb7c0a manpage: fix RST formatting errorin vf_format description 2019-10-24 13:52:05 +02:00
wm4 e3c1d12451 manpage: slap "do not use" label on vf_vapoursynth
Plus some other minor corrections.
2019-10-24 12:55:26 +02:00
wm4 45cab1562c vf: improve vf_vapoursynth description
In particular describe dataflow issues (see #7020).

Insert complaint that I'm wasting time on this crap instead of things
that benefit me.
2019-10-23 22:27:07 +02:00
Stefano Pigozzi 899e0bd16b input: add gamepad support through SDL2
The code is very basic:

- only handles gamepads, could be extended for generic joysticks in the
  future.
- only has button mappings for controllers natively supported by SDL2.
  I heard more can be added through env vars, there's also ways to load
  mappings from text files, but I'd rather not go there yet. Common ones
  like Dualshock are supported natively.
- analog buttons (TRIGGER and AXIS) are mapped to discrete buttons using an
  activation threshold.
- only supports one gamepad at a time. the feature is intented to use
  gamepads as evolved remote controls, not play multiplayer games in mpv :)
2019-10-23 09:40:30 +02:00
sfan5 79b15f50e3 DOCS/client-api-changes.rst: fix formatting 2019-10-22 15:48:34 +02:00
dudemanguy f7881ea573 wayland: don't get data device if wl_seat is null 2019-10-22 02:29:53 +00:00
wm4 e82bf5f91d manpage: finish an unfinished sentence 2019-10-21 16:54:13 +02:00
wm4 9565ff522b build: add --enable-ffmpeg-strict-abi option
This can be used by distros to disable all known FFmpeg ABI violations.

Currently only 1 is known, in demux_lavf.c. In addition to if-defing out
the access to the private FFmpeg field, this disables the possibly
fragile nested open callbacks, which make sense only if the
aforementioned field can be accessed.
2019-10-21 01:38:25 +02:00
wm4 5dba244c22 filters: extend vf_format so that it can convert color parameters
Form some reason (and because of my fault), vf_format converts image
formats, but nothing else. For example, setting the "colormatrix"
sub-parameter would not convert it to the new value, but instead
overwrite the metadata (basically "reinterpreting" the image data
without changing it).

Make the historical mistake worse, and go all the way and extend it such
that it can perform a conversion. For compatibility reasons, this needs
to be requested explicitly. (Maybe this would deserve a separate filter
to begin with, but things are messed up anyway. Feel free to suggest an
elegant and simple solution.)

This demonstrates how zimg can properly perform some conversions which
swscale cannot (see examples added to vf.rst).

Stupidly this requires 2 code paths, one for conversion, and one for
overriding the parameters.

Due to the filter bullshit (what was I thinking), this requires quite
some acrobatics that would not be necessary without these abstractions.
On the other hand, it'd definitely be more of a mess without it. Oh
whatever.
2019-10-21 01:38:25 +02:00
wm4 8a4e9d5c18 sws_utils: improve zimg fallback messages
This could log:

  [swscale] falling back to swscale

And that's a WTF, even if you're aware of the fucky way zimg was hacked
into the filter chain.
2019-10-21 01:38:25 +02:00
wm4 579b9eb8de vf_fingerprint: don't print fallback warning on each frame
f_reset, which is called on seeks, was a good place for resetting the
warning flag (so the warning would be print again). Except some other
code abused f_reset when all metadata was read (in both cases you want
to clear the metadata). Instead of spending more time on getting this
flag reset correctly, just never reset it.
2019-10-21 01:38:25 +02:00
wm4 43e903980b zimg: minor name consistency improvement
Now these are like x2ccc10_pack: MSB to LSB, with bit width following
each component (except for components with the same bit width).
2019-10-21 01:38:25 +02:00
wm4 1c96152db3 f_swscale: enable use of zimg
The usual opt-in mechanism.
2019-10-21 01:38:25 +02:00
Dudemanguy911 9dead2b932 wayland: fix presentation time
There's 2 stupid things here that need to be fixed. First of all,
vulkan wasn't actually using presentation time because somehow the
get_vsync function in context.c disappeared. Secondly, if the mpv window
was hidden it was updating the ust time based on the refresh_usec but
really it should simply just not feed any information to the vsync info
structure. So this adds some logic to assume whether or not a window is
hidden.
2019-10-20 19:50:10 +00:00
wm4 525e712757 zimg: support RGB30 output
This may be used later elsewhere.
2019-10-20 19:41:18 +02:00
wm4 631379bea9 zimg: move component order arrays to top of file 2019-10-20 19:41:18 +02:00
wm4 8f5979c5d8 img_format: add RGB30 format
FFmpeg does not support this from what I can see. This makes supporting
it a bit awkward.

Later commits use this format.
2019-10-20 19:41:18 +02:00
wm4 62bd8da490 sws_utils: provide function to check whether a format pair is supported
Normally, input and output are orthogonal. But zimg may gain image
formats not supported by FFmpeg, which means the conversion will only
work if zimg is used at all. This on the other hand, depends on whether
the other format is also supported by zimg. (For example, a later commit
adds RGB30 output to zimg. libswscale does not support this format. But
if you have P010 as input, which the zimg wrapper does not support at
all, the conversion won't work.)

This makes such a function needed; so add it.
2019-10-20 19:41:18 +02:00
wm4 a495bfe373 manpage: describe stride parameter in screenshot-raw command
This is mentioned and called "obvious", but it's conceivable users don't
necessarily know about the concept. Just explain it.
2019-10-20 19:41:18 +02:00
wm4 ff67fbf328 build: lower required FFmpeg version
The FFmpeg version was last bumped a long time ago, except in commit
1638fa7b46, where it was used for some obscure pixel
format.

This is pretty annoying, so make it optional.
2019-10-20 19:41:18 +02:00
dudemanguy 027ca4fb85 wayland: add various render-related options
The newest wayland changes have some new logic that make sense to expose
to users as configurable options.
2019-10-20 15:34:57 +00:00
dudemanguy bedca07a02 wayland: add presentation time
Use ust/msc/refresh values from wayland's presentation time in mpv's
ra_swapchain_fns.get_vsync for the wayland contexts.
2019-10-20 15:34:57 +00:00
wm4 3568aed164 sws_utils: make libswscale fallback a warning
Surely a user passing --sws-allow-zimg wants to know if zimg is actually
used.
2019-10-20 16:16:28 +02:00
wm4 f23e663a21 zimg: support 3 component 16 bit pixel unpacking
Works for RGB (e.g. rgb48le) and XYZ.

It's unsure whether XYZ is really correctly converted.
2019-10-20 16:16:28 +02:00
wm4 577c00510b zimg: avoid theoretical FFmpeg planar RGB/YUV mixup
The RGB pack/unpack code in theory supports packed, non-subsampled YUV,
although in practice FFmpeg defines no such formats. (Only one with
alpha, but all alpha input is rejected by the current code.)

This would in theory have failed, because we would have selected a GBRP
format (instead of YUV), which makes no sense and would either have been
rejected by zimg (inconsistent parameters), or lead to broken output
(wrong permutation of planes).

Select the correct format and don't permute the planes in the YUV case.
2019-10-20 16:16:28 +02:00
wm4 c9d217979e zimg: add some more colorspace mappings
As suggested by the zimg author. This is mostly related to XYZ support.

It's unclear whether this works. Using the only XYZ test sample we know,
and the next commits to consume the pixfmt, it looks wrong.
2019-10-20 16:16:28 +02:00
wm4 5dc78b61f5 vf_fingerprint: remove single-plane optimization
According to the zimg author, YUV->GREY conversion does not even read
the chroma planes, as long as no matrix conversion is involved. Since we
try to avoid the latter anyway by forcing the source parameters on the
target image, passing only the Y plane will not help with anything.

An unscientific test seems to confirm this, so remove this.

This would probably help with libswscale (I didn't test this), but on
the other hand, libswscale will rarely be used in cases where we can
extract the Y plane. (Except nv12, which should probably be added to the
zimg wrapper's unpacking.)
2019-10-20 16:16:28 +02:00
wm4 64c8dd5964 vf_fingerprint: use generic zimg wrapper
Don't duplicate the API usage. The result should be approximately the
same.
2019-10-20 16:16:28 +02:00
Niklas Haas c2ed79247f mp_image: infer XYZ as BT.2020 instead of BT.709
And update the comment both explaining why this defaulting matters and
why we use BT.2020 instead.

tl;dr BT.709 clips even the one test file we *do* have, so if we don't
handle XYZ "natively" in vo_gpu we might as well at least handle it in a
way that runs less risk of clipping
2019-10-20 16:07:21 +02:00
Niklas Haas ac906fb288 csputils: fix outdated comment
This no longer hard-codes BT.709, it converts to whatever primaries are
tagged in the same metadata struct. The actual BT.709 defaulting comes
from `mp_image_params_guess_csp`.
2019-10-20 16:00:32 +02:00
wm4 d9eac493b5 vo_x11: enable use of zimg
This will perform conversion and scaling of video with zimg, if
--sws-allow-zimg is used.

The performance probably depends on how well the compiler optimizes the
RGB pack code in zimg.c, which is written in C.
2019-10-20 02:17:31 +02:00
wm4 51e141f7ba sws_utils: hack in zimg redirection support
Awful shit. I probably wouldn't accept this code from someone else, just
so you know.

The idea is that a sws_utils user can automatically use zimg without
large code changes. Basically, laziness. Since zimg support is still
very new, and I don't want that anything breaks just because zimg was
enabled at build time, an option needs to be set to enable it. (I have
especially especially obscure stuff in mind, which is all what
libswscale is used in mpv.)

This _still_ doesn't cause zimg to be used anywhere, because the
sws_utils user has to opt-in by setting allow_zimg. This is because some
users depend on certain libswscale features.
2019-10-20 02:17:31 +02:00
wm4 07aa29ed8e video: add zimg wrapper
This provides a very similar API to sws_utils.h, which can be used to
convert and scale from one mp_image to another.

This commit adds only the code, but does not use it anywhere.

The code is quite preliminary and barely tested. It supports only a few
pixel formats, and will return failure for many others. (Unlike
libswscale, which tries to support anything that FFmpeg knows.)

zimg itself accepts only planar formats. Supporting other formats
requires manual packing/unpacking. (Compared to libswscale, the zimg API
is generally lower level, but allows for more flexibility.) Only BGR0
output was actually tested. It appears to work.
2019-10-20 02:17:31 +02:00
wm4 fd539a542f mp_image: remove old acrobatics in frame copy code
This used to be needed for the "GPU memcpy" (shitty Intel methods to
deal with certain uncached memory types). This is now done in FFmpeg,
and the code in mp_image.c was just unnecessarily convoluted.
2019-10-20 01:44:22 +02:00
wm4 df8a0ecbf3 img_format: update test program
The plane pointer checking assert() triggered at least on gray8, because
that has a "pseudo palettes" in ffmpeg, which mpv refuses to allocate.

Remove a strange duplicated printf().

Log the component type where available.

(Why is this even here, I hate it when there are commented test programs
in source files.)
2019-10-20 01:44:22 +02:00
wm4 986daac45e img_format: document a minor guarantee for certain imgfmt metadata 2019-10-20 01:44:22 +02:00
wm4 e6fb8b3c97 manpage: docoument stream-open-filename property 2019-10-20 01:44:22 +02:00
wm4 09b916965b vaapi: remove hacks for pre-libva2 log callbacks
Instead, you ancient libva will do default logging, which means printing
to stderr. Not a loss, just update your libva.
2019-10-18 15:37:16 +02:00
wm4 ad97a74940 manpage: fix a typo 2019-10-18 15:36:31 +02:00
Stephan Hilb acba87e53f player: avoid duplicate track auto selection
Since a track may not be selected twice, it makes sense e.g. for
secondary subtitles to select the next best match and avoid the
duplicate selection.
This allows for example `--slang=en,ja --secondary-sid=auto` to select
'en' as primary and 'ja' as secondary without needing to know the actual
sid for 'ja'.
2019-10-18 12:11:11 +02:00
wm4 60ab82df32 video, demux: rip out unused spherical metadata code
This was preparation into something that never happened.

Spherical video is a shit idea anyway.
2019-10-17 22:49:26 +02:00
wm4 c75e0320f6 vo_gpu: hwdec_d3d11egl: add missing P010 format to supported list
This was obviously missing from the recent commit, which probably broke
10 bit decoding. The original commit didn't test this for lack of
working hardware; this commit isn't tested either.

Fixes: a1c7d61393
2019-10-17 22:45:05 +02:00
wm4 77fd4dd681 video: remove mp_image_params.hw_flags field
This was speculatively added 2 years ago in preparation for something
that apparently never happened. The D3D code was added as an "example",
but this too was never used/finished.

No reason to keep this.
2019-10-17 22:43:14 +02:00
Emmanuel Gil Peyrot a6000d3114 vo_wlshm: use memfd_create() instead of shm_open()
This syscall avoids the need to guess an unused filename in /dev/shm and
allows seals to be placed on it.  We immediately return if no fd got
returned, as there isn’t anything we can do otherwise.

Seals especially allow the compositor to drop the SIGBUS protections,
since the kernel promises the fd won’t ever shrink.

This removes support for any platform but Linux from this vo.
2019-10-17 19:38:04 +02:00
wm4 273cc3055c video: do not disable display-sync on A/V desync
On a audio/video desync by more than 0.5 seconds, display-sync mode was
disabled, and not enabled again (until playback restart, e.g. a seek).

The idea was that it this only happens when this playback mode is broken
and can't perform well anyway (A/V desync is a clear indication that
something is very wrong). Instead of behaving like a god damn POS, it
should revert to the more robust audio-sync mode.

Unfortunately, this could happen sporadically due to temporary system
performance problems, such as toggling fullscreen. Users didn't like
this, and asked for a function to disable it, or to recover in some
other way.

This mechanism is questionable anyway. If an ignorant user enables
display-sync, and encounters problems with it (without being able to
determine that display-sync is messing up), the player will still behave
like a POS on every playback, and even after every seek. It might
actually be helpful to fail more consistently. Also, I've found that
it's sill relatively reliable anyway even without this mechanism.

So just remove the fallback.

Fixes: #7048
2019-10-17 19:23:35 +02:00
Michael Forney 2fcd5271eb Reintroduce vo_wayland as vo_wlshm
vo_wayland was removed during the wayland rewrite done in 0.28. However,
it is still useful for systems that do not have OpenGL.

The new wayland_common code makes vo_wayland much simpler, and
eliminates many of the issues the previous vo_wayland had.
2019-10-17 12:26:22 +02:00
wm4 e49db40382 manpage: update --hwdec description
vdpaurb, vaapi-glx, and ANGLE's NV12-restriction are gone, making things
much simpler.
2019-10-17 11:10:40 +02:00
wm4 bd0af9a761 vf_d3d11vpp: remove RGB conversion hack
With the previous commit, this is dead code.

This also makes the f_autoconvert.c code for this dead code
(fortunately). Will probably remove this later.
2019-10-16 23:41:06 +02:00
wm4 b7eae31834 vo_gpu: hwdec_d3d11eglrgb: remove this
Finally. Since with the previous commit we can (probably) handle
P010 directly, this hack isn't needed anymore.
2019-10-16 23:41:06 +02:00
wm4 a1c7d61393 vo_gpu: hwdec_d3d11egl: adapt to newer ANGLE API
2 years ago, ANGLE removed the old NV12-specific extension, and added
a new one that supports a number of formats, including P010. Actually
they just renamed it and removed their initial annoying and obvious
design error (bravo, Google).

Since it broke 2 years ago, nobody should give a shit about this code,
and it should just be removed. But for some reason I still dived the
shit-tank (Windows development).

I guess Intel code monkeys can't write drivers (or maybe the issue is
because we're doing zero-copy, which probably maybe is not actually
allowed by D3D11 due to array textures, see --d3d11va-zero-copy), so
the P010 path is completely untested. It doesn't work, I'll delete all
this ANGLE hwdec code.

Fixes: #7054
2019-10-16 23:41:06 +02:00
Jan Ekström eaa3c1c922 vo_gpu/d3d11: fix memleak of the adapter description string 2019-10-15 22:12:48 +03:00
Jan Ekström 03e7a36a73 vo_gpu/d3d11: remove unnecessary nullptr check
mp_to_utf8 will abort in case of either invalid input or OOM.
2019-10-15 22:12:48 +03:00
Jan Ekström 89f4ce9d6f vo_gpu/d3d11: switch adapter selection to case-insensitive startswith
This lets users set values such as "intel" or "nvidia" as the
adapter vendor is generally noted in the beginning of the
description string.
2019-10-15 22:12:48 +03:00
Jan Ekström 684ffd13b4 vo_gpu/d3d11: fixup adapter selection by switching it all to bstr
I did ponder if I should have done this right away, and it seems
like not doing it at first was a mistake.
2019-10-15 22:12:48 +03:00
wm4 f0f1387145 etc/mpv.conf: update outdated use of cache options
The --cache option does not take a number anymore. (Oh boy, this is
going to break a lot of user configs?)

The cache site is now configured with those obscure-sounding --demuxer
options.

--cache-secs is not useful anymore. The default is very high, so the
obscure-sounding --demuxer options determine how much is cached.

Advertise the --cache-on-disk option a bit. I found it useful once, and
it will trick users into wearing out their SSD for no gain, or so.
2019-10-14 18:32:58 +02:00
wm4 18bd768ecc manpage: attempt to remove some more cache option confusion
OK, so --cache-secs is useless, because the default is set to 10 hours.
And that part about the "maximum" was obviously a lie (I wonder if it
simply changed at some point).
2019-10-14 18:28:14 +02:00
Nicolas F 06765e6ac9 ytdl_hook: check youtube-dl version if it breaks
Some failures by youtube-dl prompt the user to submit a bug report.
If such a failure occurs, we can compare youtube-dl's version to the
current calendar date to see how old it is. We don't make this check
on every youtube-dl failure, as failing to extract an URL is quite
common, and waiting for a second blocking python interpreter startup
for every such case would be a bit unpleasant.

Here the assumption is made that any youtube-dl version older than
3 months is probably severely out of date. Users will be warned about
this.

We also output the trimmed stderr of youtube-dl with msg.error, as this
appeared to have been the behaviour of utils.subprocess without stderr
capturing. Since this uses mp.command_native now, we'll have to do this
ourselves where appropriate.
2019-10-13 19:08:46 +02:00
Jan Ekström 648d785930 vo_gpu/d3d11: add support for configuring swap chain format
Query information on the system output most linked to the swap chain,
and either utilize a user-configured format, or either 8bit
RGBA or 10bit RGB with 2bit alpha depending on the system output's
bit depth.
2019-10-13 22:31:33 +11:00
James Ross-Gowan 4809a3f48d vo_gpu/d3d11: utilize actual backbuffer values for bit depth
And if backbuffer is not around, return an error value utilized
elsewhere already.
2019-10-13 22:31:33 +11:00
wm4 a85fa2d2de player: accept compatible later FFmpeg library runtime versions
mpv warned if the FFmpeg runtime library version was not exactly the
same as the build version. This seemed to cause frequent conflicts. At
this point, most mpv code probably adheres to the FFmpeg ABI rules, and
FFmpeg stopped breaking ABI "accidentally". Another source of problems
were mixed FFmpeg/Libav installations, something which nobody does
anymore. It's not "our" job to check and enforce ABI compatibility
either. So I guess this behavior can be removed.

OK, still check for incompatible libraries (according to FFmpeg
versioning rules), i.e. different major versions, or if the build
version is newer than the runtime version. For now.

The comment about ABI problems is still true. In particular, the
bytes_read field mentioned in the removed comment is still accessed, and
is still an ABI violation. Have fun.
2019-10-11 21:28:04 +02:00
wm4 9683617559 av_log: use proper FFmpeg version extraction macros
Though not like they will or can never change them.
2019-10-11 21:21:51 +02:00
wm4 cde94e83a9 audio/out: rip out old unused app/softvolume reporting
This was all dead code. Commit 995c47da9a (over 3 years ago) removed all
uses of the controls.

It would be nice if AOs could apply a linear gain volume, that only
affects the AO's audio stream for low-latency volume adjust and muting.
AOCONTROL_HAS_SOFT_VOLUME was supposed to signal this, but to use it,
we'd have to thoroughly check whether it really uses the expected
semantics, so there's really nothing useful left in this old code.
2019-10-11 21:05:11 +02:00
wm4 d908fbd584 audio/out/pull, ao_sdl: implement new underrun reporting
See previous commits. ao_sdl is worthless, but it might be a good test
for pull-based AOs.

This stops using the old underrun reporting if the new one is enabled.
Also, since the AO's behavior can in theory not be according to
expectations, this needs to be enabled for every single pull AO
separately.

For some reason, in certain cases I get multiple underrun warnings while
cache-pausing is active. It fills the cache, restarts the AO,
immediately underruns again, and then fills the cache again. I'm not
sure why this happens; maybe ao_sdl tries to catch up when it shouldn't.
Who knows.
2019-10-11 20:02:23 +02:00
wm4 89c717559b audio/out/pull: fix underflow reporting
I think this was _always_ wrong. Due to the line above the first changed
line, buffered_bytes==bytes always. I can only hope I broke this in a
less under-tested edit when I originally wrote this.

Fixes: c5a82f729b
2019-10-11 20:02:23 +02:00
wm4 1723b88cdd ao_alsa: use AO underrun reporting
This enables the change introduced in the previous commit for ao_alsa.
2019-10-11 20:02:23 +02:00
wm4 f26dfb6e4d player: partially rework --cache-pause
The --cache-pause feature (enabled by default) will pause playback for a
while if network runs out of data. If this is not done, then playback
will go on frame-wise (as packets are slowly read from the network and
then instantly decoded and displayed). This feature is actually useless,
as you won't get nice playback no matter what if network is too slow,
but I guess I still prefer this behavior for some reason.

This commit changes this behavior from using the demuxer cache state
only, to trying to use underrun information from the AO/VO. This means
if you have a very large audio buffer, then cache-pausing will trigger
once that buffer is depleted, which will be some time _after_ the
demuxer cache has run out.

This requires explicit support from the AO. Otherwise, the behavior
should be mostly the same as before this commit.

This does not care about the AO buffer. In theory, the AO may underrun,
then the player will write some data to the AO buffer, then the AO will
recover and play this bit of data, then the player will probably trigger
the cache-pause behavior. The probability of this happening should be
pretty low, so I will hold off fixing this until the next refactor of
the AO chain (if ever).

The VO underflow detection was devised and tested in 5 minutes, and may
not be correct. At least I'm fairly sure that the combination of all the
factors should make incorrect behavior relatively unlikely, but problems
are possible.

Also, the demux_reader_state.underrun field may be inaccurate. It's only
the present state at the time demux_get_reader_state() was called, and
may exclude past underruns. In theory, this could cause "close" cases to
be missed. Then you might get an audio underrun without cache-pausing
acting on it. If the stars align, this could happen multiple times in
the row, effectively making this feature not work.

The most user-visible consequence of this change is that the user
will now see an AO underrun warning every time the cache runs out.

Maybe this cache-pause feature should just be removed...
2019-10-11 20:01:51 +02:00
wm4 c84ec02128 ao: add API for underrun reporting
AOs can now call ao_underrun_event() (in any context) if an underrun has
happened. It will print a message.

This will be used in the following commits. But for now, audio.c only
clears the underrun bit, so that subsequent underruns still print the
warning message.

Since the underrun flag will be used in fragile ways by the playback
state machine, there is the "reports_underruns" field that signals
strong support for underrun reporting. (Otherwise, underrun events will
not be used by it.)
2019-10-11 19:25:45 +02:00
wm4 52f3dee16a ao_alsa: handle underruns in get_space() too
This is essentially optional. But it will give the higher level code a
better guarantee that underruns were tested.
2019-10-11 19:19:59 +02:00
wm4 1d25d7fe92 player: format low cache duration with more decimals 2019-10-11 19:18:43 +02:00
wm4 c6c93499cb ao_alsa: mess with underrun handling again
This commit tries to prepare for better underrun reporting. The goal is
to report underruns relatively immediately. Until now, this happened
only when play() was called. Change this, and abuse that get_delay() is
called "relatively often" - this reports the underrun immediately in
practice.

Background:

In commit 81e51a15f7 (and also e38b0b245e), we were quite confused
about ALSA underrun handling. The commit message showed uncertainty how
case 3 happened, but it's blindingly obvious and simple.

Actually reading the code shows that ALSA does not have a concept of a
"final chunk" (or we don't use it). It's obvious we never pass the
AOPLAY_FINAL_CHUNK flag along to the ALSA API in any way. The only thing
we do is simply writing a partial fragment. Of course this will cause an
underrun. Doing a partial write saves us the trouble to pad the last
frame with silence, or so.

The main reason why the underrun message was avoided was that play() was
never called with a non-0 sample count again (except if reset() was
called before that). That was OK, at least the goal of avoiding the
unwanted message was reached. (And the original "bogus" message at end
of playback was perfectly correct, as far as ALSA goes.)

If network stalls, play() will called again only once new data is
available. Obviously, this could take a long time, thus it's too late.
2019-10-11 16:52:45 +02:00
dudemanguy ea4685b233 wayland: use callback flag + poll for buffer swap
The old way of using wayland in mpv relied on an external renderloop for
semi-accurate timings. This had multiple issues though. Display sync
would break whenever the window was hidden (since the frame callback
stopped being executed) which was really annoying. Also the entire
external renderloop logic was kind of fragile and didn't play well with
mpv's internal structure (i.e. using presentation time in that old
paradigm breaks stats.lua).

Basically the problem is that swap buffers blocks on wayland which is
crap whenever you hide the mpv window since it looks up the entire
player. So you have to make swap buffers not block, but this has a
different problem. Timings will be terrible if you use the unblocked
swap buffers call.

Based on some discussion in #wayland, the trick here is relatively
simple and works well enough for our purposes. Instead we basically
build a way to block with a timeout in the wayland buffer swap
functions.

A bool is set in the frame callback function that indicates whether or
not mpv is waiting for a frame to be displayed. In the actual buffer
swap function, we enter into a while loop waiting for this flag to be
set. At the same time, the wl_display is polled to block the thread and
wakeup if it receives any events from the compositor. This loop only
breaks if enough time has passed or if the frame callback bool is
received.

In the near future, it is better to set whether or not frame a frame has
been displayed in the presentation feedback. However as a first pass,
doing it in the frame callback is more than good enough.

The "downside" is that we render frames that aren't actually shown on
screen when the player is hidden (it seems like wayland people don't
like that). But who cares. Accurate timings are way more important. It's
probably not too hard to add that behavior back in the player though.
2019-10-10 17:41:19 +00:00
dudemanguy e0895e097b Revert "vo: add support for externally driven renderloop and make wayland use it"
The externally driven renderloop was originally added for the wayland
context (to make display sync somewhat work), but it has a lot of issues
with mpv's internal structure. A different approach should be used.

This reverts commit a743fef837.
2019-10-10 17:41:19 +00:00
James Ross-Gowan 6002e2705f vo_gpu: d3d11: use linear filtering for wrapped textures
This affects hwdec_dxva2dxgi, which uses ra_d3d11_wrap_tex to wrap RGB
video frames that are shared with a D3D9 device. Without it, mpv uses
nearest instead of bilinear scaling with --scale=bilinear (the default)
and --hwdec=dxva2. It's kind of hard to believe this bug has gone
unnoticed for almost two years, but that seems to have been the case.

Fixes: #7042
2019-10-10 19:52:19 +11:00
wm4 5cbbd25090 demux_timeline, demux_edl: correctly enable cache in pseudo-DASH mode
In pseudo-DASH mode, we may have no real streams opened until the
demuxer layer is fully loaded and playback actually starts. The only
hint that the stream is from network is, at that point, the init
segment, which is only opened as stream, and then separately as demuxer
(which is dumb but happened to fit the internal architecture better).

So just propagate the flags from the init segment stream. Seems like an
annoyance, but doesn't hurt that much I guess. (Until someone gets the
idea to pass the init segment data inline or so, but nothing does that.)

The sample link in the linked issue will probably soon switch to another
format, because that service always does this after recent uploads or
so.

Fixes: #7038
2019-10-08 23:55:05 +02:00
wm4 68bbc55eda skip-logo.lua: fix skipping in the first two frames
mpv typically decodes and filters at least 2 frames before starting
playback. This happens during seeks, as well as when playback starts
from the beginning of the file.

skip-logo.lua receives notifications for all filtered frames, even
during seeking. It should interrupt during seeking, so as a crude
heuristic, it ignored all frames while the player was seeking. This does
not mean all these frames are skipped due to seeking (thus it's a "crude
hueristic"). In particular, it means that the first 2 frames of a video
cannot be skipped, since they're filtered within the playback restart
phase (equivalent to "seeking").

Fix this by making the heuristic slightly less crude. Since we observe
the property as "none", the property is not actually read until we do it
explicitly. By not reading it during seeking, we can let the frames
internally queue up (vf_fingerprint discards them in a ringbuffer-like
fashion if they're too many). Then, if seeking ends, we get the current
playback timestamp, and check queued up frames that are at or after that
timestamp. (In some ways, this duplicates what the player's seeking
logic does.)

A disadvantage is that this is racy. While playback-time is guaranteed
to be set when seeking changes from false to true, playback could
already have progressed to the next frame (or more) before the script
gets time to react. In theory, we could add a seek restart hook or so,
but I don't want to. A property that returns the last playback restart
time would also do it, but feels to special. Not an important problem
in practice anyway.
2019-10-08 21:26:43 +02:00
wm4 0a30a4a432 DOCS: explicitly mention that property observing has an initial event
This is definitely intended from the start, and it's generally useful,
but for some reason it wasn't actually documented.
2019-10-08 21:11:55 +02:00
wm4 9e76c203f7 DOCS: some corrections around cache options 2019-10-08 18:38:23 +02:00
wm4 1f77102ee8 demux_edl: better selection of part which defines the track layout
Someone crazy is trying to mix images with videos in EDL files. Putting
an image as first thing into the EDL disabled audio, because the first
EDL entry was used to define the layout.

Change this. Make it user-configurable, and use a "better" heuristic to
select the default otherwise.

In theory, EDL could be easily extended to specify track layout and
mapping of parts to virtual EDL tracks manually and in great detail. But
I don't think it's worth it - who would bother using it?

Fixes: #6764
2019-10-06 23:35:02 +02:00
wm4 4ad68d9452 video: always decode 2 frames on playback restart
Unless --video-latency-hacks, always decode 2 frames on playback
restart. This in turn will always compute the correct frame duration
(even for the first frame), which in turn happens to fix that playback
with an image at the beginning breaks display.

If a still image precedes video, and the size/format of the frame is
different from that of the video following it, the incorrect frame
duration caused vo_reconfig2() to be called early, causing the window to
resize, and the renderer to clear the image to black. Specifically, it
hit the default value of 1 second duration (for still images), so the
image was displayed for 1 second, and changed to black until the next
proper video frame was displayed.

Normally this does not happen. Even if a video file displays still
images, it normally repeats the still image at the video's FPS (which is
sane). But you can construct such files, or use EDL to construct
something similarly behaving.

This change may increase seek latency a bit in audio video-sync mode
(the default). It needs to wait until 2 frames are decoded, before it
bothers to display the first frame. This is done even when seeking. In
theory it might be good to introduce a "seek preview" mode, which shows
the target image without all the preparations needed for starting
playback. (For example, it could not decode audio.) But since I'm using
video-sync=display-resample, which already needed to always decode 2
frames, I don't think this is a terribly high priority, nor do I
consider the slightly slower seeking a regression.

Fixes: #6765
2019-10-06 23:31:58 +02:00
ckath 9bc38bd18d player: don't load external files when reading from stdin 2019-10-06 21:35:15 +02:00
wm4 299916bde2 audio: raise log level of playback reset on audio timestamp
Make it a warning. This is such an intrusive and shitty hack (but of
course my fault) that it should not be hidden.
2019-10-06 20:46:22 +02:00
wm4 e5a97ef27f audio: do not try gapless if video is still ongoing
In this case, gapless will most likely not work. It will result in (very
slight) desync, or (more commonly with small buffer sizes), in an
underflow.

I think it would be legitimate to disable gapless at end of playback
completely if video is enabled at all. But this would need an exception
for cover art mode, so I guess the current solution is OK as well.
2019-10-06 20:46:22 +02:00
wm4 e38b0b245e ao_alsa: don't silence legitimate underrun if final chunk underruns
It turns out that case 2) mentioned in the previous commit happened
quite often when playback ended normally.

There is probably a legitimate underrun with normal buffer sizes (100
ms, 4 fragments, gapless audio in "weak" mode). This is a result of the
player waiting for video to end, and/or the time needed to kill the
video window. The former case means that it depends on your test case
whether it happens (a file where video ends slightly before audio is
less likely to trigger it).

This in turn is due to how gapless playback works. Achieving not having
a "gap" requires queuing the audio of the next file without playing a
partial chunk (as AOPLAY_FINAL_CHUNK would do). The partial chunk is
then played as part of the first chunk played from the next file. But if
it detects "later" that there is no next file, it still needs to get rid
of the last fragment with AOPLAY_FINAL_CHUNK. At this point it's too
late, and an underrun may have actually happened. The way the player
uninits and reinits the entire playback engine for the next file in a
"serial" manner means it cannot know in advance whether this works.

This is the reason why the idiot who added the underrun exception for
the last chunk in play() was wrong (I wrote that btw., before you accuse
me of being rude). Yes, it's a real underrun, and you could probably
hear it.
2019-10-06 20:46:22 +02:00
wm4 81e51a15f7 ao_alsa: remove sometimes bogus XRUN message
This XRUN (aka underrun) message was printed in the following
situations:

1) legitimate underrun during playback
2) legitimate underrun when playing final chunk
3) bogus underrun when playing final chunk

The old underrun case (in play()) happens in cases 1) and 2) as well,
but 3) did not happen. It appears 3) is indeed something that happens,
although it's not known for sure. It's still pretty annoying, so remove
the new XRUN message.

When testing, care should be taken to play with buffer sizes, video
versus no video, and gapless enabled/disabled. Also, suspending the
player with Ctrl+Z in the terminal (SIGSTOP) and then resuming is a good
way to trigger a "normal" underrun.
2019-10-06 20:46:22 +02:00
der richter 6d0f0546ee cocoa-cb: remove get_property_* usages and split up mpv helper
all the get_property_* usages were removed because in some circumstances
they can lead to deadlocks. they were replaced by accessing the vo and
mp_vo_opts structs directly, like on other vos.

additionally the mpv helper was split into a mpv and libmpv helper, to
differentiate between private and public APIs and for future changes
like a macOS vulkan context for vo=gpu.
2019-10-06 13:29:48 +02:00
Paul B Mahol 2b19a7c964 audio/filter: remove no longer used header 2019-10-05 12:36:38 +02:00
wm4 49a075d01e DOCS/compatibility.rst: add this file
Another thing nobody will read. I'm attempting to document the rules by
which incompatible changes can be made. These rules have always been
present in this project, but I don't think they were written down. Or
maybe they were, but I forgot where.

I think due to the time of the day it became increasingly incoherent
(not necessarily near the end of the text). Hopefully no logical or
freudian lapses in there.
2019-10-05 02:11:55 +02:00
wm4 788203031d DOCS/interface-changes.rst: simplify playback abort change description
Although it was not true at the time this was written, both the
"program" and "cache-size" are gone now.

Since the changelog is for the entire next release, it makes no sense to
mention these removed properties.

It also happens to make the description of this much simpler, because
it's a non-issue now. It's probably not even worth mentioning anymore.
2019-10-05 02:08:19 +02:00
Niklas Haas e8f32a92f8 player: update for --video-aspect deprecation
We had some dangling references to this option.
2019-10-04 22:41:31 +02:00
Niklas Haas cb95ce75b5 options: rename --video-aspect to --video-aspect-override
The justification for this is the fact that the `video-aspect` property
doesn't work well with `cycle_values` commands that include the value
"-1".

The "video-aspect" property has effectively no change in behavior, but
we may want to make it read-only in the future. I think it's probably
fine to leave as-is, though.

Fixes #6068.
2019-10-04 21:34:22 +02:00
wm4 6064720011 player: "subprocess" command should stop immediately in idle mode
The description of the "playback_only" field in the "subprocess" command
says "you can't start it outside of playback". This did not work
correctly: if the player was started in idle mode in the first place,
the subprocess was allowed to run even with playback_only=yes.

This is a bug, and this change fixes it. Add a test for this to
command-test.lua.

For #7025.
2019-10-04 16:30:48 +02:00
wm4 e49cec5832 manpage: clarify some details about async. commands and "subprocess"
There's potential confusion about how long a process started with the
"subprocess" command is allowed to live. Add some more explanations
regarding "subprocess" specifics (such as the playback_only field), and
things that apply to asynchronous commands in general.

Partially for #7025.
2019-10-04 16:18:10 +02:00
dudemanguy fd7aff7a9d wayland opengl: actually call uninit if init fails
This is the proper fix to the memory leak @wm4 pointed out. It turns out
that when you autoprobe opengl and vo_wayland_init returns false,
vo_wayland_uninit is never actually executed. So you have a leftover
pointer. The vulkan context does this correctly which was why my old,
dumb "fix" broke it.
2019-10-03 14:56:43 +00:00
dudemanguy 9d6ae83fdc Revert "wayland: free wayland_state on a false return"
Dumb idea. The correct thing to do is to fix the preinit and context
creation so that the uninit is correctly executed when probing fails
(and then everything gets freed).

This reverts commit defc8f359c.
2019-10-03 14:56:43 +00:00
Dudemanguy911 defc8f359c wayland: free wayland_state on a false return
wm4 mentioned that the wayland autoprobe leaked. A simple oversight in
the wayland_common code forgot to free the vo_wayland_state if
vo_wayland_init returned false.
2019-10-02 18:38:45 -05:00
wm4 c669a434f3 vf_fingerprint: fix an obvious memory leak
Leaks the entire zimg state on filter deinit. Not sure what I was
thinking; with some luck, I just didn't give a shit about this case, but
most likely I was thinking the same thing as always: nothing.
2019-10-03 01:07:25 +02:00
wm4 5f75365f44 vf_vapoursynth: fix crashing memory management mistake
As pointed out by @olifre in #7016, this line of code was wrong. p->opts
at this point is a struct allocated and managed by m_config. opts->file
is a string, and m_config explicitly frees it on destruction. The line
of code in question replaced the opts->file value, and made both the old
and new value children of the talloc allocation, so they were _also_
freed on destruction.

This crashed due to a double-free. First, talloc auto-freeing freed the
string, then m_config explicitly called talloc_free() on the stale
pointer again.

As @v-fox pointed out, commit 36dd2348a1 seems to have triggered the
crash. I suspect this code merely worked out of coincidence, since it
allowed m_config to free the value first. This removed it from the
auto-free list, and thus did not result in a double-free. The change
in order of calling alloc destructors changed the order of these calls.

There is no strong reason why new behavior (as introduced by commit
36dd2348a1) would be wrong (it feels like cleaner behavior). On the
other hand, what the vf_vapoursynth code did is clearly unclean and
going by the m_config API, you're not at all supposed to do this.
m_config manages all memroy referenced by option structs, the end.

@olifre's suggested fix also would have been correct (not just hiding
the issue), I prefer my fix, as it doesn't mess with the option struct
in tricky ways.

This wouldn't have happened if mpv were written in Haskell.
2019-10-03 00:48:12 +02:00
wm4 d2a10fb02e vf_vapoursynth: do not call vsscript_finalize() if init failed
If vsscript_finalize() is not matched by a successful vsscript_init(),
an assert in the vsscript library triggers. Makes sense, I guess.
2019-10-03 00:48:12 +02:00
wm4 f36ae05aca vf_vapoursynth: remove some Lua backend remains
Pretty funny.
2019-10-03 00:48:12 +02:00
Dudemanguy911 d823b3b39a wayland: always create wl_output before rendering
I previously skipped creating the wl_output if the --fullscreen flag
with no --fsscreen_id was inputted, so the fullscreen video lands on the
correct output (where mpv was launched). This has breakage if someone
combines the --autofit flag (or other similar options with it). Instead,
just actually read xdg_shell spec and realize that you can pass NULL to
xdg_toplevel_set_fullscreen and let the compositor choose the output if
the user doesn't specify it. If this has issues, get a better
compositor.
2019-10-02 22:43:13 +00:00
wm4 1c63869d0a demux: restore some of the DVD/BD/CDDA interaction layers
This partially reverts commit a9d83eac40
("Remove optical disc fancification layers").

Mostly due to the timestamp crap, this was never really going to work.
The playback layer is sensitive to timestamps, and derives the playback
time directly from the low level packet timestamps. DVD/BD works
differently, and libdvdnav/libbluray do not make it easy at all to
compensate for this. Which is why it never worked well, but not doing it
at all is even more awful.

demux_disc.c tried this and rewrote packet timestamps from low level TS
to playback time. So restore demux_disc.c, which should bring behavior
back to the old often non-working but slightly better state.

I did not revert anything that affects components above the demuxer
layer. For example, the properties for switching DVD angles or listing
disc titles are still gone. (Disc titles could be reimplemented as
editions. But not by me.)

This commit modifies the reverted code a bit; this can't be avoided,
because the internal API changed quite a bit. The old seek resync in
demux_lavf.c (which was a hack) is replaced with a hack. SEEK_FORCE and
demux_params.external_stream are new additions.

Some of this could/should be further cleaned up. If you don't want
"proper" DVD/BD support to disappear, you should probably volunteer.

Now why am I wasting my time for this? Just because some idiot users are
too lazy to rip their ever-wearing out shitty physical discs? Then why
should I not be lazy and drop support completely? They won't even be
thankful for me maintaining this horrible garbage for no compensation.
2019-10-03 00:22:18 +02:00
wm4 8c58375dbd f_auto_filters: use f_autoconvert for hw download
Instead of using custom code.

Now if only f_lavfi knew what formats FFmpeg's vf_yadif accepts, this
could look much nicer, and wouldn't require the additional converter
filter setup.
2019-10-02 23:13:26 +02:00
wm4 9b55009e8f f_autoconvert: provide a function to determine if conversion works
This adds the function as seen in the f_autoconvert.h part of the patch.
It's pretty simple, but goes along with an intrusive code move. I guess
the resulting code is slightly nicer anyway.
2019-10-02 23:12:50 +02:00
wm4 55424c29d3 f_autoconvert: add hw->sw download path
For some reason it could do sw->sw and sw->hw (and, in some ways, even
do hw->hw in special cases), but not hw->sw. Add this.
2019-10-02 22:30:25 +02:00
wm4 3e02f39087 f_auto_filters: use software conversion if hw deint is not possible
Before this commit, enabling hardware deinterlacing via the
"deinterlace" option/property just failed if no hardware deinterlacing
was available. An error message was logged, and playback continued
without deinterlacing.

Change this, and try to copy the hardware surface to memory, and then
use yadif. This will have approximately the same effect as
--hwdec=auto-copy. Technically it's implemented differently, because
changing the hwdec mode is much more convoluted than just inserting a
filter for performing the "download". But the low level code for
actually performing the download is the same again.

Although performance won't be as good as with a hardware deinterlacer
(probably), it's more convenient than forcing the user to switch hwdec
modes separately. The "deinterlace" property is supposed to be a
convenience thing after all.

As far as the code architecture goes, it would make sense to auto-insert
such a download filter for all software-only filters that need it.
However, libavfilter does not tell us what formats a filter supports
(isn't that fucking crazy?), so all attempts to work towards this are
kind of hopeless. In this case, we merely have hardcoded knowledge that
vf_yadif definitely does not support hardware formats. But yes, this
sucks ass.
2019-10-02 21:27:07 +02:00
wm4 49f9146fe4 f_hwtransfer: add a mp_hwdownload filter
This just wraps the mp_image_hw_download() function as a filter and adds
some minor caching/error logging. (Shame that it needs to much
boilerplate, I guess.)

Will be used by the following commit. Wrapping it as filter seemed more
convenient than other choices.
2019-10-02 21:14:58 +02:00
wm4 61961d03f6 filters: add another dumb helper
Can be used with mp_chain_filters() to combine multiple filters into a
single one. This is a bit silly, but whatever. I'm making it an explicit
separate filter, because it lets the user access mp_filter.ppins against
all conventions.
2019-10-02 21:09:30 +02:00
wm4 95e13e3d3e mp_image_pool: expose a function for reporting hw download format
Basically predicts what mp_image_hw_download() will do. It's pretty
simple if it gets the full mp_image. (Taking just a imgfmt would make
this pretty hard/impossible or inaccurate.)

Used in one of the following commits.
2019-10-02 21:07:14 +02:00
wm4 25e70f4743 video: remove vf_vavpp from automatic deinterlace property
This reverts commit 6385a5fd1b, and in
addition removes the code that automatically inserts the vavpp filter.

The reason is the same as the commit that is being reverted: this
filter seems to trigger driver bugs. It can cause GPU freezes or
just doesn't work.

This variant of disabling the filter is better. There was no way to
add the "force" parameter to the automatically inserted filter, so
the old approach just made manual filter insertion (with the --vf
option or "vf" command) more cumbersome.
2019-10-02 19:21:42 +02:00
wm4 bc03bc8214 DOCS/tech-overview.txt: caching has changed 2019-10-02 19:20:51 +02:00
wm4 f203a881e5 README.md: minor cleanups
I don't think MPlayer/mplayer2 and Libav are well-known enough anymore
to warrant such a prominent place in the top-level README file of this
project. It's just useless noise to most users. So I've moved these
things to the FAQ.

Update some other minor things.
2019-10-02 13:53:35 +02:00
Vítor Galvão 643db416a1 README.md: remove dead homebrew-mpv link 2019-10-02 13:26:10 +02:00
Marek Sebera 35e8710b86 autoload.lua: Configurable autoload types
Autoload script now suppports loading of not only video, but also
image and audio files, in a manner, where one can configure which
of the groups (audio, videos, images) is currently enabled.

Use file script-opts/autoload.conf with key=value configuration keys
disabled,images,videos,audio to configure autoload script.

See documentation on top of the script
2019-10-02 12:48:56 +02:00
Oliver Freyermuth 64ae475e40 DOCS: Document DVB changes in interface-changes. 2019-10-02 01:25:45 +02:00
Oliver Freyermuth 8c52cd4e4a stream_dvb: Remove now replaced stream-control code for good. 2019-10-02 01:25:45 +02:00
Oliver Freyermuth 5b45b2fcac DOCS: Add documentation for dvbin-prog and dvbin-channel-switch-offset. 2019-10-02 01:25:45 +02:00
Oliver Freyermuth 12d74e4d95 stream_dvb: Allow actual zapping of channels again.
This is realized by dvbin-channel-switch-offset,
which is a numeric offset on the channel initially tuned to.
Since the channel list is kept in the stream alone
depending on detected hardware and chosen card,
and no available backchannel to the player, there's no direct
property which could be switched.

Using input.conf like:
H cycle dvbin-channel-switch-offset up
K cycle dvbin-channel-switch-offset down
Q set dvbin-prog "ZDF HD"
allow fast and reliable channel switching again.
2019-10-02 01:25:45 +02:00
Oliver Freyermuth c408a48119 player: Add mp_property_dvb_channel helper.
Reinitializes the player as is needed when
tuning to a new DVB channel.
Currently triggered when dvbin-prog is written to,
i.e. when the user explicity switches to a channel by name.
2019-10-02 01:25:45 +02:00
Oliver Freyermuth 9cd4638d2b stream_dvb: Add dvb_update_config to poll config parameters.
If any parameters have been updated, reinitiate streaming_start.
Throttle checks since we poll from streaming_read.
This also requires the player to re-initialize, since all video
and audio streams and even the transport format may change.
This is added in the next commit.
2019-10-02 01:25:45 +02:00
Oliver Freyermuth 1768ea0d15 stream_dvb: Move stream->is_on initialization to state preparation.
Notably, this allows to call dvb_streaming_start more than once,
simplifying e.g. channel switching.
Also, get rid of unused timeout variable.
2019-10-02 01:25:45 +02:00
Oliver Freyermuth c15ec393dd stream_dvb: Factor out logic to determine program and card.
This is now treated in dvb_parse_path consistently
instead of logic scattered over various functions.
This is a requirement to sensibly re-evaluate config
after options have been changed, since we have two ways
to configure the stream (decorated URI and config parameters).
2019-10-02 01:25:45 +02:00
Oliver Freyermuth 76918be267 stream_dvb: Use separated out options struct.
This also allows the use of m_config_cache_alloc
which allows to watch config updates.
2019-10-02 01:25:45 +02:00
wm4 86c229fede demux_lavf: remove recently added author name from license header
This was added in 585f9ff42f by @bbarenblat (github handle). We
don't do this. This file alone probably has multiple dozen of authors (I
didn't count, but it has a history of 15 years). If everyone added their
names with each small change, this project would have giant lists of
contributing authors on every source file.

Neither copyright law nor any of the used licenses require listing
authors in the license header. Authorship is recorded in the git log.

So don't start with this, and remove this recent case to avoid setting a
precedent.

Some files still have an author in the header. These cases are
grandfathered, and usually are the actual authors of the original code.
2019-10-01 22:51:46 +02:00
wm4 f290081645 DOCS/contribute.md: split into sections, random changes
Still trying to get people to read it. Even though I wanted to make it
less of a wall of text and more readable, it got bigger. Oops.

While I'm at it, violate my own rules and mix these mostly cosmetic
changes with some actual rule changes and clarifications.
2019-10-01 22:39:56 +02:00
wm4 3bef1190e8 github: try to get contributors to read contribute.md
How hard can it be? I know contribute.md is a shitty wall of text, but
that doesn't make it less important, and each violation will make it
take longer by adding another review round anyway.

And we really don't need lazy pull requests. If you can't be assed to
follow a few simple rules, your code is probably shit or you wanted to
be quick and lazy. Why should we accept it? We're the ones who have to
maintain it and fix bugs in it, and if the contributor is lazy, the
chance of you maintaining it is probably slim as well. On the other
hand, WE the maintainers are not obligated to anything.

Don't say that though, the first contact doesn't need to be negative. I
don't know if the "lazy pull requests" is still too strong, but I can't
tell.
2019-10-01 21:44:57 +02:00
wm4 07d9ca5ee3 demux_mkv: better behavior/warnings on partial files/unseekable streams
demux_mkv may seek to the end of the file to read certain headers (which
should probably be called "footers", but in theory they are just headers
that have been placed at the end of the file unfortunately).

This commit changes behavior not to seek if the stream is not marked as
seekable. Before this, it only checked whether the stream size was
unknown (end negative). In practice it doesn't make much of a
difference, since seekable usually equals known stream size.

Also improve the wording, and distinguish between actual incomplete
files, and unseekable ones.
2019-10-01 21:27:25 +02:00
Jan Ekström 1f76e69145 vo_gpu/d3d11: add adapter name validation and listing with "help"
Not the prettiest way to get it done, but seems to work.
2019-09-29 19:39:26 +03:00
Jan Ekström bca6e14702 vo_gpu/d3d11: refactor pthread_once d3d11 loading to function
Lets us reuse this in the future.
2019-09-29 19:39:26 +03:00
Jan Ekström b7438d3aff vo_gpu/d3d11: utilize the passed adapter name
Normalize nullptr and an empty string both to nullptr to simplify
handling. API users cannot set a value back to nullptr, so both
an empty string as well as nullptr should behave the same.
2019-09-29 19:39:26 +03:00
Jan Ekström e6447e2e89 vo_gpu/d3d11: add an option for the adapter name
Set it from the adapter name in the d3d11 options.
2019-09-29 19:39:26 +03:00
Jan Ekström 8163906299 video/d3d11: add adapter selection by name into d3d11 options
This lets the user define an adapter name that can then be passed
further into the internals.
2019-09-29 19:39:26 +03:00
Jan Ekström e205e179e0 vo_gpu/d3d11_helpers: also load up CreateDXGIFactory1
Just a factory, without a device, is required for listing of devices.
2019-09-29 19:39:26 +03:00
Leonardo Taccari c833c095d7 stream_lavf: add support for gopher 2019-09-29 14:27:00 +02:00
Anton Kindestam 0d4f165d81 vo_drm: fix flickering when setting pan/scan
Turns out clearing all frambuffers in reconfig isn't such a great idea
when you also end up here when setting pan/scan.

I guess this is just a leftover from a previous iteration of vo_drm
where doing this made sense.
2019-09-29 12:16:26 +02:00
wm4 5a9046222b demux: make --record-file/cache dump command work with disabled streams
This passed all streams to mp_recorder_create(), even disabled ones. The
disabled streams never get packets, so recorder.c eventually errors out
with unrelated-looking errors. The reason is that recorder.c waits for
packets to appear on other streams, which in turn is because libavformat
refuses to mux empty streams anyway.

recorder.c could call demux_stream_is_selected(), which would have made
the patch much smaller. But this feels like a bad idea, since recorder.c
should use sh_stream only for metadata (and not in an "active" way), nor
should it care what demux.c is currently doing with it. So make the API
user (demux.c) pass only the streams it really wants.

Fixes: #6999
2019-09-29 02:36:52 +02:00
wm4 eb3aed7cf8 loadfile: make prefetching actually work
Looks like this didn't actually work. Prefetching will do nothing if
there isn't a thread to "drive" it, and the demuxer thread needs to be
explicitly enabled. (I guess I did the worst possible job in verifying
whether this actually worked when I implemented it. On the other hand,
the user didn't confirm back whether it worked, so who cares.)

Like in the previous commit, bad factoring makes everything worse. It
duplicates logic and implementation of enable_demux_thread(), since the
opener thread cannot access the mpctx->opts field freely. But it's deep
night, so fuck it.

Fixes: c1f1a0845e
Fixes: #6753
2019-09-29 02:36:02 +02:00
wm4 3b13a47993 loadfile: don't always accidentally always prefetching
demux_start_prefetch() was called unconditionally in two cases. This is
completely wrong. I'm not sure what part of my brain died off that
something this obviously wrong went in.

The prefetch case is a bit more complicated. It's a different thread, so
you can't access just access mpctx->opts there. So add an explicit field
for this, which is the simplest way to get this done. (Even if it's bad
factoring.)

Fixes: c1f1a0845e
Fixes: 556e204a11
2019-09-29 02:24:29 +02:00
wm4 a604dc12be recorder: don't use a magic index for mp_recorder_get_sink()
Although this was sort of elegant, it just seems to complicate things
slightly. Originally, the API meant that you cache mp_recorder_sink
yourself (which would avoid the mess of passing an index around), but
that too seems slightly roundabout.

In a later change, I want to change the set of streams passed to
mp_recorder_create(), and then I'd have to keep track of the index for
each stream, which would suck. With this commit, I can just pass the
unambiguous sh_stream to it, and it will be guaranteed to match the
correct stream.

The disadvantages are barely worth discussing. It's a new linear search
per packet, but usually only 2 to 4 streams are active at a time. Also,
in theory a user could want to write 2 streams using the same sh_stream
(same metadata, just writing different packets or so), but in practice
this is never done.
2019-09-29 01:41:19 +02:00
wm4 2bb5ab07b7 stream: rearrange open functions
Add yet another variant of the stream open function. This time, make it
so that it's possible to add new open parameters in an extendable way,
which should put an end to having to change this every other year.

Effectively get rid of the overly special stream_create_instance()
function and use the new one instead, which requires changes in
stream_concat.c and stream_memory.c. The function is still in private in
stream.c, but I preferred to make the mentioned users go through the new
function for orthogonality. The error handling (mostly logging) was
adjusted accordingly.

This should not have any functional changes. (To preempt any excuses, I
didn't actually test stream_concat and stream_memory.)
2019-09-29 00:46:54 +02:00
Philip Sequeira a7158ceec0 demux: sort filenames naturally when playing a directory / archive 2019-09-29 01:13:00 +03:00
Marvin Schmidt f726b368da build: lower version requirement for EGL
`egl.pc` can be provided either by mesa or libglvnd. The latter doesn't
follow the same version scheme as mesa but instead uses the API version
that the library exposes, which is 1.5 for EGL[1]

[1] https://github.com/NVIDIA/libglvnd/commit/0dfaea2bcb7cdcc785f95e244223bd004a2d7fba#diff-b58a140c00ea99fb9a708e15afaade62R8
2019-09-29 00:08:23 +02:00
Philip Langdale 8c1f94f0e7 vo_gpu: hwdec_cuda: Synchronise OpenGL Interop
Previously, there appeared to be implicit synchronisation in the
GL interop path, and we never observed any visual glitches. However,
recently, I started seeing stuttering in the GL path and on closer
examination it looked like read-before-write behaviour where GL
would display an old frame again rather than the current one.

After verifying that disabling hwdec made the problem go away,
I tried adding a cuStreamSynchronize() after the memcpys and that
also resolved the problem, so it's clearly sync related.

cuStreamSynchronize() is a CPU sync and so more heavy-weight than
you want, but it's the only tool we have. There is no mechanism
defined for synchronising GL to CUDA (It looks like there is a way
to synchronise CUDA to EGL but it appears one way and so wouldn't
directly address this problem).

Anyway, empirically, the output now looks the same as with hwdec
off.
2019-09-28 19:24:24 +03:00
Rodger Combs c940d7dc8c build: silence OpenGL deprecation warnings on macOS for C/objC
We know of the deprecation since 10.14, and thus we do not need to
be reminded of it with each compiled file.
2019-09-28 15:20:35 +03:00
Anton Kindestam 0c8eb80e98 vo_drm: support controlling swapchain depth using swapchain-depth option 2019-09-28 14:10:01 +03:00
Anton Kindestam 6290420380 vo: make swapchain-depth option generic for all VOs
In preparation for making vo_drm able to use swapchain-depth
2019-09-28 14:10:01 +03:00
Anton Kindestam 9538fb5a7a drm: refactor page_flipped callback
Avoid duplicating the same callback function in both context_drm_egl
and vo_drm.
2019-09-28 14:10:01 +03:00
Anton Kindestam 77980c8184 vo_drm: Implement N-buffering and presentation feedback
Swapchain depth currently hard-coded to 3 (4 buffers).

As we now avoid redrawing on repeat frames (we simply requeue the same fb
again), this should give a nice performance boost when playing videos with a
lower FPS than the display FPS in video-sync=display-resample mode.

Presentation feedback has also been implemented to help counter the
significant amounts of jitter we would otherwise be seeing.
2019-09-28 14:10:01 +03:00
Anton Kindestam dfe45f018e vo_drm: fix more than 2 buffers
Now we can increase BUF_COUNT. Yay.
2019-09-28 14:10:01 +03:00
Anton Kindestam 2cf8dd6451 drm: move struct vsync_tuple into drm_common as drm_vsync_tuple
This struct will be useful in vo_drm as well.
2019-09-28 14:10:01 +03:00
Aman Gupta c7d0a8f58e stream_cb: add cancel_fn callback
This allows stream_cb backends to implement blocking
behavior inside read_fn, and still get notified when the user
wants to cancel and stop playback.

Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-09-27 13:00:45 -07:00
wm4 4fdd0940ed audio: fix copy&paste error
This wasn't used at all in my tests, because it simply passed the
frame directly to libswsresample. (And, by the way, will always do
that, because s64 is so obscure literally NOTHING uses it except
a sample specifically created to test this code. Screw FFmpeg.)
2019-09-27 21:31:04 +02:00
wm4 81c872efc0 ad_lavc: log on failure to read AVFrame
This can be due to unsupported sample formats (see previous commits),
minor allocation failures, and similar things. For identifying the exact
cause it's buried too deep in abstractions. But most time it doesn't
happen anyway, since it's extremely rare that new audio formats are
added.
2019-09-27 21:24:24 +02:00
wm4 53e3cb968a audio: add support for AV_SAMPLE_FMT_S64*
What an idiotic format. It makes no sense, and should have been
converted to S32 in the demuxer, rather than plague everyone with
another extremely obscure nonsense format. Why doesn't ffmpeg add S24
instead? That's an actually useful format.

May cause compilation failure with old FFmpeg or Libav libs, but I don't
care.
2019-09-27 21:21:34 +02:00
Anton Kindestam 22252432e2 context_drm_egl: define EGL_PLATFORM_GBM_MESA, EGL_PLATFORM_GBM_KHR if not in system headers
To account for oddball setups where EGL_PLATFORM_GBM_MESA or
EGL_PLATFORM_GBM_KHR might not be defined for whatever reason.
2019-09-27 20:01:15 +02:00
Jan Ekström 95ca78b63e wscript: check tvOS define's value to be nonzero
TARGET_OS_TV seems to always be defined, but set according to the
build configuration. This fixes all Apple configurations being
mis-identified as tvOS.
2019-09-27 18:55:53 +03:00
Wessel Dankers 643417dd17 video: add pure gamma TRC curves for 2.0, 2.4 and 2.6. 2019-09-27 13:21:41 +02:00
Philip Sequeira 919b7a55cd ci: remove --enable-zsh-comp
This option no longer exists, as zsh completion is installed
unconditionally now.
2019-09-27 13:19:29 +02:00
Philip Sequeira 2712db8238 zsh completion: move generation to runtime and improve
The completion function itself now parses --list-options on the first
tab press and caches the results. This does mean a slight delay on that
first tab press, but it will only do this if the argument being
completed looks like an option (i.e. starts with "-"), so there is never
a delay when just completing a file name. I've also put some effort into
making it reasonably fast; on my machine it's consistently under 100 ms,
more than half of which is mpv itself.

Installation of zsh completion is now done unconditionally because it's
nothing more than copying a file. If you really don't want it installed,
set zshdir to empty: `./waf configure --zshdir= ...`

Improvements in functionality compared to the old script:

 * Produces the right results for mpv binaries other than the one it was
   installed with (like a dev build for testing changes).

 * Does not require running mpv at build time, so it won't cause
   problems with cross compilation.

 * Handles aliases.

 * Slightly nicer handling of options that take comma-separated values
   and/or sub-options: A space is now inserted at the end instead of a
   comma, allowing you to immediately start typing the next argument,
   but typing a comma will still remove the automatically added space,
   and = and : will now do that too, so you can immediately add a
   sub-option.

 * More general/flexible handling of values for options that print their
   possible values with --option=help. The code as is could handle quite
   a few more options (*scale, demuxers, decoders, ...), but nobody
   wants to maintain that list here so we'll just stick with what the
   old completion script already did.
2019-09-27 13:19:29 +02:00
Philip Sequeira 21a5c416d5 options: add M_OPT_FILE to some more options that take files 2019-09-27 13:19:29 +02:00
Jonas Karlman 16d2ddb505 vo_gpu: hwdec_drmprime_drm: add hwdec ctx
This allows to use drm hwaccels that require a hwdevice.

Tested with v4l2request hwaccel and cedrus driver on an allwinner device
running mpv with --vo=gpu --gpu-context=drm --hwdec=drm.
2019-09-27 13:08:27 +02:00
wm4 c3687b9eaa hwdec_vaapi_gl: add missing compatibility defines
At first, this code used only 1 plane, so the compatibility stuff was
sufficient. But then use of planes 1 and 2 was added, without extending
the compatibility stuff.

I think I've seen a case recently where this broke the build and caused
users to apply invalid fixes, but I don't remember where.

It's possible that I didn't get all defines that are needed.
2019-09-27 13:05:21 +02:00
wm4 d8f02dc5d5 stream_cb: fix a typo in a comment 2019-09-27 12:59:10 +02:00
Jan Ekström 69e4a5772a ao_pulse: add the newly added mappings for TrueHD/DTS-HD formats
Originally DTS-HD was mapped to PA_ENCODING_DTS_IEC61937 which I'm
actually not sure if it ever worked.
2019-09-27 00:23:36 +03:00
sfan5 e350ceef4c vo_gpu: vulkan: add Android context 2019-09-27 00:05:06 +03:00
sfan5 508e35881e context_android: move common code to a separate file
In preparation for a Vulkan Android context.
This also replaces querying for EGL_WIDTH and EGL_HEIGHT
with equivalent ANativeWindow calls.
2019-09-27 00:05:06 +03:00
dudemanguy 450209344b DOCS: don't lie about the keybind command
It turns out you can actually bind keybind to another keybind. Just be
careful with all the quotes.
2019-09-26 15:54:15 -05:00
Aman Gupta 9dc0a9f0e0 wscript: detect tvOS and disable posix-spawn usage
cc #5331

Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-09-26 23:45:54 +03:00
James Ross-Gowan 03cb8755e1 vo_gpu: d3d11: don't reset frame stats after pause
I think I was wrong about having to reset the stats when mpv stops
producing frames, eg. when it's paused. As long as the swapchain doesn't
underflow, last_queue_display_time will still be accurate, because the
next frame produced should still be presented one vsync after the
last one in the swapchain.

If the swapchain underflows (which is the common case for when mpv is
paused for more than 150ms,) the next predicted frame time should be in
the past. It should be fine to leave last_queue_display_time unset in
this case, since vo.c will use the current time instead, which is a
decent guess (though it doesn't take vsync phase into account.)

last_sync_refresh_count and last_sync_qpc_time should be kept on
swapchain underflow as well. Assuming the display refresh rate doesn't
change while mpv is paused, they'll only provide a more accurate guess
of the vsync duration when mpv starts playing again. Also,
vsync_duration_qpc never needs to get reset. It will get overwritten
immediately in most cases, and when it doesn't, it's still a better
guess of the vsync duration than nothing.
2019-09-26 23:41:38 +03:00
wm4 9d4f16b10d player: document FFmpeg ABI rules we intentionally violate
That's just a single one. It used to be more, when FFmpeg still required
using pointless accessors for tons of fields, which historically broke
compatibility with Libav. (I think I wrote the patch to deprecate that
crap and to allow direct access myself.)

There may be more exceptions, but I forgot about them. Another point is
that we don't really trust FFmpeg ABI stability, though.
2019-09-26 19:58:17 +02:00
wm4 c1956e82c2 audio: make playback end with --end and --audio-spdif
In spdif mode, there are hacks that try to cut audio on frame boundaries
(blame spdif, which is a hack in itself). The "alignment" is used in a
bunch of places, but --end does not respect it. This leads to some audio
that can't be pushed because the alignment is off (I don't know why, not
do I care), which puts audio into an underrun state forever.

Fix this by discarding unusable extra samples if no new data can be
expected.

Fixes: #6935
2019-09-26 19:52:10 +02:00
wm4 f44e480242 DOCS/contribute.md: talk about non-standard and C11 language features
The C11 situation is complicated. For example, MinGW doesn't seem to
have a full C11 implementation, but we pretty much rely on C11 atomics.

Regarding "#pragma once": they say it's not standard because of unsolved
(admittedly valid) issues. Btu still, fuck writing include guards, I
just can't be bothered with this crap.

(Does anyone even read this document?)
2019-09-26 14:17:00 +02:00
wm4 31c04f162b client API: be explicit about usage rules and deadlocks some more
I think a popular libmpv application did exactly this: enabling advanced
control, and then receiving deadlocks. I didn't confirm it, though. In
any case, the API docs should avoid tricking users into making this easy
mistake.
2019-09-26 14:17:00 +02:00
wm4 4d43c79e4c client API: fix potential deadlock problems by throwing more shit at it
The render API (vo_libmpv) had potential deadlock problems with
MPV_RENDER_PARAM_ADVANCED_CONTROL. This required vd-lavc-dr to be
enabled (the default). I never observed these deadlocks in the wild
(doesn't mean they didn't happen), although I could specifically provoke
them with some code changes.

The problem was mostly about DR (direct rendering, letting the video
decoder write to OpenGL buffer memory). Allocating/freeing a DR image
needs to be done on the OpenGL thread, even though _lots_ of threads are
involved with handling images. Freeing a DR image is a special case that
can happen any time. dr_helper.c does most of the evil magic of
achieving this. Unfortunately, there was a (sort of) circular lock
dependency: freeing an image while certain internal locks are held would
trigger the user's context update callback, which in turn would call
mpv_render_context_update(), which processed all pending free requests,
and then acquire an internal lock - which the caller might not release
until a further DR image could be freed.

"Solve" this by making freeing DR images asynchronous. This is slightly
risky, but actually not much. The DR images will be free'd eventually.
The biggest disadvantage is probably that debugging might get trickier.

Any solution to this problem will probably add images to free to some
sort of queue, and then process it later. I considered making this more
explicit (so there'd be a point where the caller forcibly waits for all
queued items to be free'd), but discarded these ideas as this probably
would only increase complexity.

Another consequence is that freeing DR images on the GL thread is not
synchronous anymore. Instead, it mpv_render_context_update() will do it
with a delay. This seems roundabout, but doesn't actually change
anything, and avoids additional code.

This also fixes that the render API required the render API user to
remain on the same thread, even though this wasn't documented. As such,
it was a bug. OpenGL essentially forces you to do all GL usage on a
single thread, but in theory the API user could for example move the GL
context to another thread.

The API bump is because I think you can't make enough noise about this.
Since we don't backport fixes to old versions, I'm specifically stating
that old versions are broken, and I'm supplying workarounds.

Internally, dr_helper_create() does not use pthread_self() anymore, thus
the vo.c change. I think it's better to make binding to the current
thread as explicit as possible.

Of course it's not sure that this fixes all deadlocks (probably not).
2019-09-26 14:14:49 +02:00
Stefan Pöschel 3ee6d7db4e command: fix bitrate rounding error
When the (float) bitrate is returned, it is implicitely converted to an
int64 value, merely discarding the fractional part.

However the bitrate of a CBR track can vary a bit due to timestamp
precision loss after clock conversion (this can affect MPEG-TS audio
tracks). So a bitrate like 191999.999... results in 191999 when
being returned - instead of 192000.

To fix this, apply proper rounding, as already done for the "old" case.
Hereby refactoring the "old" case to also use `llrint`.
2019-09-26 11:53:42 +02:00
der richter 41f290f54e cocoa-cb: add support for 10bit opengl rendering
this will request a 16bit half-float framebuffer instead if a 8bit
integer framebuffer.

Fixes #3613
2019-09-26 00:02:02 +02:00
wm4 ff2aed2b56 sub: make font provider user-selectable
libass had an API to configure this since 2013. mpv always used
ASS_FONTPROVIDER_AUTODETECT, because usually there's little reason to
use anything else. The intention of the now added option is to allow
users to disable use of system fonts.

I didn't consider it worth the trouble to add the coretext and
directwrite enum items from ASS_DefaultFontProvider. The "auto" choice
will have the same effect if they're available. Also, the part of the
code which defines the option does not necessarily have libass available
(it's still optional!), so defining all enum items as choices is icky. I
still added fontconfig, since that may be nice to emulate a nostalgic
2010 feeling of mpv freezing on fontconfig.

The option for OSD is even less useful. (But you get it for free, and
why pass up a chance to add yet another useless option?)

This is not quite what was requested in #6947, but as close as it gets.
2019-09-25 22:11:48 +02:00
Anton Kindestam bbf6e103b4 drm_common: add missing zero-initialization of struct vt_mode variable
Some fields were being left uninitialized. This could be a problem
particularly on non-Linux OS:s with vt_mode (see PR #6976).
2019-09-24 21:46:52 +02:00
wm4 68ce36a2db demux: force reading packets again after seeks
in->eof is used as an indicator whether reading packets still makes
sense. (Without this, the prefetcher would obviously burn CPU by
retrying reading even though everything has been read.)

This was not reset properly after seeks were performed. It led to
getting stuck in at least one corner case: when enabling a track, the
demuxer would seek backwards to get new packets from the current
playback position ("refresh seeks"). But if playback was paused, and EOF
was previously reached, it would not try to read packers again due to
in->eof being false. There was not anything else that would make it
retry reading, so it was stuck in a weird underrun/buffering state.

Fixes: #6986
2019-09-24 19:06:59 +02:00
Gunnar Marten d2a9e3fb34 demux: remove redundant seek range update
This was a leftover from commit b2752321 which fixed #6522 but after
the recent demux refactoring this fix is superseded by commit 0f6cda4ab.
Remove the redundant update call.
2019-09-24 17:14:25 +02:00
der richter 422b486200 cocoa-cb: fix title bar button state on start up
on start up it was possible to click the hidden buttons. hide the
buttons ons tart up to make the state consistent with the visible state.
2019-09-23 21:10:38 +02:00
Akemi c1cdecd147 mac: add Open Playlist menu bar item 2019-09-23 19:28:38 +02:00
Anton Kindestam b6def652a4 context_drm_egl: Don't get stuck forever if drmHandleEvent fails 2019-09-22 22:39:10 +02:00
wm4 cbff8a5862 demux_lavf: fix seeking in ogg audio streams
This detected the first packet demuxed after a seek as timestamp
discontinuity. Obviously this is non-sense. Since the OGG radio streams
for which this feature was introduced are normally unseekable, it's
simple to fix this: simply disable it (if in auto mode, the default) as
soon as a seek is performed. This code is never called if the stream is
considered unseekable, unless the user forced it.

There's still a chance this linearization is performed before a seek
happens. This will be a bit awkward, but no worse than without this
feature, since seeking with timestamp resets is inherently broken in
both mpv and libavformat.

Fixes: #6974
Fixes: 27fcd4d
2019-09-22 20:52:37 +02:00
der richter 4a2f239842 travis: use macOS 10.14 image with xcode 11 instead of xcode 10.2 2019-09-22 17:15:45 +03:00
der richter 9e52d36962 build: optimise adding additional objects for linking
splitting the string by spaces isn't the best idea, so we use a proper
list instead now.
2019-09-22 17:14:31 +03:00
der richter e3972746dc osxbundle: remove rpath definitions towards dev tools
since the loading order of rpaths is system wide lib path, dev tool path
and then bundle lib path it's possible for the xcode swift libs to be
incompatible with the libs the bundle was build with. this leads to
possible segfaults. if we distribute the bundle we don't want to load
the libs from the dev tools anyway.
2019-09-22 17:07:51 +03:00
der richter f64c0115ae build: fix swift linking with upcoming xcode 11
in xcode 11 the dynamic swift libraries were moved to a separated
versioned swift folder, which can't be used for linking and only for
distribution. additional to the std dynamic swift lib folder the system
wide folder is needed for linking too.
2019-09-22 17:07:51 +03:00
Anton Kindestam d00f9b19c7 draw_bmp: Fix for GBRP formats GBRP9 and up
First we shift the values up to the actual amount of bits in draw_ass,
so that they will be drawn correctly when using formats with more than
8 bpc. (draw_rgba is already correct w.r.t. RGB formats with 9 or more
bpc)

Then, in scale_sb_rgba, by setting the amount of bits per channel used
for planar RGB formats (formats are always planar at this point in
draw_bmp) to be the same as the source from 9 to 16 bpc (in effect all
the various GBRP formats) we manage to fit the special case that does
not require any conversion in chroma_up and chroma_down when handling
these formats (as long as the source itself is a planar format),
instead writing directly to the combined dst/src buffer. This in turn
works around a bug (incorrect colors) in libswscale when scaling
between GBRP formats with 9 or more bpc. Additionally this should be
more efficient, since we skip up- and down-conversion and temporary
buffers.
2019-09-22 15:59:24 +02:00
Anton Kindestam e2f96535f5 vo_drm: 30bpp support 2019-09-22 15:59:24 +02:00
Nicolas F 2d1d815cc7 manpage: update requirements for vdpau hwdec use
We default to EGL instead of GLX now, which means vdpau only works
if we explicitly specify that we want a GLX context, as vdpau lacks
interop for EGL.

Update the hwdec documentation to reflect this.

Concerns #6980.
2019-09-22 16:27:24 +03:00
James Ross-Gowan a9f9601ca8 vo_gpu: d3d11: add support for presentation feedback
This adds vsync reporting to the D3D11 backend using the presentation
feedback provided by DXGI, which is pretty similar to what's provided by
GLX_OML_sync_control in the GLX backend. In DirectX, PresentCount is the
SBC, PresentRefreshCount and SyncRefreshCount are kind of like the MSC
and SyncQPCTime is the UST.

Unlike GLX, the DXGI API makes it possible for PresentCount and
SyncQPCTime to refer to different physical vsyncs, in which case
PresentRefreshCount and SyncRefreshCount will be different. The code
supports this possibility, even though it's not clear whether it can
happen when using flip-model presentation. The docs say for flip-model
apps, PresentRefreshCount is equal to SyncRefreshCount "when the app
presents on every vsync," but on my hardware, they're always equal, even
when mpv misses a vsync. They can definitely be different in exclusive
fullscreen bitblt mode, though, which mpv doesn't support now, but might
support in future.

Another difference to GLX is that, at least on my hardware,
PresentRefreshCount and SyncRefreshCount always refer to the last
physical vsync on which mpv presented a frame, but glxGetSyncValues can
apparently return a MSC and UST from the most recent physical vsync,
even if mpv didn't present a new frame on it. This might result in
different behaviour between the two backends after dropped frames or
brief pauses.

Also note, the docs for the DXGI presentation feedback APIs are pretty
awful, even by Microsoft standards. In particular the docs for
DXGI_FRAME_STATISTICS are misleading (PresentCount really is the number
of times Present() has been called for that frame, not "the running
total count of times that an image was presented to the monitor since
the computer booted.")

For good documentation, try these:
https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-flip-model
https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dpresentstats
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/d3dkmthk/ns-d3dkmthk-_d3dkmt_present_stats

(Yeah, the docs for the D3D9Ex and even the kernel-mode version of this
structure are better than the DXGI ones. It seems possible that they're
all rewordings of the same internal Microsoft docs, but whoever wrote
the DXGI one didn't really understand it.)
2019-09-22 23:18:40 +10:00
Nicolas F 4247a54d98 command: add expand-path to expand mpv paths
The question came up on how a client would figure out where
screenshot-directory saved its screenshots if it contained
mpv-specific expansions. This command should remedy the situation
by providing a way for the client to ask mpv to do an expansion.
2019-09-22 15:04:58 +02:00
Avi Halachmi (:avih) 4cda63bd14 build: actually detect supported warning options
Previously the options were tested by compiling a test program with the
option, and support was "detected" if the compilation didn't fail.

However, both gcc and clang only issue a warning on unknown warning option,
hence it never failed and all the warn options were detected as supported.

Now the tested option is used together with -Werror, which makes it fail
if it warns that the warning option is unknown.

Fixes clang unknown option warnings -Wno-format-truncation since 4a6b56f .
2019-09-22 15:01:08 +03:00
Stefano Pigozzi cb32ad68f3 command: add sub-start & sub-end properties
These properties contain the current subtitle's start and end times.
Can be useful to cut sample audio through the scripting interface.
2019-09-22 09:19:45 +02:00
dudemanguy 0f938b197a wayland: create current_output in wayland_reconfig
Certain mpv config options require wl->current_output to be created
before the video can actually start rendering. Just always create it
here if the current_output doesn't exist (the one exception being the
--fs option with no --fs-screen flag). Incidentally, this also fixes
--fs-screen not working on wayland.
2019-09-22 03:33:21 +00:00
Philip Langdale 61b46d101e wscript: Fix test for ffmpeg drmprime support
This test requires libavutil headers but there is no avutil
dependency for it to use. So let's add one, and also reorder the
ffmpeg tests ahead of the video tests so that the avutil dependency
can be used.
2019-09-22 00:07:23 +03:00
Jan Ekström 6c6aba4359 vf_fingerprint: remove extraneous single quote from description
This happened to break ZSH completion and seemed to be extraneous.

Reported by LaserEyess on IRC.
2019-09-21 23:46:41 +03:00
wm4 0b127312be test/linked_list: silence nonsense warnings
../misc/linked_list.h:71:34: warning: the address of ‘e6’ will always
evaluate as ‘true’ [-Waddress]

No shit, e6 is on the stack. But the macro argument is also allowed to
be NULL. Add some dumb nonsense to shut up the useless warning. (It's
probably useful in other contexts though, so don't disable it
completely.)
2019-09-21 22:30:38 +02:00
wm4 293dfc7825 test: fix cmocka assert_float_equal shadowing warnings
Just use cmocka's function. It takes an epsilon argument, which we now
provide directly.

There's no assert_double_equal() in cmocka (and the float variant
actually forces a conversion to the float type), but fortunately we
didn't use it.
2019-09-21 22:11:52 +02:00
wm4 9280e6b322 stream_dvb: remove unused variable
(At first I left this intentionally, because the temporarily disabled
stream ctrl code used it, but there's actually no reason to annoy
everyone with the warning.)
2019-09-21 22:05:24 +02:00
dudemanguy dab28158ee waf: fix wayland-scanner deprecation warning
Use `private-code` instead of `code` here. Also this bumps up the
required wayland-client/wayland-cursor version to 1.15 which is still
pretty old anyway.
2019-09-21 23:02:48 +03:00
wm4 5858e3cdbd audio: fix use-after-free with fuzzed file
reinit_audio_filters_and_output() can fully shutdown the audio chain on
failure. Specifically, it will deallocate mpctx->ao_chain. The value of
that field was cached in ao_c. The code after the call did not account
that the audio chain can be shutdown, and used the stale ao_c value.

Fixes: #6808
2019-09-21 21:59:09 +02:00
Jan Ekström fc7decde73 sub/lavc_conv: skip ReadOrder reset when subtitle decoder gets flushed
During initial testing with US closed captions, ARIB captions,
timed text in MP4 or the specific external SRT files I tested with
there were no hints that this flag would be needed for seeking to
work.

Unfortunately, that result seems to have been incorrect.

Fixes #6970
2019-09-21 22:02:17 +03:00
wm4 d34421f4f9 dec_sub: remove unused declaration 2019-09-21 19:08:14 +02:00
Dudemanguy911 4614d432a8 input: add keybind command 2019-09-21 16:58:14 +00:00
Dudemanguy911 dd547ddcc2 playloop: don't read playback pos from byte stream
If a file format supports PTS resets, get_current_pos_ratio calculates
the ratio using the stored filepos in the demuxer struct instead of a
standard query of the current time in the stream and its total length.
This seems like a reasonable way to avoid weird PTS values, but in
reality this just causes problems and results in inaccurate ratio
values that can affect other parts of the player (most notably the osc
seekbar).

For libavformat formats, demux->filepos is obtained from the
demux_lavf_fill_buffer function which is called on the next packet. The
problem is that there is a slight delay between packets and in some
cases, this delay can be relatively large. That means the obtained
demuxer->filepos value will be very inaccurate since it obtains the pos
from the end of the upcoming packet and not its actual current position.

This is especially noticeable at the very beginning of playback where
get_current_pos_ratio sometimes returns a value of well over 2% despite
less than a second passing in the stream. Another telltale sign is to
simply watch the osc seekbar as a stream progresses and observe how it
loads in staggered steps as every packet is decoded. In contrast, the
seekbar progresses smoothly on the playback of a format that does not
support PTS resets. The simple solution is to instead use the query of
the current time and length of a stream and calculate the ratio that
way.

get_current_pos_ratio will still fallback on using the byte stream
position if the previous queries fail. However, get_current_time will
be more accurate in the vast majority of cases and should be the
preferred method of calculating the position ratio.
2019-09-21 15:49:28 +00:00
Dudemanguy911 685e927fbe wayland: avoid handling a 0-value axis event
This shouldn't be possible, but an extra check never hurts.
2019-09-21 10:38:43 -05:00
wnoun 6111f57ef9 player: expose pixel aspect ratio, bitrate and rotation value on tracks 2019-09-21 16:55:59 +02:00
wm4 dc7bd2ca29 DOCS/contribute.md: expand on recommended C99 usage 2019-09-21 16:35:45 +02:00
der richter 511a73c5ce build: don't add swift object when swift disabled 2019-09-21 16:23:51 +02:00
emersion 600824494d wayland: read xcursor size from XCURSOR_SIZE env
This allows compositors to set the cursor size from user
configuration.
2019-09-21 15:43:54 +02:00
thewisenerd 8f35b3873f player: use track title if exists instead of filename 2019-09-21 15:41:22 +02:00
thewisenerd 2a29950020 input: ignore empty lines on drag-drop mime data
do not outright err and quit the player for this
2019-09-21 15:39:47 +02:00
Leonardo Taccari 3d911d8ef0 ao_oss: Fallback to stereo when the device does not support >2 channels
ioctl(..., SNDCTL_DSP_CHANNELS, &nchannels) for not supported
nchannels does not return an error and instead set nchannels to
the default value.

Instead of failing with no audio, fallback to stereo.
2019-09-21 15:38:46 +02:00
dudemanguy 48740dfec5 osd: allow sub-text to work even if sub-visibility is disabled 2019-09-21 15:36:58 +02:00
slatchurie 1591ccfff5 x11: fix ICC profiling for multiple monitors
To find the correct ICC profile X atom, the screen number was calculated
directly from the xrandr order of the screens.
But if a primary screen is set, it should be the first Xinerama screen,
even if it is not the first xrandr screen.

Calculate the the proper atom id for each screen.
2019-09-21 15:36:16 +02:00
Ricardo Constantino ffe89415fe osc: add mouse mid-button as alias to shift+left button 2019-09-21 15:30:20 +02:00
dudemanguy cdad5cc65f wayland: don't show cursor when fullscreening 2019-09-21 15:24:06 +02:00
Thomas Weißschuh 9e304ab974 wayland: reconfigure cursor on pointer enter event
On wayland the cursor has to be configured each time the pointer enters.
Currently if the window (re)gains the focus, the pointer is not hidden,
even when configured. After the mouse has been moved the pointer hides
correctly.

https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_pointer:

    wl_pointer::enter - enter event

    ...

    When a seat's focus enters a surface, the pointer image is undefined
    and a client should respond to this event by setting an appropriate
    pointer image with the set_cursor request.

Fixes #6185.

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
2019-09-21 15:24:06 +02:00
wnoun 1c43920fb8 demux_cue: auto-detect CUE sheet charset 2019-09-21 15:18:20 +02:00
Paul B Mahol a35da6612e command: add video-add/video-remove/video-reload commands 2019-09-21 15:02:16 +02:00
dudemanguy f54ad8eb05 wayland: add mouse buttons and fix axis scaling
Previously, the only mouse buttons supported in wayland were left,
right, and middle click. This adds the thumb back/forward buttons as
valid bindings. Also it removes the old, default behavior of always
sending a right click if an unrecognized mouse button is clicked.
In a related but different fix, the magnitude of an axis event in
wayland is not important to mpv since it internally handles all scaling.
The only thing we care about is getting the sign when the event occurs.
2019-09-21 14:35:03 +02:00
Dark a41f1a21d6 client API: add mpv_command_ret
This change adds a version of `mpv_command` that also returns a result.
The main rationale behind this is `mpv_command_node` requires defining
multiple structs before you can even use it, which results in a pretty
painful to use interface just to get the result from a command.

There isn't really a good name for this function, so I'm open to
suggestions on a better name for it.
2019-09-21 14:24:42 +02:00
wm4 74b4760aa8 DOCS/contribute.md: license clarifications
Basically, both the license of the file and the preferred license of the
project (LGPLv2.1+) counts. I'm doing that so that files with more
liberal licenses don't get infected by LGPL, but allow copy & pasting to
LGPL source files without jumping through lawyer bullshit hoops.

Mention this in Copyright too.
2019-09-21 13:58:09 +02:00
wm4 cf620235a5 github: remove LGPL relicensing boilerplate
Most files are LGPL anyway by now. contribute.md still requires
contributors to provide changes under LGPL, which should cover changes
to files that are LGPL, as well as GPL files.
2019-09-21 13:53:31 +02:00
Cameron Cawley 70f8154b3d vo_sdl: Only create the SDL window once 2019-09-21 12:58:01 +02:00
Térence Clastres 41f4e8d73a ao_pulse: add --pulse-allow-suspended
This flag makes mpv continue using the PulseAudio driver even if the
sink is suspended.
This can be useful if JACK is running with PulseAudio in bridge mode and
the sink-input assigned to mpv is the one JACK controls, thus being
suspended.
By forcing mpv to still use PulseAudio in this case, the user can now
adjust the sink to an unsuspended one.
2019-09-21 12:54:36 +02:00
James Hilliard abfc58cad4 stream_libarchive: Always use LC_CTYPE_MASK for libarchive
Using LC_ALL_MASK is unnecessary and unreliable on some systems.

Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
2019-09-21 12:53:47 +02:00
wm4 4c4d7a64c6 command: drop removed cache properties from cache update events
These did nothing anymore, maybe made it slightly slower.
2019-09-20 19:22:03 +02:00
wm4 ce1e670a33 player: update status line cache display
Replace the "+" with "/". The "+" was supposed to imply that the cache
is the sum of the time (demuxer cache) and the size in bytes (stream
cache). We could not provide something nicer, because we had no idea how
many seconds of media was buffered in the stream cache.

Now the stream cache is done, and both the duration and byte size show
the amount buffered in the demuxer cache. Hopefully "/" is better to
imply this properly. Update the manpage explanations too.
2019-09-20 19:22:03 +02:00
memeka 0bdcbd75e0 context_drm_egl: Use eglGetPlatformDisplayEXT if available
Check if eglGetPlatformDisplayEXT is available and try to
use it to obtain the display connection. Fall back to eglGetDisplay
if eglGetPlatformDisplayEXT is not available or failing.

From PR #5992
2019-09-20 19:09:36 +02:00
Gunnar Marten 31a39334a2 client API: fix missing property change events after property updates
When update_prop() successfully fetched a changed property value, it
set prop->changed to true to indicate the success.
mark_property_changed() also always set
prop->changed to true and additionally prop->need_new_value to true
This is the case since 6ac0ef78
If the observed property changes every frame and then due to timing
the next mark_property_changed() is called before
gen_property_change_event() and therefore directly after update_prop(),
prop->need_new_value was again true and indicated that a new value
has to be retrieved with update_prop(). As a result the event for the
last successful update_prop() was never triggered. This meant that
a property change event were never generated for frame-based properties
only for properties that were observed with MPV_FORMAT_NONE or when the
timing was different and gen_property_change_event() was called after
update_prop().

To fix this, mark_property_change() and update_prop() should not use the
same flag to indicate different things and therefore a new flag for
successfully update a property is introduced. But with the now decoupled property
changed and updated the need_new_value flag is redundant and removed completely.

Fixes #4195
2019-09-20 19:47:39 +03:00
wm4 c1f1a0845e loadfile: restore playlist prefetching
With the stream cache gone, this function had almost no use anymore
(other than opening the stream). Improve this by triggering demuxer
cache readahead.

This enables all streams. At this point we can't know yet what streams
the user's options would select (at least not without great additional
effort). Generally this is what you want, and the stream cache would
have read the same amount of data.

In addition, this will work much better for files that e.g. need to seek
to the end when opening (typically mp4, and mkv files produced by newer
mkvmerge versions).

Remove the deselection call from add_stream_track(). This should be
fine, as streams normally start out as deselected anyway. In the
prefetch case, some code in play_current_file() actually deselects it.
Streams that appear during demuxing are disabled by default, so this
doesn't break this logic either.

Fixes: #6753
2019-09-20 18:13:16 +02:00
wm4 94bfe83355 demux: propagate streaming flag through demux_timeline
Before this commit, EDL or CUE files did not properly enable the cache
if they were on "slow" media (stream->streaming==true). This happened
because the stream is unset for demux_timeline, so the streaming flag
could not be queried anymore.

Fix this by adding this flag to struct demuxer, and propagate it exactly
like the is_network flag. is_network is not used for checking the cache
options anymore, and its main function seems to be something else.
Normal http streams set the streaming flag already.

This should fix #6958.
2019-09-20 17:01:35 +02:00
wm4 4fa8f33b92 client API, vo_libmpv: document random deadlock problems
I guess trying to make DR work on libmpv was a mistake.

I never observed such a deadlock, but it's looks like it's theoretically
possible.
2019-09-20 16:47:16 +02:00
wm4 f00af71d12 vo_libmpv: fix some more uninit issues
This is mostly for the case when mpv_render_context_free() is called
while video is going on. This is supposed to gracefully stop video and
deinitialize everything properly. (I feel like it would put too much on
the API user to require that video is stopped before calling this
function. Whether video is running or not is a fairly highlevel thing,
and the API user could not do it in a race-free way.)

One problem was that unit() accessed ctx after ctx->in_use was set to
false. The update(ctx) call was basically a racy use-after-free. It
needed that call to wake up the mpv_render_context_free() loop that
waited for VO uninit. Fix this by triggering the wakeup inside the lock,
and then doing "barrier" locking in mpv_render_context_free().

Another problem was that the wait loop didn't really wait properly. IT
seems the had_kill_update field was a botched attempt to do that. It's
indeed quite hairy to do that with update(). Instead make use of the
dispatch queue (infinite timeout, using mp_dispatch_interrupt()), which
handles the problem of having to wait both for dispatch queue updates
and VO uninit at the same time.
2019-09-20 16:31:53 +02:00
wm4 3ae728532d client API: document unfortunate render API threading requirement
This is because dr_helper.c calls pthread_self(). It's used to avoid
deadlocks. This was not a problem internal to mpv (dr_helper.c was first
created for vo_gpu.c), but it accidentally leaked as an unintended
consequence of an implementation detail to libmpv.

This problem existed for MPV_RENDER_PARAM_ADVANCED_CONTROL users, ever
since it was introduced.

Maybe this could be done differently, but it's certainly very tricky.
the pthread_t is used to avoid deadlocks when the caller is on the same
thread as the one which needs to handle the calls.

The critical code is in free_dr_buffer_on_dr_thread(). It's called when
a DR image is free'd. Freeing a DR image requires access to the GL
context, i.e. it just has to run on the "GL" thread. In libmpv's case,
this is done by calling the API user's wakeup call, and the user will
eventually call mpv_render_context_update() on the "GL" thread, which in
turn calls mp_dispatch_queue_process() on the dispatch queue that was
passed to dr_helper_create(), which then calls av_buffer_unref(), which
calls gl_video_dr_free_buffer(). (God who came up with this rube
goldberg shit.)

The above case will typically happen when e.g. vd_lavc.c (internal mpv
thread) frees images. Allocation works similarly; deallocation is just
trickier because calls to free images are everywhere.

Now consider if mpv_render_context_render() releases a DR image. This
function is always called on the "GL" thread. Going through the dispatch
queue would obviously deadlock, because according to the render API
rules, the user's wakeup callback must not mpv_render_context_update(),
instead it has to signal the "GL" thread, which must wait until
mpv_render_context_render() returns. To avoid this deadlock, dr_helper.c
checks whether the calling thread is the "GL" thread, and if so, allows
a reentrant call (basically gl_video_dr_free_buffer() is called
directly).

While with GL, you usually will stay on the same thread, API users were
in theory allowed to e.g. move the GL context to a different thread. But
this dr_helper issue means this is not possible. Moreover, other APIs
will not have the same thread-locality problems as GL.

FUCK THIS SHIT

In theory, libmpv could provide an API to "move" the context to a
separate thread, but let's not start with even more broken crap like
this. I'm not sure yet whether there is an easy solution. Maybe all
mpv_render() function could be guarded by entry/exit functions, which
set/unset a flag that dr_helper.c should use reentrant calls.

libmpv users which do not set MPV_RENDER_PARAM_ADVANCED_CONTROL were
never affected.
2019-09-20 16:04:18 +02:00
wm4 d12264acc0 vo_libmpv: always create ctx->dispatch
Preparation for the next commit. Until now, it was only needed if DR was
involved. One reason for not always creating it was that you normally
must not use it if advanced_control is not enabled. This is why e.g.
VOCTRL_SCREENSHOT now checks for that variable; it still can't use
ctx->dispatch if the render API user did not enable it.
2019-09-20 14:53:21 +02:00
wnoun 35da5a4d8e render api: fix use-after-free
render api needs to wait for vo to be destroyed before frees the context.
The purpose of kill_cb is to wake up render api after vo is destroyed,
but uninit did that before kill_cb, so kill_cb tries using the freed
memory. Remove kill_cb to fix the issue as uninit is able to do the
work.
2019-09-20 13:54:17 +02:00
Cameron Cawley db09d77e46 rpi: Update for modern systems 2019-09-20 11:39:06 +02:00
wm4 a46f83e982 Coypright: update list of files 2019-09-20 11:38:16 +02:00
wm4 257534ed18 vo: remove unused equalizer control remains
Equalizer control was redone in 03cf150ff3 (over 2 years
ago). Ever since, the equalizer control structs and the GET voctrl have
been unused. Only the SET voctrl is still used as notification mechanism
(actually a bad hack to avoid some further option change handling
complexity).

Remove the unused parts.
2019-09-20 00:45:17 +02:00
wm4 8e5cd62dca oml_sync: fix typo in comment
I think... Also reword another part of the text.
2019-09-20 00:32:29 +02:00
wm4 7000d91cf8 vf_fingerprint: use aligned_alloc instead of posix_memalign
I was assuming posix_memalign was the most portable function to use, but
MinGW does not provide it for some reason. Switch to C11 aligned_alloc()
which someone suggested was provided by MinGW (but actually isn't,
someone probably confused it with the incompatible _aligned_malloc),
and add a configure check.

Even though it turned out that MinGW doesn't provide it, the function
is slightly more elegant than posix_memalign(), so stay with it.
2019-09-19 23:09:02 +02:00
wm4 d75bdf070f demux_lavf: document intentional FFmpeg API violation
This field is documented as internal, so an API user should not
access it. However, this is the only way to get some read statistics
without replacing FFmpeg's entire HLS demuxer. (Using custom I/O as
workaround doesn't work: the HLS code uses some weird internal APIs
that cannot be provided by FFmpeg API users; I even made the author
of the relevant patch to provide a public API, but which was shot
down by another FFmpeg developer. So I take this as my right to
access this field.)

Mention this explicitly, as it affects ABI and API compatibility, and
I don't want that anyone claims this was a "mistake". Add some
explanations.
2019-09-19 20:37:05 +02:00
wm4 389f1b0ef3 packet: fix theoretical UB if called on "empty" packets
In theory, a 0 size allocation could have made it memset() on a NULL
pointer (with a non-0 size, which makes it crash in addition to
theoretical UB).

This should never happen, since even packets with size 0 should have an
associated allocation, as FFmpeg currently does. But avoiding this makes
the API slightly more orthogonal and less tricky, I guess.
2019-09-19 20:37:05 +02:00
wm4 9a7a6958ca Revert "demux/packet: fix demux_packet_shorten"
This reverts commit 95636c65e7.

This change shouldn't be needed, and in fact it's wrong. The FFmpeg API
function could do anything it wants with the packet, including changing
the packet data pointer. Likewise, it's not guaranteed that the
referenced packet's fields mirror the current state of the mpv packet
struct (the AVPacket is only kept for the AVBuffer and the side data
stuff).
2019-09-19 20:37:05 +02:00
wm4 e60bcf0d98 client API: fix some comments 2019-09-19 20:37:05 +02:00
wm4 0cd8ba72fe sd_lavc: support scaling for bitmap subtitles 2019-09-19 20:37:05 +02:00
wm4 4c5df406a8 demux: fix another incorrect BOF cache flag issue 2019-09-19 20:37:05 +02:00
wm4 380033f4a2 f_swscale: fix a typo 2019-09-19 20:37:05 +02:00
wm4 6b7ecb30d8 manpage: input.rst: fix a typo 2019-09-19 20:37:05 +02:00
wm4 9cfeafa89e video: add vf_fingerprint and a skip-logo script
skip-logo.lua is just what I wanted to have. Explanations are on the top
of that file. As usual, all documentation threatens to remove this stuff
all the time, since this stuff is just for me, and unlike a normal user
I can afford the luxuary of hacking the shit directly into the player.

vf_fingerprint is needed to support this script. It needs to scale down
video frames as part of its operation. For that, it uses zimg. zimg is
much faster than libswscale and generates more correct output. (The
filter includes a runtime fallback, but it doesn't even work because
libswscale fucks up and can't do YUV->Gray with range adjustment.)

Note on the algorithm: seems almost too simple, but was suggested to me.
It seems to be pretty effective, although long time experience with
false positives is missing. At first I wanted to use dHash [1][2], which
is also pretty simple and effective, but might actually be worse than
the implemented mechanism. dHash has the advantage that the fingerprint
is smaller. But exact matching is too unreliable, and you'd still need
to determine the number of different bits for fuzzier comparison. So
there wasn't really a reason to use it.

[1] https://pypi.org/project/dhash/
[2] http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html
2019-09-19 20:37:05 +02:00
wm4 da612acacd command: make vf-metadata/af-metadata somewhat observable
Until now they weren't observable and never reported any updates. Apply
a shitty hack to make them mostly-observable. It relies on the "idle"
event, which is basically triggered on every frame displayed, or
similar. This can lead to property change notifications not being sent
quickly enough.

The cleaner solution would be adding a notification mechanisms from
filters, but I'm too lazy for that.
2019-09-19 20:37:05 +02:00
wm4 a05b847879 command: make vf-metadata/af-metadata not query metadata twice
For simplicity, these properties usually query the metadata from the
filter twice, even if it's not technically needed at all. The reason for
this is mostly the horrible (and legacy) sub-path access (which is why
tag_property() is so complex).

But for simple cases, we can easily avoid double querying, so do that.
The benefit is performance (well, won't matter), and supporting filters
that reset information on query (for later).
2019-09-19 20:37:05 +02:00
wm4 e1157cb6e8 video: generally try to align image data on 64 bytes
Generally, using x86 SIMD efficiently (or crash-free) requires aligning
all data on boundaries of 16, 32, or 64 (depending on instruction set
used). 64 bytes is needed or AVX-512, 32 for old AVX, 16 for SSE. Both
FFmpeg and zimg usually require aligned data for this reason.

FFmpeg is very unclear about alignment. Yes, it requires you to align
data pointers and strides. No, it doesn't tell you how much, except
sometimes (libavcodec has a legacy-looking avcodec_align_dimensions2()
API function, that requires a heavy-weight AVCodecContext as argument).

Sometimes, FFmpeg will take a shit on YOUR and ITS OWN alignment. For
example, vf_crop will randomly reduce alignment of data pointers,
depending on the crop parameters. On the other hand, some libavfilter
filters or libavcodec encoders may randomly crash if they get the wrong
alignment. I have no idea how this thing works at all.

FFmpeg usually doesn't seem to signal alignment internal anywhere, and
usually leaves it to av_malloc() etc. to allocate with proper alignment.
libavutil/mem.c currently has a ALIGN define, which is set to 64 if
FFmpeg is built with AVX-512 support, or as low as 16 if built without
any AVX support. The really funny thing is that a normal FFmpeg build
will e.g. align tiny string allocations to 64 bytes, even if the machine
does not support AVX at all.

For zimg use (in a later commit), we also want guaranteed alignment.
Modern x86 should actually not be much slower at unaligned accesses, but
that doesn't help. zimg's dumb intrinsic code apparently randomly
chooses between aligned or unaligned accesses (depending on compiler, I
guess), and on some CPUs these can even cause crashes. So just treat the
requirement to align as a fact of life.

All this means that we should probably make sure our own allocations are
64 bit aligned. This still doesn't guarantee alignment in all cases, but
it's slightly better than before.

This also makes me wonder whether we should always override libavcodec's
buffer pool, just so we have a guaranteed alignment. Currently, we only
do that if --vd-lavc-dr is used (and if that actually works). On the
other hand, it always uses DR on my machine, so who cares.
2019-09-19 20:37:05 +02:00
wm4 36dd2348a1 ta: destroy/free children in reverse order
This matters when talloc allocations set destructors. Before this
commit, destructors were called in the same order as they were added to
the parent allocations. Now it happens in reverse order.

I think this makes more sense. It's reasonable to assume that an
allocation that was added later may depend on any of the previous
allocations, so later additions should be destroyed first. (Of course
other orders are entirely possible too.)

Hopefully this doesn't fix or break anything, but I can't be sure (about
either of those). It's risky. (Then why do it?)

The destructor of a parent allocation is called before its children. It
makes sense and must stay this way, because in most cases, the
destructor wants to access the children.

This is a reason why I don't really like talloc (it wasn't my idea to
use talloc, is my excuse). Quite possible that destructors should be
removed from talloc entirely. Actually, this project should probably be
rewritten in Rust (or a better language), but that would be even more of
a pain; also, I think this is just the right level of suffering and
punishment.
2019-09-19 20:37:05 +02:00
wm4 0edccfd820 m_config: add assertion to a specific case
It seems using multiple prefixes for an option isn't supported out of
laziness (and shouldn't, because what the fuck). So assert() on this.

(Unfortunately this prefix nonsense is still needed. Especially AO and
VO options use this through the options_prefix field.)
2019-09-19 20:37:05 +02:00
wm4 ae797a21ec command: don't add deprecated CLI aliases to property list
A dumb thing that the cursed property-option bridge accidentally did.

Normal deprecated options on the other hand are fine in the property
list, because they're wanted for compatibility.
2019-09-19 20:37:05 +02:00
wm4 2f5dbaa832 options: deprecate --stream-record
It's inadequate for most uses. There are better mechanisms.
2019-09-19 20:37:05 +02:00
wm4 ad20f808af builtin.conf: add clarifications
Just in case a confused user or developer finds this file and wonders
why it's "incomplete".
2019-09-19 20:37:05 +02:00
wm4 8ffd1073a2 m_config: remove m_config_create_shadow
A previous commit changed m_config so that it always creates the shadow
thing, and the function's only remaining purpose was to initialize
mpv_global. It makes much more sense to do that at the caller, and it's
only 1 line of code too.
2019-09-19 20:37:05 +02:00
wm4 cd3394f039 m_config: further minor simplifications
Now m_config_shadow is fully independent from m_config (except for the
fact that m_config is still involved in its creation).
2019-09-19 20:37:05 +02:00
wm4 4e6ede3c53 m_config: simplify some minor crap
m_config has a m_config_option array, that is used for all option
access. The code maintaining shadow copies also tried to make use of it,
and did so by "cleverly" assigning each m_sub_options run a slice of
that array. But actually it's much simpler to, you know, directly access
the damn options.

This helps separation m_config and the general option code slightly.

Still seems to work after a superficial test, good enough.
2019-09-19 20:37:05 +02:00
wm4 059262c746 m_config: move group list to internal context
This is good because a private thing is not so public anymore, and it's
also preparation for further changes.

Some tricky memory management issues: m_config_data (i.e. config->data)
now depends on m_config_shadow, instead of m_config. In particular,
free_option_data() accesses the m_config_shadow.groups array. Obviously
it must be freed before m_config_shadow.
2019-09-19 20:37:05 +02:00
wm4 98627d3a32 io: remove Windows tmpfile() emulation
Unused now. The old stream cache used it, but it was removed.

On a side note, the demuxer cache uses mp_mkostemps(). It looks like our
Windows open() emulation handles this correctly by using CREATE_NEW, so
no functionality gets lost by the "new" approach. On the other hand, the
demuxer cache does not set FILE_FLAG_DELETE_ON_CLOSE, but instead tries
to delete the file after opening (POSIX style), which probably won't
work on Windows. But I'm not sure how to make it use the DELETE_ON_CLOSE
flag, so whatever.
2019-09-19 20:37:05 +02:00
wm4 8576374faa m_config: add/move some comments
Move the comments documenting exported functions to the header. It looks
like the header is the preferred place for that (although I don't really
appreciate headers where you lose the overview because of all the
documentation comments). Add comments to some undocumented prototypes.
2019-09-19 20:37:05 +02:00
wm4 b37a9685ad m_config: remove an unused function
This was one of those "shouldn't exist" type of functions that could
access internals that were supposed to be isolated away, but some code
needed to access it anyway.

It looks like the last use of it went away in 2016, shortly after it was
introduced.
2019-09-19 20:37:05 +02:00
wm4 e265c07547 vo: fix missed option updates under rare circumstances
Dear diary,

today I fixed a shitty bug that was all my fault because I made a
horrible mess. (Except it was a horrible mess before I even touched
this shit, but let's not blame others.)

Sometimes, updates to VO option that control video sizing (like panscan)
didn't update the screen correctly. They were delayed until the next
option change or so.

It turns out that if the option update happens at the "same" time as a
VOCTRL, update_opts() doesn't actually notify the vo_driver of the
change. This in turn happened because run_control() called
m_config_cache_update(). The latter function returns true if the options
changed since the last call, and update_opts() also calls it (on the
same config cache) for the same purpose. The update_opts() call, which
is triggered by a third mechanism, comes later, but the cache update
call will return false (as it should). Basically, given the config API,
you can't act differently on multiple update calls and expect it to
work. The skipped handling in update_opts() meant that the notification
required to apply the changed option wasn't run.

Fix this by simply calling update_opts() directly instead. Now there's
only 1 m_config_cache_update() call on this specific instance. Fix the
call in run_reconfig() too, so the previous sentence isn't a lie (but it
probably doesn't make a difference in practice due to certain details).

I'm not sure how I even ran into this sort-of race condition. The VOCTRL
that messed up the option update was VOCTRL_UPDATE_PLAYBACK_STATE, which
happens semi-regularly.

Why this config cache shit and all the other shit? Rediscovering this
crap wasn't pleasant. It's a bunch of hacks that became necessary when
the ancient MPlayer architecture made it hard to move the VO to a
separate thread.

All the VO code typically accesses vo->opts (whose fields all used to be
global variables in MPlayer). The frontend changes these on user input.
Putting locking around all the options would be a nightmare, and keeping
a copy of the options in the thread was much simpler. You need a way to
propagate option changes, notify the thread, and update the local copy
too. And the result of these thoughts was the config cache mechanism.

In this specific case, the relevant cache update call in update_opts()
triggers a VOCTRL_SET_PANSCAN to the VO driver, which isn't related to
its former function anymore. Instead, it causes the VO driver to update
the video sizing/placing options, which the generic VO code can't do.
(Mostly because the VO driver includes the windowing stuff and is
responsible for resizing etc. itself.)

VOCTRLs sent by the frontend are even worse. MPlayer had no real runtime
option change mechanism. Some options were vaguely duplicated by
properties, so you could effectively change those options at runtime.
Each of these options had its own VOCTRL, which still exist today, e.g.
VOCTRL_FULLSCREEN, or VOCTRL_ONTOP. I tried to make all options runtime
changeable, and to unify properties with options. But I couldn't be
bothered with updating all VO drivers to listen to option changes
directly, because that would be pretty tedious. So the property code is
still all there and sends the old VOCTRLs. But of course you need to
sync up the options, which is why the run_control() code did that.

(Unrelated: VO_EVENT_FULLSCREEN_STATE is the worst shithack of them all.
Currently, only the frontend can actually write to options (for awful
reasons), so if the fullscreen state changes due to outside interaction,
the VO driver can't update the corresponding option fields. So the VO
notifies the frontend with said VO_EVENT_, and the frontend then sends
VOCTRL_GET_FULLSCREEN, and updates the global copy of the option with
the value returned by that. I still like to think the situation is not
that bad considering the monstrous effort of converting single-threaded
code that had hundreds of options in global variables to multi-threaded
code with no global variables at all.)
2019-09-19 20:37:05 +02:00
wm4 82f2613ade command, demux: add AB-loop keyframe cache align command
Helper for the ab-loop-dump-cache command, see manpage additions.

This is kind of shit. Not only is this a very "special" feature, but it
also vomits more messy code into the big and already bloated demux.c,
and the implementation is sort of duplicated with the dump-cache code.
(Except it's different.) In addition, the results sort of depend what a
video player would do with the dump-cache output, or what the user wants
(for example, a user might be more interested in the range of output
audio, instead of the video).

But hey, I don't actually need to justify it. I'm only justifying it for
fun.
2019-09-19 20:37:05 +02:00
wm4 1dd0b2fe34 command: shuffle cache-dump start message
This is better?
2019-09-19 20:37:05 +02:00
wm4 f7678575a5 recorder: always mux all packets on discont/close
This is the muxer used by all 3 stream recording features (why are there
so many?). It tried hard to avoid writing broken files. In particular,
it buffered packets until it new there was a keyframe packet (which, in
mpv's/FFmpeg's definition, mean seek points from which decoding can
resume), or final EOF. The danger that was probably considered here was
that due to video frame reordering, not muxing some trailing, missing
packets of a keyframe range could lead to broken decoding or skipped
frames, so better discard packets belonging to an incomplete range.
Sounds like a good idea so far.

Unfortunately, this will drop an entire keyframe range even if the
current packet run is complete and mp_recorder_mark_discontinuity() is
called, simply because recorder.c can not know that the next packet
would have been a keyframe.

It seems better to mux all packets to avoid losing valid data, even if
it means that sometimes packets/frames will be missing from the file. It
benefits especially the dump-cache command, which will call the function
to signal a discontinuity after every range. Before this commit, it
discarded the last packets, even if they were perfectly fine.

(An alternative solution for dump-cache would have been a second
discontinuity marker function, that communicates that the current packet
range is complete. But this commit's solution is simpler and overall
more robust, at the danger of producing more semi-broken files.)

This may make some of the complex buffering/waiting logic in recorder.c
pointless.

Untested (in this final form).
2019-09-19 20:37:05 +02:00
wm4 9d97c4d814 manpage: mention that there's a Lua API for async commands
But don't tell the reader which those APIs are. Hope the user will just
search for "async" in the Lua section (lua.rst). But of course, nobody
will ever care about anything related to this.
2019-09-19 20:37:05 +02:00
wm4 023b5964b0 demux, command: add a third stream recording mechanism
That's right, and it's probably not the end of it. I'll just claim that
I have no idea how to create a proper user interface for this, so I'm
creating multiple partially-orthogonal, of which some may work better in
each of its special use cases.

Until now, there was --record-file. You get relatively good control
about what is muxed, and it can use the cache. But it sucks that it's
bound to playback. If you pause while it's set, muxing stops. If you
seek while it's set, the output will be sort-of trashed, and that's by
design.

Then --stream-record was added. This is a bit better (especially for
live streams), but you can't really control well when muxing stops or
ends. In particular, it can't use the cache (it just dumps whatever the
underlying demuxer returns).

Today, the idea is that the user should just be able to select a time
range to dump to a file, and it should not affected by the user seeking
around in the cache. In addition, the stream may still be running, so
there's some need to continue dumping, even if it's redundant to
--stream-record.

One notable thing is that it uses the async command shit. Not sure
whether this is a good idea. Maybe not, but whatever. Also, a user can
always use the "async" prefix to pretend it doesn't.

Much of this was barely tested (especially the reinterleaving crap),
let's just hope it mostly works. I'm sure you can tolerate the one or
other crash?
2019-09-19 20:37:05 +02:00
wm4 226e050b83 demux: move packet cache reading to a function
Useful for a following commit.
2019-09-19 20:37:05 +02:00
wm4 c43846f2cb screenshot: move message showing to common code
The screenshot command has this weird behavior that it shows messages
both on terminal and OSD by default, but that a command prefix can be
used to disable the OSD message.

Move this mechanism to common code, and make this available to other
commands too (although as of this commit only the screenshot commands
use it).

This gets rid of the weird screenshot_ctx.osd field too, which was sort
of set on a command, and sometimes inconsistently restored after the
command.
2019-09-19 20:37:05 +02:00
wm4 b55b9cb98c demux: move a seek helper to a separate function
It makes some slight sense and helps with one of the following commits.

Also rename that other function to make it sound less similar to
find_seek_target().
2019-09-19 20:37:05 +02:00
wm4 7893ab5a7e demux: minor simplification for backward cache size option
Always set max_bytes_bw to 0 if seekable cache is disabled, instead at
the place of its use. This is the only use of it, so the commit should
not change any behavior.

(Alternatively, this could drop the max_bytes_bw variable, use the
option directly, and keep the old code that resets it on use of the
cache is disabled.)
2019-09-19 20:37:05 +02:00
wm4 5c0a626dee demux: allow backward cache to use unused forward cache
Until now, the following could happen: if you set a 1GB forward cache,
and a 1GB backward cache, and you opened a 2GB file, it would prune away
the data cached at the start as playback progressed past the 50% mark.

With this commit, nothing gets pruned, because the total memory usage
will still be 2GB, which equals the total allowed memory usage of 1GB +
1GB.

There are no explicit buffers (every packet is malloc'ed and put into a
linked list), so it all comes down to buffer size computations. Both
reader and prune code use these sizes to decide whether a new packet
should be read / an old packet discarded. So just add the remaining free
"space" from the forward buffer to the available backward buffer. Still
respect if the back buffer is set to 0 (e.g. unseekable cache where it
doesn't make sense to keep old packets).

We need to make sure that the forward buffer can always append, as long
as the forward buffer doesn't exceed the set size, even if the back
buffer "borrows" free space from it. For this reason, always keep 1 byte
free, which is enough to allow it to read a new packet. Also, it's now
necessary to call pruning when adding a packet, to get back "borrowed"
space that may need to be free'd up after a packet has been added.

I refrained from doing the same for forward caching (making forward
cache use unused backward cache). This would work, but has a
disadvantage. Assume playback starts paused. Demuxing will stop once the
total allowed low total cache size is reached. When unpausing, the
forward buffer will slowly move to the back buffer. That alone will not
change the total buffer size, so demuxing remains stopped. Playback
would need to pass over data of the size of the back buffer until
demuxing resume; consider this unacceptable. Live playback would break
(or rather, would not resume in unintuitive ways), even normal streaming
may break if the server invalidates the URL due to inactivity. As an
alternative implementation, you could prune the back buffer immediately,
so the forward buffer can grow, but then the back buffer would never
grow. Also makes no sense.

As far as the user interface is concerned, the idea is that the limits
on their own aren't really meaningful, the purpose is merely to vaguely
restrict the cache memory usage. There could be just a single option to
set the total allowed memory usage, but the separate backward cache
controls the default ratio of backward/forward cache sizes. From that
perspective, it doesn't matter if the backward cache uses more of the
total buffer than assigned, if the forward buffer is complete.
2019-09-19 20:37:05 +02:00
wm4 e6911f82a5 demux: don't clobber internal demuxer EOF state in cache seeks
The last_eof field is the last known EOF state from the underlying
demuxer. Normally, seeks reset it, because obviously if seek back into
the middle of the file, you don't want last_eof to have a "wrong" value
for a short time window (until a packet is read, which would reset the
field to its correct value).

This shouldn't happen during cache seeks, because you don't touch the
underlying demuxer state.

At first, I made this change because some other work in progress
required it. It turned out that it was unnecessary, but keep the change
anyway, since it's still correct and makes the logic cleaner.
2019-09-19 20:37:05 +02:00
wm4 9e1945d307 win_state: silence a valgrind warning
m_geometry_apply() will read and modify the dummy variable. It's not
actually used for anything, but valgrind will still warn against
uninitialized data. I'm not sure whether this was UB, but in any case
it's annoying when running valgrind.
2019-09-19 20:37:05 +02:00
wm4 11027e99f2 packet: change memory estimation heuristics
Determining how much memory something uses is very hard, especially in
high level code (yes we call code using malloc high level). There's no
way to get an exact amount, especially since the malloc arena is shared
with the entire process anyway. So the demuxer packet cache tries to get
by with an estimate using a number of rough guesses.

It seems this wasn't quite good. In some ways, it was too optimistic, in
others it seemed to account for too much data. Try to get it closer to
what malloc and ta probably do. In particular, talloc adds some
singificant overhead (using talloc for mass-data was a mistake, and it's
even my fault). The result appears to match better with measured memory
usage. This is still extremely dependent on malloc implementation and so
on.

The effect is that you may need to adjust the demuxer cache limits to
cache as much data as it did before this commit. In any case, seems to
be better for me.
2019-09-19 20:37:05 +02:00
wm4 3cea180cc0 packet: free some unnecessary memory in disk cache case
If the disk cache is used, the AVPacket is not used anymore and is
completely deallocated when the packet is written to disk. As a minor
bug, the AVPacket allocation itself was not freed (although it wasn't a
memory leak, since talloc still automatically freed it when the entire
demux_packet was freed). For very large caches, this could easily add up
to over hundred MB, so actually free the unneeded allocation.
2019-09-19 20:37:05 +02:00
wm4 a8be8fe4f4 vd_lavc: put vaapi before vdpau in autoprobe order
--hwdec=auto-copy was preferring vdpau over vaapi. In the HEVC 10 bit
case, this also led to hardware decoding not being enabled. (Probably
because the probing can't start over after enabling hw decoding fails at
runtime, or something like that.)

Possible that this subtly breaks on some setups. You can't always win.
2019-09-19 20:37:05 +02:00
wm4 a17337910c vo_gpu: hwdec_vaegl: silence confusing message during probing
During probing on a system with AMD GPU, mpv used to output the
following messages if hardware decoding was enabled:

[ffmpeg] AVHWFramesContext: Failed to create surface: 2 (resource
allocation failed).
[ffmpeg] AVHWFramesContext: Unable to allocate a surface from internal
buffer pool.

This commit removed the message, with hopefully no other side effects.
Long explanations follow, better don't read them, it's just tedious
drivel about the details. People should learn to write concise commit
messages, not drone on and on endlessly all while they have no fucking
point.

The code probes supported hardware pixel format, and checks whether they
can be mapped as textures. av_hwdevice_get_hwframe_constraints() returns
a list of hardware pixel formats in the valid_sw_formats field (the "sw"
means software, but they're still hardware pixel formats, makes sense).
This contained the format yuv420p, even though this is not a valid
hardware format. Trying to create a surface of this type results in VA
surface creation failure, upon which FFmpeg prints the error messages
above. We'd be fine with this, except FFmpeg has a global log callback,
and there's no way to suppress these messages without creating other
issues.

It turns out that FFmpeg's vaapi implementation returns all formats from
vaQueryImageFormats() if no "hwconfig" is provided. This list includes
yuv420p, which is probably supported for surface upload/download, but
not as native format. Following FFmpeg's logic, it should not appear in
the valid_sw_formats list, because formats for transfers are returned by
another roundabout API.

Idiotically, there doesn't seem to be any vaapi call that determines
whether a format is a valid surface format. All mechanisms to do this
are bound to a VAConfigID (= video codec or video processor), all while
the actual surface creation API strangely does not take a VAConfigID (a
big WTF).

Also, calling the vaCreateSurfaces() API ourselves for probing is out of
the question, because that functions is utterly and idiotically complex.
Look at the FFmpeg code and how much effort it requires to setup a
complete set of attributes - we can't duplicate this.

So the only way left to do this is the most idiotic and tedious way:
enumerating all VAProfile (and VAEntrypoints) to create all possible
VAConfigIDs. Each of the VAConfigIDs is associated with a list of
formats, which FFmpeg can return (by passing the ID along with the
"hwconfig"), and which is probed separately.

Note that VAConfigID actually refers to a dynamic instance of something,
and creating a VAConfigID takes not only the VAProfile and the
VAEntrypoint, but also an arbitrary attribute array. In theory, this
means our attempt to get to know all possible configurations cannot
work, but in practice this attribute array seems to be pointless for
decoding and video processing, and FFmpeg doesn't use it (though the
encoding path does use it). This probably just makes it _barely_ OK to
do it this way.

Could we discard all this probing shit, and somehow do it another way?
Probably not. The EGL API for mapping surfaces doesn't even seem to
provide a way to enumerate supported formats, we may not even know
whether DRM/dmabuf interop is actually supported (AFAIR the EGL
extensions are present even if they don't work), nor do we know whether
the VAAPI driver supports this interop (not sure). So actually trying is
the only way.

Further, mpv initializes the decoder on a another thread, where you
can't just access OpenGL state. This suckage is mostly to be blamed on
OpenGL itself and its crazy thread boundedness. In theory, this could be
done anyway (see how software decoding "direct rendering" tries to get
around this). But to make it worse, the decoder never cares about the
list of supported formats determined by this code; instead,
f_autoconvert.c tries to deal with it and insert a video processor
(well, good luck with this crap, I bet it doesn't even work). So this
whole endeavor might be pointless, other than the fact that failed
probing can disable use of vaapi (which is correct and necessary). But
if you have a shovel, you don't use it to smash the flat end on the heap
of shit that's piled up before you, or do you?

While this method probably works, it's still orgasmically tedious. It
was tedious before: we had to create a real surface, create a GL
texture, map the surface with it, then destroy everything again. But the
added code is tedious on its own. Highlights include the need to malloc
a FFmpeg struct just to pass a single damn integer, the need to
enumerate "entrypoints" for each VA profile, even though all profiles
have exactly 1 entrypoint, and the kind of obnoxious way how vaapi
requires you to preallocate arrays for returned things, even they could
for example reasonably be returned as immutable arrays or have some
other simpler API.

The main grand fuckup is of course that vaapi requires a VAConfigID to
query surface properties, but not for creating surfaces. This
awkwardness even affected the FFmpeg API design, which has a "hwconfig"
concept that is only used by vaapi (vaapi is only 1 out of 10 hardware
decoding APIs supported by the FFmpeg hwcontext stuff). Maybe I'm just
missing something. It's as if vaapi required setting radioactive shit on
fire. Look how clean the native D3D11 code is instead. (Even the ANGLE
code manages to avoid being this fucked up. Or the VDPAU code, despite
supporting multiple mapping methods.)

Another only barely related change is that the valid_sw_formats field
can be NULL, and the API explicitly documents this. Technically, the mpv
code was buggy for not checking this, although until now the FFmpeg
implementation so far could not return it when we still passed NULL for
the hwconfig parameter.
2019-09-19 20:37:05 +02:00
wm4 c42a21c9fa vo_gpu: hwdec_vaegl: refactor format probing
No functional changes, just preparation for the next commit. Split the
probing into multiple functions. Prepare for the yet unused possibility
to pass AVVAAPIHWConfig to probing. try_format_pixfmt() now assumes it
can be called multiple times with the same format, so it filters the
format.

The format probing is now something like O(n^2) for n formats, but n
will most likely remain something under 50 or so.
2019-09-19 20:37:05 +02:00
wm4 f7d9365eb9 m_config: fix typo in comment 2019-09-19 20:37:05 +02:00
wm4 1b5d1adad0 recorder: use shared PTS macros
These macros explicitly honor MP_NOPTS_VALUE, instead of implicitly
relying on the fact that this value is the lowest allowed value.

In addition, this changes one case to use MP_NOPTS_VALUE instead of
INFINITY, also a cosmetic change.
2019-09-19 20:37:05 +02:00
wm4 739cd99881 demux: honor seek discontinuities with --stream-record
Do the same thing --record-file does when seeks happen.
2019-09-19 20:37:05 +02:00
wm4 b945952e0d demux: runtime option changing for cache and stream recording
Make most of the demuxer options runtime-changeable. This includes the
cache options and stream recording. The manpage documents some of the
possibly weird issues related to this.

In particular, the disk cache isn't shuffled around if the setting
changes at runtime.
2019-09-19 20:37:05 +02:00
wm4 c942178c92 m_config: add an assert for a theoretical issue
Or at least I hope it's theoretical. This function is supposed to unset
any old listeners for the given cache, and the code works only if
there's at most 1. Add a defense break to avoid UB if there's more than
one, and add an assert() to check the assumption that there's at most
one.

The added comment is unrelated.
2019-09-19 20:37:05 +02:00
wm4 8a48a277ed demux: enable --stream-record for things using timeline
Although this is not useful in general, it makes --stream-record work
with a certain video streaming service by a large dystopian company.

In the general case, this fails because normal muxing can, quite
obviously, not handle the segmented metadata in the packets. (There
isn't even a file format which could handle these, except possibly mp4.)
On the other hand, ytdl merely uses timeline/EDL to emulate DASH
streaming (unfortunately), which does not use the segmented stuff, and
stream recording will actually work.
2019-09-19 20:37:05 +02:00
wm4 943fc88989 win32: remove -municode from mpv binary
If this is used, the runtime expects that wmain() instead of main() is
defined. This caused me severe problems in a certain now irrelevant
case. I think it's a good idea to avoid this special case.

We can just use main() and call GetCommandLineW() instead. This function
returns a single string, so use CommandLineToArgvW() to split it, and
hope it has the same semantics. Should this ever return NULL, hope that
it leaves argc at 0.

Untested, I think.
2019-09-19 20:37:05 +02:00
wm4 3e22ed46b4 build: stop defining _LARGEFILE[64]_SOURCE
_LARGEFILE_SOURCE and _LARGEFILE64_SOURCE are not required for 64 bit
off_t, only _FILE_OFFSET_BITS.

See somewhere on: https://wiki.musl-libc.org/faq.html

I didn't test this anywhere except 64 bit Linux. It's probably a good
idea to test on Windows and all Android versions.
2019-09-19 20:37:05 +02:00
wm4 9fd90c549c build: better POSIX check
This is the "official" method to do this.
2019-09-19 20:37:05 +02:00
wm4 fb8d240c4d vf_vapourynth: remove Lua backend
I once created this because someone wanted to use vapoursynth without
the Python dependency. No idea if anyone ever actually used it. It's
sort of icky (it calls itself "lazy" to preempt complaints about how
much it sucks), and complicates the build process. Kill it.

It seems much more promising to have something like this:

https://github.com/vapoursynth/vapoursynth/issues/386

This would either solve the build distribution problem by relaxing the
Python dependency, and/or allow a Lua backend to be included without
pain.
2019-09-19 20:37:05 +02:00
wm4 c8b8fe9981 audio: remove unreferenced af_lavrresample
This filter wasn't referenced anywhere and thus was dead code. It should
have been in the audio filter list in user_filters.c. This was intended
as compatibility wrapper (to avoid breaking old command lines and config
files), and has no real use. Apparently I forgot to add it to the filter
list (did I even test this shit?), and so it was rotting around for 1.5
years doing nothing (just like myself).

Note that users can just use the libavfilter provided filter to force
resampling, just that it has a different name and different options.
There's also af_format to force inserting auto conversion through the
internal f_swsresample filter.
2019-09-19 20:37:05 +02:00
wm4 c6773692ad vo_gpu: remove vdpau/GLX backend
Useless garbage.

This was once added to test whether vdpau presentation feedback could be
used. Results were always unsatisfactory, and now vdpau is dead.
2019-09-19 20:37:05 +02:00
wm4 83d7123dc3 vo_gpu: remove mali-fbdev
Useless at this point, I don't even know if it still works, or how to
test it.
2019-09-19 20:37:05 +02:00
wm4 ba31c15c72 manpage: fix minor typo 2019-09-19 20:37:05 +02:00
wm4 f5d6edd4a2 stats.lua: add graphs for readahead time and total byte usage
The readahead time should be interesting for latency vs. underruns
(which idiot protocols like HLS suffer from).

The total byte usage is less interesting than I hoped; maybe the
frequency at which it samples should be reduced. (Kind of dumb - you
want high frequency for the readahead field, but much lower for byte
usage.)

Of course, the code was copy&pasted from the DS ratio/jitter stuff. Some
of the choices may not make any sense for the new code.
2019-09-19 20:37:05 +02:00
wm4 9083bbda08 msg: remove unnecessary condition
Atomics were made mandatory some time ago.
2019-09-19 20:37:05 +02:00
wm4 7b382f3acd demux_mkv: add hacks to avoid a single warning
It prints "Unexpected end of file (no clusters found)" when opening a
webm init fragment. The warning is correct, but unwanted in this case.
Add tons of kludges to avoid it.

(Actually it prints that twice, for audio and video each.)

Also, suppress another warning about a seek head entry that points
exactly to the end of the file. This is a MATROSKA_ID_CUES, which is
harmless, and, very strangely, doesn't point at any cues when you
concatenate the init fragment with a media fragment. No idea what that
crap is supposed to be.
2019-09-19 20:37:05 +02:00
wm4 c4dc600f1f demux: make webm dash work by using init fragment on all demuxers
Retarded webshit streaming protocols (well, DASH) chop a stream into
small fragments, and move unchanging header parts to an "init" fragment
to save some bytes (in the case at hand about 300 bytes for each
fragment that is 100KB-200KB, sure was worth it, fucking idiots).

Since mpv uses an even more retarded hack to inefficiently emulate DASH
through EDL, it opens a new demuxer for every fragment. Thus the
fragment needs to be virtually concatenated with the init fragment. (To
be fair, I'm not sure whether the alternative, reusing the demuxer and
letting it see a stream of byte-wise concatenated fragmenmts, would
actually be saner.)

demux_lavc.c contained a hack for this. Unfortunately, a certain shitty
streaming site by an evil company, that will bestow dytopia upon us soon
enough, sometimes serves webm based DASH instead of the expected mp4
DASH. And for some reason, libavformat's mkv demuxer can't handle the
init fragment or rejects it for some reason. Since I'd rather eat
mushrooms grown in Chernobyl than debugging, hacking, or (god no)
contributing to FFmpeg, and since Chernobyl is so far away, make it work
with our builtin mkv demuxer instead.

This is not hard. We just need to copy the hack in demux_lavf.c to
demux_mkv.c. Since I'm not _that_ much of a dumbfuck to actually do
this, remove the shitty gross demux_lavf.c hack, and replace it by a
slightly less bad generic implementation (stream_concat.c from the
previous commit), and use it on all demuxers. Although this requires
much more code, this frees demux_lavf.c from a hack, and doesn't require
adding a duplicated one to demux_mkv.c, so to the naive eye this seems
to be a much better outcome.

Regarding the code, for some reason stream_memory_open() is never meant
to fail, while stream_concat_open() can in extremely obscure situations,
and (currently) not in this case, but we handle failure of it anyway.
Yep.
2019-09-19 20:37:05 +02:00
wm4 43fc314279 stream: add a generic concat implementation
This is not available to users. It can be used only though the
stream_concat_open(). It's unused yet; to be used in the following
commit.
2019-09-19 20:37:05 +02:00
wm4 2b37f9a984 demux: never set demux->stream for timeline mess
Timeline (demux_timeline, for EDL and mkv ordered chapters) are a mess,
because it's the only nested demuxer case. Part of the mess comes from
shared struct stream pointers. This makes no sense, because the wrapper
(demux_timeline) doesn't have any business setting it.

Try to lessen it by not passing down streams. Instead, pass down NULL.
This prevents unintended interference, and tightens the ownership rules.
Now a demuxer always owns its stream.

On the other hand, demuxer->stream can now be NULL. This was never the
case before, and consequently there will be new bugs. At least they will
be spotted, because they've been bugs before.

struct stream is also used to access stream properties (such as whether
something is considered a network stream). Most of these have been
mirrored in struct demuxer (because the frontend has been forbidden to
access struct stream because of threading). But during initialization
was still used, so introduce an awkward struct parent_stream_info, which
unifies these.

Commit e0419fb181 changed demux_is_network_cached() to use
demuxer->stream->streaming instead of demuxer->is_network. To enable
timeline stuff to use the cache anyway, change it so that both flags can
contribute to it. The stream NULL-check is obviously due to changes in
this commit.
2019-09-19 20:37:05 +02:00
wm4 e40885d963 stream: create memory streams in more straightforward way
Instead of having to rely on the protocol matching, make a function that
creates a stream from a stream_info_t directly. Instead of going through
a weird indirection with STREAM_CTRL, add a direct argument for non-text
arguments to the open callback. Instead of creating a weird dummy
mpv_global, just pass an existing one from all callers. (The latter one
is just an artifact from the past, where mpv_global wasn't available
everywhere.)

Actually I just wanted a function that creates a stream without any of
that bullshit. This goal was slightly missed, since you still need this
heavy "constructor" just to setup a shitty struct with some shitty
callbacks.
2019-09-19 20:37:05 +02:00
wm4 de3ecc60cb demux_playlist: extend maximum line size
Raise it from 8KB to 512KB.

Do this because ytdl_hook.lua generated a 40KB EDL file (from 80KB
youtube-dl JSON output), and putting it into a .m3u file for easier
debugging failed due to the size limit.
2019-09-19 20:37:05 +02:00
wm4 56f09fa03d common: add macro for checking whether a value is a power of two
I think I repeated this inline in some places (or maybe not), and some
experimental but discarded code used it. Add it anyway, maybe it'll be
useful. Or it'll give someone a chance to get a contribution into mpv by
removing an unused macro.
2019-09-19 20:37:05 +02:00
wm4 4291329d56 demux: fix backward demuxing not grabbing all audio packets
The previous commit broke audio playback (maybe this is what 4. was
about?). But it wasn't the fault of the commit; it just exposed
pre-existing issues.

If the packet queue search can't get all packets, it checked
queue->is_bof to see whether there could be previous packets. But
obviously, is_bof can be set, even if the search start packet wasn't the
first one.

This was especially observable with audio, because audio by default
needs preroll packets, and plays artifacts if they're missing.

Fix by using the BOF playback condition for this purpose too.
2019-09-19 20:37:05 +02:00
wm4 f2cee22311 demux: another questionable backwards playback mud party
In theory, backward demuxing does way too much work by doing a full
cache seek every time you need to step back through a packet queue. In
theory, it would be exceedingly more efficient to just iterate backwards
through the queue, but this is not possible because I'm too stingy to
add 8 bytes per packet for backlinks. (In theory, you could probably
come up with some sort of deque, that'd allow efficient iteration into
any direction, but other requirements make this tricky, and I'm
currently too dumb/lazy to do this. For example, the queue can grow to
millions of elements, all while packet pointers need to stay valid.)

Another possibility is to "locally" seek the queue. This still has less
overhead than a full seek.

Also, it just so happens that, as a side effect, this avoids performing
range merging, which commit f4b0e7e942 "broke". That wasn't a bug at
all, but since range joining is relatively slow, avoiding it is good.
This is really just a coincidental side effect, I'm not even quite sure
why it happens this way.

There are 4 ugly things about this change:

1. To get a keyframe "before" a certain one, we recompute the target
PTS, and then subtract 0.001 as arbitrary number to "fudge" it. This
isn't the first place where this is done, and hey, it wasn't my damn
idea that MPlayer should use floats for timestamps. (At first, it even
used 32 bit timestamps.)

2. This is the first time reader_head is reset to an earlier position
outside of the seek code. This might cause conceptual problems since
this code is now "duplicated".

3. In theory, find_backward_restart_pos() needs to be run again after
the backstep. Normally, the seek code calls it explicitly. We could call
it right in the new code, but then the damn function would be recursive.
We could shuffle the code around to make it a loop, but even then
there'd be an offchance into running into an unexpected corner case (aka
subtle bug), where it would loop forever. To avoid refactoring the code
and having to think too hard about it, make it deferred - add some new
state and the check_backward_seek() function for this. Great, even more
subtle mutable state for this backwards shit.

4. I forgot this one, but I can assure you, it's bad.

Without doubt someone will have to clean up this slightly in the future
(or rip it out), but it won't be me.
2019-09-19 20:37:05 +02:00
wm4 2f64c84b44 demux: remove some redundancy in backward playback code
This code tries to determine the "current" position, which is used as
base for the seek target when it needs to seek back more (the point is
to prevent seeking back too far). But compute_keyframe_times() almost
computes the same thing, so use that. Unfortunately needs a forward
declaration.

("Almost", because it differs in some details that should not really
matter.)
2019-09-19 20:37:05 +02:00
wm4 c13bfd271c demux_mkv: fix subtitle preroll in some cases
Subtitle packets with a timestamp before the seek target may overlap
with the seek target anyway. This is why this subtitle preroll crap
exists: it needs to return packets before the seek target to ensure that
the subtitle is displayed at the seek target.

This didn't always work. Maybe it's a regression, but it must have been
an old one. The breakage is triggered by heuristic that is to prevent
excessive queuing of packets in garbage files (this heuristic apparently
became immediately necessary when this preroll mechanism was
implemented).

If a video keyframe packet was found, but no audio packet yet, then
subtitle_preroll was set to 0, and since a_skip_to_keyframe was still 0,
the subtitle packet was discarded. The dumb thing is that subtitle and
video seeking is finished at this point, so the preroll crap should not
be applied at all.

Fix this by moving the preoll overflow code into the block that handles
preroll.
2019-09-19 20:37:05 +02:00
wm4 530b203e5d osc: add feature to bottombar to not cover the video
Normally I use the OSC like this: not at all, but have a key binding
that does "cycle osc" to show it. And in that case, I don't really want
it to overlap the damn video.

I could use the zoom/pan options to move the video out of the way, but
this is also sort of annoying. Likewise, you could write a script or so
which does this automatically if the OSC appears, but that's still
annoying, and computing values for these options such that the video is
moved correctly is tricky.

So I added a bunch of options that set explicit video borders (previous
commit), and a option for the OSC to use them (this commit).

Disabled by default, since I'm afraid this is too awkward and
unpolished, especially with OSC default settings.

I'm also using "osc-visibility=always". Effectively, making the OSC
appear will box the video, and making it disappear (by unloading
osc.lua) will restore the video back to normal.
2019-09-19 20:37:05 +02:00
wm4 0b4790f23f aspect: add video margin options
Semantics a bit questionable. This is done for the OSC (next commit),
and a comment added the manpage explicitly states this. Meaning this is
probably garbage and needs to revisit when the OSC changes and/or
someone wants to use this margin feature for something else.

Not sure about the subtitle thing. It's imaginable that someone uses
these options to create empty borders for subtitles on the bottom, so
subtitles should be located there. On the other hand, this gives a
rather unpolished user experience when using the (later added) OSC
feature to not overlap with the video. There's not much of a point if
the OSC still overlaps the video. However, I'm too lazy to think about
this, so it stays like it is.
2019-09-19 20:37:05 +02:00
wm4 e1c8069b68 aspect: fix some UB problems in corner cases
--video-margin-ratio-left=0.2 --video-margin-ratio-right=0.9 (added in
the the next commit) will set f_w to inf, resulting in some garbage
being propagated. Later, the OSD margins are computed from values before
various sanity clamping is applied, which makes libass suffer from
bullshit values.

I'm very sure it's OK and more correct to compute the OSD margins using
the later values, but I'm not sure about that.
2019-09-19 20:37:05 +02:00
wm4 d34550930b stats.lua: add cache info page
Uses page 3, which was apparently reserved for filter info.
2019-09-19 20:37:05 +02:00
wm4 2575f26f2c manpage: fix false statement 2019-09-19 20:37:05 +02:00
wm4 021ccb9644 demux: turn some redundant assignments into asserts
demux_packet.next should not be used outside of demux.c, and in this
case it's a packet that was just passed to demux.c from the outside.

demux_packet.stream is already set by the demuxer, and this is assured
by the add_packet_locked() caller.
2019-09-19 20:37:05 +02:00
wm4 e320f02187 demux: move a function
The new location makes equally much sense (or more, since it's close to
its per-stream companion function), and we don't need a forward
declaration.
2019-09-19 20:37:05 +02:00
wm4 95c97cd66e demux: disable backward demuxing if it fatally fails
We don't care much about this case, because backward playback can fail
terribly without a good way to detect it, so this was fine.

However, this froze in certain situations. Reading from a subtitle file
for which backward demuxing failed could make it get stuck in
demux_read_packet_async() in unthreaded mode. (That we don't support
backwards subtitle decoding anyway doesn't matter for this.)

So aggressively disable backward demuxing to prevent worse in these
situations. The behavior will still be awful, because the frontend is
still in backwards playback mode, but at least it won't freeze.
2019-09-19 20:37:05 +02:00
wm4 17da9071a4 demux: add a on-disk cache
Somewhat similar to the old --cache-file, except for the demuxer cache.
Instead of keeping packet data in memory, it's written to disk and read
back when needed.

The idea is to reduce main memory usage, while allowing fast seeking in
large cached network streams (especially live streams). Keeping the
packet metadata on disk would be rather hard (would use mmap or so, or
rewrite the entire demux.c packet queue handling), and since it's
relatively small, just keep it in memory.

Also for simplicity, the disk cache is append-only. If you're watching
really long livestreams, and need pruning, you're probably out of luck.
This still could be improved by trying to free unused blocks with
fallocate(), but since we're writing multiple streams in an interleaved
manner, this is slightly hard.

Some rather gross ugliness in packet.h: we want to store the file
position of the cached data somewhere, but on 32 bit architectures, we
don't have any usable 64 bit members for this, just the buf/len fields,
which add up to 64 bit - so the shitty union aliases this memory.

Error paths untested. Side data (the complicated part of trying to
serialize ffmpeg packets) untested.

Stream recording had to be adjusted. Some minor details change due to
this, but probably nothing important.

The change in attempt_range_joining() is because packets in cache
have no valid len field. It was a useful check (heuristically
finding broken cases), but not a necessary one.

Various other approaches were tried. It would be interesting to list
them and to mention the pros and cons, but I don't feel like it.
2019-09-19 20:37:05 +02:00
wm4 ef507ad50a osdep: add mkostemps() emulation
Supposed to follow the standard function.

The standard function is not standard, but a GNU extension. Adding some
ifdef mess is pointless too - it has no advantages other than having a
mess, and not spotting implementation bugs in the emulation due to
running it only on "obscure" platforms (like Windows, so most computers
actually, except the developer's platform).

There is mkstemp(), which at least is in POSIX 2008. But it's 100%
useless, except in some obscure cases: it doesn't set O_CLOEXEC, nor can
you pass it to it. Without O_CLOEXEC, we'd leak the temporary file to
all child processes. (The fact that the file, which is expected to reach
double or tripple digit GB sizes, will be deleted only once all
processes unreference the FD, makes this sort of a big deal. You could
ftruncate() it, but that doesn't fix all the other problems.)

Why did POSIX standardize mkstemp() and O_CLOEXEC apparently at the same
time, but provided no way to pass O_CLOEXEC to mkstemp()? With the
introduction of O_CLOEXEC, they acknowledged that there's a need to
atomically set the FD_CLOEXEC flag when creating file descriptors.
(FD_CLOEXEC was standard before that, but setting it with fcntl() is
racy.) You're much more likely to need a temp file that is CLOEXEC
rather than the opposite, and even if they were somehow opposed to
CLOEXEC by default (such as for compat. reasons), surely POSIX could
have standardized mkostemp() too or instead.

And then there's the fact that this whole O_CLOEXEC mess is stupid.
Surely there would have been a better way to handle this, instead of
requiring adding O_CLOEXEC to almost ALL instances of open() in all code
that has been written ever. The justification for this is that the
historic default was wrong, and you can't change it (e.g. this won't
work: changing the behavior of exec() and not inherit the FD to the
child process, unless a hypothetical O_KEEP_EXEC flag is set).

But on the other hand, surely you could have introduced an exec()
variant which does close all FDs, except a whitelist of FDs passed to
it. Let's call it execve2(). In fact, I'm going to argue that exec()
call sites are the most aware of whether (and which) FDs to inherit.
Some programs even tried to explicitly iterate over all opened FDs and
explicitly close "unwanted" FDs (which of course was problematic for
other reasons), and such an execve2() call would have been the ideal
solution.

Maybe this proposed solution would have had problems too. But surely
revisiting and reviewing every exec*() call would have been simpler than
reviewing every open() call. And more importantly, having to extend
every damn library function that either calls open() or creates FDs in
some other way, like mkstemp().

What argument are there going to be against this? That there will be
library code that can't keep working correctly with processes that use
the "old" exec? Well, what about all my legacy library code that uses
open() incorrectly, and that will break no matter what?

Well, I'm not going to claim that I can come up with better solutions
than POSIX (generally or in this case), but this situation is ABSOLUTELY
ATROCIOUS. It makes win32 programming look attractive compared to POSIX,
that standard pandering to dead people from the past. (Note: not trying
to insult dead people.)

I'm not sure what POSIX is even doing. Anything useful? Doesn't look
like it to me. Are they paid? Why? They didn't even fix the locale mess,
nor do they intend to. I bet they're proud of discussing compatibility
to 70ies code day in and day out iwtohut ever producing anything useful.
What a load of crap. They seriously got to do better than this.

Oh, and my wrapper is probably buggy. Fortunately that doesn't matter.
Also I'm dumping this into io.h. Originally, io.h was just supposed to
replace broken implementation of standard functions by MinGW (and then
by Android), but whatever, just give a dumping ground for shit code.
2019-09-19 20:37:05 +02:00
wm4 2e3d3bbfc8 demux: move comment to slightly better location 2019-09-19 20:37:05 +02:00
wm4 e8ff816ccd demux: fix excessive backwards seeking with backwards playback
Backwards demuxing usually seeks back back by a "random" amount (set by
a user option) when it needs new preceding packets. It turns out a past
change made these backwards seek amounts add up when it didn't need to
(i.e. subtracting the amount from the seek pos without properly
resetting it), which could possibly slow down playback as it went on.

The reason for this was that back_seek_pos was set for every stream on
every seek. This made the reset not affect other streams (in particular
streams which weren't used and never were reset, or which didn't reset
that often). But as the commit adding it showed, this is needed only to
set the initial position. So do that.

Fixes: "demux: fix initial backward demuxing state in some cases"
2019-09-19 20:37:05 +02:00
wm4 73a48ff47b demux: fix minor seek_preroll consistency issue
When packet appending sets the start of the range, it adjusts the range
by seek_preroll. Do this when packets are pruned from the start of the
range too.

(Yeah, seek_preroll handling is probably broken in some other cases. It
was halfhearted to begin with.)
2019-09-19 20:37:05 +02:00
wm4 0f6cda4ab1 demux: mess with seek range updates and pruning
The main thing this commit does is removing demux_packet.kf_seek_pts. It
gets rid of 8 bytes per packet. Which doesn't matter, but whatever.

This field was involved with much of seek range updating and pruning,
because it tracked the canonical seek PTS (i.e. start PTS) of a packet
range. We have to deal with timestamp reordering, and assume the start
PTS is the lowest PTS across all packets (not necessarily just the first
packet). So knowing this PTS requires looping over all packets of a
range (no, the demuxer isn't going to tell us, that would be too sane).

Having this as packet field was perfectly fine. I'm just removing it
because I started hating extra packet fields recently.

Before this commit, this value was cached in the kf_seek_pts field (and
computed "incrementally" when adding packets). This commit computes the
value on demand (compute_keyframe_times()) by iterating over the placket
list. There is some similarity with the state before 10d0963d85,
where I introduced the kf_seek_pts field - maybe I'm just moving in
circles. The commit message claims something about quadratic complexity,
but if the code before that had this problem, this new commit doesn't
reintroduce it, at least. (See below.)

The pruning logic is simplified (I think?) - there is no "incremental"
cached pruning decision anymore (next_prune_target is removed), and
instead it simply prunes until the next keyframe like it's supposed to.
I think this incremental stuff was only there because of very old code
that got refactored away before. I don't even know what I was thinking
there, it just seems complex. Now the seek range is updated when a
keyframe packet is removed.

Instead of using the kf_seek_pts field, queue->seek_start is used to
determine the stream with the lowest timestamp, which should be pruned
first. This is different, but should work well. Doing the same as the
previous code would require compute_keyframe_times(), which would
introduce quadratic complexity.

On the other hand, it's fine to call compute_keyframe_times() when the
seek range is recomputed on pruning, because this is called only once
per removed keyframe packet. Effectively, this will iterate over the
packet list twice instead of once, and with some locality. The same
happens when packets are appended - it loops over the recently added
packets once again. (And not more often, which would go above linear
complexity.)

This introduces some "cleverness" with avoiding calling
update_seek_ranges() even when keyframe packets added/removed, which is
not really tightly coupled to the new code, and could have been in a
separate commit.

Removing next_prune_target achieves the same as commit b275232141,
which is hereby reverted (stale is_bof flags prevent seeking before the
current range, even if the beginning of the file was pruned). The seek
range is now strictly computed after at least one packet was removed,
and stale state should not be possible anymore.

Range joining may over-allocate the index a little. It tried hard to
avoid this before by explicitly freeing the old index before creating a
new one. Now it iterates over the old index while adding the entries to
the new one, which is simpler, but may allocate twice the memory in the
worst case. It's not going to matter for anything, though.

Seeking will be slightly slower. It needs to compute the seek PTS values
across all packets in the vicinity of the seek target. The previous code
also iterated over these packets, but now it iterates one packet range
more.

Another minor detail is that the special seeking code for SEEK_FORWARD
goes away. The seeking code will now iterate over the very last packet
range too, even if it's incomplete (i.e. packets are still being
appended to it). It's fine that it touches the incomplete range, because
the seek_end fields prevent that anything particularly incorrect can
happen. On the other hand, SEEK_FORWARD can now consider this as seek
target, which the deleted code had to do explicitly, as kf_seek_pts was
unset for incomplete packet ranges.
2019-09-19 20:37:05 +02:00
wm4 e8ec271859 demux: fix a comment
Obviously doesn't sense with this order. The git history shows that this
comment was touched multiple times, without ever fixing it. It was
originally added in 2016, where the "for" was missing. Later, the "for"
was added, but to the wrong position.

What the fuck?
2019-09-19 20:37:05 +02:00
wm4 628abf53d1 demux: cache a value
Just for readability purposes. Although the field is mutable, it never
changes within the function.
2019-09-19 20:37:05 +02:00
wm4 aa03ee7300 demux: redo timed metadata
The old implementation didn't work for the OGG case. Discard the old
shit code (instead of fixing it), and write new shit code. The old code
was already over a year old, so it's about time to rewrite it for no
reason anyway.

While it's true that the old code appears to be broken, the main reason
to rewrite this is to make it simpler. While the amount of code seems to
be about the same, both the concept and the actual tag handling are
simpler. The result is probably a bit more correct.

The packet struct shrinks by 8 byte. That fact that it wasted 8 bytes
per packet for a rather obscure use case was the reason I started this
at all (and when I found that OGG updates didn't work). While these 8
bytes aren't going to hurt, the packet struct was getting too bloated.
If you buffer a lot of data, these extra fields will add up. Still quite
some effort for 8 bytes. Fortunately, it's not like there are any
managers that need to be convinced whether it's worth doing. The freedom
to waste time on dumb shit.

The old implementation attached the current metadata to each packet.
When the decoder read the packet, the packet's metadata was made
current. The new implementation stores metadata as separate list, and
requires that the player frontend tells it the current playback time,
which will be used to find the currently valid metadata. In both cases,
the objective was to correctly update metadata even if a lot of data is
buffered ahead (and to update them correctly when seeking within the
demuxer cache).

The new implementation is actually slightly more correct, because it
uses the playback time for the metadata lookup. Consider if you have an
audio filter which buffers 15 seconds (unfortunately such a filter
exists), then the old code would update the current title 15 seconds too
early, while the new one does it correctly.

The new code also simplifies mixing the 3 metadata sources (global, per
stream, ICY). We assume these aren't mixed in a meaningful way. The old
code tried to be a bit more "exact". I didn't bother to look how the old
code did this, but the new code simply always "merges" with the previous
metadata, so if a newer tag removes a field, it's going to stick around
anyway.

I tried to keep it simple. Other approaches include making metadata a
special sh_stream with metadata packets. This would have been
conceptually clean, but the implementation would probably have been
unnatural (and doesn't match well with libavformat's API anyway). It
would have been nice to make the metadata updates chapter points (makes
a lot of sense for the intended use case, web radio current song
information), but I don't think it would have been a good idea to make
chapters suddenly so dynamic. (Still an idea to keep in mind; the new
code actually makes it easier to work towards this.)

You could mention how subtitles are timed metadata, and actually are
implemented as sparse packet streams in some formats. mp4 implements
chapters as special subtitle stream, AFAIK. (Ironically, this is very
not-ideal for files. It would be useful for streaming like web radio,
but mp4 is extremely bad for streaming by design for other reasons.)

bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
2019-09-19 20:37:05 +02:00
wm4 27fcd4ddc6 demux_lavf: compensate timestamp resets for OGG web radio streams
Some OGG web radio streams use timestamp resets when a new song starts
(you can find those Xiph's directory - other streams there don't show
this behavior). Basically, the OGG stream behaves like concatenated OGG
files, and "of course" the timestamps will start at 0 again when the
song changes. This is very inconvenient, and breaks the seekable demuxer
cache. In fact, any kind of seeking will break

This is more time wasted in Xiph's bullshit. No, having timestamp resets
by design is not reasonable, and fuck you. I much prefer the awful
ICY/mp3 streaming mess, even if that's lower quality and awful. Maybe it
wouldn't be so bad if libavformat could tell us WHERE THE FUCK THE RESET
HAPPENS. But it doesn't, and the randomly changing timestamps is the
only thing we get from its API.

At this point, demux_lavf.c is like 90% hacks. But well, if libavformat
applies this strange mixture of being clever for us vs. giving us
unfiltered garbage (while pretending it abstracts everything, and hiding
_useful_ implementation/low level details), not much we can do.

This timestamp linearizing would, in general, probably be better done
after the decoder, because then we wouldn't need to deal with timestamp
resets. But the main purpose of this change is to fix seeking within the
demuxer cache, so we have to do it on the lowest level.

This can probably be applied to other containers and video streams too.
But that is untested. Some further caveats are explained in the manpage.
2019-09-19 20:37:05 +02:00
wm4 cb82a206a9 demux_lavf: add per-stream state
Seems like this will be useful later.
2019-09-19 20:37:05 +02:00
wm4 91abd7a4f7 demux_lavf: use common mpv/ffmpeg timestamp conversion function
Probably doesn't change anything, other than looking slightly better. In
theory, the common function has some stuff that makes it more likely
that timestamps round-trip through conversions properly, but I didn't
confirm that.
2019-09-19 20:37:05 +02:00
wm4 4e4949b4dc audio_buffer: fix some more theoretical UB
This may call memmove() with size==0 and a NULL data pointer. In
addition to this being UB with memmove(), I think it's UB to do
arithmetic on a NULL pointer too. Of course, this doesn't matter in
practice at all, and is just stupidity to torture programmers.
2019-09-19 20:37:05 +02:00
wm4 fae31f39c7 demux: refactor cache range init/deinit
Remove the duplicated creation of the first range. Explicitly destroy
ranges, including the last one on final deinit.

It looks like this also fixes a leak of removed range structs, which was
never noticed because they're so small, and were freed on final deinit
due to having the demuxer as talloc parent.

This improves upon the previous commit too (that change should have
been part of it I guess). Sub-demuxers (demux_timeline only) now
automatically don't use the cache (like it was intended by the previous
commit). The cache is "initialized" (or disabled) last in the recursive
call chain, which is messy, but this sub demuxer stuff FUCKING SUCKS, as
mentioned in the previous commit message. This would be no problem if
the caching layer and actual demuxer implementations were separate.

Most of this change has no purpose. Might make (de-)initialization of
further cache exerpiments simpler.
2019-09-19 20:37:05 +02:00
wm4 e8147843fc demux: really disable cache for sub-demuxers
It seems the so called demuxer cache wasn't really disabled for
sub-demuxers (timeline stuff). This was relatively harmless, since the
actual packet data was shared anyway via refcounting. But with the
addition of a mmap cache backend, this may change a lot.

So strictly disable any caching for sub-demuxers. This assumes that
users of sub-demuxers (only demux_timeline.c by now?) strictly use
demux_read_any_packet(), since demux_read_packet_async() will require
some minor read-ahead if a low level packet read returned a packet for a
different stream.

This requires some awkward messing with this fucking heap of trash. The
thing that is really wrong here is that the demuxer API mixes different
concepts, and sub-demuxers get the same API as decoders, and use the
cache code.
2019-09-19 20:37:05 +02:00
wm4 5d6b7c39ab demux: handle accounting for index size differently
The demuxer cache tries to track the number of bytes allocated for the
cache. In addition to the packet queue, the seek index is another data
structure that roughly depends on the amount of packets cached. So the
index size should somehow be part of the total number of bytes tracking.

Until now, this was handled with KF_SEEK_ENTRY_WORST_CASE, basically a
shitty heuristic. It was a guess (and probably rather an upper bound
than a lower bound). The implementation details made it annoying, and it
was conceptually inaccurate too.

Change this, and instead simply add the index size to the total cache
size. This essentially makes it part of the backbuffer. It's nice that
this cleanly decouples it from the packet size tracking itself.

Since it's part of the backbuffer number of bytes now, packet pruning
can't necessarily free enough space in the backbuffer anymore. Before
this commit, the backbuffer consisted of packets only, so it was
possible to reduce its size to 0 by pruning all packets until the
decoder reader position, at which point a packet was accounted as
forward buffered. Now the index is added to this, and it can't be
pruned. Replace the assert() because of this changed invariant.
2019-09-19 20:37:05 +02:00
wm4 b45c17e5a9 m_option: add "B" suffix to human-readable byte numbers
The conversion to string as the pretty printer returns it is
sometimes used on OSD. I think it's pretty odd that quantities below 1
KB are shown as number without suffix. So use "B" for them.

For orthogonality, allow the same for parsing. (Although strictly
speaking, this is not a requirement of the option API. Option parsers
don't need to accept pretty-printed strings.)
2019-09-19 20:37:05 +02:00
wm4 46247df6e5 common: add MP_IS_ALIGNED macro 2019-09-19 20:37:05 +02:00
wm4 7c356ee836 packet: change len field from int to size_t
Why not. struct demux_packet doesn't change on 64 bit size due to
alignment padding.
2019-09-19 20:37:05 +02:00
wm4 b9250569cd demux: fix assertion when switching tracks during backward playback
Someone who rams a knife into his own hand just to see what happens is
normally put in a psychiatric ward. But in software, this is acceptable
behavior. Programs are not supposed to crash just because a user did
something unreasonably dumb.

Switching tracks during backward playback is such a thing. It triggered
an assertion because the newly enabled stream was not properly
initialized for backward playback. Fix this, and make it actually work
(mostly; it still takes a "while" until playback recovers fully).

This actually makes some aspects of initialization slightly cleaner.
2019-09-19 20:37:05 +02:00
wm4 60a0db39aa player: ensure backward playback state is propagated on track switching
Track switching doesn't run reset_playback_state(), so a track enabled
at runtime during backward playback would lead to a messed up state.

This commit just does a bad code monkey fix to this. It feels like there
needs to be a much better way to propagate this state.
2019-09-19 20:37:05 +02:00
wm4 911718c413 demux: use binary search for cache seek index
Not sure if this is bug-free. You _always_ make bugs when writing a
binary search from scratch (and such is the curse of C, though if I did
this in C++ it would probably end in blood). It seems to work though,
checking against the normal linear search.

It's slightly faster. Not much.

I wonder if the termination condition can be written in a nicer/elegant
way. I guess the fact that it's not a == predicate makes this slightly
messier?
2019-09-19 20:37:05 +02:00
wm4 1f13bd0942 demux: create full seek index for cached packets
The purpose of the seek index is to avoid having to iterate over the
full linked list of cached packets, which should speed up seeking. Until
now, there was an excuse of a seek index, that didn't really work.

The idea of the old index was nice: have a fixed number of entries (no
need to worry about exceeding memory requirements), which are
"stretched" out as the cache gets bigger. The size of it was 16 entries,
which in theory should speed up seeking by the factor 16, given evenly
spaced out entries. To achieve this even spacing, it attempted to "thin
out" the index by half once the index was full (see e.g. index_distance
field). In my observations this didn't really work, and the distribution
of the index entries was very uneven. Effectively, this did nothing. It
probably worked once and I can't be assed to debug my own shit code.
Writing new shit code is more fun.

Write new shit code for fun. This time it's a complete index. It's kept
in a ringbuffer (for easier LIFO style appending/removing), which is
resized with realloc if it becomes too small.

Actually, the index is not completely completely; it's still "thinned
out" by a hardcoded time value (INDEX_STEP_SIZE). This should help with
things like audio or crazy subtitle tracks (do they still create
those?), where we can just iterate over a small part of the linked
packet list to get the exact seek position. For example, for AAC audio
tracks with typical samplerates/framesizes we'd iterate about 50 packets
in the linked list.

The results are good. Seeking in large caches is much faster now,
apparently at least 1 or 2 orders of magnitude. Part of this is because
we don't need to touch every damn packet in a huge linked list (bad
cache behavior - the index is a linear memory region instead), but
"thinning" out the search space also helps. Both aspects can be easily
tested (setting INDEX_STEP_SIZE to 0, and replacing e->pts with
e->pkt->kf_seek_pts in find_seek_target()).

This does use more memory of course. In theory, we could tolerate memory
allocation failures (the index is optional and only for performance),
but I didn't bother and inserted an apologetic comment instead, have fun
with the shit code). the memory usage doesn't seem to be that bad,
though. Due to INDEX_STEP_SIZE it's bounded by the file duration too.

Try to account for the additional memory usage with an approximation
(see KF_SEEK_ENTRY_WORST_CASE). It's still a bit different, because the
index needs a single, potentially large allocation.
2019-09-19 20:37:05 +02:00
wm4 aa275b2f0c demux: simplify cache search and exit early
The search was slightly more complicated and slow than it had to be. It
didn't assume that the packet list was sorted, which is responsible for
much of this. (I think the search code was borrowed from demux_mkv.c,
which does not sort index entries.)

There was a half-hearted attempt to make it exit early, but it was
mostly ineffective.

Simplify the code based on the assumption that the list is sorted. This
will exit the search loop once the worst case candidate entry was
checked.
2019-09-19 20:37:05 +02:00
wm4 c0014e2f93 demux: update some comments
Mostly about the packet queue and the subtitle handling of it.

(This mess sure sounds like a good argument to give up the separate
stream queues, and using a single packet queue per cached range.)
2019-09-19 20:37:05 +02:00
wm4 a0d59a9a15 demux: shorten some redundant output
This message would always show "correct_dts=0 correct_pos=0".
2019-09-19 20:37:05 +02:00
wm4 277ab02f38 command: show number of hidden items in OSD lists
Affects the "classic" OSD rendering of some properties, like playlists.
2019-09-19 20:37:05 +02:00
wm4 7ed4d77a97 manpage: some more backward playback edits 2019-09-19 20:37:05 +02:00
wm4 f439064e7f demux: demux multiple audio frames in backward playback
Until now, this usually passed a single audio frame to the decoder, and
then did a backstep operation (cache seek + frame search) again. This is
probably not very efficient, especially considering it has to search the
packet queue from the "start" every time again.

Also, with most audio codecs, an additional "preroll" frame was passed
first. In these cases, the preroll frame would make up 50% of audio
decoding time. Also not very efficient.

Attempt to fix this by returning multiple frames at once. This reduces
the number of backstep operations and the ratio the preoll frames. In
theory, this should help efficiency. I didn't test it though, why would
I do this? It's just a pain. Set it to unscientific 10 frames.
(Actually, these are 10 keyframes, so it's much more for codecs like
TrueHD. But I don't care about TrueHD.)

This commit changes some other implementation details. Since we can
return more than 1 non-preroll keyframe to the decoder, some new state
is needed to remember how much. The resume packet search is adjusted to
find N ("total") keyframe packets in general, not just preroll frames.
I'm removing the special case for 1 preroll packet; audio used this, but
doesn't anymore, and it's premature optimization anyway.

Expose the new mechanism with 2 new options. They're almost completely
pointless, since nobody will try them, and if they do, they won't
understand what these options truly do. And if they actually do, they
most likely would be capable of editing the source code, and we could
just hardcode the parameters. Just so you know that I know that the
added options are pointless.

The following two things are truly unrelated to this commit, and more
like general refactoring, but fortunately nobody can stop me.

Don't set back_seek_pos in dequeue_packet() anymore. This was sort of
pointless, since it was set in find_backward_restart_pos() anyway (using
some of the same packets). The latter function tries to restrict this to
the first keyframe range though, which is an optimization that in theory
might break with broken files (duh), but in these cases a lot of other
things would be broken anyway.

Don't set back_restart_* in dequeue_packet(). I think this is an
artifact of the old restart code (cf. ad9e473c555). It can be done
directly in find_backward_restart_pos() now. Although this adds another
shitty packet search loop, I prefer this, because clearer what's
actually happening.
2019-09-19 20:37:05 +02:00
wm4 e62afe4055 demux: remove further calls to packet size estimation function
May as well be part of the previous commit.
2019-09-19 20:37:05 +02:00
wm4 976ee96e45 demux: don't loop over all packets to find forward buffered size on seek
The size of all forward buffered packets is used to control maximum
buffering.

Until now, this size was incrementally adjusted, but had to be
recomputed on seeks within the cache. Doing this was actually pretty
expensive. It iterates over a linked list of separate memory allocations
(which are probably spread all over the heap due to the allocation
behavior), and the demux_packet_estimate_total_size() call touches a lot
of further memory locations. I guess this affects the cache rather
negatively. In an unscientific test, the recompute_buffers() function
(which contained this loop) was responsible for roughly half of the time
seeking took.

Replace this with a way that computes the buffered size between 2
packets in constant times. The demux_packet.cum_pos field contains the
summed sizes of all previous packets, so subtracting cum_pos between two
packets yields the size of all packets in between. We can do this
because we never remove packets from the middle of the queue. We only
add packets to the end, or remove packets at the beginning.

The tail_cum_pos field is needed because we don't store the end position
of a packet, so the last packet's position would be unknown. We could
recompute the "estimated" packet size, or store the estimated size in
the packet struct, but I just didn't like this.

This also removes the cached fw_bytes fields. It's slightly nicer to
just recompute them when needed. Maintaining them incrementally was
annoying. total_size stays though, since recomputing it isn't that cheap
(would need to loop over all ranges every time).

I'm always using uint64_t for sizes. This is certainly needed (a stream
could easily burn through more than 4GB of data, even if much less of
that is cached). The actual cached amount should always fit into size_t,
so it's casted to size_t for printfs (yes, I hate the way you specify
stdint.h types in printfs, the less I have to use that crap, the
better).
2019-09-19 20:37:05 +02:00
wm4 e7db262450 demux: remove tracking of number of forward buffered packets
In ancient times, the number of packets was used to limit excessive
read-ahead. This was completely replaced by tracking the size in bytes.
The number of packets was used in debugging output only.

In one case (packet got demuxed and is added to a queue), only log
whether there were packets on this stream before. (Unknown whether it's
useful.)

In another case (queue overflow), actually count the number of packets.
It's vaguely useful, and the message with the number of packets is shown
only once after a seek reset, so it doesn't matter whether it's slow.
2019-09-19 20:37:05 +02:00
wm4 aacc868bdd f_decoder_wrapper: fix initialization state
Some state wasn't reset when decoding was started without a seek reset
before it. The code used to rely on reset_decoder() resetting this
state, but since the commit referenced below, reset_decoder() does less
than reset().

Fix this by explicitly calling reset() on initialization.

Fixes: "f_decoder_wrapper: avoid full reset on timeline switch etc."
2019-09-19 20:37:05 +02:00
wm4 be0878e121 demux: fix backward demuxing freeze if first packet is not a keyframe
Some files don't start with keyframe packets. Normally, this is not
sane, but the sample file which triggered this was a cut TV capture
transport stream. And this shouldn't happen anyway.

Introduce a further heuristic: if the last seek target was before the
start of the cached data, and the start of the cache is marked as BOF
(beginning of file), then we won't find anything better. This is
possibly a bit shaky, because both seek_start and back_seek_pos weren't
made for this purpose. But I can't come up with situations where this
would actually break. (Leave this to shitty broken files I hit later.)

I also considered finding the first packet in the cache that is marked
as keyframe, i.e. the first actual seek target, and comparing it to
"first", but I didn't like it much. Well whatever.

It's a bit silly that this caused a hard freeze (and similar issues
still will). The problem is that the demuxer holds the lock and has no
reason to release it. And in general, there's a single lock for the
entire demuxer cache. Finer grained locking would probably not make much
sense. In theory status of available data and maybe certain commands to
the demuxer could be moved to separate locks, but it would raise
complexity, and you'd probably still need to get the central lock in
some cases, which would deadlock you anyway.

It would still be nice if some minor corner case in the wonderfully
terrible and complex backward demuxer state machine couldn't lock up the
player. As a hack, unlock and then immediately lock again. Depending on
the OS mutex implementation, this may give other waiters a chance to
grab the lock. This is not a guarantee (some OSes may for example not
wake up other waiters until the next time slice or something), but works
well on Linux.
2019-09-19 20:37:05 +02:00
wm4 9c32997c65 demux: simplify and improve performance of backward playback stepping
The step_backwards function set reader_head to the start of the current
cache range. This was completely unnecessary and made it _much_ slower.
Remove the code that adjusts reader_head. Merge the rest of the code
into the only caller and remove the function.

The comment on the removed code was quite right. It was "inefficient".
Removing it delegates going to an early position to the normal seek
code, triggered by find_backward_restart_pos() incremental back seek
logic. I suppose especially audio benefits from this, because this
happens for every single audio packet (except maybe freaky bullshit like
TrueHD, which has "keyframes").

The blabla about performance in the removed comments is still true, but
now applies to the seek code itself only.
2019-09-19 20:37:05 +02:00
wm4 d25fbb0813 demux: fix backward playback at EOF with full demuxer cache
Fixes "mpv file.mkv --cache --demuxer-cache-wait --play-dir=backward",
and other situations where the demuxer cache contains the entire file,
and playback is to start from the end. It also can be triggered when
starting playback normally with --cache, and once everything is in the
cache, enabling backward playback and seeking past EOF.

In all cases, the cache seek will set reader_head=NULL (because you
seeked to/past EOF). Then the code (the one modified by this commit)
sees that ds->queue->is_bof==true, and thinks we've reached BOF
(beginning of file) while searching for a useful packet, i.e. we found
nothing and playback really can only end.

Obviously this is nonsense, we've found only nothing if we actually
searched from the beginning, not some "random" reader_head (== first)
value that does not include the entire cache. That means the condition
should trigger only if the start of the search (first variable) points
to the beginning of the cache (ds->queue->head).

Not taking this if means we'll seek to an earlier position and retry.
Also, a seek before the beginning of the cache will always end up with
reader_head==ds->queue->head, i.e. we'll terminate properly.

That comment was quite right.
2019-09-19 20:37:05 +02:00
wm4 a88b7bf0fc manpage: another comment on backward playback with hardware decoding 2019-09-19 20:37:05 +02:00
wm4 165799157d vd_lavc: add --hwdec-extra-frames option
Surprised this didn't exist before.
2019-09-19 20:37:05 +02:00
wm4 e8a051b3cb f_decoder_wrapper: reorganize, fix EDL/ordered chapters backward playback
Before this commit, there was a single process_decoded_frame() function.
It handled various aspects of dealing with a newly decoded frame. Move
some of these to a separate process_output_frame() function.

This new function is called in the order the frames are returned to the
playback core. Some correct_audio_pts() (was process_audio_frame())
becomes slightly less awkward due to this, and the timestamp smoothing
can actually work in backward playback mode now (thus moving p->pts out
of reset_decoder()).

Behavior for normal playback also changes subtly. This shouldn't matter
in sane cases, but if you mix broken files, --no-correct-pts, and
timeline stuff, differences in behavior might be visible.

Timeline clipping (EDL/ordered chapters) works now, because it's done
before "transforming" the timestamps. Audio timestamp smoothing happens
after it, which is a behavior change, but should be more correct. This
still runs crazy_video_pts_stuff() before everything else. On the pther
hand, --no-correct-pts or missing timestamp processing is done last. But
these things didn't really work with timeline before.
2019-09-19 20:37:05 +02:00
wm4 d55c2a1243 f_decoder_wrapper: avoid full reset on timeline switch etc.
Slightly cleaner. We don't need to awkwardly backup "some" state on
backwards playback. Due to not resetting last_format, normal timeline
switches don't unconditionally trigger recomputing of certain image
parameters. Also probably doesn't reset framedrop parameters, although I
don't care about that part.
2019-09-19 20:37:05 +02:00
wm4 ea5c15874a f_decoder_wrapper: fully reset timestamp fixup logic on seeks
This could lead to nonsense when backward playback is involved. Better
reduce the possible interactions. Besides, it's better to fully reset
things on seeks in general.

The only exception is has_broken_packet_pts, which enables hr-seek if
everything looks good. It's intended to trigger at the second hr-seek or
so if the file is normal, and to disable it if the file is broken. It
tries to avoid enabling the hr-seek logic before it can know about
whether things are "good", so resetting it on seeks would obviously
never enable it. Document it as explicit exception.
2019-09-19 20:37:05 +02:00
wm4 e86a0df52e f_decoder_wrapper: move option update to a common entrypoint
process() calls these functions. It's a much better place to potentially
copy changed option values into the cache struct.
2019-09-19 20:37:05 +02:00
wm4 0c5df2965e options: rename --play-direction to --play-dir
And add simpler aliases for the modes.

I'm not sure how to name things, and the option list is in general full
of different conventions. Some names are shortened, some are explicit
and long.

I guess options that have a chance to be used normally (i.e. not obscure
tuning or debugging) should have a short and convenient names.

In this specific case, play-direction is like a mixture of both. It
should be either playback-direction or play-dir, not shorten one word
but not the other.

The convenience aliases are because I got sick of typing out "backward".
I guess "back" would also do it, but there's no proper antonym (and
maybe it's "wrong" in the strict sense of the word).
2019-09-19 20:37:05 +02:00
wm4 8812530b31 demux: more backwards playback preroll packets for vorbis and mp3
Together with the previous commit, this seems to make backward playback
work in files with vorbis and mp3 audio codecs.

For Vorbis (with libavcodec's decoder, didn't test libvorbis), the first
packet was just always completely discarded. This happened even though
we tell libavcodec that we do discarding of padding manually. It simply
happened inside the codec, not libavcodec's general initial padding
handling. In addition, the first output decoded frame seems to contain
partial data. (Unlike the opus decoder, it doesn't report any padding at
all.)

The Opus decoder (again libavcodec only tested) reports an initial
padding, but it appears to be too small, and it sounds right only with 2
packets discarded. So its status doesn't change.

I'm not sure why I need 2 frames for mp3, but with that value I had
success on the samples I tested.
2019-09-19 20:37:05 +02:00
wm4 da6e862c4f f_decoder_wrapper: hack for discarding preroll in backward playback mode
Some audio codecs will discard or cut the first frames when starting
decoding. While some of that works through well-defined mechanisms (like
initial padding), it's in general very codec/decoder specific, and not
really predictable. In addition, libavcodec isn't very good with
reporting "dropped" frames (and our internal interface reflects this).
It seems our only chance to handle this is through timestamps.

In theory, it would be best to discard frames that have timestamps
before the "resume" position. But since video has reordered timestamps,
we'd need to put some effort into finding this position. The first video
packet doesn't necessarily contain this timestamp. (In theory, we could
just do this in the demuxer with some trivial additional work, and set
it on the packet's kf_seek_pts field. Although this field is supposed to
contain just this value, the field is considered demuxer-internal, and I
didn't want to make matters worse by reusing it for the interface to the
decoder. With some more effort and buffering, we could calculate this
value within the decoder, but fuck that.)

The approach chosen in this commit is setting the timestamp to NOPTS.
This will break in some obscure situations, but backward playback is a
pretty obscure feature to begin with, so I considered this a reasonable
implementation choice.

Before passing a preroll packet to the decoder, its timestamps are set
to NOPTS. Frames that are returned from the decoder and have the NOPTS
timestamp are considered preroll and are discarded. This happens only
during "preroll" mode (preroll_discard==true), so it doesn't affect
normal forward playback. It's disabled on the first packet with a
timestamp, so it can tolerate some crap even in backward playback mode.
We don't check the dts fields out of laziness (decoded audio frames
don't even have this field).

I considered using an approach using the EDL clipping infrastructure (as
mentioned in the last two paragraphs in the commit message of commit
" demux_lavf: implement bad hack for backward playback of wav"). This
didn't work, and I blamed timestamp rounding within mpv for it. But the
problem was actually due to Matroska-rounded timestamps. Since the audio
frame size isn't exactly aligned to 1ms, there will be an overlap (or
gap) in the timestamps. This overlap is much smaller than 1ms, since
it's just the sub-millisecond remainder part of the audio frame size.
This makes the timestamps discontinuous and unreliable for the purpose
we wanted to use it. We can't just smooth the timestamps in the demuxer
either.
2019-09-19 20:37:05 +02:00
wm4 ab19888ba4 demux_mkv: don't set keyframe flag for timestamp-less audio frames
Matroska has this weird concept of "lacing", which are really sub-blocks
packed into a larger actual block. They are demuxed as individual
packets, because that's what the decoder needs. Basically they're a
Matroska hack to reduce per-packet muxing overhead.

One problem is that these sub-blocks don't have timestamps. The
timestamps need to be created from the "default duration". If this
default duration isn't in the file header (or if we drop it when it has
a known broken value), the resulting packets won't have a timestamp.

This is an usual and weird situation, that may confuse the demuxer layer
(and backward playback in particular). Fix this by not setting the
keyframe flag for these.

This affects only audio packets. Subtitle lacing is explicitly not
supported (in theory would at least lack a way to specify durations),
and video won't usually use it for real video codecs (not every frame is
a "keyframe", timestamp reordering).
2019-09-19 20:37:05 +02:00
wm4 af60a45fdf f_decoder_wrapper: remove stale/duplicated comment 2019-09-19 20:37:05 +02:00
wm4 6646e82daa demux: move timestamp helper macros to common.h
These are probably generally useful.
2019-09-19 20:37:05 +02:00
wm4 7d3bdb91da manpage: document accidental feature/bug
Clarify existing semantics for the --start/--end/--length options.
De-emphasize the difference between absolute and relative timestamps,
since they've not been different by default since mpv 0.14.

Document a bug, that also happens to work as a feature: if the option
value begins with spaces, the code for checking for relative timestamps
is inactive, and they're always considered absolute. The check is done
on the first character of the string - so even a negative timestamp will
be treated as absolute.)

Yes, this is useful in extremely rare situations, such as when you
really want send a specific timestamp (even a negative one) to the
demuxer.
2019-09-19 20:37:05 +02:00
wm4 a11aad4964 player: partially fix seek_to_last_frame in backward mode
Another shitty obscure feature that usually nobody notices.
Unsurprisingly, it doesn't go well with backward playback mode.

If you use --keep-open in forward playback mode, and seek past the end
of the file, it tries to seek to the very last frame. The demuxer will
seek to the last "keyframe" before the end (i.e. some frames to go in
most cases), and trying to hr-seek to the file duration often won't cut
it, so this requires some special code. The function at hand seeks
"close" to the end, and then stops hr-seek when the last frame us
encountered (simple enough and very effective).

In backward playback mode, start and end are reversed, and we need to
seek "close" to the start of the file instead. Simple enough to do, and
it works.

One problem is that command.c has some weird logic to make going beyond
the last chapter either end playback (--keep-open=no), or jump to the
last frame. Now this will jump to the first frame, which is weird, but
let's ignore this.

Another problem is that seeking before playback start position hits EOF
in backward playback mode, which is a demuxer bug, and has nothing to do
with this code. But it triggers this code, so seeking before the start
will show the "last" frame. (My description is a mess with directions.
Figure it out yourself.)
2019-09-19 20:37:05 +02:00
wm4 c7269e4e84 player: fix --loop with backward playback
Obviously should seek back to the end of the file when it loops.

Also remove some minor code duplication around start times. This isn't
the correct solution by the way. Rather than hoping we know a reasonable
start/end time, this stuff should instruct the demuxer to seek to the
exact location. It'll work with 99% of all normal files, but add an
appropriate comment (that basically says the function is bullshit) to
get_start_time() anyway.
2019-09-19 20:37:05 +02:00
wm4 878d4ea2ee player: remove some duplication between normal looping and ab-loops
Not sure if this is better or worse.

Some minor behavior changes.
2019-09-19 20:37:05 +02:00
wm4 7a0f112a44 player: modify/simplify AB-loop behavior
This changes the behavior of the --ab-loop-a/b options. In addition, it
makes it work with backward playback mode.

The most obvious change is that the both the A and B point need to be
set now before any looping happens. Unlike before, unset points don't
implicitly use the start or end of the file. I think the old behavior
was a feature that was explicitly added/wanted. Well, it's gone now.

This is because of 2 reasons:

1. I never liked this feature, and it always got in my way (as user).
2. It's inherently annoying with backward playback mode.

In backward playback mode, the user wants to set A/B in the wrong order.
The ab-loop command will first set A, then B, so if you use this command
during backward playback, A will be set to a higher timestamps than B.
If you switch back to forward playback mode, the loop would stop
working. I want the loop to just continue to work, and the chosen
solution conflicts with the removed feature.

The order issue above _could_ be fixed by also switching the AB-loop
user option values around on direction switch. But there are no other
instances of option changes magically affecting other options, and doing
this would probably lead to unexpected misery (dying from corner cases
and such).

Another solution is sorting the A/B points by timestamps after copying
them from the user options. Then A/B options set in backward mode will
work in forward mode. This is the chosen solution. If you sort the
points, you don't know anymore whether the unset point is supposed to
signify the end or the start of the file.

The AB-loop code is slightly better abstracted now, so it should be easy
to restore the removed feature. It would still require coming up with a
solution for backwards playback, though.

A minor change is that if one point is set and the other is unset, I'm
rendering both the chapter markers and the marker for the set point.
Why? I don't know. My test file had chapters, and I guess I decided this
looked better.

This commit also fixes some subtle and obvious issues that I already
forgot about when I wrote this commit message. It cleans up some minor
code duplication and nonsense too.

Regarding backward playback, the code uses an unsanitary mix of internal
("transformed") and user timestamps. So the play_dir variable appears
more than usual.

To mention one unfixed issue: if you set an AB-loop that is completely
past the end of the file, it will get stuck in an infinite seeking loop
once playback reaches the end of the file. Fixing this reliably seemed
annoying, so the fix is "just don't do this". It's not a hard freeze
anyway.
2019-09-19 20:37:05 +02:00
wm4 6f9059f858 player: replace a magic numer by another magic number
This code attempts to seek to the last frame by seeking close to the
end, and then decoding until the last frame has been reached. To do so
it sets hrseek_lastframe, which for video enables some logic to "catch"
this last frame, and completely ignores hrseek_pts. But audio still may
use hrseek_pts

I don't know if the original author (me) was thinking, if anything, when
setting this variable to 1e99, essentially a random, number. It's very
large, and a timestamp like this will never happen, so it does its job.
But it's random.

Use INFINITY instead. It will skip all audio samples in the audio code
correctly. This change doesn't fix anything, but it does get rid of the
random looking number.
2019-09-19 20:37:05 +02:00
wm4 2363e15eee player: simplify/fix --start/--end handling with --rebase-start-time=no
The get_play_start_pts() function was supposed to return "rebased"
(relative to 0) timestamps. This was roundabout, because one of 2
callers just added the offset back, and the other caller actually
expected an absolute timestamp.

Change rel_time_to_abs() (whose return value get_play_start_pts()
returns without further changes) to return absolute times.

This should fix that absolute and relative times passed to --start and
--end were treated the same, which can't be right. It probably also
fixes --end if --rebase-start-time=no is used (which can't have been
correct either).

All in all I'm not sure why --rebase-start-time=no or absolute vs.
relative times in --start/--end even exist, when they were incorrectly
implemented for years.

Untested, because no sample file and I don't care. However, if anyone
cares, and I got it wrong, I hope it's simple to fix.
2019-09-19 20:37:05 +02:00
wm4 23a73938fa player: minor --end simplification 2019-09-19 20:37:05 +02:00
wm4 900a9624f9 options: remove --chapter
Has been deprecated for almost 3 years. Manpage didn't mention the
deprecation, but CLI and release notes did. It wouldn't be much effort
to keep this option working, but I just don't see the damn point.

--start/--end can specify chapters using special syntax, which is
equivalent.
2019-09-19 20:37:05 +02:00
wm4 f68d9e75f8 player: fix --end for backwards playback
We need to transform the timestamp returned by get_play_end_pts().

I considered making it return the transformed timestamp directly. There
are 4 callers; 2 need a transformed timestamps, 2 don't. So I guess it
doesn't matter.
2019-09-19 20:37:04 +02:00
wm4 aebccb8801 osd: simplify AB-loop rendering on progress bar
This adds the stops using the same logic get_play_end_pts() and
handle_loop_file(). It did that before, it just looks slightly different
now. It also won't try to add MP_NOPTS_VALUE as stop value.
2019-09-19 20:37:04 +02:00
wm4 281e998290 player: make a function static 2019-09-19 20:37:04 +02:00
wm4 2c3c6aae66 demux, f_decoder_wrapper: fix coverart in backward mode
Shitty ancient hack that wastes my time all the time.

demux.c: always return the coverart packet as soon as possible, and
don't let the backward demux state machine possibly stop it.

f_decoder_wrapper.c: mess with some shit until it somehow starts to
work. I think the old code tried to let it cleverly fall through so the
packet was processed "normally"; just make it run the "usual" code
instead.
2019-09-19 20:37:04 +02:00
wm4 aaf4efd012 player: fix --hr-seek-demuxer-offset with backward playback 2019-09-19 20:37:04 +02:00
wm4 204a7725de demux_lavf: implement bad hack for backward playback of wav
This commit generally fixes backward playing in wav, at least in most
PCM cases.

libavformat's wav demuxer (and actually all other raw PCM based
demuxers) have a specific behavior that breaks backward demuxing. The
same thing also breaks persistent seek ranges in the demuxer cache,
although that's less critical (it just means some cached data gets
discarded). The backward demuxing issue is fatal,  will log the message
"Demuxer not cooperating.", and then typically stop doing anything.

Unlike modern media formats, these formats don't organize media data in
packets, but just wrap a monolithic byte stream that is described by a
header. This is good enough for PCM, which uses fixed frames (a single
sample for all audio channels), and for which it would be too expensive
to have per frame headers.

libavformat (and mpv) is heavily packet based, and using a single packet
for each PCM frame causes too much overhead. So they typically "bundle"
multiple frames into a single packet. This packet size is obviously
arbitrary, and in libavformat's case hardcoded in its source code.

The problem is that seeking doesn't respect this arbitrary packet
boundary. Seeking is sample accurate. You can essentially seek inside a
packet. The resulting packets will not be aligned with previously
demuxed packets. This is normally OK.

Backward seeking (and some other demuxer layer features) expect that
demuxing an earlier demuxed file position eventually results in the same
packets, regardless of the seeks that were done to get there. I like to
call this "deterministic" demuxing. Backward demuxing in particular
requires this to avoid overlaps, which would make it rather hard to get
continuous output.

Fix this issue by detecting wav and hopefully other raw audio formats
with a heuristic (even PCM needs to be detected as heuristic). Then, if
a seek is requested, align the seek timestamps on the guessed number of
samples in the audio packets returned by the demuxer.

The heuristic excludes files with multiple streams. (Except "attachment"
video streams, which could be an ID3 tag. Yes, FFmpeg allows ID3 tags on
WAV files.) Such files will inherently use the packet concept in some
way.

We don't know how the demuxer chooses the internal packet size, but we
assume that it's fixed and aligned to PCM frame sizes. The frame size is
most likely given by block_align (the native wav frame size, according
to Microsoft). We possibly need to explicitly read and discard a packet
if the seek is done without reading anything before that. We ignore any
subsequent packet sizes; we need to avoid the very last packet, which
likely has a different size.

This hack should be rather benign. In the worst case, it will "round"
the seek target a little, but the maximum rounding amount is bounded.
Maybe we _could_ round up if SEEK_FORWARD is specified, but I didn't
bother.

An earlier commit fixed the same issue for mpv's demux_raw.

An alternative, and probably much better solution would be clipping
decoded data by timestamp. demux.c could allow the type of overlap the
wav demuxer introduces, and instruct the decoder to clip the output
against the last decoded timestamp. There's already an infrastructure
for this (demux_packet.end field) used by EDL/ordered chapters.

Although this sounds like a good solution, mpv unfortunately uses floats
for timestamps. The rounding errors break sample accuracy. Even if you
used integers, you'd need a timebase that is sample accurate (not always
easy, since EDL can merge tracks with different sample rates).
2019-09-19 20:37:04 +02:00
wm4 f24ff0e948 demux: add an explicit start state for backward demuxing
Yay, more subtle state on top of this nightmarish, fragile state
machine. But this is what happens when you subvert the laws of nature.

This simple checks where playback should "resume" from when no packets
were returned to the decoder yet after the seek that initiated backward
playback. The main purpose is to process the first returned keyframe
range in the same way like all other ranges. This ensures that things
like preroll are included properly.

Before this commit, it could for example have happened that the start of
the first audio frame was slightly broken, because no preroll was
included. Since the audio frame is reversed before sending it to the
audio output, it would have added an audible discontinuity before the
second frame was played; all subsequent frames would have been fine.
(Although I didn't test and confirm this particular issue.)

In future, this could be useful for certain other things.

At least the condition for delaying the backstep seek becomes simpler
and more explicit.

Move the code that attempts to start demuxing up in dequeue_packet.
Before, it was not called when the stream was in back_restarting state.
This commit makes streams be in back_restarting state at initialization,
so the demuxer would never have started reading.

Likewise, we need to call back_demux_see_packets() right after seek in
case the seek was within the cache. (We don't bother with checking
whether it was a cached seek; nothing happens if it was a normal one.)
There is nothing else that would process these cached packets
explicitly, although coincidences could sporadically trigger it.

The check for back_restart_next in find_backward_restart_pos() now
decides whether to use this EOF special code. Since the backward
playback start state also sets this variable, we don't need some of
the complex checks in dequeue_packet() anymore either.
2019-09-19 20:37:04 +02:00
wm4 a84c4de31f manpage: deinterlacing with backwards playback probably works
As well as other filtering. I was writing this with the assumption that
timestamps go backwards (which I first planned to do). But in fact,
timestamps go forward, frame durations are positive, and adding a frame
duration to a timestamp yields the correct result. The only strange
thing is that timestamps are negative.

Also, media of course goes backwards. In other possible implementation,
filters would see normal forward playback, interrupted by seeks or
discontinuities. It turns out the current implementation of providing a
continuous backward media stream is probably better for filters.

Even deinterlacing seems to work. libavcodec always outputs fields in as
interleaved frames (i.e. fields are not reversed), and making up
timestamps for the new frames (when doubling the framerate) works
exactly like like in the forward case.

Actually the previous paragraph was a lie, and libavcodec does not
output fields as interleaved frames in rare cases. Sometimes AVFrame
contains single fields. In this case you'd need to inverse the field
dominance for deinterlacing filters to work correctly.
2019-09-19 20:37:04 +02:00
wm4 b04a761ce4 manpage: backward encoding actually appears to work
The way backward playback is implemented doesn't break basic assumptions
about timestamps after the decoder, so I guess all the encoding mode
needs to do is to adjust for the start offset, which it already does.

Though I might be wrong and my test was possibly flawed.

Stream recording on the other hand will fail immediately with
--record-file, and --stream-record will probably yield unexpected
results if any backstep seeks are done.
2019-09-19 20:37:04 +02:00
wm4 f53f9b89b1 demux: add a special case for backward demuxing of opus
Make --audio-backward-overlap default to 2 for Opus. I have no idea why
this is needed. It seems to fix backward decoding though (going purely
by listening).

Normally, this should not be needed, since initial padding is completely
contained within the first packet (normally, and in the case I tested).
So the 2nd packet/frame should be fine, but for some unknown reason it
works only with the 3rd.
2019-09-19 20:37:04 +02:00
wm4 6d11668a9c demux: use no overlapping packets for lossless audio
Worthless optimization, but at least it justifies that the
--audio-backward-overlap option has an "auto" choice. Tested with PCM
and FLAC.
2019-09-19 20:37:04 +02:00
wm4 327f3fc848 manpage: document why Vorbis backward playback does not work
The only reasonable solution to this is probably to make discarding of
preroll frames based on timestmaps, instead of frame/packet count. But
then you get issues with video and its dumb timestamp reordering. So for
now, fuck it.
2019-09-19 20:37:04 +02:00
wm4 001db94d1e demux: remove some redundant pointer indirections
In all of these cases ds->in should be the same as the local variable
in, and neither ds->in nor in ever change, i.e. a cosmetic
simplification.
2019-09-19 20:37:04 +02:00
wm4 085c7106b9 demux: change backward-overlap to keyframe ranges instead of packets
This seems more useful in general. This change also happens to fix a
miscounting of preroll packets when some of them were "rounded" away,
and which could make it stuck.

Also a simple intra-refresh encode with x264 (and muxed to mkv by it)
seems to work now. I guess I misinterpreted earlier results.
2019-09-19 20:37:04 +02:00
wm4 ba95a0b573 demux: fix typos 2019-09-19 20:37:04 +02:00
wm4 4f7684463f demux: redo backstep seek handling slightly again
Backstepping still could get "stuck" if the demuxer didn't seek far back
enough. This commit fixes getting stuck if playing backwards from the
end, and audio has ended much earlier than the video.

In commit "demux: fix initial backward demuxing state in some cases",
I claimed that the backward seek semantics ("snapping" backward in
normal seeking, unrelated to backward playing) would take care of
this. Unfortunately, this is not always quite true.

In theory, a seek to any position (that does not use SEEK_FORWARD, i.e.
backward snapping) should return a packet for every stream. But I have a
mkv sample, where audio ends much earlier than video. Its mkvmerge
created index does not have entries for audio packets, so the video
index is used. This index has its last entry somewhere close after the
end of audio. So no audio packets will be returned. With a "too small"
back_seek_size, the demuxer will retry a seek target that ends up in
this place forever. (This does not happen if you use --index=recreate.
It also doesn't happen with libavformat, which always prefers its own
index, while mpv's internal mkv demuxer strictly prefers the index from
the file if it can be read.)

Fix this by adding the back_seek_size every time we fail to see enough
packets. This way the seek step can add up until it works.

To prevent that back_seek_pos just "runs away" towards negative infinity
by subtracting back_seek_size every time we back step to undo forward
reading (e.g. if --no-cache is used), readjust the back_seek_pos to the
lowest known resume position. (If the cache is active, kf_seek_pts can
be used, but to work in all situations, the code needs to grab the
minimum PTS in the keyframe range.)
2019-09-19 20:37:04 +02:00
wm4 a8b9ba10ac demux: set SEEK_HR for backstep seeks, move a hr-seek detail to playloop
Just rearranging shit. Setting SEEK_HR for backstep seeks actually
doesn't have much meaning, but disables the weird audio snapping for
"keyframe" seeks, and I don't know it's late.
2019-09-19 20:37:04 +02:00
wm4 adf4d52ee8 demux: rename a variable
It's "better". This is all what's left from an attempt to make the code
slightly nicer.
2019-09-19 20:37:04 +02:00
wm4 e2ae3676c2 demux: remove minor code duplication
This code used to be simpler, but now it's enough that it should be
factored into a single function.

Both uses of the new function are annoyingly different. The first use is
the special case when a decoder tries to read packets, but the demuxer
doesn't see any (like mp4 files with sparse video packets, which
actually turned out to be chapter thumbnail "tracks"). Then the other
stream queues will overflow, and the stream with no packets is marked
EOF to avoid stalling playback.

The second case is when the demxuer returns global EOF.

It would be more awkward to have the loop iterating the streams in the
function, because then you'd need a weird parameter to control the
behavior.
2019-09-19 20:37:04 +02:00
wm4 a3ac2019ed demux: fix initial backward demuxing state in some cases
Just "mpv file.mkv --play-direction=backward" did not work, because
backward demuxing from the very end was not implemented. This is another
corner case, because the resume mechanism so far requires a packet
"position" (dts or pos) as reference. Now "EOF" is another possible
reference.

Also, the backstep mechanism could cause streams to find different
playback start positions, basically leading to random playback start
(instead of what you specified with --start). This happens only if
backstep seeks are involved (i.e. no cached data yet), but since this is
usually the case at playback start, it always happened. It was racy too,
because it depended on the order the decoders on other threads requested
new data. The comment below "resume_earlier" has some more blabla.

Some other details are changed.

I'm giving up on the "from_cache" parameter, and don't try to detect the
situation when the demuxer does not seek properly. Instead, always seek
back, hopefully some more.

Instead of trying to adjust the backstep seek target by a random value
of 1.0 seconds. Instead, always rely on the random value provided by the
user via --demuxer-backward-playback-step. If the demuxer should really
get "stuck" and somehow miss the seek target badly, or the user sets the
option value to 0, then the demuxer will not make any progress and just
eat CPU. (Although due to backward seek semantics used for backstep
seeks, even a very small seek step size will work. Just not 0.)

It seems this also fixes backstepping correctly when the initial seek
ended at the last keyframe range. (The explanation above was about the
case when it ends at EOF. These two cases are different. In the former,
you just need to step to the previous keyframe range, which was broken
because it didn't always react correctly to reaching EOF. In the latter,
you need to do a separate search for the last keyframe.)
2019-09-19 20:37:04 +02:00
wm4 27c5550de2 sd_lavc: implement --sub-pos for bitmap subtitles
Simple enough to do. May have mixed results. Typically, bitmap subtitles
will have a tight bounding box around the rendered text. But if for
example there is text on the top and bottom, it may be a single big
bitmap with a large transparent area between top and bottom. In
particular, DVD subtitles are really just a single screen-sized
RLE-encoded bitmap, though libavcodec will crop off transparent areas.

Like with sd_ass, you can't move subtitles _down_ if they are already in
their origin position. This could probably be improved, but I don't want
to deal with that right now.
2019-09-19 20:37:04 +02:00
wm4 f06b3d7f88 demux_lavf: also fix cache seeking with large codec delay
Fixes the same thing as the previous commit did with demux_mkv. I'm not
sure if this is correct or a good idea (well, it works with my sample
file).

There are some shady things in this, but describing them would require
too many expletives.
2019-09-19 20:37:04 +02:00
wm4 01423d8c03 demux, demux_mkv: fix seeking in cache with large codec delay
In this scenario, the demuxer will output timestamps offset by the codec
delay (e.g. negative timestamps at the start; mkv simulates those), and
the trimming in the decoder (often libavcodec, but ad_lavc.c in our
case) will adjust the timestamps back (e.g. stream actually starts at
0).

This offset needs to be taken into account when seeking. This worked in
the uncached case. (demux_mkv.c is a bit tricky in that the index is
already in the offset space, so it compensates even though the seek call
does not reference codec_delay.) But in the cached case, seeks backwards
did not seek enough, and forward they seeked too much.

Fix this by adding the codec delay to the index search. We need to get
"earlier" packets, so e.g. seeking to position 0 really gets the initial
packets with negative timestamps.

This also adjusts the seek range start. This is also pretty obvious: if
the beginning of the file is cached, the seek range should start at 0,
not a negative value. We compare 0-based timestamps to it later on.

Not sure if this is the best approach. I also could have thought
about/checked some corner cases harder. But fuck this shit.

Not fixing duration (who cares) or end trimming, which would reduce the
seek range and duration (who cares).
2019-09-19 20:37:04 +02:00
wm4 b90723bccb demux_mkv: stop setting per-packet initial padding from codec delay
This is a bad approach, and should be handled by a codec parameter field
(in mp_codec_params or AVCodecParameters).

It's bad because it's overly complicated, and has potential to break
demuxer cache assumptions: packets that were "intended" for seek
resuming may suddenly appear in the middle of a stream, when you seek
back and play a cached part again. (In general it was fine though,
because seek range joining tends to remove the first audio packet of the
next range when trying to find an overlap.)

demux_mkv.c does not try to export its codec_delay field through the
codec parameters mentioned above. In the only case I spotted this
element, the codec itself (opus) set this field within libavcodec. And I
think that's actually how it should be. On the other hand, a file could
in theory set this field via mkv headers if the codec is too stupid to
have such a field internally. But I don't really care until I see such a
file.

The end trimming is still sort of needed (though not sure if anything
uses it, other than the opus/mkv test sample I was using). The decoder
can't know whether something is the last packet, until it's too late.

The codec_delay field is still needed to offset timestamps.
2019-09-19 20:37:04 +02:00
wm4 32e3033666 ad_lavc: skip fully skipped frames
Fixes stupid messages with a opus/mkv test file that had an absurdly
huge codec delay.

This file fully skips several frames at the start. ad_lavc.c trimmed
these frames to 0 samples and returned them. The next layer
(f_decoder_wrapper.c) saw discontinuous PTS values, because the PTS
values increased by a frame, but amounted to 0 audio samples. This was
harmless, but logged PTS discontinuity errors.
2019-09-19 20:37:04 +02:00
wm4 6f7260d29c manpage: document that backward playback from the end does not work
Not specifying a --start or using --start=100% with
--play-direction=backward usually does not work. The demuxer gets no
packets and immediately enters EOF state, which then hangs because
backward playback mode neither considers this mode, nor propagates the
EOF.

As far as demuxer implementations are concerned, this behavior is OK and
even wanted. Seeking near the end with SEEK_FORWARD set is allowed not
to return any packets (so a normal relative forward seek as done by the
user would end playback). Seeking exactly to the end or past it without
SEEK_FORWARD set is probably also sane.

Another vaguely related issue is that a backward seek during playback
start does not "establish" the demux position correctly: if stream A
hits the next keyframe and seeks back, while stream B has not had a
chance to read a packet yet, then stream B will never try to read from
the old position. The effect is that stream B (and thus playback) will
effectively miss the seek target. This is "random" because it depends on
the order and number of packet read calls made by the decoders.

Fixing this is probably hard, and requires extending the already complex
state machine with more states, so turn the manpage into a TODO list for
now.
2019-09-19 20:37:04 +02:00
wm4 5ebbde7327 demux: don't adjust internal backward playback seeks by start time
Only timestamps that enter or leave the demuxer API should be adjusted
by ts_offset (which is usually the start time). queue_seek() is also
used by backward demux seeks, which uses an internal timestamp.
2019-09-19 20:37:04 +02:00
wm4 5b4ae42328 demux_raw: fix operation with demuxer cache and backward playback
Raw audio formats can be accessed sample-wise, and logically audio
packets demuxed from it would contain only 1 sample. This is
inefficient, so raw audio demuxers typically "bundle" multiple samples
in one packet.

The problem for the demuxer cache and backward playback is that they
need properly aligned packets to make seeking "deterministic". The
requirement is that if you read some packets, and then seek back, you
eventually see the same packets again. demux_raw basically allowed to
seek into the middle of a previously returned packet, which makes it
impossible to make the transition seamless. (Unless you'd be aware of
the packet data format and cut them to make it seamless, which is too
complex for such a use case.)

Solve this by always aligning seeks to packet boundaries. This reduces
the seek accuracy to the arbitrarily chosen packet size. But you can use
hr-seek to fix this. The gain from not making raw audio an awful special
case pays in exchange for this "stupid" suggestion to use hr-seek.

It appears this also fixes that it could and did seek into the middle of
the frame (not sure if this code was ever tested - it goes back to
removing the code duplication between the former demux_rawaudio.c and
demux_rawvideo.c).

If you really cared, you could introduce a seek flag that controls
whether the seek is aligned or not. Then code which requires
"deterministic" demuxing could set it. But this isn't really useful for
us, and we'd always set the flag anyway, unless maybe the caching were
forced disabled.

libavformat's wav demuxer exhibits the same issue. We can't fix it (it
would require the unpleasant experience of contributing to FFmpeg), so
document this in otions.rst. In theory, this also affects seek range
joining, but the only bad effect should be that cached data is
discarded.
2019-09-19 20:37:04 +02:00
wm4 5d69dcfb89 demux_raw: set keyframe flag
This is for uncompressed data, so every frame is a "keyframe". This is
part of making this demuxer work with the demuxer layer caching and
backward playback.
2019-09-19 20:37:04 +02:00
wm4 501876e2fa sub: fix typo in comment 2019-09-19 20:37:04 +02:00
wm4 b9d351f02a Implement backwards playback
See manpage additions. This is a huge hack. You can bet there are shit
tons of bugs. It's literally forcing square pegs into round holes.
Hopefully, the manpage wall of text makes it clear enough that the whole
shit can easily crash and burn. (Although it shouldn't literally crash.
That would be a bug. It possibly _could_ start a fire by entering some
sort of endless loop, not a literal one, just something where it tries
to do work without making progress.)

(Some obvious bugs I simply ignored for this initial version, but
there's a number of potential bugs I can't even imagine. Normal playback
should remain completely unaffected, though.)

How this works is also described in the manpage. Basically, we demux in
reverse, then we decode in reverse, then we render in reverse.

The decoding part is the simplest: just reorder the decoder output. This
weirdly integrates with the timeline/ordered chapter code, which also
has special requirements on feeding the packets to the decoder in a
non-straightforward way (it doesn't conflict, although a bugmessmass
breaks correct slicing of segments, so EDL/ordered chapter playback is
broken in backward direction).

Backward demuxing is pretty involved. In theory, it could be much
easier: simply iterating the usual demuxer output backward. But this
just doesn't fit into our code, so there's a cthulhu nightmare of shit.
To be specific, each stream (audio, video) is reversed separately. At
least this means we can do backward playback within cached content (for
example, you could play backwards in a live stream; on that note, it
disables prefetching, which would lead to losing new live video, but
this could be avoided).

The fuckmess also meant that I didn't bother trying to support
subtitles. Subtitles are a problem because they're "sparse" streams.
They need to be "passively" demuxed: you don't try to read a subtitle
packet, you demux audio and video, and then look whether there was a
subtitle packet. This means to get subtitles for a time range, you need
to know that you demuxed video and audio over this range, which becomes
pretty messy when you demux audio and video backwards separately.

Backward display is the most weird (and potentially buggy) part. To
avoid that we need to touch a LOT of timing code, we negate all
timestamps. The basic idea is that due to the navigation, all
comparisons and subtractions of timestamps keep working, and you don't
need to touch every single of them to "reverse" them.

E.g.:

    bool before = pts_a < pts_b;

would need to be:

    bool before = forward
        ? pts_a < pts_b
        : pts_a > pts_b;

or:

    bool before = pts_a * dir < pts_b * dir;

or if you, as it's implemented now, just do this after decoding:

    pts_a *= dir;
    pts_b *= dir;

and then in the normal timing/renderer code:

    bool before = pts_a < pts_b;

Consequently, we don't need many changes in the latter code. But some
assumptions inhererently true for forward playback may have been broken
anyway. What is mainly needed is fixing places where values are passed
between positive and negative "domains". For example, seeking and
timestamp user display always uses positive timestamps. The main mess is
that it's not obvious which domain a given variable should or does use.

Well, in my tests with a single file, it suddenly started to work when I
did this. I'm honestly surprised that it did, and that I didn't have to
change a single line in the timing code past decoder (just something
minor to make external/cached text subtitles display). I committed it
immediately while avoiding thinking about it. But there really likely
are subtle problems of all sorts.

As far as I'm aware, gstreamer also supports backward playback. When I
looked at this years ago, I couldn't find a way to actually try this,
and I didn't revisit it now. Back then I also read talk slides from the
person who implemented it, and I'm not sure if and which ideas I might
have taken from it. It's possible that the timestamp reversal is
inspired by it, but I didn't check. (I think it claimed that it could
avoid large changes by changing a sign?)

VapourSynth has some sort of reverse function, which provides a backward
view on a video. The function itself is trivial to implement, as
VapourSynth aims to provide random access to video by frame numbers (so
you just request decreasing frame numbers). From what I remember, it
wasn't exactly fluid, but it worked. It's implemented by creating an
index, and seeking to the target on demand, and a bunch of caching. mpv
could use it, but it would either require using VapourSynth as demuxer
and decoder for everything, or replacing the current file every time
something is supposed to be played backwards.

FFmpeg's libavfilter has reversal filters for audio and video. These
require buffering the entire media data of the file, and don't really
fit into mpv's architecture. It could be used by playing a libavfilter
graph that also demuxes, but that's like VapourSynth but worse.
2019-09-19 20:37:04 +02:00
wm4 fc4e59f25d demux: cleaner mutex usage
The demuxer layer can start a thread to decouple the rest of the player
from blocking I/O (such as network accesses). But this particular
function does not support running with the thread enabled. The mutex use
within it is only since thread_work() may temporarily unlock the mutex,
and unlocking an unlocked mutex is not allowed. Most of the rest of the
code still does proper locking, even if it's pointless and effectively
single-threaded.

To make this look slightly cleaner, extend the mutex around the rest of
the code (like threaded code would have to do). This is mostly a
cosmetic change.
2019-09-19 20:37:04 +02:00
wm4 62e9a0c5f6 demux: add shitty start of stream detection
The demuxer cache benefits slightly from knowing where the current file
or stream begins. For example, seeking "left most" when the start is
cached would not trigger a low level seek (which would be followed by
messy range joining when it notices that the newly demuxed packets
overlap with an existing range).

Unfortunately, since multimedia is so crazy (or actually FFmpeg in its
quite imperfect attempt to be able to demux anything), it's hard to tell
where a file starts. There is no feedback whether a specific seek went
to the start of the file. Packets are not tagged with a flag indicating
they were demuxed from the start position. There is no index available
that could be used to cross-check this (even if the file contains a full
and "perfect" index, like mp4). You could go by the timestamps, but who
says streams start at 0? Streams can start somewhere at an extremely
high timestamps (transport streams like to do that), or they could start
at negative times (e.g. files with audio pre-padding will do that), and
maybe some file formats simply allow negative timestamps and could start
at any negative time. Even if the affected file formats don't allow it
in theory, they may in practice. In addition, FFmpeg exports a
start_time field, which may or may not be useful. (mpv's internal mkv
demuxer also exports such a field, but doesn't bother to set it for
efficiency and robustness reasons.)

Anyway, this is all a huge load of crap, so I decided that if the user
performs a seek command to time 0 or earlier, we consider the first
packet demuxed from each stream to be at the start of the file. In
addition, just trust the start_time field. This is the "shitty" part of
this commit.

One common case of negative timestamps is audio pre-padding. Demuxers
normally behave sanely, and will treat 0 as the start of the file, and
the first packets demuxed will have negative timestamps (since they
contain data to discard), which doesn't break our assumptions in this
commit. (Although, unfortunately, do break some other demuxer cache
assumptions, and the first cached range will be shown as starting at a
negative time.)

Implementation-wise, this is quite simple. Just split the existing
initial_state flag into two, since we want to deal with two separate
aspects. In addition, this avoids the refresh seek on track switching
when it happens right after a seek, instead of only after opening the
demuxer.
2019-09-19 20:37:04 +02:00
wm4 8a58355a23 command: put seek ranges at the end of output
This is a minor benign hack that reorders the MPV_FORMAT_NODE output.
The order of members is not supposed to matter, but it's how the OSD
renders them as raw output. Normally this isn't used, but
demuxer-cache-state is a "prominent" case. Moving the seek ranges to the
end avoids that the more important other fields are not cut off by going
out of the screen on the bottom.

Also output the seek ranges in reverse. The order doesn't matter either
(as declared by input.rst). Currently, the demuxer orders them by least
recent use. Reversing it makes the most recently used range (the current
range) show up on top.

In other words, this commit does basically nothing but fudge stuff in a
cosmetic way to make debugging easier for me, and you've wasted your
time reading this commit message and the diff. Good.
2019-09-19 20:37:04 +02:00
wm4 455c085538 manpage: remove double fw-bytes documentation
It was documented two times, with different text. Merge them and reword
it a little.
2019-09-19 20:37:04 +02:00
wm4 a3991078bd demux, command: export bof/eof flags
Export these flags with demuxer-cache-state. Useful for debugging, but
any client API users could also make use of it.
2019-09-19 20:37:04 +02:00
wm4 f57fad4a4d command: make demuxer-cache-state property observable
The update is throttled by the normal playloop cache update mechanism.
2019-09-19 20:37:04 +02:00
wm4 f99d9c5b08 playloop: update cache properties in idle state
This will properly notify observed properties if the player hasn't
started actual playback yet, such as with --demuxer-cache-wait.

This also happens to cause the main loop more often, which triggers
MPV_EVENT_IDLE, and fixes the OSC display. (See previous commit
message.)
2019-09-19 20:37:04 +02:00
wm4 eb951835ff player: send MPV_EVENT_TICK during init for the sake of the osc
The OSC's (osc.lua) event handling is fundamentally broken. It waits for
MPV_EVENT_TICK to update the UI, and MPV_EVENT_TICK has become entirely
meaningless, except as a hack for the OSC. There are many situations
where the OSC doesn't properly update because the TICK event it expects
isn't sent.

Fix one of them: it doesn't update the cache state if the VO window is
forced and --demuxer-cache-wait is used. Make it so that the tick event
is sent even if playback initialization is taking time.

This is still slightly broken, because it works only if the mainloop is
actually run, which depends on random circumstances (such as moving the
mouse over the VO window). The next commit will add another such
circumstance which will make it appear to work, although it's still
conceptually broken. If we "fixed" it and strictly woke up the player
if the idle timer ran out, we'd send tick events all the time, even
if nothing is going on, which we don't want. Fucking shitshow.
2019-09-19 20:37:04 +02:00
wm4 f08387c552 demux: remove logic duplication from packet read functions
There were 3 packet reading functions: the "old" demux_read_packet()
that blocked (leftover from MPlayer times, but was still used until
recently by some obscure code), the "new" demux_read_packet_async(), and
the special demux_read_any_packet(), that is used by pseudo-demuxers
like demux_edl.

The first two could be used both in threaded and un-threaded mode. This
made 5 cases in total. Some bits of logic was spread across all of them.

Unify the logic. A recent commit made demux_read_packet() private, and
the code for it in threaded mode disappears. The difference between
threaded and un-threaded is minimized.

It's possible that this commit causes random regression. Enjoy.
2019-09-19 20:37:04 +02:00
wm4 287166b02e sub: remove only user of demux_read_packet()
There are 3 packet reading functions in the demux API, which all
function completely differently. One of them, demux_read_packet(), has
only 1 caller, which is in dec_sub.c. Change this caller to use
demux_read_packet_async() instead. Since it really wants to do a
blocking call, setup some proper waiting. This uses mp_dispatch_queue,
because even though it's overkill, it needs the least code.

In practice, waiting actually never happens. This code is only called on
code paths where everything is already read into memory (libavformat's
subtitle demuxers simply behave this way). It's still a bit of a
"coincidence", so implement it properly anyway.

If suubtitle decoder init fails, we still need to unset the demuxer
wakeup callback. Add a sub_destroy() call to the failure path. This also
happens to fix a missed pthread_mutex_destroy() call (in practice this
was a nop, or a memory leak on BSDs).
2019-09-19 20:37:04 +02:00
wm4 d9cc13f311 f_decoder_wrapper: move cover art retrieval
This is basically a refactor in preparation for future changes and
shouldn't have much influence on actual behavior.
2019-09-19 20:37:04 +02:00
wm4 a80f63cb9a player: don't print "Playing:" message if there's only 1 file
This is just redundant and slightly annoying, at least for normal
command line usage. If there are multiple entries, still print it
(because you want to know where you are). Also still print it if the
player was redirected (because you want to know where you got redirected
to).
2019-09-19 20:37:04 +02:00
wm4 53cf4e27d4 demux: adjust reader_head on range joining
I'm not sure about this, but it looks like a bug. If a stream didn't
have packets, but the joined range does, the stream should obviously
read the packets added by the joined range. Until now, due to
reader_head being NULL, reading was only resumed if a _new_ packet was
added by actual demuxing (in add_packet_locked()), which means the
stream would suddenly skip ahead, past the original end of the joined
range.

Change it so that it will pick up the new range.

Also, clear the skip_to_keyframe flag. Nothing useful can come from this
flag being set; in the first place, the first packet of a range (that
isn't the current range) should start with a keyframe. Some code
probably enforced it (although it's fuzzy).

Completely untested.
2019-09-19 20:37:04 +02:00
wm4 2d2d96f00b demux: don't process obscure skipped packets
When doing a seek to the end of the cache, ds->skip_to_keyframe can be
set to true. Then some packets passed to add_packet_locked() may have to
be skipped. In some aspects, the skipped packet was still treated as if
it was going to be returned to the reader.

It almost doesn't matter though: it only caused a redundant wakeup_ds()
call, and could pass the packet to the stream recorder. Fix it anyway.
2019-09-19 20:37:04 +02:00
wm4 781e9fcd66 demux: factor out a some packet queue code
Might be helpful for later. The "duplicated" ds->reader_head check above
the function call is redundant, but leaving it also for later.
2019-09-19 20:37:04 +02:00
wm4 d91a82c206 demux: fix typos in comments
How does this happen?
2019-09-19 20:37:04 +02:00
wm4 556e204a11 player: add --demuxer-cache-wait option 2019-09-19 20:37:04 +02:00
wm4 d7c7f80cc1 packet: reorder fields
Saves 8 bytes on 64 bit platforms.
2019-09-19 20:37:04 +02:00
wm4 075111c4d2 sd_lavc: fix some obscure UB
UB-sanitizer complains that we shift bits into the sign (when a is
used). Change it to unsigned, which in theory is more correct and
silences the warning.

Doesn't matter in practice, both the "bug" and the fix have 0 impact.
2019-09-19 20:37:04 +02:00
wm4 5901c3ae0d demux_edl: fix assertion failure on exit in obscure ytdl cases
If a DASH-hack EDL has an init fragment is set, it opens the init
fragment as such to get the track layout (including codec etc.) and
avoids opening actual fragments until actual playback. It does not get
added to the source array, so it leaks on exit, which triggers an
obscure (but very justified) assertion in thread_tools.c:106. Fix the
leak by adding the additional demuxer instance to the sources arrays,
which gets it freed.

This is a regression from when I rewrote some of the timeline handling.
I decided that in order to make memory management slightly simpler,
freeing a timeline should only free elements in the sources array. That
is OK; I just didn't re-test with pseudo-DASH that has init fragments,
and just hit a video that uses that by accidents. These videos are
rather scarce (apparently) so it happened only now.

The real solution would probably be adding demuxer reference counting.
This EDL memory management is just too messy, and throwing refcounting
at such problems is an effective and popular fix. Then you'd get
debugging nightmares with incorrect refcounts too, though.
2019-09-19 20:37:04 +02:00
wm4 a52ab8dc30 demux_mkv: fix seeking in broken mjpeg files 2019-09-19 20:37:04 +02:00
wm4 1053a7916a DOCS/edl-mpv.rst: make clear the DASH stuff is for internal use only
ytdl_hook.lua essentially uses these headers to implement parts of DASH.
Hopefully the FFmpeg DASH demuxer gets usable at some point, and/or mpv
gets a proper DASH demuxer. In any case, these EDL hacks could get
removed as soon as they get unnecessary and too annoying.
2019-09-19 20:37:04 +02:00
wm4 7d0e0b3a5c demux_timeline: add heuristic to fix shifted seeks with separate audio
If you have a EDL stream with separate sources for audio and video
stream (like ytdl_hook now creates), you can get the problem that the
video stream seeks to a different position than audio due to different
key frame granularity.

In particular, if you seek backward, the video might undershoot the seek
target by a lot. Then video will resume from an earlier position than
audio, and the player plays silence. This is annoying.

Fix this by explicitly implementing a heuristic to detect separate
audio/video streams, determining where a video seek ends up, and then
seeking the audio stream to the video destination. This also makes sure
to not seek audio with SEEK_FORWARD, so it will always seek before the
video position. Non-precise seeks still skip audio to the video target,
so this helps with ensuring that audio is present at the final seek
target.

The implementation is very annoying, because the only way to determine
the seek target is to actually read a packet. Thus a 1-packet queue
needs to be added. In theory, we could get the seek target from the
index of the video file (especially if it's mp4), but libavformat does
not have public API that exports this index, so we're stuck with this
roundabout generic method.

Note that this is only for non-precise seeks. If precise seeks are done,
the problem is handled by the frontend by skipping unwanted video
frames. But non-precise seeking should still work. (Personally I prefer
non-precise seek mode by default because they're still significantly
faster.)

It also needs to be said that this is the 4th implementation of this
seek adjustment thing in mpv. The 1st implementation is in the frontend
(look for MPContext.seek_slave). This works only if the external audio
stream is known as such on the frontend level. The 2nd implementation is
in the demuxer level packet cache (top of execute_cache_seek()). This is
similar to code that any demuxer needs to handle non-precise seeks
sufficiently nicely. The 3rd is in demux_mkv.c. Since mkv is an
interleaved format, this implementation mostly consists on trying to
pick index entries for video packets if a video stream is selected.
Maybe these "redundant" implementations could be avoided by exposing
separate streams through the demuxer API (and making them individually
seekable) or something like this, but this is messy and not without
problems for multiple reasons. So for now this commit is the best way to
fix the observed behavior.
2019-09-19 20:37:04 +02:00
wm4 87db2f24e8 demux_edl, cue, mkv: slightly nicer file format indication
Instead of just using "edl/" for the file format, report mkv_oc if it's
generated from ordered chapters, "cue/" if from .cue, "multi/" if it's
from EDL but only for adding separate streams, "dash/" if it's from EDL
but only using the DASH hack, and "edl/" for everything else.

The EDL variants are mostly special-cased to the variants the ytdl
wrapper usually generates.

This has no effect other than what the command.c file-format property
returns.
2019-09-19 20:37:04 +02:00
wm4 a09396ee60 demux_edl, cue, mkv: clean up timeline stuff slightly
Remove the singly linked list hack, replace it with a slightly more
proper data structure. This probably gets rid of a few minor bugs along
the way, caused by the awkward nonsensical sharing/duplication of some
fields.

Another change (because I'm touching everything related to timeline
anyway) is that I'm removing the special semantics for parts[num_parts].
This is now strictly out of bounds, and instead of using the start time
of the next/beyond-last part, there is an end time field now.

Unfortunately, this also requires touching the code for cue and mkv
ordered chapters. From some superficial testing, they still seem to
mostly work.

One observable change is that the "no_chapters" header is per-stream
now, which is arguably more correct, and getting the old behavior would
require adding code to handle it as special-case, so just adjust
ytdl_hook.lua to the new behavior.
2019-09-19 20:37:04 +02:00
wm4 6efcde06e3 ytdl_hook: use no_clip for separate audio streams
I noticed that some ytdl streams have a start time other than 0. There's
currently no mechanism inside of the EDL stuff that determines this
start time correctly, so it can happen that if the start time is high,
demux_timeline.c tries to clip off the entire video and audio, resulting
in failure of playback.

As a counter measure, use the no_clip header, which entirely disables
clipping against time ranges in demux_timeline.c. (It's basically a
hack.)
2019-09-19 20:37:04 +02:00
wm4 19422f0eea demux_edl: add no_clip
Used by the next commit. It mostly exposes part of mp4_dash
functionality. It actually makes little sense other than for ytdl
special-use. See next commit.
2019-09-19 20:37:04 +02:00
wm4 7498fa0b3d video: fix player not exiting if no video frame was rendered
E.g. "mpv null:// --demuxer=rawvideo" will "hang" by waiting for video
EOF forever. It's not signalled correctly because of the last-frame
corner case, which attempts to wait until the current frame is finally
displayed (which is signalled by whether a new frame can be queued, see
commit 1a339fa09d for some details). If no frame was ever queued, the VO
is not configured, and vo_is_ready_for_frame() never returns true.

Fix this by using vo_has_frame(), which seems to be exactly the correct
thing we need.
2019-09-19 20:37:04 +02:00
wm4 2bf1862bc1 stream: log positions on seek failures 2019-09-19 20:37:04 +02:00
wm4 d23336089c ytdl_hook: fix pseudo-DASH if no init fragment is present
Init fragments are not a necessity for DASH, but this code assumed so.
Maybe the check was to prevent worse. But using normal EDL here leads to
very shitty behavior where it tries to open hundreds or thousands of
fragments, each with its own demuxer and HTTP connection. (This behavior
is fine for normal uses of EDLs, but completely unacceptable when
emulating fragmented streaming protocols. I'm not sure why the normal
EDL code is needed here, but I think someone claimed some obscure sites
just need it.)

This happens in the same situation as the one described in the previous
commit.
2019-09-19 20:37:04 +02:00
wm4 80d2016075 ytdl_hook: audio can use fragmented DASH too
Otherwise we'd just use the base URL as media URL, which would fail with
a 404 error.

Not sure if there's a deeper reason why the audio path was explicitly
different from the video one. But this actually works now for a video
that returned fragmented DASH audio with the default format selection.
(This affects streams on that well known site of a big evil Silicon
Valley company. Typically happens after live stream gets converted to a
normal video, though after some time passes, this fragmented version is
deleted, and replaced by a non-fragmented one. I've observed this
several times and this seems to be the "normal" behavior.)
2019-09-19 20:37:04 +02:00
wm4 5eb7b7eb04 demux_timeline: include "dash" hint in reported file format 2019-09-19 20:37:04 +02:00
wm4 8ba484f47c demux_timeline: disable end-of-segment handling in DASH mode
Normal EDL needs to clip packets coming from the underlying demuxer to
the segment range (including complicated stuff due to frame reordering).
This is unwanted In pseudo-DASH mode. A broken or subtly incorrect
manifest would lead to "bad stuff" happening. The intention of the
pseudo-DASH mode is to literally concatenate fragments.
2019-09-19 20:37:04 +02:00
wm4 b157e22838 demux: fix typo in a comment 2019-09-19 20:37:04 +02:00
wm4 007defb06f demux: fix SEEK_FORWARD into end of cached range
This fixes that there were weird delay ("buffering") when seeking into
the last part of a seekable range. The exact case which triggers it if
SEEK_FORWARD is used, and the seek pts is after the second-last
keyframe, but before the end of the range. In that case,
find_seek_target() returned NULL, and the cache layer waited until the
_next_ keyframe the underlying demuxer returned until resuming playback.

find_seek_target() returned NULL, because the last keyframe had
kf_seek_pts unset. This field contains the lowest PTS in the packet
range from the keyframe until the next keyframe (or EOF). For normal
seeks, this is needed because keyframes don't necessarily have the
minimum PTS in the packet range, so it needs to be computed by waiting
for all packets until the next keyframe (or EOF).

Strictly speaking, this behavior was correct, but it meant that the
caller would set ds->skip_to_keyframe, which waits for the next newly
demuxed keyframe. No packets were returned to the decoder until this
happened, usually resulting in the frontend entering "buffering" mode.

What it really needs to do is returning the last keyframe in the cache.
In this situation, the seek target points in the middle of the last
completely cached packet range (as delimited by keyframes), and
SEEK_FORWARD is supposed to skip to the next keyframe. This is in line
with the basic assumptions the packet cache makes (e.g. the keyframe
flag means it's possible to start decoding, and the frames decoded from
it and following packets will strictly have PTS values above the
previous keyframe range). This means in this situation the kf_seek_pts
value doesn't matter either.

So fix this situation by explicitly detecting it and then returning the
last cached keyframe.

Should the search loop look at all packets, instead of only keyframe
ones? This would mean it can know that it's within the last keyframe
range (without looking at queue->seek_end). Maybe this would be a bit
more natural for the SEEK_FORWARD case, but due to PTS reordering it
doesn't sound like a useful thing to do.

Should skip_to_keyframe be checked by the code that sets kf_seek_pts to
a known value? This wouldn't help too much; the frontend would still go
into "buffering" mode for no reason until the packet range is completed,
although it would resume from the correct range.

Should a NULL return always unconditionally use keyframe_latest? This
makes sense because the seek PTS is usually already in the cached range,
so this is the only case that should happen. But there are scary special
cases, like sparse subtitle streams, or other uses of find_seek_target()
which could be out of range now or in future. Basically, don't "risk"
it.

One other potential problem with this is that the "adjust seek target"
code will be disabled in this case. It checks kf_seek_pts, and if it's
unset, the adjustment is not done. Maybe this could be changed to use
the queue's seek_end time, but I'm not sure if this is fully kosher. On
the other hand, I think the main use for this adjustment is with
backwards seeks, so this shouldn't matter.

A previous commit dealing with audio/video stream merging mentioned how
seeking forward entered "buffering" mode for unknown reasons; this
commit fixes this issue.
2019-09-19 20:37:04 +02:00
wm4 390772b58f demux_timeline: report network speed of slave connections
demux_timeline doesn't do any transport accesses itself. The slave
demuxers do this (these will actually access the stream layer and
perform e.g. network accesses). As a consequence, demux_timeline always
reported 0 bytes read, and network speed display didn't work.

Fix this by awkwardly reporting the amount of read bytes upwards. This
is not very nice, and requires explicit calls whenever the slave "might"
have read data.

Due to the way the reporting is done, it only works if the slaves do not
run demuxer threads, which makes things even less nice. (Fortunately
they don't anyway, because it would be a waste of resources.) Some
identifiers contain the word "hack" as a warning.

Some of the stupidity comes from the fact that demux.c itself resets the
stats randomly in order to calculate the bytes_per_second value, which
is useless for a slave, but of course is still done, because demux.c
itself is not aware of whether it's on the slave or top-level layer.

Unfortunately, this must do.

In theory, the demuxer thread/cache layer should be separated from
demuxer implementations. This would get rid of all the awkwardness and
nonsense. For example, the only threading involved would be the caching
layer, completely separate from demuxers themselves. It'd be the only
thing calculates speed rates for the player frontend, too (instead of
doing it for each demuxer, even if unused).
2019-09-19 20:37:04 +02:00
wm4 ebf183eeec demux: slightly cleanup network speed reporting
It was an ugly hack, and the next commit will make it even uglier.
Slightly reduce the ugliness to prevent death of too many brain cells,
though it's still an ugly hack.

The cleanup is really minor, but I guess the following commit would be
much worse otherwise. In particular, this commit checks accesses
(instead of having a public field with evil access rules), which should
avoid misunderstandings and incorrect use. Strictly speaking, the added
field is redundant, but the next commit complicates it a bit.
2019-09-19 20:37:04 +02:00
wm4 27a09b42ed ytdl_hook: disable EDL-generated useless chapters when merging streams
(Yes, a bit odd how this header is needed only for the first stream.)
2019-09-19 20:37:04 +02:00
wm4 b230525352 demux_edl: add a special header to disable chapter generation
A bit of a hack.
2019-09-19 20:37:04 +02:00
wm4 b8f282fd32 demux_edl: explicitly error on unknown header types
I think this is better. On the other hand, this is a behavior change.
The EDL "spec" says that unknown fields are igored. But strictly
speaking, unknown headers are not "fields", but unknown entities.
2019-09-19 20:37:04 +02:00
wm4 9f8d9c218b demux_edl: minor cleanup to header parsing
EDL "headers" were always an afterthought, and kind of hacked on top of
the existing code. Improve it slightly, and make it follow the
conventions of the normal parsing. Basically use the same code structure
for them, just that they use different field names.
2019-09-19 20:37:04 +02:00
wm4 f485e34fc9 ytdl_hook: merge separate audio tracks via EDL
This merges separate audio and video tracks into one virtual stream,
which helps the mpv caching layer. See previous EDL commit for details.

It's apparently active for most of evil Silicon Valley giant's streaming
videos.

Initial tests seem to work fine, except it happens pretty often that
playback goes into buffering immediately even when seeking within a
cached range, because there is not enough forward cache data yet to
fully restart playback. (Or something like this.)

The audio stream title used to be derived from track.format_note; this
commit stops doing so. It seemed pointless anyway. If really necessary,
it could be restored by adding new EDL headers.

Note that we explicitly don't do this with subtitle tracks. Subtitle
tracks still have a chance with on-demand loading or loading in the
background while video is already playing; merging them with EDL would
prevent this. Currently, subtitles are still added in a "blocking"
manner, but in theory this could be loosened. For example, the Lua API
already provides a way to run processes asynchronously, which could be
used to add subtitles during playback. EDL will probably be never
flexible enough to provide this. Also, subtitles are downloaded at
once, rather than streamed like audio and video.

Still missing: disabling EDL's pointless chapter generation, and
propagating download speed statistics through the EDL wrapper.
2019-09-19 20:37:04 +02:00
wm4 d2ef2f98a8 loadfile, ytdl_hook: don't reject EDL-resolved URLs through playlist
The ytdl wrapper can resolve web links to playlists. This playlist is
passed as big memory:// blob, and will contain further quite normal web
links. When playback of one of these playlist entries starts, ytdl is
called again and will resolve the web link to a media URL again.

This didn't work if playlist entries resolved to EDL URLs. Playback was
rejected with a "potentially unsafe URL from playlist" error. This was
completely weird and unexpected: using the playlist entry directly on
the command line worked fine, and there isn't a reason why it should be
different for a playlist entry (both are resolved by the ytdl wrapper
anyway). Also, if the only EDL URL was added via audio-add or sub-add,
the URL was accessed successfully.

The reason this happened is because the playlist entries were marked as
STREAM_SAFE_ONLY, and edl:// is not marked as "safe". Playlist entries
passed via command line directly are not marked, so resolving them to
EDL worked.

Fix this by making the ytdl hook set load-unsafe-playlists while the
playlist is parsed. (After the playlist is parsed, and before the first
playlist entry is played, file-local options are reset again.) Further,
extend the load-unsafe-playlists option so that the playlist entries are
not marked while the playlist is loaded.

Since playlist entries are already verified, this should change nothing
about the actual security situation.

There are now 2 locations which check load_unsafe_playlists. The old one
is a bit redundant now. In theory, the playlist loading code might not
be the only code which sets these flags, so keeping the old code is
somewhat justified (and in any case it doesn't hurt to keep it).

In general, the security concept sucks (and always did). I can for
example not answer the question whether you can "break" this mechanism
with various combinations of archives, EDL files, playlists files,
compromised sites, and so on. You probably can, and I'm fully aware that
it's probably possible, so don't blame me.
2019-09-19 20:37:04 +02:00
wm4 7fad173cfd demux, demux_edl: add extension for tracks sourced from separate streams
This commit adds an extension to mpv EDL, which basically allows you to
do the same as --audio-file, --external-file, etc. in a single EDL file.

This is a relatively quick & dirty implementation. The dirty part lies
in the fact that several shortcuts are taken. For example, struct
timeline now forms a singly linked list, which is really weird, but also
means the other timeline using demuxers (cue, mkv) don't need to be
touched. Also, memory management becomes even worse (weird object
ownership rules that are just fragile WTFs). There are some other
dubious small changes, mostly related to the weird representation of
separate streams.

demux_timeline.c contains the actual implementation of the separate
stream handling. For the most part, most things that used to be on the
top level are now in struct virtual_source, of which one for each
separate stream exists. This is basically like running multiple
demux_edl.c in parallel. Some changes could strictly speaking be split
into a separate commit, such as the stream_map type change.

Mostly untested. Seems to work for the intended purpose. Potential for
regressions for other timeline uses (like ordered chapters) is probably
low. One thing which could definitely break and which I didn't test is
the pseudo-DASH fragmented EDL code, of which ytdl can trigger various
forms in obscure situations. (Uh why don't we have a test suite.)

Background:

The intention is to use this for the ytdl wrapper. A certain streaming
site from a particularly brain damaged and plain evil Silicon Valley
company usually provides streams as separate audio and video streams.
The ytdl wrapper simply does use audio-add (i.e. adding it as external
track, like with --audio-file), which works mostly fine. Unfortunately,
mpv manages caching completely separately for external files. This has
the following potential problems:

1. Seek ranges are rendered incorrectly. They always use the "main"
stream, in this case the video stream. E.g. clicking into a cached range
on the OSC could trigger a low level seek if the audio stream is
actually not cached at the target position.

2. The stream cache bloats unnecessarily. Each stream may allocate the
full configured maximum cache size, which is not what the user intends
to do. Cached ranges are not pruned the same way, which creates disjoint
cache ranges, which only use memory and won't help with fast seeking or
playback.

3. mpv will try to aggressively read from both streams. This is done
from different threads, with no regard which stream is more important.
So it might happen that one stream starves the other one, especially if
they have different bitrates.

4. Every stream will use a separate thread, which is an unnecessary
waste of system resources.

In theory, the following solutions are available (this commit works
towards D):

A. Centrally manage reading and caching of all streams. A single thread
would do all I/O, and decide from which stream it should read next. As
long as the total TCP/socket buffering is not too high, this should be
effective to avoid starvation issues. This can also manage the cached
ranges better. It would also get rid of the quite useless additional
demuxer threads. This solution is conceptually simple, but requires
refactoring the entire demuxer middle layer.

B. Attempt to coordinate the demuxer threads. This would maintain a
shared cache and readahead state to solve the mentioned problems
explicitly. While this sounds simple and like an incremental change,
it's probably hard to implement, creates more messy special cases,
solution A. seems just a better and simpler variant of this. (On the
other hand, A. requires refactoring more code.)

C. Render an intersection of the seek ranges across all streams. This
fixes only problem 1.

D. Merge all streams in a dedicated wrapper demuxer. The general demuxer
layer remains unchanged, and reading from separate streams is handled as
special case. This effectively achieves the same as A. In particular,
caching is simply handled by the usual demuxer cache layer, which sees
the wrapper demuxer as a single stream of interleaved packets. One
implementation variant of this is to reuse the EDL infrastructure, which
this commit does.

All in all, solution A would be preferable, because it's cleaner and
works for all external streams in general.

Some previous commit tried to prepare for implementing solution A. This
could still happen. But it could take years until this is finally
seriously started and finished. In any case, this commit doesn't block
or complicate such attempts, which is also why it's the way to go.

It's worth mentioning that original mplayer handles external files by
creating a wrapper demuxer. This is like a less ideal mixture of A. and
D. (The similarity with A. is that extending the mplayer approach to be
fully dynamic and without certain disadvantages caused by the wrapper
would end up with A. anyway. The similarity with D. is that due to the
wrapper, no higher level code needs to be changed.)
2019-09-19 20:37:04 +02:00
wm4 1d0da7d950 demux: make demuxer list static, remove ancient comment
I'd actually very much encourage demuxer implementations outside
problematic libavformat.
2019-09-19 20:37:04 +02:00
wm4 4a6b56fe56 build: silence idiotic -Wformat-truncation
This warns about player/audio.c:253 with gcc 8.2.0. Although this
warning could be useful to check the worst case estimation, the compiler
doesn't explain how it gets its dumb, bogus result, so this is useless.
You'd just end up trying to make the compiler happy for no reason.
2019-09-19 20:37:04 +02:00
wm4 ff1f863bda demux_lavf: increase max. probe size
For those shitty mp3s with extremely large ID3v2/APIC tags, and for
which libavformat insists on reading all data until after the ID3v2.
2019-09-19 20:37:04 +02:00
wm4 c91e659f88 stream: redo buffer handling and allow arbitrary size for stream_peek()
struct stream used to include the stream buffer, including peek buffer,
inline in the struct. It could not be resized, which means the maximum
peek size was set in stone. This meant demux_lavf.c could peek only so
much data.

Change it to use a dynamic buffer. Because it's possible, keep the
inline buffer for default buffer sizes (which are basically always used
outside of file opening). It's unknown whether it really helps with
anything. Probably not.

This is also the fallback plan in case we need something like the old
stream cache in order to deal with mp4 + unseekable http: the code can
now be easily changed to use any buffer size.
2019-09-19 20:37:04 +02:00
wm4 ca142be7e8 demux: another unused function 2019-09-19 20:37:04 +02:00
wm4 475f61710e command: report unknown file size as unavailable, not -1 2019-09-19 20:37:04 +02:00
wm4 adbd035b50 demux: autoselection is gone
Was used by DVD, I think.
2019-09-19 20:37:04 +02:00
wm4 cb51dfa76a stats.lua: silence annoying fontconfig warnings
Apparently I don't have this font.
2019-09-19 20:37:04 +02:00
wm4 cfa5c73cb5 demux: remove some more minor dead code
Also add clarifications.
2019-09-19 20:37:04 +02:00
wm4 18180ae89b demux: get rid of ->control callback
The only thing left is the notification for track switching. Just get
rid of that.

There's probably no real reason to get rid of control(), but why not. I
think I was actually trying to do some real work but fuck that.
2019-09-19 20:37:04 +02:00
wm4 5114c69c7f demux: change hack for closing subtitle files early
Subtitles (and a few other file types, like playlists) are not streamed,
but fully read on opening. This means keeping the file handle or network
socket open is a waste of resources and could cause other weird
behavior. This is why there's a hack to close them after opening.

Change this hack to make the demuxer itself do this, which is less
weird. (Until recently, demuxer->stream ownership was more complex,
which is why it was done this way.)

There is some evil shit due to a huge ownership/lifetime mess of various
objects. Especially EDL (the currently only nested demuxer case)
requires being careful about mp_cancel and passing down stream pointers.

As one defensive programming measure, stop accessing the "stream"
variable in open_given_type(), even where it would still work. This
includes removing a redundant line of code, and removing the peak call,
which should not be needed anymore, as the remaining demuxers do this
mostly correctly.
2019-09-19 20:37:04 +02:00
wm4 b1c202c12f demux: make demux_open() private
I always wanted to get rid of this, because it makes the ownership rules
for the stream pointer really awkward. demux_edl.c was the only
remaining user of this. Replace it with a semi-clever idea: the init
segment shit can be used to pass the "file" contents as memory block,
and "memory://" itself provides an empty stream. I have no idea if this
actually works, because I didn't immediately find a test stream (would
have to be some youtube DASH shit).
2019-09-19 20:37:04 +02:00
wm4 5c7ecad93a demux: simplify API for returning cache status
Instead of going through those weird DEMUXER_CTRLs, query this
information directly. I'm not sure which kind of brain damage made me
use CTRLs for these. Since there are no other DEMUXER_CTRLs that make
sense for the frontend, remove the remaining infrastructure for them
too.
2019-09-19 20:37:04 +02:00
wm4 b298140b07 demux: return stream file size differently, rip out stream ctrls
The stream size return was the only thing that still required doing
STREAM_CTRLs from frontend through the demuxer layer. This can be done
much easier, so rip it out. Also rip out the now unused infrastructure
for STREAM_CTRLs via demuxer layer.
2019-09-19 20:37:04 +02:00
wm4 f77515ebaf stream_libarchive: remove base filename stuff
Apparently this was so that when playing a video file from a .rar file,
it would load external subtitles with the same name (instead of looking
for mpv's rar:// mangled URL). This was requested on github almost 5
years ago. Seems like a weird feature, and I don't care. Drop it,
because it complicates some in progress change.
2019-09-19 20:37:04 +02:00
wm4 0fa38121a6 demux_timeline: fix off by one error, rearrange weird code
This code set pkt->stream to a value which I'm not sure whether it's
correct. A recent commit overwrote it with a value that is definitely
correct.

There appears to be an off by one error. No fucking clue whether this
was somehow correct, but applying an apparent fix does not seem to break
anything, so whatever.
2019-09-19 20:37:04 +02:00
wm4 b9be20b529 demux: return packets directly from demuxer instead of using sh_stream
Preparation for other potential changes to separate demuxer cache/thread
and actual demuxers.

Most things are untested, but it seems to work somewhat.
2019-09-19 20:37:04 +02:00
wm4 8a83430ae7 DOCS/edl-mpv: document a dumb thing
EDLs can be provided either as external file, or "inline" as a big
edl:// URL. There is no difference between them, except if it's loaded
from an external file, there is some weird filename sanitation going on
(see fix_filenames() in demux_edl.c). It seems this is intended to be a
security mechanism, but probably makes no sense at all.

Note that playlists are allowed to access anything locally. One
difference to playlists is that the EDL code lacks the "security"
mechanism when accessing playlist entries (see handling of the
playlist_entry.stream_flags field - EDL would need something similar),
so don't remove that, as I'm unaware of the exact consequences.
2019-09-19 20:37:04 +02:00
wm4 4bc96e8204 command: make playlist builtin OSD property show titles instead of URLs
Useful for ytdl.
2019-09-19 20:37:04 +02:00
wm4 8ca4386366 stream_libarchive: fix another crash with broken rar files
libarchive (sometimes affectionately called libcve) has this annoying
behavior that if after a "fatal" error, you do any operation on the
archive context other than querying the error and closing the context,
you get a free CVE. So we close the archive context in these situations.
This can set p->mpa to NULL, so code accessing this field needs to be
careful.

This was not considered in a certain code path, and a simple truncated
.rar file made it crash. Part of the problem was that the file inside
the rar was a mkv file, which triggered seeking when the demux_mkv
resync code encountered bogus data.

This is probably a regression from a relatively recent change to this
code (in any case mpv 0.29.1 doesn't crash).

Fix this by adding the check.

There's also a mechanism to reopen an archive context used to emulate
seeking, since most libarchive format handlers don't support this
natively. Add a reopen call to the codepath, because obviously it should
always be possible to seek back into a "working" area of the file.

There is a second bug with this: if reopening fails, we don't adjust the
current position back to 0, which in some cases means we accidentally
return bogus data to the reader when we shouldn't. Fix this by always
resetting the position on reopening.
2019-09-19 20:37:03 +02:00
Jan Ekström e5c1cf2e3e sub/sd_ass: always set the libass track type to TRACK_TYPE_ASS
It would always autodetect it based on the passed style block,
but as we are defining it - we might as well define it always.

(As far as I can see all decoders in libavcodec utilize 4+ style
blocks)
2019-09-19 00:02:03 +03:00
Jan Ekström 2d74b2d832 sub/sd_ass: utilize UINT32_MAX subtitle duration for unknown
US closed captions, teletext and ARIB caption decoders utilize this
value.
2019-09-19 00:02:03 +03:00
Jan Ekström 1b9370ff92 sub/lavc_conv: switch to the newer "ass" subtitle decoding mode
Existing since 2016, this removes timestamps from the lines,
and gives more precision in the timestamps (1:1000).
2019-09-19 00:02:03 +03:00
dudemanguy 80c4aaa2a4 wayland: fix wl_proxy leak
This one is probably not terribly obvious from just the valgrind log,
but a wayland dev explained it to me just a second ago. Whenever mpv
sends events to the screen with wl_display_dispatch, wayland internally
allocates memory to a struct wl_proxy object if a new id is found. Quite
a few more things happen to that proxy object, but eventually mpv stores
the data on the client-side in a wrapper type of struct (struct
wl_data_offer). mpv's data_device_listener keeps track of those proxies
and frees the memory when appropriate. Of course, mpv is constantly
sending events to the screen and does so until the user quits the
player. What happens here is that one final wl_display_dispatch is called
right before the user quits the player and before mpv's
data_device_listener can handle that object. So the result is that you
always have one extra dangling proxy that doesn't get properly freed.
The solution is to just simply call wl_data_offer_destroy before closing
the wl_display to free that final dangling wl_proxy.
2019-09-19 00:00:19 +03:00
Anton Kindestam e08f235578 drm: fix libmpv ABI breakage introduced in 351c083487
Extending the client-allocated mpv_opengl_drm_params struct
constituted a break of ABI that could cause UB.

Create a clean break by deprecating "drm_params" and related structs
and enum values, and replacing it with "drm_params_v2".

Also fix some comments and code that wrongly assumed that open could
return any other negative number than -1 for failure.

This commit updates the libmpv version to 1.104
2019-09-18 23:59:32 +03:00
wm4 b04ddcdc0b stream: stop randomly corrupting memory
The intent of the line above the modified one code was raising the
amount of read data, so that many stream_peek() calls with small len
values would not degrade performance by effectively turning every
stream_peak() into an unbuffered read call to the stream implementation.
So this confusing looking MPMAX() was correct, but "chunk" could still
get beyond the buffer.

So just fix that and limit "chunk" correctly.

I'm not sure whether the commit referenced below accidentally removed
some intricate guarantee that this couldn't happen, since the code was
around since 2013. It could have relied on TOTAL_BUFFER_SIZE >
STREAM_BUFFER_SIZE. But not sure. I've rewritten all this code in my own
branch a year ago, so who knows.

Fixes: 162e0f5ad9
Fixes: #6948
2019-09-18 20:47:40 +02:00
Philip Langdale fa0a905ea0 vo_gpu: hwdec_vaapi: Refactor Vulkan and OpenGL interops for VAAPI
Like hwdec_cuda, you get a big #ifdef mess if you try and keep the
OpenGL and Vulkan interops in the same file. So, I've refactored
them into separate files in a similar way.
2019-09-15 17:51:47 -07:00
Philip Langdale 237f5fa1b7 vo_gpu: hwdec_cuda: Improve interop selection mechanism
This change updates the interop selection to match what I did for
VAAPI, by iterating through an array of init functions until one
of them works.
2019-09-15 17:51:47 -07:00
wm4 0abe34ed21 vo_gpu: x11: remove special vdpau probing, use EGL by default
Originally, vo_gpu/vo_opengl considered the case of Nvidia proprietary
drivers, which required vdpau/GLX, and Intel open source drivers, which
require vaapi/EGL. Since window creation and GPU context creation are
inseparable in mpv's internal API, it had to pick the correct API very
early, or hardware decoding wouldn't work. "x11probe" was introduced for
this reason. It created a GLX context (without showing the window yet),
and checked whether vdpau was available. If yes, it used GLX, if not, it
continued probing x11/EGL. (Obviously it couldn't always fail on GLX
without vdpau, which is why it was a separate "probe" backend.)

Years passed, and now the situation is different. Vdpau is dead. Nvidia
drivers and libavcodec now provide CUDA interop, which requires EGL, and
fixes some of the vdpau problems. AMD drivers now provide vaapi, which
generally works better than vdpau. Intel didn't change.

In particular, vaapi provides working HEVC Main10 support. In theory, it
should work on vdpau too, with quality reduction (no 10 bit surfaces),
but I couldn't get it to work.

So always prefer EGL. And suddenly hardware decoding works. This is
actually rather important, because HEVC is unfortunately on the rise,
despite shitty encoders and unoptimized decoders. The latter may mean
that hardware decoding works better than libavcodec.

This should have been done a long, long time ago.
2019-09-15 20:00:52 +03:00
wm4 6385a5fd1b vf_vavpp: disable this filter
Might be unreasonable, but I'm angry at the shit driver freezing my
machine.
2019-09-15 17:59:25 +02:00
Niklas Haas a416b3f084 vo_gpu: correctly normalize src.sig_peak
In some cases, src.sig_peak remains undefined as 0, which was definitely
the case when using the OSD, since it never got passed through the usual
color space normalization process. Most robust work-around is to simply
force the normalization at the site where it's needed. This ensures this
value is always valid and defined, to make the peak-dependent logic in
these two functions always work.

Fixes 4b25ec3a9d
Fixes #6917
Fixes #6918
2019-09-15 01:33:27 +02:00
sfan5 ee0f4444f9 image_writer: add webp-compression option 2019-09-14 23:02:39 +02:00
sfan5 0f79444c6d image_writer: add WebP support (lossy or lossless) 2019-09-14 23:02:39 +02:00
sfan5 8925f10962 image_writer: move convert_image() to player/screenshot.c 2019-09-14 23:02:39 +02:00
Niklas Haas 7cf288ec77 DOCS: remove references to --video-stereo-mode
This option was removed by a5610b2a but the documentation persisted.
Also adds an OPT_REMOVED.

Closes #6938.
2019-09-14 21:16:38 +02:00
wm4 3a035f2a8c README: remove old googlegroups mailing list address
Is anyone still monitoring this in any way? I think not.
2019-09-14 16:40:50 +02:00
sfan5 46aa3394bf manpage: minor fixes to VO manpage 2019-09-14 13:50:10 +02:00
sfan5 5c313f1f59 vo: add warning message to vo_vaapi and vo_vdpau
These are a common source of bug reports, due to misconceptions that
they are required to make use of hardware decoding.
2019-09-14 13:50:10 +02:00
Hui Jin fda45f4537 vo_d3d11/context: fix crash due to ctx->ra is null pointer access
'ctx->ra' is null pointer when d3d11 init failed before call 'ra_d3d11_create' in 'd3d11_init'.
2019-09-14 21:35:49 +10:00
Hui Jin 191737b9c9 vo_d3d11/hwdec_dxva2dxgi: fix memory leak that 'ctx11' be not release
'ctx11' be not release when d3d11 hwdec be uninit with 'mapper_uninit' method.
2019-09-14 21:35:49 +10:00
wm4 116ab73566 stream_smb: remove unnecessary short write logic
See previous commit. It compiles, but 100% untested.
2019-09-14 13:00:43 +02:00
wm4 22568fece6 stream_file: remove unnecessary short write logic
See previous commit.
2019-09-14 13:00:10 +02:00
wm4 bec218c4ad stream: handle short writes
The write functionality is almost unused (only encoding 2-pass mode uses
it to write the log file). Moreover, it almost makes no sense to use
this in a not local scenario. This change is just to prevent people from
duplicating the short write logic across all streams that happen to
support writing. Mostly untested; local log file writing still works.
2019-09-14 12:55:06 +02:00
wm4 ebab42c9a8 ci: remove now unuspported libdvdread 2019-09-13 18:19:50 +02:00
wm4 a25b3d61a1 demux, stream: remove old rar support in favor of libarchive
The old rar code could do uncompressed rar, libarchive supports at least
some rar compression algorithms. There is no need to keep the old rar
code.
2019-09-13 17:35:06 +02:00
wm4 a75b249b0b command, demux: remove program property
The "program" property could switch between TS programs. It was rather
complex and rather obscure (even if you deal with TS captures, you
usually don't need it). If anyone actually needs it (did anyone ever
attempt to even use it?), it should be rewritten. The demuxer should
export a program list, and the frontend should handle the "cycling"
logic.
2019-09-13 17:33:58 +02:00
wm4 ddcbe66768 stream: remove some more optical disc leftovers 2019-09-13 17:32:21 +02:00
wm4 b30e85508a Remove classic Linux analog TV support, and DVB runtime controls
Linux analog TV support (via tv://) was excessively complex, and
whenever I attempted to use it (cameras or loopback devices), it didn't
work well, or would have required some major work to update it. It's
very much stuck in the analog past (my favorite are the frequency tables
in frequencies.c for analog TV channels which don't exist anymore).

Especially cameras and such work fine with libavdevice and better than
tv://, for example:

  mpv av://v4l2:/dev/video0

(adding --profile=low-latency --untimed even makes it mostly realtime)

Adding a new input layer that targets such "modern" uses would be
acceptable, if anyone is interested in it. The old TV code is just too
focused on actual analog TV.

DVB is rather obscure, but has an active maintainer, so don't remove it.
However, the demux/stream ctrl layer must go, so remove controls for
channel switching. Most of these could be reimplemented by using the
normal method for option runtime changes.
2019-09-13 17:32:19 +02:00
wm4 162e0f5ad9 stream: remove BD/DVD/CDDA sector size alignment
This was possibly needed by libdvdread, and/or old CD drivers on some
system. It still works with on-filesystem DVD and BD test images, so
this can go.
2019-09-13 17:32:05 +02:00
wm4 a9d83eac40 Remove optical disc fancification layers
This removes anything related to DVD/BD/CD that negatively affected the
core code. It includes trying to rewrite timestamps (since DVDs and
Blurays do not set packet stream timestamps to playback time, and can
even have resets mid-stream), export of chapters, stream languages,
export of title/track lists, and all that.

Only basic seeking is supported. It is very much possible that seeking
completely fails on some discs (on some parts of the timeline), because
timestamp rewriting was removed.

Note that I don't give a shit about optical media. If you want to watch
them, rip them. Keeping some bare support for DVD/BD is the most I'm
going to do to appease the type of lazy, obnoxious users who will care.
There are other players which are better at optical discs.
2019-09-13 17:31:59 +02:00
wm4 cf36e3d15b stream_dvdnav: merge stream_dvd_common
Isolate icky DVD garbage into a single file.
2019-09-13 15:35:23 +02:00
wm4 6229404985 Remove libdvdread support in favor of libdvdnav
stream_dvd.c contained large amounts of ancient, unmaintained code,
which has been historically moved to libdvdnav. Basically, it's full of
low level parsing of DVD on-disc structures.

Kill it for good. Users can use the remaining dvdnav support (which
basically operates in non-menu mode). Users have reported that
libdvdread  sometimes works better, but this is just libdvdnav's problem
and not ours.
2019-09-13 15:29:27 +02:00
Aman Gupta 877ae46125 stream_file: avoid redundant free
s->priv->cancel will be freed when s is freed, so
freeing it explicitly is not required.

Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-09-11 13:10:03 -07:00
Avi Halachmi (:avih) 44f8dccfb6 js: expose mpv_abort_async_command() (match dbe831bd)
With minor difference from lua, as documented.
2019-09-11 21:08:04 +03:00
Avi Halachmi (:avih) ad0a525f20 js: reimplement subprocess_detached using the run command (match 7f91e268) 2019-09-11 21:08:04 +03:00
Avi Halachmi (:avih) fea39b5a6b js: reimplement subprocess using the subprocess command (match 548ef078)
Semantics changes are the same as at 548ef078 .

Also, the previous C implementation returnd a string for the `stdout`
value, but stdout of the subprocess command is MPV_FORMAT_BYTE_ARRAY
which js previously didn't support, so support it too (at pushnode)
by returning it as a string - the same as the lua code does.
2019-09-11 21:08:04 +03:00
Avi Halachmi (:avih) 5b5f776900 js: expose async commands (match 159379980e) 2019-09-11 21:08:04 +03:00
Avi Halachmi (:avih) fc56798aca js: correctness: use integer range checks
There were some cases where a js number (double) was blindly casted to
int or uint64, but that can be undefined behavior (out of range to int)
or wrong (negative to uint).

Now the code throws a js error if the value is out of range.

Additionally, commit ec625266 added these checks for the new hooks API,
but incorrectly tested int64 range rather than uint64. Fix this too.
2019-09-11 21:08:04 +03:00
dudemanguy 6e6ec33168 audio: block ao buffer for keep-open
This prevents the pause state from triggering before the audio output is
finished playing back audio. This is particularly helpful for gapless
audio.
2019-09-09 00:01:16 +02:00
wm4 10a1b98082 vo_gpu: x11egl: support Mesa OML sync extension
Mesa supports the EGL_CHROMIUM_sync_control extension, and it's
available out of the box with AMD drivers. In practice, this is exactly
the same as GLX_OML_sync_control, but for EGL. The extension
specification is separate from the GLX one though, and buried somewhere
in the Chromium code.

This appears to work, although I don't know if it really works.

In theory, this could be useful for other EGL targets. Support code for
it could have been added to egl_helpers.c to avoid some minor duplicated
glue code if another EGL target were to provide this extension. I didn't
bother with that. ANGLE on Windows can't support it, because the
extension spec. explicitly requires POSIX timers. ANGLE on Linux/OSX is
actively harmful for mpv and hopefully won't ever use it. Wayland uses
EGL, but has its own fancy presentation feedback stuff (and besides, I
don't think basic video player functionality works on Wayland at all).
context_drm_egl maybe? But I think DRM has its own stuff.
2019-09-08 23:23:43 +10:00
wm4 8d7960f6ef vo_gpu: glx: move OML sync code to an independent file
So the next commit can make EGL use it. EGL has a quite similar
function, that practically works the same. Although it's relatively
trivial, it's still tricky, and probably shouldn't end up as duplicated
code.

There are no functional changes, except initialization, and how failure
of the glXGetSyncValues call is handled. Also, some comments mention the
EGL extension.

Note that there's no intention for this code to handle anything else
than the very specific OML sync extension (and its EGL equivalent). This
is just too weirdly specific to the weird idiosyncrasies of the
extension, and it makes no sense to extend it to handle anything else.
(Such as Wayland or DXGI presentation feedback.)
2019-09-08 23:23:43 +10:00
Niklas Haas 4b25ec3a9d vo/gpu: fix check on src/dst peak mismatch
In the past, src peak was always equal to or higher than dst peak. But
since `--target-peak` got introduced, this could no longer be the case.
This leads to an incorrect result (scaling for peak mismatch in gamma
light) unless some other option (CMS, --linear-scaling, etc.) forces the
linearization.

Fixes #6533
2019-09-05 19:13:44 +03:00
Guido Cella 6d90517275 external_files: add .lrc subtitle extension 2019-09-02 01:25:43 +03:00
Tom Yan 763eaad2aa demux: ignore forced demuxer type for directories
this for example allows --demuxer=rawaudio to work on directories
2019-09-02 01:24:26 +03:00
Oliver Freyermuth c8424a3bee stream_dvb: Increase timeout of streaming read.
It seems some DVB-T2 cards take longer to push out data.
2019-09-02 01:19:33 +03:00
Oliver Freyermuth 66128dec82 stream_dvb: Adapt to VDR channel config format.
While they accept the frequency field with MHz for DVB-S,
for DVB-C and DVB-T, it may be in Hz, kHz or MHz.
The official rule is to multiply whatever is in the channels.conf
by 1000 until a value > 1000000 is reached to get correct units for tuning.
2019-09-02 01:19:33 +03:00
Jan Janssen 94c414bd1c osc: improve look of seekranges 2019-09-02 01:11:04 +03:00
der richter c8a911f35f cocoa-cb: remove an unused variable 2019-09-02 00:39:36 +03:00
sfan5 8f96169117 ao_opensles: fix delayed audio
This was forgotten in commit 5a8c48fde2
when the number of buffers was reduced to 1.
2019-09-02 00:38:05 +03:00
Jan Ekström 56d31ae190 travis: rework scripts to re-enable macOS
* Adds a script to clone and build FFmpeg as well as
  to configure and build mpv itself. Currently only used
  for macOS and contain hard-coded macOS specific options.
* Still works with the Linux containers.
* Moves our language back to "c" from "generic"
* Defines our Linux distribution as "bionic" to get the latest
  Ubuntu base distribution to be the runner for our containers.
* Adds the homebrew add-on for macOS package installation for
  dependencies. Installs everything required but FFmpeg, as we want
  to have our own FFmpeg snapshots.
2019-09-02 00:34:49 +03:00
Philip Langdale b539eb222b vo/gpu: vulkan: Pass the device name option through to libplacebo
We collect a 'vulkan-device' option today but then don't actually
pass it on, so it's useless. Once that's fixed, it can be used
to select a specific vulkan device by name.

Tested with the new nvidia offload feature to select between the
nvidia and intel GPUs.
2019-08-24 18:38:27 +02:00
James Ross-Gowan 80552ab28e vo_gpu: d3d11: fix storage lifetime of compound literals
Somehow I got the idea that compound literals had function-scoped
lifetime. Instead, like all other objects with automatic storage
duration, compound literals are block-scoped, so they become invalid
after exiting the block they were declared in. It seems like a recent
change to GCC actually reuses the memory that the compound literals
used to occupy, which was causing a few bugs.

The pattern of conditionally assigning a pointer to a compound literal
was used in a few places in ra_d3d11 where the Direct3D API expects
either a pointer to an initialised struct or NULL. Change these to
ensure the lifetime of the struct includes the API call.

Should fix #6775.
2019-08-20 18:12:21 +10:00
ekisu cd7bcb9d0c encode: set sample_aspect_ratio on AVStream struct
Some libavformat muxers (e.g. matroskaenc.c) expect this field to be set
on the AVStream struct, and not only in the AVCodecParameters.
2019-08-14 21:54:44 +02:00
wnoun ae8cb39ab2 vo_gpu: fix taking screenshots of rotated videos 2019-08-14 21:54:14 +02:00
Philip Langdale 639ee55df7 vo_gpu: hwdec_vaapi: Synchronise after exporting VA surface
This is documented as required (although we did not do it in
the old GL codepath, with no visible problems) and I have seen
transient artifacts after seeking which _appear_ to have gone
away after introducing this.
2019-08-07 10:51:43 +02:00
Ricardo Constantino 69c93b6f0e DOCS/compile-windows: remove angleproject-git from deps
Basically just to trigger a doc rebuild, but might as well do a useful
change, since angleproject-git is no longer a valid package in MSYS2.
2019-07-30 23:57:50 +01:00
Ricardo Constantino 82ba31c636 TOOLS/travis-rebuild-website: update condition after docker transition
Closes #6822
2019-07-30 20:12:33 +01:00
der richter a8c2e29868 cocoa-cb: migrate to swift 5 with swift 4 fallback
this migrates our current swift code to version 5 and 4. building is
support from 10.12.6 and xcode 9.1 onwards.

dynamic linking is the new default, since Apple removed static libs
from their new toolchains and it's the recommended way.

additionally the found macOS SDK version is printed since it's an
important information for finding possible errors now.

Fixes #6470
2019-07-21 18:13:07 +03:00
der richter 0602f082cb cocoa-cb: fix optional cases on macOS 10.12 2019-07-21 18:13:07 +03:00
der richter 4a8bf91d4c build: fix build with older command line tools 2019-07-21 18:13:07 +03:00
der richter 916f4146a7 build: make macOS SDK path and version configurable via env vars 2019-07-21 18:13:07 +03:00
der richter c540ac8485 cocoa-cb: conditional compilation for Dark Mode and Material features
Fixes #6621
2019-07-21 18:13:07 +03:00
der richter 850b303732 build: add check for macOS SDK version
this provides an easy way to check for a specific macOS SDK version and
with that the availability of features.
2019-07-21 18:13:07 +03:00
der richter 9a2c760614 osxbundle: bundle the dynamic swift std library when needed 2019-07-21 18:13:07 +03:00
der richter efde2d8644 osxbundle: print the output of the dylib-unhell call 2019-07-21 18:13:07 +03:00
der richter 3f6d79ddb6 build: add Swift dynamic linking support
this is in preparation for the upcoming swift 5 transition, where static
linking was replaced by dynamic linking the swift libraries as the
preferred way, by Apple. furthermore Apple removed the static swift libs
from their dev Tools starting with xcode 10.2/swift 5.

because of ABI incompatibility dynamic linking for swift versions prior
to 5 doesn't use the system lib path for the dynamic swift libs.

for now static linking is still the default, but that will be changed
when swift 5 support is added and swift 3 support is dropped.

Fixes #6232
2019-07-21 18:13:07 +03:00
der richter 770fc52215 build: make Swift lib and compiler paths configurable via env vars 2019-07-21 18:13:07 +03:00
der richter 76858ba91c build: add support for Swift toolchains not provided by Apple
the xcode-select tool only properly works with Apple provided toolchains
but not with third party ones from swift.org. in the latter case the
swift compiler executable is found in the proper path but the swift libs
from the xcode or command line tools will be picked. this leads to a
not wanted discrepancy of the swift compiler and libs and possible
errors.

instead of relying on the xcode-select tool search for the libs relative
to the swift executable. that relative path seems to be the same for all
toolchains. if for any reasons a swift executable is not found in the
relative path, fall back to the old xcode-select method.

furthermore, both static and dynamic libs will be searched for but only
the former will be used for now. this is a preparation for the upcoming
swift 5 migration.
2019-07-21 18:13:07 +03:00
der richter bc014f2ad4 build: add all configure flags as conditional flags to Swift compiler 2019-07-21 18:13:07 +03:00
der richter f7f5bd80bb build: don't check for Swift when disabled 2019-07-21 18:13:07 +03:00
dudemanguy 65b1c2d065 client: fix potential mpv_cmd/async leak 2019-07-08 16:42:47 +02:00
Philip Langdale b5b0350371 vo_gpu: hwdec_vaapi: Count planes rather than layers in Vulkan interop
We saw a segfault when trying to use the intel-media-driver (iHD)
rather than the normal intel va driver. This happened because the
iHD driver reports P010 (and maybe other formats) with multiple
layers to represent the interleaved UV plane. The normal va driver
reports one UV layer to match the plane.

This threw off my logic which assumed that the number of layers
could not exceed the number of planes.

There's a way one could fix this in a fully generalised form, but
I'm just going to do what the EGL path does and assume that:
 * Layer 'n' is on Plane 'n' for n < total number of planes
 * These layers always start at offset 0 on the plane

You can imagine ways that these assumptions are violated, but at
least the failure will look the same for both EGL and Vulkan
paths.
2019-07-08 01:57:02 +02:00
Philip Langdale b33ced193e vo_gpu: hwdec_vaapi: Suppress format errors when probing
Today, we normally see a format error when probing because yuyv422
cannot be used, but it's in the normal set of probed formats.

This error is distracting and confusing, so only log probing errors
at the VERBOSE level.

Fixes #6411
2019-07-08 01:57:02 +02:00
Philip Langdale b70ed35ba4 vo_gpu: hwdec_vaapi: Add Vulkan interop
This change introduces a vulkan interop path for the vaapi hwdec.
The basic principles are mostly the same as for EGL, with the
exported dma_buf being imported by Vukan. The biggest difference
is that we cannot reuse the texture as we do with OpenGL - there's
no way to rebind a VkImage to a different piece of memory, as far
as I can see. So, a new texture is created on each map call.

I did not bother implementing a code path for the old libva API as
I think it's safe to assume any system with a working vulkan driver
will have access to a newer libva.

Note that we are using separate layers for the vaapi surface, just
as is done for EGL. This is because libplacebo doesn't support
multiplane images.

This change does not include format negotiation because no driver
implements the vk_ext_image_drm_format_modifier extension that
would be required to do that. In practice, the two formats we care
about (nv12, p010) work correctly, so we are not blocked. A separate
change had to be made in libplacebo to filter out non-fatal validation
errors related to surface sizes due to the lack of format negotiation.
2019-07-08 01:57:02 +02:00
Philip Langdale 6842755feb vo_gpu: hwdec_vaegl: Rename and move to hwdec_vaapi
In preparation for adding Vulkan interop support, let's rename
to remove the egl reference and move to an api neutral location.
2019-07-08 01:57:02 +02:00
Chainik 7f0f1a1b72 vf_vapoursynth: allow multithreaded writing of source frames 2019-07-08 01:53:22 +02:00
Chainik 5907bc023c vf_vapoursynth: allow multithreaded reading of returned frames 2019-07-08 01:53:22 +02:00
Philip Langdale 1638fa7b46 vo/gpu: hwdec_vdpau: Support direct mode for 4:4:4 content
New releases of VDPAU support decoding 4:4:4 content, and that comes
back as NV24 when using 'direct mode' in OpenGL Interop. That means we
need to be a little bit smarter about how we set up the OpenGL
textures.
2019-07-08 01:11:27 +02:00
Michael Forney 13e14d95e1 opengl/context_wayland: Fix crash on configure before initial reconfig
If the compositor sends a configure event before the surface is initially
mapped, resize gets called before the egl_window gets created, resulting
in a crash in wl_egl_window_resize.

This was fixed back in 618361c697, but was reintroduced when the wayland
code was rewritten in 68f9ee7e0b.
2019-07-08 01:00:01 +02:00
Philip Langdale e2976e662d video/out/gpu: Add a storable flag to ra_format
While `ra` supports the concept of a texture as a storage
destination, it does not support the concept of a texture format
being usable for a storage texture. This can lead to us attempting
to create a texture from an incompatible format, with undefined
results.

So, let's introduce an explicit format flag for storage and use
it. In `ra_pl` we can simply reflect the `storable` flag. For
GL and D3D, we'll need to write some new code to do the compatibility
checks. I'm not going to do it here because it's not a regression;
we were already implicitly assuming all formats were storable.

Fixes #6657
2019-07-08 00:59:28 +02:00
wm4 c379950ce0 codec_tags: fix wrong buffer size
Obvious mistake. This reported 44 bytes more data than what was
available. Could cause out of bounds reads. Security researchers would
claim a major victory if they found something like this in more popular
software, and would create a website for it.
2019-07-03 17:47:24 +03:00
James Ross-Gowan ea91162802 appveyor: remove broken packages, install libplacebo
Support for Ada and Objective-C was removed from MSYS2, which made
pacman refuse to update GCC while the gcc-ada and gcc-objc packages were
installed. Remove those packages before updating the others. Also remove
ANGLE, which has been removed from MSYS2, and add libplacebo, which is
now needed for the Vulkan VO.
2019-07-03 17:30:50 +03:00
Bin Jin c9e7473d67 vo_gpu: process three component together in error diffusion
This started as a desperate attempt to lower the memory requirement
of error diffusion, but later it turns out that this change also
improved the rendering performance a lot (by 40% as I tested).

Errors was stored in three uint before this change, each with 24bit
precision. This change encoded them into a single uint, each with 8bit
precision. This reduced the shared memory usage, as well as number of
atomic operations, all by three times.

Before this change, with the minimum required 32kb shared memory, only
the `simple` kernel can be used to render 1080p video, which is mostly
useless compare to `--dither=fruit`. After this change, 32kb can
handle `burkes` kernel for 1080p, or `sierra-lite` for 4K resolution.
2019-06-16 11:19:44 +02:00
Bin Jin f6fd127fe8 vo_gpu: fix use of existing textures in error diffusion
error diffusion requires two texture rendering pass. The existing code
reuses `screen_tex` and creates another for such purpose. This works
generally well for opengl, but could potentially be problematic for
vulkan, due to its async natural.
2019-06-16 11:19:44 +02:00
Bin Jin ca2f193671 vo_gpu: implement error diffusion for dithering
This is a straightforward parallel implementation of error diffusion
algorithms in compute shader. Basically we use single work group with
maximal possible size to process the whole image. After a shift
mapping we are able to process all pixels column by column.

A large ring buffer are allocated in shared memory to speed things up.
However the size of required shared memory depends linearly on the
height of video window (or screen height in fullscreen mode). In case
there is no enough shared memory, it will fallback to `--dither=fruit`.

The maximal allowed work group size is hardcoded as 1024. Ideally we
could query `GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS`. But for whatever
reason, it seems most high end card from nvidia and amd support only
the minimal required value, so I guess we can stick to it for now.
2019-06-16 11:19:44 +02:00
Martin Herkt 6aecd10eba ci: Remove snapshot-deps config from tw builds
OBS isn’t really set up to support this. If needed, we should instead
git clone FFmpeg as part of the CI. I don’t think it is, though.
2019-06-14 05:24:35 +02:00
Martin Herkt 59f1e72a3c build: Add support for static spirv-cross
This assumes a non-upstream .pc file since upstream doesn’t seem
to give a fuck about this use case at all.
2019-06-14 04:56:30 +02:00
Philip Sequeira a38aa74454 demux_mkv: copy attachments (fonts) from ordered chapter sources
They might be needed for rendering subs from those sources.

Fixes #6009.
2019-06-12 23:34:47 +03:00
James Ross-Gowan cc38035841 vo_gpu: d3d11: use the SPIRV-Cross C API directly
When the D3D11 backend was first written, SPIRV-Cross only had a C++ API
and no guarantee of API or ABI stability, so instead of using
SPIRV-Cross directly, mpv used an unofficial C wrapper called crossc.

Now that KhronosGroup/SPIRV-Cross#611 is resolved, SPIRV-Cross has an
official C API that can be used instead, so remove crossc and use
SPIRV-Cross directly.
2019-06-12 23:03:55 +03:00
Bin Jin fbe267150d vo_gpu: fix --scaler-resizes-only for fractional ratio scaling
The calculation of scale factor involves 32-bit float, and a strict
equality test will effectively ignore `--scaler-resizes-only` option
for some non-integer scale factor.

Fix this by using non-strict equality check.
2019-06-06 20:01:56 +02:00
Bin Jin f2119d9d88 vo_gpu: expose texture_off to user shader
It will provide low level access to coordinate mapping other than
texmap().
2019-06-06 20:01:56 +02:00
Bin Jin ae1c489b31 vo_gpu: allow user shader to fix texture offset
This commit essentially makes user shader able to fix offset (produced
by other prescaler, for example) like builtin `--scale`.
2019-06-06 20:01:56 +02:00
Niklas Haas 4d001bb30d wayland: fix segfault on uninit
Probably the same issue as #6732
2019-05-26 11:09:16 +02:00
dudemanguy 6e4971f697 wayland: fix various memory leaks 2019-05-21 22:41:22 +02:00
der richter 64cdc3694e cocoa-cb: fix quit in fs with none native fs
since the none native fs is a special legacy case it needs a special
quit routine. it indefinitely waited for an exit fs screen event to
shutdown properly, though that event only fires for the native fs.
now we check if we really are using a native fullscreen and if not
shutdown immediately.

Fixes #6704
2019-05-11 12:54:44 +02:00
James Ross-Gowan 86bdd22060 win32-console-wrapper: silence missing prototype warnings 2019-05-10 21:06:58 +10:00
James Ross-Gowan c754c31d6f w32_common: avoid unnecessary sprintfs
These were unnecessary for a couple of reasons, but it seems like the
old code went through a lot of effort to avoid duplicating the code to
print a RECT, even though the windowrc gets printed anyway at the end of
the function.

Avoid printing the same windowrc twice by only printing it when it gets
changed (in the w32->current_fs branch.)
2019-05-10 20:47:05 +10:00
Nicolas F 91c1691b35 man: clarify vavpp requirements
I assume (but cannot confirm) that VA-AP-API is in fact a typo, because
most if not all search engine results related to it are from mpv's manual
page.

By changing this to VA-API and clarifying that this requires VA-API support
on a system to use it, we can hopefully make it clear to unsuspecting
Windows users that this is not the filter they're looking for.

Concerns #6690.
2019-05-05 21:06:18 +02:00
dudemanguy 037cbacb8c libarchive: add fallback for systems without C.UTF-8 2019-05-04 14:17:40 +02:00
Anton Kindestam dcb7838bb7 drm_common: Support --drm-mode=<preferred|highest|N|WxH[@R]>
This allows to select the drm mode using a string specification. You
can either select the the preferred mode, the mode with the highest
resolution, by specifying WxH[@R] or by its index in the list of modes
as before.
2019-05-04 14:17:11 +02:00
Anton Kindestam d155b7541f drm_common: Don't export functions only being used internally
As far as I know none of these functions were being used outside of
drm_common, nor should there really be a need to use them.
2019-05-04 14:17:11 +02:00
Anton Kindestam 8261924db9 drm_common: Add proper help option to drm-mode
This was implemented by using OPT_STRING_VALIDATE for drm-mode,
instead of OPT_INT. Using a string here also prepares for future
additions to drm-mode that aim to allow specifying a mode by its
resolution.
2019-05-04 14:17:11 +02:00
Anton Kindestam a776628d88 drm_common: Add option to toggle use of atomic modesetting
It is useful when debugging to be able to force atomic off, or as a
workaround if atomic breaks for some user. Legacy modesetting is less
likely to break by virtue of being a less complex API.
2019-05-04 14:17:11 +02:00
Philip Langdale 23a324215b vo/gpu: hwdec_cuda: Refactor gpu api specific code into separate files
The amount of code now present that's specific to Vulkan or OpenGL
has reached the point where we really want to split it out to
avoid a mess of #ifdefs.

At the same time, I'm moving the code to an api neutral location.
2019-05-03 18:02:18 +02:00
Anton Kindestam 738fda3677 context_drm_egl: Add support for presentation feedback
This implements presentation feedback for context_drm_egl using the
values that get fed to the page flip handler.
2019-05-03 18:01:56 +02:00
der richter 71ad1e2f4c cocoa-cb: remove all force unwrappings of optionals
the force unwrapping of optionals caused many unpredictable segfaults
instead of gracefully exiting or falling back. besides that, it is bad
practice and the code is a lot more stable now.
2019-04-25 23:02:19 +03:00
Jan Ekström edbc199914 vo_gpu/hwdec_cuda: fixup compilation with vulkan disabled
The actual code utilizing this enum was seemingly properly if'd,
but not the enum in the struct itself.

Fixes compilation.
2019-04-22 18:17:30 +03:00
Jan Ekström 9b8d3eff78 docs: add mentions of the Vulkan rendering abstraction replacement
From internal to libplacebo.
2019-04-22 15:58:10 +03:00
Philip Langdale 74831dd651 vo/gpu: hwdec_cuda: Reorganise backend-specific code
This tries to tidy up the GL vs Vulkan code to be a bit cleaner
and easier to read.
2019-04-21 23:55:22 +03:00
Philip Langdale 4005cda614 vo_gpu: hwdec_cuda: Implement interop for placebo
This change updates the vulkan interop code to work with the
libplacebo based ra_vk, but also introduces direct VkImage
sharing to avoid the use of the intermediate buffer.

It is also necessary and desirable to introduce explicit
semaphore bsed synchronisation for operations on the shared
images.

Synchronisation means we can safely reuse the same VkImage for every
mapped frame, by ensuring the frame is copied to the VkImage before
mapping the next frame.

This functionality requires a 417.xx or newer nvidia driver, due to
bugs in the VkImage interop in the earlier 411 and 415 drivers.

It's definitely worth the effort, as the raw throughput is about
twice that of implementation using an intermediate buffer.
2019-04-21 23:55:22 +03:00
Philip Langdale ffb8ffdd55 vo/gpu: ra_pl: Add helper to get pl_fmt from ra_format
When interacting directly with libplacebo, we may need to pass a
pl_fmt based on an ra_format. Although the mapping is currently
trivial, it's worth wrapping to make it easy to adapt if this
changes in the future.
2019-04-21 23:55:22 +03:00
Philip Langdale 4c133f3b45 vo_gpu: ra_pl: Add getter for pl_gpu
We need access to the underlying pl_gpu to make libplacebo calls
from hwdecs.
2019-04-21 23:55:22 +03:00
Philip Langdale b74b39dfb5 vo_gpu: vulkan: Add back context_win for libplacebo
Feature parity with the original ra_vk obviously requires win32 support,
so let's put it back in.
2019-04-21 23:55:22 +03:00
Niklas Haas 7006d6752d vo_gpu: vulkan: use libplacebo instead
This commit rips out the entire mpv vulkan implementation in favor of
exposing lightweight wrappers on top of libplacebo instead, which
provides much of the same except in a more up-to-date and polished form.

This (finally) unifies the code base between mpv and libplacebo, which
is something I've been hoping to do for a long time.

Note: The ra_pl wrappers are abstract enough from the actual libplacebo
device type that we can in theory re-use them for other devices like
d3d11 or even opengl in the future, so I moved them to a separate
directory for the time being. However, the rest of the code is still
vulkan-specific, so I've kept the "vulkan" naming and file paths, rather
than introducing a new `--gpu-api` type. (Which would have been ended up
with significantly more code duplicaiton)

Plus, the code and functionality is similar enough that for most users
this should just be a straight-up drop-in replacement.

Note: This commit excludes some changes; specifically, the updates to
context_win and hwdec_cuda are deferred to separate commits for
authorship reasons.
2019-04-21 23:55:22 +03:00
Niklas Haas 9f7dcc0726 mp_image: align stride to multiple of texel size
This helps with compatibility and/or performance in particular for
oddly-sized formats like rgb24. We use a loop to avoid having to
calculate the lcm (or waste bytes in the extremely common case of the
byte size and the stride align having shared factors).
2019-04-21 23:55:22 +03:00
Niklas Haas a3c808c6c8 vo_gpu: fix segfault when OSD tex creation fails
If !osd->texture, then mpgl_osd_draw_prepare fails.
2019-04-21 23:55:22 +03:00
Niklas Haas f0b6860d62 vo_gpu: index desc namespaces by ra
No reason to require them be constant. This allows them to depend on
runtime characteristics of the `ra`.
2019-04-21 23:55:22 +03:00
James Ross-Gowan 4e9dc60d9e appveyor: fix shaderc dependencies
Shaderc comes with a Python script that automatically fetches
"known-good" versions of its dependencies. Use that instead of manually
cloning dependencies to third-party.
2019-04-16 21:35:00 +03:00
JCount 7f1d7c38bc version.sh: update MPVCOPYRIGHT to include the current year, 2019 2019-04-16 20:11:30 +02:00
john e9fae413fd options/path: fix url detection per RFC3986 2019-04-05 20:48:24 +03:00
Aman Gupta 8b114e574a ao/audiounit: include AVAudioSession buffer in latency calc
Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-04-05 10:29:44 +07:00
Aman Gupta e35aca3cb4 ao/audiounit: improve a/v sync
This more closely mimics ao_coreaudio, on which this driver was
originally based.

Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-04-05 10:29:44 +07:00
NoSuck 6c91314900 man/input: clarify behavior of seek's +exact
As discussed here:

https://github.com/mpv-player/mpv/issues/6545#issuecomment-476015318
2019-04-02 09:09:14 +02:00
der richter 90e44d3ff2 cocoa-cb: add support for custom colored title bar 2019-04-02 02:09:01 +03:00
der richter 837e5058ff cocoa-cb: refactor title bar styling
half of the materials we used were deprecated with macOS 10.14, broken
and not supported by run time changes of the macOS theme. furthermore
our styling names were completely inconsistent with the actually look
since macOS 10.14, eg ultradark got a lot brighter and couldn't be
considered ultradark anymore.

i decided to drop the old option --macos-title-bar-style and rework
the whole mechanism to allow more freedom. now materials and appearance
can be set separately. even if apple changes the look or semantics in
the future the new options can be easily adapted.
2019-04-02 02:09:01 +03:00
Akemi 23f55569be cocoa-cb: add support for mac 10.14 Dark mode and run time switching
setting the appearance of the window to nil will always use the system
setting and changes on run time switches too. this is only the case for
macOS 10.14.
2019-04-02 02:09:01 +03:00
der richter d5be1e2729 cocoa-cb: move all title bar related functionality in its own file
quite a lot of the title bar functionality and logic was within our
window. since we recently added a custom title bar class to our window
i decided to move all that functionality into that class and in its
own file.

this is also a preparation for the next commits.
2019-04-02 02:09:01 +03:00
Akemi 9d5805fba4 cocoa-cb: remove an unused variable 2019-04-02 02:09:01 +03:00
Akemi 0bea384153 cocoa-cb: simplify CGL pixel format creation
i found the old pixel format creation a bit too messy. pixel format
attribute arrays and look ups were all over the place, the actual logic
what kind of format was created was inscrutable, the software pixel
format was hardcoded and no probing was done.

i split the attributes into mandatory and optional ones, one mandatory
for a hardware and software pixel format each, and moved those to the
top of the class. that way new attributes can be easily added to either
the mandatory or optional attributes and they don't mess up the actual
pixel creation logic any more. furthermore both hardware and software
pixel formats are being probed the same way now. to minimise code
duplications the probing was moved into its own function.
2019-04-02 02:05:11 +03:00
Akemi 716b871928 cocoa-cb: add support for dragging certain strings onto the window
only the dragged types NSFilenamesPboardType and NSURLPboardType were
supported to be dropped on the window, which was inconsistent with the
dragged types the dock icon supports. the dock icon additional supports
strings that represents an URL or a path. the system takes care of
validating the strings properly in the case of the dock icon, but in the
case of dropping on the window it needs to be done manually.

support for strings is added by also allowing the NSPasteboardTypeString
type and manually validating the strings. strings are split by new lines
and trimmed, to also support a list of URLs and paths. every new element
is checked if being an URL or path and only then being added to the
playlist.
2019-04-02 02:04:31 +03:00
Akemi 3f6be83350 cocoa-cb: synchronise the flush with the render
this could lead to a crash on deinit when flush
was called while the opengl state was cleaned up.

Fixes #6323
2019-04-02 02:02:02 +03:00
Akemi b207c1d4a1 cocoa-cb: fix a Cocoa window position on init bug
on init an NSWindow can't be placed on a none Main screen NSScreen
outside the Main screen's frame bounds.

To fix this we just check if the target screen is different from the
main screen and if that is the case we check the actual position with
the expect one. if they are different we try to reposition the window
to the wanted position.

Fixes #6453
2019-04-02 02:01:02 +03:00
Akemi 9aa0905c10 cocoa-cb: fix Space switching when quitting fs
when quitting mpv in fullscreen the System always switchs to Space 1
regardless of which Space mpv was on previous to switching to fs. to fix
this we close the window before quitting fs. that way the System
switches back the the Space mpv was previous on before fs.
2019-04-02 01:59:52 +03:00
Akemi 0caaa1a37c cocoa-cb: notify vo when window is minimised 2019-04-02 01:51:42 +03:00
Akemi 731804a27e cocoa-cb: fix crash when querying window state
Fixes #6489
2019-04-02 01:51:42 +03:00
Akemi 48a463d641 cocoa-cb: wakeup vo when new events are available
new events were added but not fetched by the vo, because we didn't
signal the vo that new events were available.

actually wakeup the vo when new events are available.
2019-04-02 01:46:52 +03:00
Akemi 61005e10ea build: bump minimum swift version to 3.0.2
#6299 reported problems with earlier 3.0.x swift versions. i tested with
3.0.2/SDK 10.12.2 and just assumed it also works with the older 3.0.x
swift and 10.12.x SDK versions. due to the unstable nature of swift
there were slight API differences that caused build problems.

since swift is bundled with the SDK we just bump the minimum swift
version.
2019-04-02 01:43:54 +03:00
der richter c90f083614 build: slightly adjust swift check output messages on fail
to make it consistent with the other checks and their output messages.
2019-04-02 01:43:54 +03:00
Akemi a3e6b81305 build: use StrictVersion for swift version comparison 2019-04-02 01:43:54 +03:00
zc62 de2b1920f3 demux: support cue sheets longer than 100 minutes
Remove the 2-digit-number restriction when reading the number of
minutes in the cue sheet INDEX command.

Fixes #6481
2019-04-01 23:39:08 +02:00
Aman Gupta 9c22bd4898 player: show restart position
Signed-off-by: Aman Gupta <aman@tmm1.net>
2019-04-01 23:38:38 +02:00
Leo Izen fcb320fd3f DOCS/man/mpv.rst: Fix big-cache profile example
The cache options were changed, and this commit
fixes the example big-cache profile to use the
new cache options.
2019-03-16 21:17:56 +01:00
Philip Sequeira 98eea65605 x11: fix cursor hiding initial state
Regression from 8e3308d687.

Broken cases were:
* --no-cursor-autohide acted like --cursor-autohide=always.
* --cursor-autohide-fs-only always hid the cursor if starting
  non-fullscreen; entering fullscreen at least once fixed it.
2019-03-16 21:17:32 +01:00
Bin Jin dd83b66652 vo_gpu: increase user shader size limit
The old size limit was chosen before LUT texture was supported in user
shader. At that time, the whole user shader will be compiled and run
on GPU, which makes large user shader impractical to be used.

With the introduction of LUT texture, the old size limit doesn't make
any sense. For example, a 1024x1024 rgba16f LUT will cost 32MB shader
size.

Fix this by increasing the size limit to a value that's unlikely be
reached.
2019-03-13 21:47:24 +02:00
Akemi 92e9b6da71 build: fix adding of object files to linking with cplugins disabled
this was meant to be fixed by 546f038, but with --disable-cplugins the
do_the_symbol_stuff function was never called and the handle_add_object
function was again always called before the actual linking task was
created.

to fix this we explicitly call handle_add_object only after all the
tasks the do_the_symbol_stuff function is called after too.

Fixes #6028
2019-03-13 21:44:43 +02:00
Rodger Combs 4fd3af14cd macosx_events: fix crash when shutting down during window animations 2019-03-13 19:44:34 +01:00
Rodger Combs ec0b5e527b build: enable swift debug information when requested 2019-03-13 19:44:34 +01:00
Avi Halachmi (:avih)andwnoun d6ca985831 player: fix core activity state check
Adds the negation missed in 8816e1117e
when moving from a positive-is-active to positive-is-idle variable.

This leads to proper updates to properties such as "eof-reached",
as well as fixes screensaver state updates.

Separately found and fixed by avih and wnoun.

Co-authored-by: wnoun <wnoun@outlook.com>
2019-03-12 01:56:32 +02:00
wnoun 94203436c4 vo_libmpv: fix null pointer dereference
Closes: #6507
2019-03-11 01:55:59 +02:00
Jan Ekström 199aabddcc Merge branch 'master' into pr6360
Manual changes done:
  * Merged the interface-changes under the already master'd changes.
  * Moved the hwdec-related option changes to video/decode/vd_lavc.c.
2019-03-11 01:00:27 +02:00
Bin Jin 1d0349d3b5 vo_gpu: add two useful operators to user shader
modulo operator could be used to check if size is multiple of a
certain number.

equal operator could be used to verify if size of different textures
aligns.
2019-03-09 12:56:11 +01:00
Bin Jin b3cbd46509 vo_gpu: make texture offset available to CHROMA hooks
Before this commit, texture offset is set after all source textures
are finalized. Which means CHROMA hooks won't be able to align with
luma planes. This could be problematic for chroma prescalers utilizing
information from luma plane.

Fix this by find the reference texture early, and set global texture
offset early.
2019-03-09 12:56:11 +01:00
zc62 e37c253b92 lcms: allow infinite contrast
Fixes #5980
2019-03-09 12:55:44 +01:00
Philip Sequeira 89eacf8131 demux_edl: don't assume data follows a comment line
There could be another comment line or the end of the file.

Fixes #6529.
2019-03-03 13:13:45 +01:00
zc62 b9cde8d95c sub: recognize UTF-8 characters in SDH subtitle filter
Only printable ASCII characters were considered to be valid texts. Make
it possible that UTF-8 contents are also considered valid.

This does not make the SDH subtitle filter support non-English
languages. This just prevents the filter from blindly marking lines that
have only UTF-8 characters as empty.

Fixes #6502
2019-03-02 02:05:58 +01:00
Martin Herkt 8f5a42b1a0 options: do not enable WMV3 hwdec by default
Crashes NVIDIA, probably buggy on others. No one ever tests this shit.

See #2192
2019-03-01 12:44:45 +01:00
Gunnar Marten b275232141 demux: fix seek range update after head packets are pruned
The seek range update was to early and did not take the removed head
packets into account. And therefore missed that the queue was not
BOF anymore.
This led to not be able to backward seek before the first packet of
the first seek range.

Fix it by moving the seek range update after the possible removal and
the change of the BOF flag.

Fixes: #6522
2019-03-01 00:55:06 +02:00
zc62 d38c4879d7 player: do not rebase start time for subtitle streams
As stated in the original commit message, if the demuxer set the start
time to the first subtitle packet, the subtitles would be shifted
incorrectly. It appears that it is the case for external PGS subtitles.

This reverts commit 520fc74036.

Fixes #5485
2019-02-28 23:23:47 +01:00
Anton Kindestam 537006965e context_drm_egl: implement n-buffering
This allows context_drm_egl to use as many buffers as libgbm or the
swapchain_depth setting allows (whichever is smaller).

On pause and on still images (cover art etc.) to make sure that output does not
lag behind user input, the swapchain is drained and reverts to working in a dual
buffered (equivalent to swapchain-depth=1) manner.

When possible (swapchain-depth>=2), the wait on the page flip event is now not
done immediately after queueing, but is deferred to the next invocation of
swap_buffers. Which should give us more CPU time between invocations.

Although, since gbm_surface_has_free_buffers() can only tell us a boolean value
and not how many buffers we have left, we are forced to do this contortionist
dance where we first overshoot until gbm_surface_has_free_buffers() reports 0,
followed by immediately waiting so we can free a buffer, to be able to get the
deferred wait on page flip rolling.

With this commit we do not rely on the default vsync fences/latency emulation of
video/out/opengl/context.c, but supply our own, since the places we create and
wait for the fences needs to be somewhat different for best performance.

Minor fixes:

 * According to GBM documentation all BO:s gotten with
   gbm_surface_lock_front_buffer must be released before gbm_surface_destroy is
   called on the surface.
 * We let the page flip handler function handle the waiting_for_flip flag.
2019-02-25 01:25:25 +01:00
Anton Kindestam ae115bd8d8 opengl: Support GL_ARB_sync style fences on OpenGL ES 3.0
OpenGL ES 3.0 and up has suppport for for GL_ARB_sync style fences.
Make sure that mpv can use them.
2019-02-25 01:25:25 +01:00
zc62 a127912345 audio: fix segfault caused by incorrect number of planes
Use `mp_aframe_get_planes` to properly get the number of planes, instead
of assuming it to be the number of channels.

Fixes #6092
2019-02-23 00:21:54 +02:00
Niklas Haas 8b563a0346 vo_gpu: fix initial seeding of the peak detect ssbo
This solves some edge cases when using files with very weird metadata
(e.g. MaxCLL 10k and so forth). Instead of just blindly seeding it with
the tagged metadata, forcibly set the initial state from the detected
values.
2019-02-18 01:54:06 +02:00
Niklas Haas 3f1bc25d4d vo_gpu: use dB units for scene change detection
Rather than the linear cd/m^2 units, these (relative) logarithmic units
lend themselves much better to actually detecting scene changes,
especially since the scene averaging was changed to also work
logarithmically.
2019-02-18 01:54:06 +02:00
Niklas Haas b4b719e337 vo_gpu: clamp sigmoid function
Can explode on some clips otherwise
2019-02-18 01:54:06 +02:00
Niklas Haas 258ed5d471 vo_gpu: tone map before gamut mapping
Gamut mapping can take very bright out-of-gamut colors into the
negatives, which completely destroys the color balance (which tone
mapping tries its best to preserve).
2019-02-18 01:54:06 +02:00
Niklas Haas 677ae4f8fe vo_gpu: make --gamut-warning warn on negative colors
As is the case for actually out-of-gamut colors (rather than just too
bright colors).
2019-02-18 01:54:06 +02:00
Niklas Haas 11b58415d5 vo_gpu: improve numerical accuracy of PQ OETF constant
Not a huge deal, but we can do the division in C, which makes the float
constant larger.
2019-02-18 01:54:06 +02:00
Niklas Haas 4e8022da26 vo_gpu: allow color management in dumb mode
There's no point to disallow target-trc/prim in dumb mode, since they
still work fine.
2019-02-18 01:54:06 +02:00
Niklas Haas fdd671188d vo_gpu: improve accuracy of HDR brightness estimation
This change switches to a logarithmic mean to estimate the average
signal brightness. This handles dark scenes with isolated highlights
much more faithfully than the linear mean did, since the log of the
signal roughly corresponds to the perceptual brightness.
2019-02-18 01:54:06 +02:00
Niklas Haas 12e58ff8a6 vo_gpu: allow boosting dark scenes when tone mapping
In theory our "eye adaptation" algorithm works in both ways, both
darkening bright scenes and brightening dark scenes. But I've always
just prevented the latter with a hard clamp, since I wanted to avoid
blowing up dark scenes into looking funny (and full of noise).

But allowing a tiny bit of over-exposure might be a good thing. I won't
change the default just yet (better let users test), but a moderate
value of 1.2 might be better than the current 1.0 limit. Needs testing
especially on dark scenes.
2019-02-18 01:54:06 +02:00
Niklas Haas 6179dcbb79 vo_gpu: redesign peak detection algorithm
The previous approach of using an FIR with tunable hard threshold for
scene changes had several problems:

- the FIR involved annoying hard-coded buffer sizes, high VRAM usage,
  and the FIR sum was prone to numerical overflow which limited the
  number of frames we could average over. We also totally redesign the
  scene change detection.

- the hard scene change detection was prone to both false positives and
  false negatives, each with their own (annoying) issues.

Scrap this entirely and switch to a dual approach of using a simple
single-pole IIR low pass filter to smooth out noise, while using a
softer scene change curve (with tunable low and high thresholds), based
on `smoothstep`. The IIR filter is extremely simple in its
implementation and has an arbitrarily user-tunable cutoff frequency,
while the smoothstep-based scene change curve provides a good, tunable
tradeoff between adaptation speed and stability - without exhibiting
either of the traditional issues associated with the hard cutoff.

Another way to think about the new options is that the "low threshold"
provides a margin of error within which we don't care about small
fluctuations in the scene (which will therefore be smoothed out by the
IIR filter).
2019-02-18 01:54:06 +02:00
Niklas Haas 3fe882d4ae vo_gpu: improve tone mapping desaturation
Instead of desaturating towards luma, we desaturate towards the
per-channel tone mapped version. This essentially proves a smooth
roll-off towards the "hollywood"-style (non-chromatic) tone mapping
algorithm, which works better for bright content, while continuing to
use the "linear" style (chromatic) tone mapping algorithm for primarily
in-gamut content.

We also split up the desaturation algorithm into strength and exponent,
which allows users to use less aggressive desaturation settings without
affecting the overall curve.
2019-02-18 01:54:06 +02:00
Emmanuel Gil Peyrot 36600ff163 wayland_common: rename “shell” into “wm_base”
This is the naming xdg-shell stable adopted, it doesn’t make much sense
to keep using “shell” everywhere with all functions calling it
“wm_base”.

Finishes what 76211609e3 started.
2019-02-17 23:44:34 +02:00
Martin Herkt 3dd59dbed0 options: do not enable MPEG2 hwdec by default
Too many broken hardware decoders. Noticed wrong decoding of a video
file encoded with x262 on RX Vega when using VAAPI (Mesa 18.3.2).
Looks fine with swdec and a cheap hardware BD player.

Reverts 017f3d0674
2019-02-13 02:43:57 +01:00
Akemi 777a863bb6 cocoa-cb: remove empty elements from dropped URLs
Fixes #6241
2019-02-10 23:47:34 +02:00
Akemi 6ce570359a cocoa-cb: add support for VOCTRL_GET_DISPLAY_NAMES 2019-02-10 22:39:25 +02:00
Akemi ace61c120f cocoa-cb: use Swift Extensions for convenience
preparations for the following commit.
2019-02-10 22:39:25 +02:00
Ken f2e7e81bda mac: add missing semicolon to macosx_compat.h
fixes build on older systems
2019-01-26 20:44:36 +01:00
Aman Gupta 9284543ab9 wscript_build: de-duplicate build file list 2019-01-25 21:24:36 +02:00
Akemi a4298b1a69 cocoa-cb: fix side by side Split View again
some safety mechanism for the async fs animation aren't needed anymore,
due to possible improved logic and slightly different behaviour on new
macOS versions. that safety fallback prevented the Split View because
it always returned a rectangle of the whole screen, instead of just
part/half of it.

Fixes #6443
2019-01-23 09:32:02 +01:00
Kotori Itsuka 94d35627f5 DOCS/options.rst: update target-peak description
List auto as an option for target-peak, and state that auto is its
default operation.
2019-01-23 09:31:35 +01:00
Kotori Itsuka 05f0980b96 vo_gpu: allow resetting target-peak to the trc default
Add "auto" the possible values of target-peak.  The default value
for target_peak is to calculate the target using mp_trc_nom_peak.
Unfortunately, this default was outside the acceptable range of
10-10000 nits, which prevented its later reassignment.  So add an
"auto" choice to target-peak which lets clients and scripts go back
to using the trc default after assigning a value.
2019-01-23 09:31:35 +01:00
Akemi 08679f756c vd_lavc: increase the possible length of the hwdec name
this lead to an unexpected videotoolbox-copy hwdec name due to the last
two chars being cut off. since selection is also done by that name one
had to use "videotoolbox-co" to explicitly use the copy mode of
videotoolbox.
2019-01-23 09:30:58 +01:00
Julian 73fe0611b3 stats: merge multiple properties into one line
Merge file-size/file-format and audio channel-count/format into one line
respectively. This fixes stats overflowing the screen in larger than
19:6 aspect ratios. In this case a problem was reported for ~21:9 which
should be common enough for us to "support" it.
2019-01-16 16:59:00 +01:00
Olivier Perret 9be68e49b2 lua: execute idle handlers after timers have been processed
Idle handlers used to not be executed when timers were active
Now they are executed:
* After all expired timers have been executed
* After all events have been processed (same as when there are no timers)
2019-01-16 16:58:46 +01:00
Benjamin Barenblat c681fc133c DOCS/man: update man pages to describe ReplayGain fallback
Describe ReplayGain album-to-track fallback behavior introduced in
commits e392d6610d and
be90f2c8dd0431e252e43d5249e89446309113af.
2019-01-16 16:58:33 +01:00
Benjamin Barenblat 585f9ff42f demux: make ALBUM ReplayGain tags optional when using libavformat
Commit e392d6610d modified the native
demuxer to use track gain as a fallback for album gain if the latter is
not present. This commit makes functionally equivalent changes in the
libavformat demuxer.
2019-01-16 16:58:33 +01:00
Dan Oscarsson aab595f828 command: notify on multiply
doing multiply on a property is also a set property command
and the change should be notified so others can observe the change
2019-01-16 16:58:15 +01:00
Oliver Freyermuth d6d6da4711 stream_dvb: Correct range for dvbin-card option.
Adapt documentation accordingly and
also, fix an off-by-one check in the code.
closes #6371
2018-12-12 01:50:43 +02:00
sfan5 7c565547b8 docs: add removed properties and options to interface-changes.rst 2018-12-06 19:14:14 +01:00
sfan5 179ad276f2 stats: remove duplicate cache sizes
The stream cache no longer exists, so there is no need to show the demuxer cache separately anymore.
2018-12-06 19:01:26 +01:00
sfan5 e0419fb181 demux: fix regression in decision about stream caching
The `streaming` flag covers more cases than just networked streams,
such as files read from NFS, SMB or FUSE mountpoints.
2018-12-06 18:46:29 +01:00
Niklas Haas 3dc2d7d7dd demux: fix memleak in allocation with params=NULL
The default behavior for `does not own stream` should be false, but this
condition is inverted so we need to default the base case to `true`.
2018-12-06 15:47:16 +01:00
wm4 32385a784c osd: another shitty pointless UB
The pointer could be NULL if the number of bytes to copy was 0. In a
sane world, this would be fine, but not the current world.
2018-12-06 10:34:06 +01:00
wm4 af9722cd3e demux: fix some theoretical UB with no impact
If the number of chapters is 0, the chapter list can be NULL. clang
complains that we pass NULL to qsort(). This is yet another pointless UB
that exists for no reason other than wasting your time.
2018-12-06 10:33:52 +01:00
wm4 8e3308d687 x11: don't hide cursor if window isn't focused
I found this sort of annoying.

You could argue that the "frontend" should maybe contain this logic, but
who cares.
2018-12-06 10:33:42 +01:00
wm4 19a38c4b1f stream: silence failed seek message on termination
Seems to happen often with ytdl pseudo-DASH streams, so whatever. I
couldn't reproduce it and check what triggers it, I just remember seeing
the error message and found it annoying.
2018-12-06 10:33:28 +01:00
wm4 9b10869a61 stream: something 2018-12-06 10:33:14 +01:00
wm4 f4ce3b8bb9 vo, vo_gpu, glx: correct GLX_OML_sync_control usage
I misunderstood how this extension works. If I understand it correctly
now, it's worse than I thought. They key thing is that the (ust, msc,
sbc) tripple is not for a single swap event. Instead, (ust, msc) run
independently from sbc. Assuming a CFR display/compositor, this means
you can at best know the vsync phase and frequency, but not the exact
time a sbc changed value.

There is GLX_INTEL_swap_event, which might work as expected, but it has
no EGL equivalent (while GLX_OML_sync_control does, in theory).

Redo the context_glx sync code. Now it's either more correct or less
correct. I wanted to add proper skip detection (if a vsync gets skipped
due to rendering taking too long and other problems), but it turned out
to be too complex, so only some unused fields in vo.h are left of it.
The "generic" skip detection has to do.

The vsync_duration field is also unused by vo.c.

Actually this seems to be an improvement. In cases where the flip call
timing is off, but the real driver-level timing apparently still works,
this will not report vsync skips or higher vsync jitter anymore. I could
observe this with screenshots and fullscreen switching. On the other
hand, maybe it just introduces an A/V offset or so.

Why the fuck can't there be a proper API for retrieving these
statistics? I'm not even asking for much.
2018-12-06 10:32:27 +01:00
wm4 ace16fcfff demux_mkv: simplify avi compat. codec_tags.c GUID lookup
The redundancy here always annoyed me. Back then I didn't change it
because it's hard to test and I just had fixed something. This doesn't
matter anymore, so simplify it, without testing and with the risk that
something breaks (why care).
2018-12-06 10:31:59 +01:00
wm4 21c9ee71e2 demux: remove some dead code
No idea what that shit is. Likely forgotten when timed metadata was
introduced, and some of the old mechanisms were replaced.
2018-12-06 10:31:30 +01:00
wm4 9d8afcf79e demux: add another stream recording feature
--record-file is nice, but only sometimes. If you watch some sort of
livestream which you want to record, it's actually much nicer not to
record what you're currently "seeing", but anything you're receiving.
2018-12-06 10:31:10 +01:00
wm4 02756c3735 demux_lavf: to get effective HLS bitrate
In theory, this could be easily done with custom I/O. In practice, all
the halfassed garbage in FFmpeg shits itself and fucks up like there's
no tomorrow. There are several problems:

1. FFmpeg pretends you can do custom I/O, but in reality there's a lot
that custom I/O can do. hls.c even contains explicit checks to disable
important things if custom I/O is used! In particular, you can't use the
HTTP keepalive functionality (needed for somewhat decent HLS
performance), because some cranky asshole in the cursed FFmpeg dev.
community blocked it.

2. The implementation of nested I/O callbacks (io_open/io_close) is
bogus and halfassed (like everything in FFmpeg, really). It will call
io_open on some URLs without ever calling io_close. Instead, it'll call
avio_close() on the context directly. From what I can tell, avio_close()
is incompable to custom I/O anyway (overwhelmed by their own garbage,
the fFmpeg devs created the io_close callback for this reason, because
they couldn't fix their own fucking garbage). This commit adds some
shitty workaround for this (technically triggers UB, but with that
garbage heap of a library we depend on it's not like it matters).

3. Even then, you can't proxy I/O contexts (see 1.), but we can just
keep track of the opened nested I/O contexts. The bytes_read is
documented as not public, but reading it is literally the only way to
get what we want.

A more reasonable approach would probably be using curl. It could
transparently handle the keep-alive thing, as well as propagating
cookies etc. (which doesn't work with the FFmpeg approach if you use
custom I/O). Of course even better if there were an independent HLS
implementation anywhere. FFmpeg's HLS support is so embarrassing
pathetic and just goes to show that they belong into the past
(multimedia from 2000-2010) and should either modernize or fuck off.
With FFmpeg's shit-crusted structures, todic communities, and retarded
assholes denying progress, probably the latter. Did I already mention
that FFmpeg is a shit fucked steaming pile of garbage shit?

And all just to get some basic I/O stats, that any proper HLS consumer
requires in order to implement adaptive streaming correctly (i.e.
browser based players, and nothing FFmshit based).
2018-12-06 10:30:57 +01:00
wm4 4dfaa37384 demux, stream: readd cache-speed in some other form
it's more like an input speed rather than a cache speed, but who cares.
2018-12-06 10:30:41 +01:00
wm4 b1ba7de34d vo: use a struct for vsync feedback stuff
So new useless stuff can be easily added.
2018-12-06 10:30:25 +01:00
wm4 83884fdf03 vo_gpu: glx: use GLX_OML_sync_control for better vsync reporting
Use the extension to compute the (hopefully correct) video delay and
vsync phase.

This is very fuzzy, because the latency will suddenly be applied after
some frames have already been shown. This means there _will_ be "jumps"
in the time accounting, which can lead to strange effects at start of
playback (such as making initial "dropped" etc. frames worse). The only
reasonable way to fix this would be running a few dummy frame swaps at
start of playback until the latency is known. The same happens when
unpausing.

This only affects display-sync mode.

Correct function was not confirmed. It only "looks right". I don't have
the equipment to make scientifically correct measurements.

A potentially bad thing is that we trust the timestamps we're receiving.
Out of bounds timestamps could wreak havoc. On the other hand, this will
probably cause the higher level code to panic and just disable DS.

As a further caveat, this makes a bunch of assumptions about UST
timestamps. If there are delayed frames (i.e. we skipped one or more
vsyncs), the latency logic is mostly reset. There is no attempt to make
the vo.c skipped vsync logic to use this. Also, the latency computation
determines a vsync duration, and there's no effort to reconcile or share
the vo.c logic for determining vsync duration.
2018-12-06 10:30:14 +01:00
Anton Kindestam 8b83c89966 Merge commit '559a400ac36e75a8d73ba263fd7fa6736df1c2da' into wm4-commits--merge-edition
This bumps libmpv version to 1.103
2018-12-05 19:19:24 +01:00
Niklas Haas 5bcac8580d spirv: remove --spirv-compiler=nvidia
This option has been deprecated upstream for a long time, probably
doesn't even work anymore, and won't work moving forwards as we replace
the vulkan code by libplacebo wrappers.

I haven't removed the option completely yet since in theory we could
still add support for e.g. a native glslang wrapper in the future. But
most likely the future of this code is deletion.

As an aside, fix an issue where the man page didn't mention d3d11.
2018-12-01 15:50:23 +02:00
Anton Kindestam f0509d3738 drm: rename plane options to better, invariant, names
This commit bumps the libmpv version to 1.102

drm-osd-plane -> drm-draw-plane
drm-video-plane -> drm-drmprime-video-plane
drm-osd-size -> drm-draw-surface-size

"draw plane", as in the plane that OpenGL draws to, whether it be
video + OSD or just OSD.

"drmprime video plane", as in the plane used for hwdec video imported
via drmprime.

"draw surface size", as in the size of the surface used for the draw plane

The new names are invariant whether or not hwdec_drmprime_drm is being
used or not. The original naming was very confusing, as when doing
regular rendering (swdec or vaapi) the video would be displayed on the
"OSD plane", and the "Video plane" would remain unused.
2018-12-01 15:42:20 +02:00
Anton Kindestam c151fae054 drm_atomic: Add general primary/overlay plane option
Add general primary/overlay plane option to drm-osd-plane-id and
drm-video-plane-id, so that the user can just request any usable
primary or overlay plane for either of these two options. This should
be somewhat more user-friendly (especially as neither of these two
options currently have a useful help function), as usually you would
only be interested in the type of the plane, and not exactly which
plane gets picked.
2018-12-01 15:42:20 +02:00
TheAMM b6a431ec55 man: fix --watch-later-directory formatting
Extra line prevents the sub-title formatting.
Removing it, the option is formatted like the others.
2018-11-28 18:02:45 +01:00
dudemanguy 8b6064de76 gpu: prefer wayland context on autodetect 2018-11-19 00:26:39 +02:00
Niklas Haas b8bb5329a5 vulkan: slightly improve vsync jitter measurements
By design, some vulkan implementations block until vsync during
vkAcquireNextImageKHR. Since mpv only considers the time that
`swap_buffers` spent blocking as constituting part of the vsync, we can
help it out a bit by pre-emptively calling this function here in order
to improve the accuracy of vsync jitter measurements on vulkan.

(If it fails, we just ignore the error and have the user call it a
second time later - maybe it will work then)

On my system this drops vsync-jitter from ~0.030 to ~0.007, an accuracy
of +/- 100μs. (Which *might* have something to do with the fact that
this is the polling interval for command polling)
2018-11-19 00:23:15 +02:00
Niklas Haas 34df6bd82f vo_gpu: vulkan: only rotate the queues on swap
Makes performance slightly better when using multiple queues by avoiding
unnecessary semaphores due to bad queue selection.

Also remove an aeons-old workaround for an nvidia bug that only ever
existed in the earliest beta vulkan drivers anyway.
2018-11-19 00:22:41 +02:00
emersion 95589fd4f8 wayland: remove KDE server-decoration support 2018-11-19 00:15:31 +02:00
emersion 6d2be82094 wayland: use xdg-decoration if available 2018-11-19 00:15:31 +02:00
Philip Langdale ce2253b358 filters: Add cuda/nvdec deinterlacing auto-filter using vf_yadif_cuda
Historically, there's been no way to offer deinterlacing with nvdec,
and for cuviddec, it required a command line flag, with no way to
toggle while playing.

Now that we have a cuda deinterlacing filter in ffmpeg, we can hook
it up hook it up as the cuda auto-deinterlacer. In practice, this
isn't going to be present very often, due to the licensing mess with
the cuda sdk, but we can support it when it is there.
2018-11-19 00:02:41 +02:00
Philip Langdale 721bec7dde vo_gpu: hwdec_cuda: Guard GL and Vulkan headers properly
We are currently unnecessarily including vulkan headers even when
not building with vulkan support. I also guarded the GL header
inclusion even though this doesn't appear to break anything today.

Fixes #6330.
2018-11-18 23:50:38 +02:00
pavelxdd edbe25f38a w32_common: use the screen working area when resizing the window
This makes the default fit on screen, autofit and window-scale
changing behavior to use the screen working area, instead of
the whole screen area.

As a result mpv window doesn't cover the taskbar now when opening
videos with size larger than the screen size.

The actual behavior now is the same as expected behavior for
usecases 1-4 from #4363.

This commit also removes the screenrc from w32 struct.
The screen rect can now be retrieved via `get_screen_area` function,
which was renamed from `update_screen_rect`.

On a multi-monitor system, if the user moved the window between
monitors, this function will return the current screen area under
the window, and not the screen area from monitor specified by
`--screen` option. The `--screen` option sets the initial monitor
the mpv window is displayed on.
2018-11-18 00:56:34 +02:00
Rikard Falkeborn f1ba1ef77f vo_x11: fix return value in resize() error paths
Returning -1 in a function with return type bool is the same as
returning true. In the error paths, false should be returned to
indicate that something went wrong.
2018-11-17 00:53:56 +01:00
Niklas Haas 2704625e3f vo_gpu: opengl: disable compute shaders for old GLSL
Fixes #6272.
2018-11-17 00:49:10 +01:00
Akemi b222980394 cocoa: fix drawing on macOS 10.14 2018-11-13 21:14:29 +02:00
Akemi e5c4164088 cocoa-cb: add logging for CGL pixel format attributes
depending on the capabilities of the system and testing of various
attributes the resulting CGL pixel format can change. due to that
probing it can be helpful to know which pixel format is used to create
the CGL context. added some verbose logging that outputs final pixel
format.
2018-11-13 20:43:29 +02:00
Akemi e72093581b vo_libmpv: support render performance data 2018-11-13 20:43:29 +02:00
Akemi 9e466ee621 cocoa-cb: use libmpv's advanced rendering control and timing
this adds support for GPU rendered screenshots, DR (theoretically) and
possible other advanced functions in the future that need to be executed
from the rendering thread.
additionally frames that would be off screen or not be displayed when on
screen are being dropped now.
2018-11-13 20:43:29 +02:00
Jan Ekström 317d3ac266 build: add a version requirement for vulkan pkg-config check
`vkGetPhysicalDeviceProperties2KHR` was added in Vulkan 1.0.39,
but 1.0.61 from Ubuntu Xenial (16.04) was the lowest anyone tried
to build mpv with as of late, so we are marking that as the minimum
required version.

This fixes issues arising during build time from having too old
version of vulkan available on a system, instead of causing a failure
to build.
2018-11-04 00:19:12 +02:00
Philip Langdale c8a065df12 vo_gpu: vulkan: Always use KHR suffix types and defines
I was inconsistent about this originally, as the functionality was
moved into the core spec in 1.1 and so both suffixed and unsuffixed
versions of everything exist and can be mixed together.

There's no reason to fail to build with 1.0.39+ so I'm fixing the
names.
2018-11-03 23:53:08 +02:00
Niklas Haas 880c59d189 ipc-unix: don't blow up on readonly fd://
On my system, when trying to use mpv with a read-only fd created by
python 3.7, `send` triggers ENOTSOCK, not EBADF. Extend the logic to
detect non-writable fds by this `errno`.
2018-10-31 09:20:44 +01:00
Ben Boeckel 6f0ed8e0b2 audio: increase a buffer size
The buffer is written to in `audio_config_to_str_buf` using `snprintf`
with a `%s` formatting of a 128-byte buffer. This can overflow the
target buffer of 80 causing a truncated output.
2018-10-31 09:20:26 +01:00
Ben Boeckel e3e1bdfb13 ipc-unix: leave room for a NUL terminator
The `strncpy` function will not always place a terminating `NUL` if the
source is longer than the destination buffer. Instead, let `strncpy`
truncate as it normally would, but leave the last byte alone (it is
zero-initialized when declared).
2018-10-31 09:20:26 +01:00
Philip Langdale 84d6638907 vo_gpu: hwdec_cuda: Clean up init() error handling
Currently, the error paths in init() are a bit confusing, and we can
end up trying to pop the current context when there is no context,
which leads to distracting error messages.

I also added an explicit path to return early if the GPU backend is
not OpenGL or Vulkan. It's pointless to do any other cuda init
after that point. (Of course, someone could write more interops.)

Fixes #6256
2018-10-31 09:20:06 +01:00
Jan Ekström 4056a9a420 ad_spdif: cosmetic alignment 2018-10-30 02:13:04 +02:00
Jan Ekström 25ee18d6e5 ad_spdif: fix DTS-HD HRA handling
Apparently, for bit streaming DTS-HD MA is specified to be handled as an
eight channel (7.1) bit stream, while DTS-HD HRA is specified to be
handled as a stereo bit stream.

Define a variable for this, and utilize it to set the correct values
for both the DTS-HD bit streaming rate, as well as the channel count
for the SPDIF encoder.

Fixes #6148
2018-10-30 02:13:04 +02:00
Akemi 865627d849 build: pass include paths as a list instead of a string in cocoa check
when passed as a string check_cc tries to split that string, since it
assumes that several include paths can be passed to it. instead we just
use a list to make it unambiguous.
2018-10-28 15:48:37 +02:00
Akemi 543a3bc0bd build: don't hardcode swift module name 2018-10-28 15:48:37 +02:00
Akemi eab30807fe build: use an argument list for the Swift build args
that way we don't need to quote or escape anything.

Fixes #6220
2018-10-28 15:48:37 +02:00
Anton Kindestam ba2dee38fb hwdec_drmprime_drm: Missing NULL-check on drm_atomic_context video_plane
Since 810acf32d6 video_plane can be NULL
under some circumstances. While there is a check in init, init treats
this as an error condition and would call uninit, which in turn calls
disable_video_plane, which would then segfault. Fix this by including
a NULL check inside disable_video_plane, so that it doesn't try to
disable what isnt' there.
2018-10-25 13:50:09 +02:00
pavelxdd bdec4421e6 stream_smb: make sure the string is NULL-terminated after strncpy
strncpy does not guarantee that the string will be NULL-terminated.
2018-10-25 13:49:49 +02:00
Philip Langdale da1073c247 vo_gpu: vulkan: hwdec_cuda: Add support for Vulkan interop
Despite their place in the tree, hwdecs can be loaded and used just
fine by the vulkan GPU backend.

In this change we add Vulkan interop support to the cuda/nvdec hwdec.

The overall process is mostly straight forward, so the main observation
here is that I had to implement it using an intermediate Vulkan buffer
because the direct VkImage usage is blocked by a bug in the nvidia
driver. When that gets fixed, I will revist this.

Nevertheless, the intermediate buffer copy is very cheap as it's all
device memory from start to finish. Overall CPU utilisiation is pretty
much the same as with the OpenGL GPU backend.

Note that we cannot use a single intermediate buffer - rather there
is a pool of them. This is done because the cuda memcpys are not
explicitly synchronised with the texture uploads.

In the basic case, this doesn't matter because the hwdec is not
asked to map and copy the next frame until after the previous one
is rendered. In the interpolation case, we need extra future frames
available immediately, so we'll be asked to map/copy those frames
and vulkan will be asked to render them. So far, harmless right? No.

All the vulkan rendering, including the upload steps, are batched
together and end up running very asynchronously from the CUDA copies.

The end result is that all the copies happen one after another, and
only then do the uploads happen, which means all textures are uploaded
the same, final, frame data. Whoops. Unsurprisingly this results in
the jerky motion because every 3/4 frames are identical.

The buffer pool ensures that we do not overwrite a buffer that is
still waiting to be uploaded. The ra_buf_pool implementation
automatically checks if existing buffers are available for use and
only creates a new one if it really has to. It's hard to say for sure
what the maximum number of buffers might be but we believe it won't
be so large as to make this strategy unusable. The highest I've seen
is 12 when using interpolation with tscale=bicubic.

A future optimisation here is to synchronise the CUDA copies with
respect to the vulkan uploads. This can be done with shared semaphores
that would ensure the copy of the second frames only happens after the
upload of the first frame, and so on. This isn't trivial to implement
as I'd have to first adjust the hwdec code to use asynchronous cuda;
without that, there's no way to use the semaphore for synchronisation.
This should result in fewer intermediate buffers being required.
2018-10-22 21:35:48 +02:00
Philip Langdale 621389134a vo_gpu: vulkan: Add a function to get the device UUID
We need this to do device matching for the cuda interop.
2018-10-22 21:35:48 +02:00
Philip Langdale a782197d21 vo_gpu: vulkan: Add arbitrary user data for an ra_vk_buf
This is arguably a little contrived, but in the case of CUDA interop,
we have to track additional state on the cuda side for each exported
buffer. If we want to be able to manage buffers with an ra_buf_pool,
we need some way to keep that CUDA state associated with each created
buffer. The easiest way to do that is to attach it directly to the
buffers.
2018-10-22 21:35:48 +02:00
Philip Langdale 93f800a00f vo_gpu: vulkan: Add support for exporting buffer memory
The CUDA/Vulkan interop works on the basis of memory being exported
from Vulkan and then imported by CUDA. To enable this, we add a way
to declare a buffer as being intended for export, and then add a
function to do the export.

For now, we support the fd and Handle based exports on Linux and
Windows respectively. There are others, which we can support when
a need arises.

Also note that this is just for exporting buffers, rather than
textures (VkImages). Image import on the CUDA side is supposed to
work, but it is currently buggy and waiting for a new driver release.

Finally, at least with my nvidia hardware and drivers, everything
seems to work even if we don't initialise the buffer with the right
exportability options. Nevertheless I'm enforcing it so that we're
following the spec.
2018-10-22 21:35:48 +02:00
Akemi 6fbd933108 build: more reliable way of getting the Swift version from a string
Fixes #6212
2018-10-22 01:41:09 +03:00
Niklas Haas facc63b862 vo_gpu: vulkan: suppress bogus error message on --vulkan-device
Since the code just broke out of the loop on a match rather than jumping
straight to the end of the function body, it ended up hitting the code
path for when the end of the list was reached.
2018-10-21 23:33:36 +02:00
Akemi 9a52b90f04 cocoa-cb: fix double clicking the title bar
since we draw our own title bar we lose the standard functionality of
the system provided title bar. because of that we have to reimplement
the functionality of double clicking the title bar. depending on the
system preferences we want to minimize, zoom or do nothing.

Fixes #6223
2018-10-21 23:33:25 +02:00
BtbN f3098cd61b vo_gpu: vulkan: fix strncpy truncation in spirv_compiler_init
Fixes GCC8 warning
../video/out/gpu/spirv.c: In function 'spirv_compiler_init':
../video/out/gpu/spirv.c:68:9: warning: 'strncpy' specified bound 32 equals destination size [-Wstringop-truncation]
2018-10-21 23:33:10 +02:00
slatchurie 24e21a0236 x11: fix icc profile when the window goes near off screen
On a multi monitor setup, when the center of the window was going off
screen, the icc profile would always switch to the profile of the first
screen.

This fixes the issue by defaulting the value to the current screen.
2018-10-21 23:32:50 +02:00
Niklas Haas 0f3e25cb0a vo_gpu: vulkan: fix the buffer size on partial upload
This was pased on the texture height, which was a mistake. In some cases
it could exceed the actual size of the buffer, leading to a vulkan API
error. This didn't seem to cause any problems in practice, since a
too-large synchronization is just bad for performance and shouldn't do
any harm internally, but either way, it was still undefined behavior to
submit a barrier outside of the buffer size.

Fix the calculation, thus fixing this issue.
2018-10-19 22:58:16 +02:00
Niklas Haas 7ad60a7c5e vo_gpu: split --linear-scaling into two separate options
Since linear downscaling makes sense to handle independently from
linear/sigmoid upscaling, we split this option up. Now,
linear-downscaling is its own option that only controls linearization
when downscaling and nothing more. Likewise, linear-upscaling /
sigmoid-upscaling are two mutually exclusive options (the latter
overriding the former) that apply only to upscaling and no longer
implicitly enable linear light downscaling as well.

The old behavior was very confusing, as evidenced by issues such
as #6213. The current behavior should make much more sense, and only
minimally breaks backwards compatibility (since using linear-scaling
directly was very uncommon - most users got this for free as part of
gpu-hq and relied only on that).

Closes #6213.
2018-10-19 22:58:01 +02:00
Nicolas F 448cbd472e x11_common: replace atoi with strtoul
Using strtol and strtoul is allegedly better practice, and I'm going
for strtoul here because I'm pretty sure X11 displays cannot be in
the negative.
2018-10-19 22:57:49 +02:00
Niklas Haas 104b510774 vo_gpu: opengl: fix segfault when gl->DeleteSync is unavailable
This deinit code was never checked, so this line would always crash on
implementations without support for sync objects.

Fixes #6197.
2018-10-16 01:57:49 +03:00
Nicolas F ce27b17a65 man: mention stats in interactive control
Someone on IRC pointed out that the default stats bindings weren't
documented in the interactive control section of the manual, so
let's add them with a short mention and a reference to the STATS
section of the manual.
2018-10-14 21:56:34 +03:00
Akemi 2b0b9bb6a1 cocoa-cb: fix side by side Split View
when entering a Split View a windowDidEnterFullScreen event happens
without a previous toggleFullScreen call. in that case it tries to stop
an animation that was never initiated by us and basically breaks the
system initiated fullscreen, or in this case the Split View. immediately
after entering the fullscreen it tries top stop the animation and
resizes the window, which causes the window to exit fullscreen. only
try to stop an animation that was initiated by us and is safe to stop.
2018-10-02 20:13:19 +03:00
Rodger Combs 1842a932d3 {mac,cocoa}: trim trailing null out of macosx_icon when loading it
This prevents crashes when loading the application icon image.

Suggested-by: Akemi <der.richter@gmx.de>
2018-10-02 00:20:43 +03:00
Rodger Combs ada4f7c600 mac: fix crash if we can't get an event tap
without assistive-device permissions the event tap can't be create on
10.14 any more which lead to an assertion.

System Preferences > Security & Privacy > Privacy > Accessibility and
add mpv or your terminal App to the list.
2018-10-02 00:20:02 +03:00
Jan Ekström be47e22b55 encode: simplify encode_lavc_add_packet
We're doing the same thing as the primary path - just that we log
and set 'failed' to true.
2018-10-01 23:34:11 +03:00
Niklas Haas 6d61c5f68a encode: fix AVPacket deinitialization logic
Since this function is called with packets on the stack, trying to free
them makes no sense. Instead, it should unref (which is what
`av_interleaved_write_frame` does anyway, rather than freeing).

Also, the calling code tried unreffing the packet a second time, even
after it was "freed" by the callee in the failure case - and after
ownership was taken over by `av_interleaved_write_frame` in the
successful case. Both of these cases were wrong.
2018-10-01 20:20:25 +03:00
wm4 9f6147a56f stats: show file format
Useful in particular with ytdl, where you never know what you get.
2018-10-01 10:41:01 +02:00
wm4 315004a38a demux_lavf: hack-fix EDL mp4 DASH hack
I encountered a stream that fails with "Could not demux init fragment.".
It turns out this is a regression from the recent change to that code.
The assumption was that demux_lavf.c would treat this as concatenated
stream - which it does, but not for probing.

Doing this transparently is hard without doing it properly. Doing it
properly would mean creating some sort of stream_concat (reminiscent of
that FFmpeg security bug). I probably don't want to go there, and I
think libavformat should just support this directly, so whatever.
Hack-fix this with the knowledge that the init segment will always
contain the headers.
2018-10-01 10:41:01 +02:00
wm4 7e85dc2167 stream_libarchive: fix hangs when demuxer does out of bound seeks
This happened with a .flac file inside an archive. It tried to seek
beyond the end of the archive entry in a format where seeking isn't
supported. stream_libarchive handles these situations by skipping data.
But when the end of the archive is reached, archive_read_data() returns
0. While libarchive didn't bother to fucking document this, they do say
it's supposed to work like read(), so I guess a return value of 0 really
means EOF. So change the "< 0" to "<= 0". Also add some error logging.

The same file actually worked without out of bounds reads when
extracted, so there still might be something very wrong.
2018-10-01 10:41:01 +02:00
wm4 a6fb94cf07 rendezvous: fix a typo 2018-10-01 10:41:01 +02:00
wm4 36e7ef96fc demux: allow cache sizes > 2GB
There was no reason to limit this. Only some int fields had to be
changed to size_t.
2018-10-01 10:41:01 +02:00
wm4 20d381d1e9 demux_lavf: v4l streams are not seekable
FFmpeg is retarded enough not to give us any indication whether it is
(unless we query fields not in the ABI/API). I bet FFmpeg developers
love it when library users have to litter their code with duplicated
information.
2018-10-01 10:41:01 +02:00
Josh Lehman 515c4163ea ao_audiounit: rename pause function to reset
AudioUnit output driver uses the pull based api so it should have
a reset function instead of a pause function.
2018-09-30 16:01:21 -07:00
Akemi 8d2d0f0640 cocoa-cb: add Apple Software Renderer support
by default the pixel format creation falls back to software renderer
when everything fails. this is mostly needed for VMs. additionally one
can directly request an sw renderer or exclude it entirely.
2018-09-30 17:13:34 +03:00
Akemi 44e49aee3c cocoa-cb: move macOS option retrieval to the earliest point possible
moved the retrieval of the macOS specific options from the backend
initialisation to the initialisation of the CocoaCB class, the earliest
point possible. this way macOS specific options can be used for the
opengl context creation for example.
2018-09-30 17:13:34 +03:00
Akemi 5c2056ad0a add swift as main dependency so all dependencies can be disabled easily 2018-09-30 16:54:03 +03:00
Akemi 50787acb27 build: check for Swift version and disable dependencies if needed 2018-09-30 16:54:03 +03:00
Aman b7339a7c7e Improve readme aesthetics.
This fixes the line under the header, creates a title header, and
slightly improves list formatting.
2018-09-30 15:56:22 +03:00
Anton Kindestam 810acf32d6 drm_atomic: Allow to create atomic context w/o drmprime video plane
This is to improve the experience when running with default settings
on a driver that doesn't have any overlay planes (or indeed only one
plane), but still supports DRM atomic. Since the drmprime video plane
is set to pick an overlay plane by default it would fail on these
drivers due to not being able to create any atomic context. Users with
such cards had to specify --drm-video-plane-id manually to some bogus
value (it's not used after all).

The "video" plane is only ever used by the drmprime-drm hwdec interop,
which is not used at all in the typical usecase where everything is
actually rendered on to the "OSD" plane using EGL, so having an atomic
context without the "video" plane should be fine most of the time.
2018-09-30 14:22:49 +03:00
Anton Kindestam f277f9f6d2 manpage: minor fix to --drm-format
Looking at other examples, a bar should be used when listing OPT_CHOICE options.
2018-09-30 14:22:49 +03:00
Tom Yan 95636c65e7 demux/packet: fix demux_packet_shorten
for the rawaudio demuxer to do the expected gapless playback
2018-09-30 12:32:03 +03:00
Jan Ekström 085943df25 travis: enable CI for release branches 2018-09-29 22:34:34 +03:00
Niklas Haas 730469cb29 vo_gpu: fix vec3 packing in UBOs/push_constants
For vec3, the alignment and size differ. The current code will pack a
struct like { vec3; float; vec2 } into 8 machine words, whereas the spec
would only use 6.

This actually fixes a real bug: The only place in the code I could find
where it was conceivably possible that a vec3 is followed by a float was
when using --gpu-dumb-mode in combination with --gamma-factor, and only
when --gpu-api=vulkan. So it's no surprised nobody ran into it yet.
2018-09-29 20:15:10 +02:00
Niklas Haas 39d10e3359 vo_gpu: use explicit offsets for push constants
These used to be unsupported long ago, but it seems glslang added
support in the meantime. (I don't know which version, but I'm guessing
it was long enough ago that we don't have to add a feature check)

Should hopefully help make push constant layouts more robust against
possible bugs either in our code or in the driver.
2018-09-29 20:15:10 +02:00
Jan Ekström cea4ff3e5f ao_alsa: log the ALSA state if we get a non-XRUN error
The ALSA state generally can tell us more information in case we
get an unexpected error.
2018-09-29 20:02:46 +02:00
Jan Ekström fdc952486a ao_alsa: handle XRUNs separately from other errors
According to ALSA doxy, EPIPE is a synonym to SND_PCM_STATE_XRUN,
and that is a state that we should attempt to automatically recover
from. In case recovery fails, log an error and return zero.

A warning message will still be output for each XRUN since those
are not something we should generally be receiving.
2018-09-29 20:02:46 +02:00
Jan Ekström 3218a58082 ao_alsa: early exit get_space if paused or ALSA is not ready
This has been way too long coming, and for me to notice that a
whole lot of ao_alsa functions do an early return if the AO is
paused.

For the STATE_SETUP case, I had this reproduced once, and never
since. Still, seems like we can start calling this function before
the ALSA device has been fully initialized so we might as well
early exit in that case.
2018-09-29 20:02:46 +02:00
Ricardo Constantino 9c184078a6 man/options: emphasize ytdl_hook's script options 2018-09-26 22:25:06 +01:00
sfan5 a4c5a4486e vo_gpu: adjust PRNG variant used by GL shaders
Certain low-end Mali GPUs have a rather low precision and overflow
during the PRNG calculations, thereby breaking e.g. deband-grain.
Modify the permute() to avoid this, this does not impact the
quality of PRNG output (noticeably).

This problem was observed on:
GL_VENDOR='ARM', GL_RENDERER='Mali-T720'
GL_VERSION='OpenGL ES 3.1 v1.r15p0-00rel0.bdd9e62cdc8c88e0610a16b5901161e9'
2018-09-26 23:53:05 +03:00
Ricardo Constantino 9dbab9661c ytdl_hook: fix audio not being picked up for some sites 2018-09-26 22:41:04 +02:00
Niklas Haas fed0ea111b ao_jack: only auto-connect to audio ports
This prevents ao_jack from auto-connecting to MIDI ports (or other,
hypothetical future port types).
2018-09-26 22:44:48 +03:00
TSaaristo 3744d0bda9 encode: fix expected streams when using --lavfi-complex
mpctx->current_track[0][STREAM_VIDEO] (and STREAM_AUDIO) are empty when
using --lavfi-complex. Moving the muxer stream hinting after audio/video chain
initialization and checking if the chains exist fixes encoding with --lavfi-complex.

Previously, the output audio/video streams did not get prepared and the encode
would fail due to unexpected stream addition.
2018-09-26 22:42:53 +03:00
Martin Herkt 6eb59fea2f ci: explicitly call waf with python3
Python 2 may not be present in the CI images in the future,
but waf’s shebang line still uses its executable name.
Explicitly call the right major version of the interpreter.
2018-09-11 01:26:28 +02:00
Niklas Haas 48c38f730d mp_image: strip all HDR peak information from SDR clips
By overriding it with 1.0 (aka SDR). This prevents blowing up on
mistagged clips.

Fixes #6111
2018-09-05 22:09:30 +02:00
Niklas Haas a5b0d59084 vo_gpu: switch to optimization level performance
Upstream has this now. Didn't really make any different for me (except
making the polar compute shader 2%-3% faster), but maybe it does for
somebody else.
2018-09-01 16:14:22 +02:00
Tom Yan 9d6b15ab32 ao_pulse: fix tlength calculation
also remove the now unused non-sensical af_fmt_seconds_to_bytes.
2018-09-01 16:14:11 +02:00
wm4 559a400ac3 demux, stream: rip out the classic stream cache
The demuxer cache is the only cache now. Might need another change to
combat seeking failures in mp4 etc. The only bad thing is the loss of
cache-speed, which was sort of nice to have.
2018-08-31 12:55:22 +02:00
wm4 5f83b6a5f5 rendezvous: fix a typo 2018-08-31 11:40:33 +02:00
Michael Hoang 91786fa99c Revert "ao_openal: enable building on OSX"
This reverts commit af6126adbe. Apple's
OpenAL support is ridiculously out of date, revert back to just using
OpenAL Soft on macOS (fixes #4645).
2018-08-26 15:49:22 +03:00
Niklas Haas 1890ca024e vo_gpu: avoid overwriting compute shader block sizes
When using multiple compute shaders as part of the same pass, there can
be a conflict in the block sizes. In the problematic case, the HDR
detection shader can collide with the polar sampling shader. In this
case, the solution is clear - the passes that can handle any size should
"give in" and not overwrite the block sizes.

Fixes #6083.
2018-08-26 12:32:20 +02:00
Hector Martin a10754f038 af_rubberband: reset delay to 0 on reset
This fixes A-V drift on seeking
2018-08-25 19:20:42 +03:00
wm4 120dcdf5cc demux: allow cache sizes > 2GB
There was no reason to limit this. Only some int fields had to be
changed to size_t.
2018-08-24 12:56:41 +02:00
wm4 9467e90c5b demux_lavf: v4l streams are not seekable
FFmpeg is retarded enough not to give us any indication whether it is
(unless we query fields not in the ABI/API). I bet FFmpeg developers
love it when library users have to litter their code with duplicated
information.
2018-08-24 12:55:10 +02:00
Tom Yan d4bbfb8453 osdep: make use of HAVE_ANDROID 2018-08-20 17:16:22 +02:00
Tom Yan d48786f682 wscript: split egl-android from android 2018-08-20 17:16:22 +02:00
Anton Kindestam d2d7dba6ee manpage: fix reference to --tone-mapping by old option name 2018-08-18 20:32:41 +02:00
Ricardo Constantino d8131568c8 ytdl_hook: always load ytdl:// links with ytdl_hook first
Suggested in IRC by sfan5.
2018-08-17 19:28:27 +01:00
Tom Yan 6c2d6a3046 ao_opensles: set numBuffers to 8
Apparently some Android builds/forks require this for Bluetooth
audio to work as they unexpectedly accept fast flag for it.

Shouldn't cause any side-effect (e.g. buffer requirement increased
when on wired audio). It's a hardcoded default in the upstream
AAudio implementation anyway.

Ref.:
https://android.googlesource.com/platform/frameworks/av/+/android-8.0.0_r1/media/libaaudio/src/legacy/AudioStreamTrack.cpp#109
https://android.googlesource.com/platform/frameworks/wilhelm/+/android-8.0.0_r1/src/android/AudioPlayer_to_android.cpp#1680
https://android.googlesource.com/platform/frameworks/av/+/android-8.0.0_r1/media/libaudioclient/AudioTrack.cpp#488
2018-08-13 19:10:10 +02:00
sfan5 2e7f60c386 demux_edl: add title option to override title of chapters 2018-08-13 19:09:57 +02:00
Aman Gupta d5cad85625 player: expose hearing/visual impaired flags on audio tracks
Signed-off-by: Aman Gupta <aman@tmm1.net>
2018-08-13 19:09:44 +02:00
Philip Sequeira c5d03d338e build: add --no-download option to bootstrap.py
With this option, the script will check that the expected waf version is
present, but will simply fail if it's not, rather than trying to
download it. This allows a package build script to avoid compile-time
network access but still ensure it's using the right waf version.
2018-08-13 19:09:35 +02:00
wm4 cdc05c33b3 player: don't print status line again when quitting
Quitting is slightly asynchronous, so the status line can be updated
again. Normally, that's fine, but if quitting comes with a message (such
as with quit_watch_later), it will print the status line again after the
message, which looks annoying. So flush and clear the status message if
it's updated during quitting.
2018-08-11 22:45:03 +02:00
Michael Hoang 4e9e46b9f8 osx: Fix initialization and access of service menu
Replace dot syntax with accessor syntax so that clang no longer errors
out due to not finding the property servicesMenu on NSApp.
2018-08-11 13:00:08 +02:00
Akemi 049816c145 cocoa-cb: fix crash on macOS 10.10
the colorspace of the layer is only available on 10.11 and upwards.

Fixes #6041
2018-08-11 12:59:50 +02:00
Akemi 6bf0edc59c cocoa-cb: fix crash when no screen is available
instead of force unwrapping and chaining the optional vars in our
containsMouseLocation function, safely unwrap and guard the resulting
var.

Fixes #6062
2018-08-11 12:59:44 +02:00
Tom Yan f2311ff514 audio/format: decouple af_fmt_is_planar from af_fmt_to_planar
so that af_fmt_to_planar (and hence af_fmt_from_planar) can just
return the input when it is not an interleaved (planar) format.
2018-08-11 11:56:27 +02:00
jaseg cfecbac863 manpage: Correct show-text duration default value
duration is parsed as an integer, and the default value is used if ```-1``` is passed. Passing ```-``` as described here causes a parameter value error.
2018-08-05 23:02:01 +02:00
pavelxdd 759a6a259e manpage: fix --vf exclamation mark description
An exclamation mark disables the filter by default instead of
enabling it.
2018-08-05 23:01:45 +02:00
Tom Yan 93a57d4c8b ao_opensles: update interface-changes 2018-08-05 17:52:01 +02:00
Tom Yan e1bd5288b7 ao_opensles: rework the heuristic of buffer/enqueue size setting
ao->device_buffer will only affect the enqueue size if the latter
is not specified. In other word, its intended purpose will solely
be setting/guarding the soft buffer size.

This guarantees that the soft buffer size will be consistent no
matter a specific enqueue size is set or not. (In the past it
would drop to the default of the generic audio-buffer option.)

opensles-frames-per-buffer has been renamed to opensles-frames-per
-enqueue, as it was never purposed to set the soft buffer size. It
will only make sure the size is never smaller than itself, just as
before.

opensles-buffer-size-in-ms is introduced to allow easy tuning of
the relative (i.e. in time) soft buffer size (and enqueue size,
unless the aforementioned option is set). As "device buffer" never
really made sense in this AO, this option OVERRIDES audio-buffer
whenever its value (including the default) is larger than 0.

Setting opensl-buffer-size-in-ms to 1 allows you to equate the soft
buffer size to the absolute enqueue size set with opensl-frames-per
-enqueue conveniently (unless it is less than 1ms).

When both are set to 0, audio-buffer will be the ultimate fallback.
If audio-buffer is also 0, the AO errors out.
2018-08-05 17:52:01 +02:00
Tom Yan 8baad91e7b ao_opensles: allow s32 and float output
OpenSLES (and its AudioTrack backend) in Android can take 32-bit
fixed and floating point input since Android L (API 21).
2018-08-05 17:51:45 +02:00
Tom Yan 4e91cb72ef audio/format: minor fix for af_fmt_from_planar
See af_fmt_to_planar.
2018-08-05 17:51:45 +02:00
Yclept Nemo 5532a3da1e stream_smb/stream_file: fix write_buffer
Functions `write` and `smbc_write` are given a diminishing buffer of
incorrect constant size. After partial writes, the code would do another
write of the full original length, failing to subtract the amount
already written.
2018-07-29 12:54:56 +03:00
Yclept Nemo 112b3fa922 stream_smb: locking to bypass libsmbclient issues
Thread-unsafe libsmbclient is likely to crash when used simultaneously
across threads. For example, by:

    mpv "smb://...mkv" --sub-file "smb://...srt"

Work around this by locking all calls to this library under a single
global mutex. This is a temporary solution. When the libsmbclient bug
[1] is fixed, switch to the code from branch [2] which uses a new api to
create per-thread smb contexts. Fixes [3].

[1] https://bugzilla.samba.org/show_bug.cgi?id=11413
[2] https://github.com/orbisvicis/mpv/tree/smbclient_threaded_api
[3] https://github.com/mpv-player/mpv/issues/5936
2018-07-29 12:54:56 +03:00
Jan Ekström 2d785f3ea3 ci: do bootstrap outside the docker container
This way the docker container in itself does no networking.

It seems like travis disabled network access from the actual docker
containers.
2018-07-29 12:07:43 +03:00
Daniel M. Capella 45beb7073a manpage: fixup mistaken show playlist/track-list shortcuts
This was mistaken in 496b13227b and
not noticed in review.
2018-07-23 01:31:41 +03:00
Martin Herkt e2a616bab2 Update VERSION 2018-07-22 18:47:16 +02:00
wm4 bf05697653 HACK: prefetch subtitles on track switch a bit more
To get overlapping shit etc.
2018-06-30 17:55:21 +02:00
wm4 99afa8d51b player: don't cache subtitles across deselection
This means reselection triggers full reinit. This is better if you have
options that "edit" subtitles or whatever.
2018-06-30 17:15:29 +02:00
wm4 4d6d3a3455 player: fix coding style
I'm also not sure whether this condition doesn't subtly break a lot of
things.
2018-05-24 20:00:13 +02:00
wm4 8527102121 m_config: remove a redundant condition
Always true, because a few lines above it checks for the same thing.
2018-05-24 19:56:39 +02:00
wm4 982416266c demux_lavf: drop obscure genpts option
This code shouldn't even exist in libavformat. If you still need it, you
can enable it via --demuxer-lavf-o.
2018-05-24 19:56:35 +02:00
wm4 b406f679b1 vo: remove bogus #if
If anyone happened to build with GL disabled, this could lead to option
changes not always refreshing the screen. Since vo_gpu is always enabled
now (just not necessarily any backend for it), we can drop the #if
completely.

(The way this works is a bit idiotic - the option cache exists only to
grab the change notification, which will trigger a redraw and make
vo_gpu update its own second copy of them. But at least it avoids some
layering issues for now.)
2018-05-24 19:56:35 +02:00
wm4 1112b1ba33 terminal-unix: stop trying to read when terminal disappears
Avoids 100% CPU usage due to terminal code retrying read(). Seems like
this was "forgotten" (or there was somehow the assumption poll() would
not signal POLLIN anymore).

Fixes #5842.
2018-05-24 19:56:35 +02:00
wm4 b2e24f42d5 options: add --http-proxy
Often requested, trivial.
2018-05-24 19:56:35 +02:00
wm4 115aaec76c command: avoid some direct MPOpts write accesses
This is working towards a change intended in the future: nothing should
write to the option struct directly, but use functions that raise proper
notifications. Until this is complete it will take a while, and this
commit does not change all cases of direct access, just some simple
ones.

In all of these 3 changes, the actual write access is done by the
generic property-option bridge.
2018-05-24 19:56:35 +02:00
wm4 0317d7350e m_config: fix build with emulated stdatomic
C11 can access atomic variables normally (in which case they use the
strictest memory access semantics). But the mpv stdatomic wrapper for
C99 compilers does not allow it, because it couldn't give any
guarantees. This means we always need to access them with atomic macros.

While we're at, use relaxed semantics for the m_config_cache field,
since because it's accessed from a single thread only (essentially
used in a non-atomic way). Switch the comparison arguments to make the
formatting look slightly less weird.
2018-05-24 19:56:35 +02:00
wm4 1a86bb59df m_config: make m_config_cache_update() return more fine grained
Although the new code actually fires update notifications only when
needed, m_config_cache_update() itself returned a rather coarse change
value, which could indicate change even if none of the cached options
were changed. On top of that, some code (like vo_gpu) calls the update
function on every frame, which would reconfigure the renderer even on
unrelated option changes.
2018-05-24 19:56:35 +02:00
wm4 f8ab59eacd player: get rid of mpv_global.opts
This was always a legacy thing. Remove it by applying an orgy of
mp_get_config_group() calls, and sometimes m_config_cache_alloc() or
mp_read_option_raw().

win32 changes untested.
2018-05-24 19:56:35 +02:00
wm4 a770006c6e vd_lavc: move hwdec opts to local config, don't use global MPOpts
The --hwdec* options are a good fit for the vd_lavc local option
struct. This annoyingly requires manual prefixing of most of these
options with --vd-lavc (could be avoided by using more sub-struct
craziness, but let's not).
2018-05-24 19:56:35 +02:00
wm4 3569857b75 path: don't access global option struct
The path functions need to access the option that forces non-default
config directories. Just add it as a field to mpv_global - it seems
justified. The accessed options were always enforced as immutable after
init, so there's not much of a change.
2018-05-24 19:56:35 +02:00
wm4 fe6b2f9103 m_config: add a special define to access main config
Passing NULL to mp_get_config_group() returns the main option struct.
This is just a dumb hack to deal with inconsistencies caused by legacy
things (as I'll claim), and will probably be changed in the future. So
before littering the whole code base with hard to find NULL parameters,
require using callers an easy to find separate define.
2018-05-24 19:56:35 +02:00
wm4 fb22bf2317 ao: use a local option struct
Instead of accessing MPOpts.
2018-05-24 19:56:35 +02:00
wm4 160e5c8377 player: remove deprecated vo/ao auto profiles
These were deprecated almost 2 years ago. Now they happen to be in the
way.
2018-05-24 19:56:35 +02:00
wm4 455af6aa68 m_config: optimize initialization of each option
Options with dynamic memory allocations (such as strings) require some
care. They need to be fully copied on initialization, and if a static
default value was declared, we must not free that value either.

Instead of going through the entire thing even for simple types like
integers, really run it only for options with dynamic allocations. To
distinguish types which use dynamic allocations, we can use the fact
that they require a free callback (otherwise they would leak). As a
result initialization of simple types becomes chaper, and the init
function does nothing at all if src==dst for a simple type.

(It's funny how mplayer had M_OPT_TYPE_DYNAMIC since 2002, until we
replaced it by the same heuristic as used here in commit 3bb134969e.
It's also funny how the new check was used only for some asserts, and
finally removed in commit 7539928c1c. I guess at this time I felt like
having uniform code was more important than pointless
micro-optimizations.)

The src==NULL case is removed because it can't happen.
2018-05-24 19:56:35 +02:00
wm4 816ad03519 m_config: remove extra default_data field
Just wastes memory (a few KB, because there are so many options).
2018-05-24 19:56:35 +02:00
wm4 3f061dd629 m_config: remove unused fields 2018-05-24 19:56:35 +02:00
wm4 5ae271e4f4 build: prefer C11 mode
C99 still works, but in theory we're using C11 features already, such as
stdatomic.h. gcc/clang let us use it in C99 mode too, but using C11 is
at least more proper.
2018-05-24 19:56:35 +02:00
wm4 1ebc72d05c m_config: reduce redundant option change notifications 2018-05-24 19:56:35 +02:00
wm4 4cb264a3ff m_config: remove an old temporary hack
Actually rewrite most of the option management code. This affects how
options are allocated, and how thread-safe access to them is done.

One thing that is nicer is that creating m_config_cache does not need to
ridiculously recreate and store the entire option list again. Instead,
option metadata and option storage are now separated. m_config contains
the metadata, and m_config_data all or parts of the actual option
values. (m_config_cache simply uses the metadata part of m_config, which
is immutable after creation.)

The mentioned hack was introduced in commit 1a2319f3e4, and is the
global state around g_group_mutex. Although it was "benign" global
state, it's good that it's finally removed.
2018-05-24 19:56:35 +02:00
wm4 707b404820 osdep: add portable C11-like alignof() macro 2018-05-24 19:56:35 +02:00
wm4 af4fe28af7 m_config: remove outdated comment 2018-05-24 19:56:35 +02:00
wm4 246a828c26 m_config: check for int16_t offset overflow
For some reason shadow_offset is a int16_t variable (to save some space
or something), which means the static part of the entire option list
must be below 32KB. This is fine, but still add a check against
overflows. (Currently it's 3.6KB. This does not include dynamic
allocations like strings.)
2018-05-24 19:56:35 +02:00
wm4 4e9166f22d m_config: remove an unused function 2018-05-24 19:56:35 +02:00
wm4 a7c853fc64 m_option: remove an unused field 2018-05-24 19:56:35 +02:00
wm4 3ed173643e m_config: cosmetics: fix 2 typos 2018-05-24 19:56:35 +02:00
wm4 b3968ecf05 input: remove now unused "abort command" and cancel infrastructure
The previous commit removed all uses.
2018-05-24 19:56:35 +02:00
wm4 dbcd654e61 player: make playback termination asynchronous
Until now, stopping playback aborted the demuxer and I/O layer violently
by signaling mp_cancel (bound to libavformat's AVIOInterruptCB
mechanism). Change it to try closing them gracefully.

The main purpose is to silence those libavformat errors that happen when
you request termination. Most of libavformat barely cares about the
termination mechanism (AVIOInterruptCB), and essentially it's like the
network connection is abruptly severed, or file I/O suddenly returns I/O
errors. There were issues with dumb TLS warnings, parsers complaining
about incomplete data, and some special protocols that require server
communication to gracefully disconnect.

We still want to abort it forcefully if it refuses to terminate on its
own, so a timeout is required. Users can set the timeout to 0, which
should give them the old behavior.

This also removes the old mechanism that treats certain commands (like
"quit") specially, and tries to terminate the demuxers even if the core
is currently frozen. This is for situations where the core synchronized
to the demuxer or stream layer while network is unresponsive. This in
turn can only happen due to the "program" or "cache-size" properties in
the current code (see one of the previous commits). Also, the old
mechanism doesn't fit particularly well with the new one. We wouldn't
want to abort playback immediately on a "quit" command - the new code is
all about giving it a chance to end it gracefully. We'd need some sort
of watchdog thread or something equally complicated to handle this. So
just remove it.

The change in osd.c is to prevent that it clears the status line while
waiting for termination. The normal status line code doesn't output
anything useful at this point, and the code path taken clears it, both
of which is an annoying behavior change, so just let it show the old
one.
2018-05-24 19:56:35 +02:00
wm4 8816e1117e player: change the role of the "stop_play" and "playing" variable
Before this, mpctx->playing was often used to determine whether certain
new state could be added to the playback state. In particular this
affected external files (which added tracks and demuxers). The variable
was checked to prevent that they were added before the corresponding
uninit code. We want to make a small part of uninit asynchronous, but
mpctx->playing needs to stay in the place where it is. It can't be used
for this purpose anymore.

Use mpctx->stop_play instead. Make it never have the value 0 outside of
loading/playback. On unloading, it obviously has to be non-0.

Change some other code in playloop.c to use this, because it seems
slightly more correct. But mostly this is preparation for the following
commit.
2018-05-24 19:56:35 +02:00
wm4 c24520b7f3 demux: add a way to destroy the demuxer asynchronously
This will enable the player core to terminate the demuxers in a "nicer"
way without having to block on network. If it just used demux_free(), it
would either have to block on network, or like currently, essentially
kill all I/O forcefully.

The API is slightly awkward, because demuxer lifetime is bound to its
allocation. On the other hand, changing that would also be awkward, and
introduce weird in-between states that would have to be handled in tons
of places.

Currently unused, to be user later.
2018-05-24 19:56:35 +02:00
wm4 ee88ae15b3 player: move a function (no functional changes) 2018-05-24 19:56:35 +02:00
wm4 dee84be222 manpage: update --demuxer-thread option
Be a bit more detailed, and discourage disabling it.
2018-05-24 19:56:35 +02:00
wm4 29a51900c6 player: some further cleanup of the mp_cancel crap
Alway give each demuxer its own mp_cancel instance. This makes
management of the mp_cancel things much easier. Also, instead of having
add/remove functions for mp_cancel slaves, replace them with a simpler
to use set_parent function. Remove cancel_and_free_demuxer(), which had
mpctx as parameter only to check an assumption. With this commit,
demuxers have their own mp_cancel, so add demux_cancel_and_free() which
makes use of it.
2018-05-24 19:56:35 +02:00
wm4 d33e5972b3 demux: get rid of free_demuxer[_and_stream]()
Them being separate is just dumb. Replace them with a single
demux_free() function, and free its stream by default. Not freeing the
stream is only needed in 1 special case (demux_disc.c), use a special
flag to not free the stream in this case.
2018-05-24 19:56:35 +02:00
wm4 562d8e6d32 player: simplify edition switching
The player fully restarts playback when the edition or disk title is
changed. Before this, the player tried to reinitialized playback
partially. For example, it did not print a new "Playing: <file>"
message, and did not send playback end to libmpv users (scripts or
applications).

This playback restart code was a bit messy and could have unforeseen
interactions with various state. There have been bugs before. Since it's
a mostly cosmetic thing for an obscure feature, just change it to a full
restart. This works well, though since it may have consequences for
scripts or client API users, mention it in interface-changes.rst.
2018-05-24 19:56:35 +02:00
wm4 d7ca95c3ea command: whitelist some blocking accesses for certain demuxers/streams
The properties/commands touched in this commit are all for obscure
special inputs (BD/DVD/DVB/TV), and they all block on the demuxer/stream
layer. For network streams, this blocking is very unwelcome. They will
affect playback and probably introduce pauses and frame drops. The
player can even freeze fully, and the logic that tries to make playback
abortable even if frozen complicates the player.

Since the mentioned accesses are not needed for network streams, but
they will block on network streams even though they're going to fail,
add a flag that coarsely enables/disables these accesses. Essentially it
establishes a whitelist of demuxers/streams which support them.

In theory you could to access BD/DVD images over network (or add such
support, I don't think it's a thing in mpv). In these cases these
controls still can block and could even "freeze" the player completely.

Writing to the "program" and "cache-size" properties still can block
even for network streams. Just don't use them if you don't want freezes.
2018-05-24 19:56:35 +02:00
wm4 b6214b2644 timer: remove an unused helper function
It's also dumb.
2018-05-24 19:56:35 +02:00
wm4 1ad027e8fd thread_pool: add a helper function
The behavior of mp_thread_pool_queue() doesn't or shouldn't change, but
the new helper function requires touching its logic.
2018-05-24 19:56:35 +02:00
wm4 f0cc6ba18d thread_pool: move comments to .h file 2018-05-24 19:56:35 +02:00
wm4 76dc5d9aa9 command: make loadlist command async and abortable
Don't allow it to freeze everything when loading a playlist from network
(although you definitely shouldn't do that, but whatever).

This also affects the really obscure --ordered-chapters-files option.
The --playlist option on the other hand has no choice but to freeze the
shit, because there's no concept of aborting the player during command
line parsing.
2018-05-24 19:56:35 +02:00
wm4 12d1404b04 player: make various commands for managing external tracks abortable
Until now, they could be aborted only by ending playback, and calling
mpv_abort_async_command didn't do anything.

This requires furthering the mess how playback abort is done. The main
reason why mp_cancel exists at all is to avoid that a "frozen" demuxer
(blocked on network I/O or whatever) cannot freeze the core. The core
should always get its way. Previously, there was a single mp_cancel
handle, that could be signaled, and all demuxers would unfreeze. With
external files, we might want to abort loading of a certain external
file, which automatically means they need a separate mp_cancel. So give
every demuxer its own mp_cancel, and "slave" it to whatever parent
mp_cancel handles aborting.

Since the mpv demuxer API conflates creating the demuxer and reading the
file headers, mp_cancel strictly need to be created before the demuxer
is created (or we couldn't abort loading). Although we give every
demuxer its own mp_cancel (as "enforced" by cancel_and_free_demuxer),
it's still rather messy to create/destroy it along with the demuxer.
2018-05-24 19:56:35 +02:00
wm4 f9713921a3 demux: add a "cancel" field
Instead of relying on demuxer->stream->cancel. This is better because
the stream is potentially closed and replaced.
2018-05-24 19:56:35 +02:00
wm4 a0cce7f775 stream_file: use a separate mp_cancel thing
The intention is to avoid that the parent mp_cancel retains the
internally allocated wakeup pipe. File FDs are a relatively scarce
resource, so try to avoid having too many. This might matter for
subtitle files, for which it is relatively likely that they are loaded
in large quantities.

demux_lavf.c will close the underlying stream for most subtitle files,
and now it will free the wakeup pipe too. Actually, there are currently
only 1 or 2 mp_cancel objects per mpv core, but this could change if
every external subtitle track gets its own mp_cancel in later commits.
2018-05-24 19:56:35 +02:00
wm4 a253c72dbb thread_tools: unify mp_cancel POSIX/win32 paths, add features
The OS specifics are merged because the resulting ifdeffery is not much
worse than the old ifdeffery, but the logic that is now shared is
becoming more complex.

Create all objects lazily. The intention is to make mp_cancel instances
cheaper. POSIX pipes and win32 Events are pretty heavy weight, and are
only needed in special situations.

Add a mechanism to "chain" mp_cancel instances. Needed by the later
commits for whatever reasons.

Untested on win32.
2018-05-24 19:56:35 +02:00
wm4 782e428284 misc: add linked list helpers
This provides macros for managing intrusive doubly linked lists.

There are many ways how to do those in a "generic" way in C. For example
Solaris style lists are pretty nice:

https://github.com/illumos/illumos-gate/blob/master/usr/src/uts/common/sys/list.h
https://github.com/illumos/illumos-gate/blob/master/usr/src/common/list/list.c

I even have an independent implementation of this, which could be ISC
licensed. But I think it's easier to vomit ~100 lines of preprocessor
garbage, which has a lower footprint, and I think it wins slightly on
the side of type safety, simplicity, and ease of use, even if it doesn't
look as magically nice.
2018-05-24 19:56:35 +02:00
wm4 094f6be600 thread_tools: minor simplification 2018-05-24 19:56:35 +02:00
wm4 31b78ad7fa misc: move mp_cancel from stream.c to thread_tools.c
It seems a bit inappropriate to have dumped this into stream.c, even if
it's roughly speaking its main user. At least it made its way somewhat
unfortunately to other components not related to the stream or demuxer
layer at all.

I'm too greedy to give this weird helper its own file, so dump it into
thread_tools.c.

Probably a somewhat pointless change.
2018-05-24 19:56:35 +02:00
wm4 12bd4fe9ab cmd: do not use a random value for MP_CMD_OPT_ARG
This flag is used only by the command parser. Its value overlapped with
some of the existing m_option flags, but only flags that did not matter
for the command parser (i.e. the flag bits used had mostly private uses
in each component). It's still a bit unclean and dangerous to use an
essentially random value, so reuse M_OPT_OPTIONAL_PARAM for it.

Since M_OPT_OPTIONAL_PARAM has a slightly longer name than
MP_CMD_OPT_ARG, I'm going to keep the old name.
2018-05-24 19:56:34 +02:00
wm4 0a7a4779a3 input: slightly improve --input-cmdlist output
Output argument names, whether varargs are used, and indicate optional
arguments correctly (instead of only half of them).
2018-05-24 19:56:34 +02:00
wm4 332907e1d7 command: give named arguments to almost all commands
Before this change, only 1 command or so had named arguments. There is
no reason why other commands can't have them, except that it's a bit of
work to add them.

Commands with variable number of arguments are inherently incompatible
to named arguments, such as the "run" command. They still have dummy
names, but obviously you can't assign multiple values to a single named
argument (unless the argument has an array type, which would be
something different). For now, disallow using named argument APIs with
these commands. This might change later.

2 commands are adjusted to not need a separate default value by changing
flag constants. (The numeric values are C only and can't be set by
users.)

Make the command syntax in the manpage more consistent. Now none of the
allowed choice/flag names are in the command header, and all arguments
are shown with their proper name and quoted with <...>.

Some places in the manpage and the client.h doxygen are updated to
reflect that most commands support named arguments. In addition, try to
improve the documentation of the syntax and need for escaping etc. as
well.

(Or actually most uses of the word "argument" should be "parameter".)
2018-05-24 19:56:34 +02:00
wm4 d36b85cfdf json: add some non-standard extensions
Also clarify this and previously existing differences to standard JSON
in ipc.rst.
2018-05-24 19:56:34 +02:00
wm4 76bff1a000 json: format slightly nicer escape sequences
Make use the escape sequences allowed by JSON.

Also update the linked RFC to the newest one.
2018-05-24 19:56:34 +02:00
wm4 711858377c test: add tests for json parser/formatter
This should have been done sooner.
2018-05-24 19:56:34 +02:00
wm4 cec37e98d5 misc: move some helper code from client.c
(Slightly oddly function names, because I want to avoid starting them
with mpv_*, which is reserved for public API.)
2018-05-24 19:56:34 +02:00
wm4 ec7d1e86b6 player: use canonical playback time for video refreshes
When changing video filters during initialization, there was a small
time window where video was initialized, but playback restart was not
complete yet. In this time window, playback_pts is not set. But since
issue_refresh_seek() was using this, it could lead to no refresh being
done _if_ the "video" had only 1 frame (such as cover art).

Fix this by using get_current_time() instead, which is the current time
with corner cases such as ongoing loading or seeks taken into account.

See also the previous commit. Without that, get_current_time() could
return NOPTS during init.

Fixes #5831.
2018-05-24 19:56:34 +02:00
wm4 4d2b3fca3b player: don't reset last_seek_pts on playback state reset
This is nonsense. Didn't matter in most situations, because seeking
itself set this after it was cleared. But some callers don't do this,
see e.g. commit ed73ba8964. There is no need to clear it at all, and
it causes issues with the next commit. It only needs to be reset on
loading.

Also move the initialization on loading up, which doesn't change
behavior, but makes the intention clearer.
2018-05-24 19:56:34 +02:00
wm4 972989db7e manpage: mention that fd:// file descriptors may be modified
For example, we call setmode() to switch a FD from text to binary mode
on garbage OSes.
2018-05-24 19:56:34 +02:00
wm4 34259f11dc stream_file: properly detect stdin as pipe
There is some code that checks a FD for whether it is a regular file or
not. If it's not a regular file, it e.g. enables use of poll() to avoid
blocking forever.

But this was done only for FDs that were open()ed by us, not from stdin
special handling or fd://. Consequently, " | mpv -" could block the
player. Fix this by moving the code and running for it on all FDs.

Also, set p->regular_file even on mingw.
2018-05-24 19:56:34 +02:00
wm4 c9fcd20959 vd_lavc: minor simplification for get_format fallback
The default get_format does exactly do this, so we don't need to
duplicate it.

The only potential problem with this is that the logic doesn't entirely
prevent that the avcodec_default_get_format hw_device_ctx path is
triggered, which would probably work, but has unknown consequences and
interactions. But the way the logic currently works it can't happen,
provided the hwaccel metadata libavcodec provides is correct.
2018-05-24 19:56:34 +02:00
wm4 5f61892c42 manpage: remove a reference to a removed option 2018-05-24 19:56:34 +02:00
wm4 75b2e6ed67 demux: late streams on start shouldn't restrict the seek range
If a stream starts later than the others at the start of the file, it
shouldn't restrict the seek range to the time stamp where it begins.
This is similar to the previous commit, just for the other end.
2018-05-24 19:56:34 +02:00
wm4 2fc59ea8b3 demux: streams that reached EOF shouldn't restrict the seek range
Normally, the seek range is the minimum overlap of the cached ranges of
each stream. But if one of the streams ends earlier, this leads to the
seek range getting cut off, even if you could seek there.

Change it so that EOF streams cannot restrict the end of the seek range.
They can only extend it. This is the opposite from not-EOF streams, so
they need to be handled separately. In particular, they get exluded from
normal end range calculation, but when full EOF is reached, all streams
are EOF, and the maximum end time can be used to set the seek end time.
(In theory we could also take the max with the demuxer signaled total
file duration, but let's not for now.)

Also, if a stream is completely empty, essentially skip it, instead of
considering the range unseekable. (Also, we don't need to mess with
seek_start in this case, because it will be NOPTS and is skipped
anyway.)
2018-05-24 19:56:34 +02:00
wm4 9ceccd6fca demux: fix/improve aspects of EOF signaling
When the current packet queue was completely empty, and EOF was reached,
the queue->is_eof flag was not correctly set to true. Change this by
reading ds->eof to check whether the stream is considered EOF. We also
need to make sure update_seek_ranges() is called in this case, so change
the code to simply call it when queue->is_eof changes.

Also, read_packet() needs to call adjust_seek_range_on_packet() if
ds->eof changes. In that case, the decoder also needs to be notified
about EOF. So both of these should be called when ds->eof changes to
true. (Other code outside of this function deals with the case when
ds->eof is changed to false.)

In addition, this code was kind of shoddy about calling wakeup_ds()
correctly. It looks like there was an inverted condition, and sent a
wakeup to the decoder only when ds->eof was already true, which is
obviously bogus. The final EOF case tried to be somehow clever about
checking in->last_eof for notifying the codec, which is sort of OK, but
seems to be strictly worse than just checking whether ds->eof changed.
Fix these things.
2018-05-24 19:56:34 +02:00
wm4 7428cc5149 client API: kill async commands on termination
This affects async commands started by client API, commands with async
capability run in a sync way by client API (think mpv_command_node()
with "subprocess"), and detached async work.

Since scripts might want to do some cleanup work (that might involve
launching processes, don't ask), we don't unconditionally kill
everything on exit, but apply an arbitrary timeout of 2 seconds until
async commands are aborted.
2018-05-24 19:56:34 +02:00
wm4 4e05f75261 demux_lavf: remove ffm blacklist entry
ffm (ffserver) was removed from ffmpeg.
2018-05-24 19:56:34 +02:00
wm4 fc574ee563 ipc: some user-visible changes to prepare for making all commands async
I wanted to put all commands through mpv_command_node_async() instead of
mpv_command_node(). Using synchronous commands over a synchronous
transport doesn't make sense anyway.

This would have used the request_id field in IPC requests as reply ID
for the async commands. But the latter need to be [u]int64, while the
former can be any type. To avoid that we need an extra lookup table for
mapping reply IDs to request_id values, we now require that request_id
fields are integers.

Since this would be an incompatible change, just deprecate non-integers
for now, and plan the change for a later time.
2018-05-24 19:56:34 +02:00
wm4 11c74068b2 ipc: cosmetic: switch a negated if/else 2018-05-24 19:56:34 +02:00
wm4 b44ea70209 ipc: alias set_property_string to set_property
The only effective difference is that the former explicitly checks
whether the JSON value type is string, and errors out if not. The rest
is exactly the same (mpv_set_property_string is mpv_set_property with
MPV_FORMAT_STRING).

It seems silly to keep this, so just remove it.
2018-05-24 19:56:34 +02:00
wm4 dbe831bd02 lua: expose mpv_abort_async_command()
Also somewhat cleans up mp.command_native_async() error handling.
2018-05-24 19:56:34 +02:00
wm4 9c530c7ee9 command: make "subprocess" explicitly abortable
Now mpv_abort_async_command() can be used to stop the process.
2018-05-24 19:56:34 +02:00
wm4 e4fb23ed7d command: add a way to abort asynchronous commands
Many asynchronous commands are potentially long running operations, such
as loading something from network or running a foreign process.
Obviously it shouldn't just be possible for them to freeze the player if
they don't terminate as expected. Also, there will be situations where
you want to explicitly stop some of those operations explicitly. So add
an infrastructure for this.

Commands have to support this explicitly. The next commit uses this to
actually add support to a command.
2018-05-24 19:56:34 +02:00
wm4 ce1f5e78c2 player: rename "lock" to "abort_lock"
If a struct as large as MPContext contains a field named "lock", it
creates the impression that it is the primary lock for MPContext. This
is wrong, the lock just protects a single field.
2018-05-24 19:56:34 +02:00
wm4 7f91e2684e lua: reimplement mp.subprocess_detached() by invoking the "run" command
The "run" command is old. I'm not sure why the separate Lua
implementation was added. But maybe it as because the "run" command used
to be limited to a small number of arguments. This limit has been
removed a while ago. In any case, the old implementation is not needed
anymore.
2018-05-24 19:56:34 +02:00
wm4 548ef07864 lua: reimplement mp.subprocess() by invoking the new subprocess command
We keep mp.subprocess() with roughly the same semantics for
compatibility with scripts (including the internal ytdl script).

Seems to work with rhe ytdl wrapper. Not tested further.
2018-05-24 19:56:34 +02:00
wm4 d9bc97bda6 command: add a subprocess command
This supports named arguments. It benefits from the infrastructure of
async commands.

The plan is to reimplement Lua's utils.subprocess() on top of it.
2018-05-24 19:56:34 +02:00
wm4 1aae88b487 input: add glue code for named arguments
Named arguments should make it easier to have long time compatibility,
even if command arguments get added or removed. They're also much nicer
for commands with a large number of arguments, especially if many
arguments are optional.

As of this commit, this can not be used, because there is no command yet
which supports them. See the following commit.
2018-05-24 19:56:34 +02:00
wm4 1157f07c5b node: move a mpv_node helper from ipc.c to shared code
This particular one is needed in a following commit.
2018-05-24 19:56:34 +02:00
wm4 4fd3ad8d63 thread_pool: set thread name 2018-05-24 19:56:34 +02:00
wm4 0354e7c599 video: trust container FPS early on if possible
If the container FPS is correct, this can help getting ideal mix factors
for vo_gpu interpolation mode. Otherwise, it doesn't matter.
2018-05-24 19:56:34 +02:00
wm4 cc2490ea7e input: add a define for the number of mouse buttons and use it
(Why the fuck are there up to 20 mouse buttons?)
2018-05-24 19:56:34 +02:00
wm4 be5e46222b TOOLS: add a stupid test program for Lua async commands 2018-05-24 19:56:34 +02:00
wm4 159379980e lua: expose async commands
Might be useful for some.
2018-05-24 19:56:34 +02:00
wm4 d7ed3ba473 screenshot: report success to caller
Matters only to API callers, but still nice to have.
2018-05-24 19:56:34 +02:00
wm4 b0a04b8dea client API: merge status_reply() helper with only remaining caller
All other callers had to be changed, so there's no point in keeping this
helper function around. It's just another unnecessary indirection.
2018-05-24 19:56:34 +02:00
wm4 f0678afba0 client API: add returning of data from async commands
This was not done sooner out of laziness.
2018-05-24 19:56:34 +02:00
wm4 005d3bc81a client API: clarify asynchronous call ordering non-guarantees
Both asynchronous and synchronous calls used to be put into the core's
dispatch queue. Also, asynchronous calls were actually synchronous, just
without forcing a wait on the client's thread. This meant that both
kinds of calls were always strictly ordered.

A longer time ago, synchronous calls were changed to simply lock the
core. This could possibly lead to reordering. Recently, some commands
were changed to run on worker threads, which made the order even looser.

Also remove another now incorrect doxygen comment regarding async
commands.
2018-05-24 19:56:34 +02:00
wm4 95c4f0f769 input: remove unused field
This was forgotten in commit fb9bbf2a0d.
2018-05-24 19:56:34 +02:00
wm4 a4321cf687 screenshot: change async behavior to be in line with new semantics
Basically reimplement the async behavior on top of the async command
code. With this, all screenshot commands are async, and the "async"
prefix basically does nothing. The prefix now behaves exactly like with
other commands that use spawn_thread.

This also means using the prefix in the preset input.conf is pointless
(without effect) and misleading, so remove that.

The each_frame mode was actually particularly painful in making this
change, since the player wants to block for it when writing a
screenshot, and generally doesn't fit into the new infrastructure. It
was still relatively easy to reimplement by copying the original command
and then repeating it on each frame. The waiting is reentrant now, so
move the call in video.c to a "safer" spot.

One way to observe how the new semantics interact with everything is
using the mpv repl script and sending a screenshot command through it.
Without async flag, the script will freeze while writing the screenshot
(while playback continues), while with async flag it continues.
2018-05-24 19:56:34 +02:00
wm4 059e7fdb3a command: move screenshot command stubs to screenshot.c
Commands are not a monolithic giant switch() statement anymore, but
individual functions. There's no reason to have the command handlers
themselves in command.c, with a weird under-defined API in between.

(In the future, I'd like to split up command.c further, and when I do
that, scrrenshot.c will probably gets its own mp_cmd_def[] array, and
define the commands locally instead of exporting the raw handlers.)
2018-05-24 19:56:34 +02:00
wm4 fb62ffdb94 manpage: mention that --no-correct-pts can break seeking too 2018-05-24 19:56:34 +02:00
wm4 1b611e38ef player: make all external file loading actions async
Still missing: not freezing when removing a track (i.e. closing demuxer)
with the sub-remove/audio-remove/rescan-external-files commands.
2018-05-24 19:56:34 +02:00
wm4 115a9b19f1 player: make abort during loading faster if ytdl_hook is used
Basically, the ytdl_hook script will not terminate the script, even if
you change to a new playlist entry. This happens because ytdl_hook keeps
the player core in an early loading stage, and the forceful playback
abort is done only in the ermination code.

This does not handle the "stop" and "quit" commands, which can still
take longer than expected, but on the other hand have some weird special
handling (see below). I'm not doing this out of laziness. Playback
stopping will have to be somewhat redone anyway. Basically we want to
give everything a chance to terminate, and if it doesn't work, we want
to stop loading or playback forcefully after a small timeout. We also
want to remove the mess with input.c's special handling of "quit" and
some other commands (see abort_playback_cb stuff).
2018-05-24 19:56:34 +02:00
wm4 79596113ea player: don't even start loading external tracks when aborting loading
It seems the ytdl script like to continue loading external tracks even
if loading was aborted. Trying to do so will still quickly fail, but not
without a load of log noise. So check and error out early.
2018-05-24 19:56:34 +02:00
wm4 c349e2f337 command: make sub-add and audio-add commands async
Pretty trivial, since commands can be async now, and the common code
even provides convenience like running commands on a worker thread.

The only ugly thing is that mp_add_external_file() needs an extra flag
for locking. This is because there's still some code which calls this
synchronously from the main thread, and unlocking the core makes no
sense there.
2018-05-24 19:56:34 +02:00
wm4 b440f6dfb3 command: add infrastructure for async commands
This enables two types of command behavior:

1. Plain async behavior, like "loadfile" not completing until the file
   is fully loaded.
2. Running parts of the command on worker threads, e.g. for I/O, such as
   "sub-add" doing network accesses on a thread while the core
   continues.

Both have no implementation yet, and most new code is actually inactive.
The plan is to implement a number of useful cases in the following
commits.

The most tricky part is handling internal keybindings (input.conf) and
the multi-command feature (concatenating commands with ";"). It requires
a bunch of roundabout code to make it do the expected thing in
combination with async commands.

There is the question how commands should be handled that come in at a
higher rate than what can be handled by the core. Currently, it will
simply queue up input.conf commands as long as memory lasts. The client
API is limited by the size of the reply queue per client. For commands
which require a worker thread, the thread pool is limited to 30 threads,
and then will queue up work in memory. The number is completely
arbitrary.
2018-05-24 19:56:34 +02:00
wm4 a1ed1f8be0 thread_pool: make it slightly less dumb
The existing thread pool code is the most primitive thread pool
possible. That's fine, but one annoying thing was that it used a static
number of threads. Make it dynamic, so we don't need to "waste" idle
threads.

This tries to add threads as needed. If threads are idle for some time,
destroy them again until a minimum number of threads is reached.

Also change the license to ISC.
2018-05-24 19:56:34 +02:00
wm4 a0308d3169 client: merge can_terminate() function
This has some tricky interactions. In particular, it requires the core
to be locked due to reading outstanding_async, which is documented on
the only caller only. It's probably better to merge it with its only
caller.

The new code should be strictly equivalent, other than the fact that it
doesn't temporarily unlock+lock when entering the loop for the first
time (which doesn't matter here).
2018-05-24 19:56:34 +02:00
wm4 22c002138d misc: add a synchronization helper
This is almost like rendezvous(), except it allows async wakeup, and
does not require global state. It will be used by a later commit.

struct mp_waiter is intended to be allocated on the stack, and uses an
initializer including PTHREAD_MUTEX_INITIALIZER. This is the first case
in mpv that it uses PTHREAD_MUTEX_INITIALIZER for stack-allocated
mutexes. It seems POSIX still does not allow this formally, but since
POSIX is worth less than used toilet paper, I don't really care. Modern
OSes use futexes, which means you can make _every_ memory location a
lock, and this code tries to make use of it, without using OS specific
code.

The name of the source file is rather generic, because I intend to dump
further small helpers there (or maybe move mp_rendezvous() to it).
2018-05-24 19:56:34 +02:00
wm4 383da1bfd5 input: move an enum back to its correct place
This was accidentally moved together with the cmd stuff.
2018-05-24 19:56:33 +02:00
wm4 dc00566963 command: handle list commands like normal commands
Pretty annoying.
2018-05-24 19:56:33 +02:00
wm4 88f9506f42 dispatch: add an assert() 2018-05-24 19:56:33 +02:00
wm4 95ab93d9f1 client API: some doxygen fixes/additions 2018-05-24 19:56:33 +02:00
470 changed files with 36569 additions and 29941 deletions

No files matched your search

+6 -6
View File
@@ -11,13 +11,13 @@ Releases are listed here: https://github.com/mpv-player/mpv/releases
### Log file
Make a log file made with -v or --log-file=output.txt, paste it to
https://0x0.st/ or a similar site, and replace this text with a link to it.
Make a log file made with -v -v or --log-file=output.txt, paste it to
https://0x0.st/ or attach it to the github issue, and replace this text with a
link to it. If the issue is a build failure, upload build/config.log instead.
Providing a log file is strongly encouraged. It is very helpful for reproducing
bugs or getting important technical context. Without a log it might not be
possible to analyze and fix certain bugs, and your bug report will be closed
or ignored.
If this is a normal runtime bug, and no log is provided, the issue will be
closed for ignoring the issue template. This is because analyzing a bug without
a log file is harder than necessary. Low quality bug reports are noise.
### Sample files
+4 -6
View File
@@ -1,7 +1,5 @@
Ideally, you shouldn't need enter any text here, and your commit messages should
explain your changes sufficiently (especially why they are needed). Read
https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md for coding
style and development conventions. Remove this text block, but if you haven't
agreed to it before, leave the following sentence in place:
Read this before you submit this pull request:
https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md
I agree that my changes can be relicensed to LGPL 2.1 or later.
Reading this link and following the rules will get your pull request reviewed
and merged faster. Nobody wants lazy pull requests.
+44 -12
View File
@@ -1,21 +1,34 @@
language: generic
language: c
os:
- linux
matrix:
include:
- os: osx
osx_image: xcode11
compiler: clang
- os: osx
osx_image: xcode10.1
compiler: clang
- os: osx
osx_image: xcode9.2
compiler: clang
- os: linux
compiler: gcc
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:stable-deps CI_SCRIPT=ci/build-tumbleweed.sh
- os: linux
compiler: clang
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:stable-deps CI_SCRIPT=ci/build-tumbleweed.sh
- os: linux
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci-mingw64:i686 CI_SCRIPT=ci/build-mingw64.sh TARGET=i686-w64-mingw32
- os: linux
env: CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci-mingw64:x86_64 CI_SCRIPT=ci/build-mingw64.sh TARGET=x86_64-w64-mingw32
dist: bionic
services:
- docker
sudo: required
env:
matrix:
- CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:stable-deps CI_SCRIPT=ci/build-tumbleweed.sh CC=gcc
- CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:stable-deps CI_SCRIPT=ci/build-tumbleweed.sh CC=clang
- CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:snapshot-deps CI_SCRIPT=ci/build-tumbleweed.sh CC=gcc
- CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci:snapshot-deps CI_SCRIPT=ci/build-tumbleweed.sh CC=clang
- CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci-mingw64:i686 CI_SCRIPT=ci/build-mingw64.sh TARGET=i686-w64-mingw32
- CONTAINER=registry.cirno.systems/kiwi/containers/mpv-ci-mingw64:x86_64 CI_SCRIPT=ci/build-mingw64.sh TARGET=x86_64-w64-mingw32
global:
# Coverity token
- secure: "H21mSRlMhk4BKS0xHZvCFGJxteCP0hRVUxTuNfM2Z9HBsyutuLEYMtViLO86VtM+Tqla3xXPzUdS4ozLwI72Ax/5ZUDXACROj73yW6QhFB5D6rLut12+FjqC7M33Qv2hl0xwgNBmR5dsm1ToP37+Wn+ecJQNvN8fkTXF+HVzOEw="
@@ -27,11 +40,17 @@ branches:
- master
- ci
- coverity_scan
- /release\/.*$/
before_install:
- docker pull $CONTAINER
- if [ "$TRAVIS_COMPILER" = "clang" ]; then export CXX="clang++"; fi
- if [ "$TRAVIS_COMPILER" = "gcc" ]; then export CXX="g++"; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then docker pull $CONTAINER; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then "$TRAVIS_BUILD_DIR/ci/get_ffmpeg.sh"; fi
script:
- docker run --env CC --env TARGET -v $TRAVIS_BUILD_DIR:/build $CONTAINER /bin/sh -c "cd /build && $CI_SCRIPT"
- ./bootstrap.py
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then docker run --env CC --env TARGET -v $TRAVIS_BUILD_DIR:/build $CONTAINER /bin/sh -c "cd /build && $CI_SCRIPT"; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./ci/build-macos.sh; fi
after_failure: cat ./build/config.log
after_script: TOOLS/travis-rebuild-website
@@ -52,3 +71,16 @@ addons:
build_command_prepend: "./bootstrap.py && ./waf configure"
build_command: "./waf build"
branch_pattern: coverity_scan
homebrew:
packages:
- autoconf
- automake
- freetype
- fribidi
- libass
- libtool
- little-cms2
- luajit
- nasm
- pkg-config
update: true
+3 -13
View File
@@ -21,6 +21,8 @@ project can relicense the changes to LGPLv2.1+ at a later point without asking
the contributor. This is a safeguard for making potential relicensing of
remaining GPL code to LGPLv2.1+ easier.
See DOCS/contribute.md for binding rules wrt. licensing for contributions.
For information about authors and contributors, consult the git log, which
contains the complete SVN and CVS history as well.
@@ -47,19 +49,11 @@ The following files are still GPL only (--enable-lgpl disables them):
audio/out/ao_jack.c will stay GPL
audio/out/ao_oss.c will stay GPL
demux/demux_tv.c will stay GPL
stream/ai_* will stay GPL (TV code)
stream/audio_in.* will stay GPL (TV code)
stream/dvb* must stay GPL
stream/frequencies.* must stay GPL
stream/stream_cdda.c unknown
stream/stream_dvb.* must stay GPL
stream/stream_dvd.c unknown
stream/stream_dvd_common.* unknown
stream/stream_dvdnav.c unknown
stream/stream_smb.c will stay GPLv3
stream/stream_tv.c will stay GPL
stream/tv* will stay GPL
video/out/vo_caca.c unknown
video/out/vo_direct3d.c unknown
video/out/vo_vaapi.c probably impossible (some company's code)
@@ -76,10 +70,6 @@ The following files are still GPL only (--enable-lgpl disables them):
mpv.desktop unknown license, probably GPLv2+
etc/restore-old-bindings.conf unknown license, probably GPLv2+
The following files contain some optional GPL code (--enable-lgpl disables it):
options/parse_commandline.c dvd:// expansion
None of the exceptions listed above affect the final binary if it's built as
None of the cases listed above affect the final binary if it's built as
LGPL. Linked libraries still can affect the final license (for example if
FFmpeg was built as GPL).
+22 -1
View File
@@ -16,7 +16,7 @@ The version number is the same as used for MPV_CLIENT_API_VERSION (see
``client.h`` how to convert between major/minor version numbers and the flat
32 bit integer).
Also, read the section ``Compatibility`` in ``client.h``.
Also, read the section ``Compatibility`` in ``client.h``, and compatibility.rst.
Options, commands, properties
=============================
@@ -32,6 +32,27 @@ API changes
::
--- mpv 0.31.0 ---
1.107 - Deprecate MPV_EVENT_TICK
--- mpv 0.30.0 ---
1.106 - Add cancel_fn to mpv_stream_cb_info
1.105 - Fix deadlock problems with MPV_RENDER_PARAM_ADVANCED_CONTROL and if
the "vd-lavc-dr" option is enabled (which it is by default).
There were no actual API changes.
API users on older API versions and mpv releases should set
"vd-lavc-dr" to "no" to avoid these issues.
API users must still adhere to the tricky rules documented in render.h
to avoid other deadlocks.
1.104 - Deprecate struct mpv_opengl_drm_params. Replaced by mpv_opengl_drm_params_v2
- Deprecate MPV_RENDER_PARAM_DRM_DISPLAY. Replaced by MPV_RENDER_PARAM_DRM_DISPLAY_V2.
1.103 - redo handling of async commands
- add mpv_event_command and make it possible to return values from
commands issued with mpv_command_async() or mpv_command_node_async()
- add mpv_abort_async_command()
1.102 - rename struct mpv_opengl_drm_osd_size to mpv_opengl_drm_draw_surface_size
- rename MPV_RENDER_PARAM_DRM_OSD_SIZE to MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE
--- mpv 0.29.0 ---
1.101 - add MPV_RENDER_PARAM_ADVANCED_CONTROL and related API
- add MPV_RENDER_PARAM_NEXT_FRAME_INFO and related symbols
+177
View File
@@ -0,0 +1,177 @@
CLI and API compatibility policy
================================
Human users and API users rely on the mpv/libmpv/scripting/IPC interface not
breaking their use case. On the other hand, active development occasionally
requires breaking things, such as removing old options or changing options in
a way that may break.
This document lists rules when, what, and how incompatible changes can be made.
It's interesting both for mpv developers, who want to change user-visible parts,
and mpv users, who want to know what is guaranteed to remain stable.
Any of the rules below may be overridden by statements in more specific
documentation (for example, if the manpage says that a particular option may be
removed any time, it means that, and the option probably won't even go through
deprecation).
Additions
---------
Additions are basically always allowed. API users etc. are supposed to deal with
the possibility that for example new API functions are added. Some parts of the
API may document how they are extended.
Options, commands, properties, events, hooks (command interface)
----------------------------------------------------------------
All of these are important for interfacing both with end users and API users
(which include Lua scripts, libmpv, and the JSON IPC). As such, they constitute
a large part of the user interface and APIs.
All incompatible changes to this must be declared in interface-changes.rst.
(This may also list compatible additions, but it's not a requirement.)
Degrees of importance and compatibility preservation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Critical and central parts of the command interface have the strictest
requirements. It may not be reasonable to break them, and other means to achieve
some change have to be found. For example, the "seek" command is a bit of a
mess, but since changing it would likely affect almost every user, it may be
impossible to break at least the commonly used syntax. If changed anyway, there
should be a deprecation period of at least 1 year, during which the command
still works, and possibly a warning should remain even after this.
Important/often used parts must be deprecated for at least 2 releases before
they can be broken. There must be at least 1 release where the deprecated
functionality still works, and a replacement is available (if technically
reasonable). For example, a feature deprecated in mpv 0.30.0 may be removed in
mpv 0.32.0. Minor releases do not count towards this.
Less useful parts can be broken immediately, but must come with some sort of
removal warning-
Parts for debugging and testing may be removed any time, potentially even
without any sort of documentation.
Currently, the importance of a part is not documented and not even well-defined,
which is probably a mistake.
Renaming or removing options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Typically, renaming an option can be done in a compatible way with OPT_REPLACED.
You may need to check whether the corresponding properties still work (including
messy details like observing properties for changes).
OPT_REMOVED can be used to inform the user of alternatives or reasons for the
removal, which is better than an option not found error. Likewise,
m_option.deprecation_message should be set to something helpful.
Both OPT_REPLACED and OPT_REMOVED can remain in the code for a long time, since
they're unintrusive and hopefully make incompatible changes less painful for
users.
Scripting APIs
--------------
This affects internal scripting APIs (currently Lua and JavaScript).
Vaguely the same rules as with the command interface apply. Since there is a
large number of scripts, an effort should be made to provide compatibility
for old scripts, but it does not need to be stronger than that of the command
interface.
Undocumented parts of the scripting APIs are _not_ guaranteed for compatibility.
This applies especially for internals. Languages like Lua do not have strict
access control (nor does the mpv code try to emulate any), so if a script
accesses private parts, and breaks on the next mpv release, it's not mpv's
problem.
JSON IPC
--------
The JSON IPC is a thin protocol wrapping the libmpv API and the command
interface. Compatibility-wise, it's about the same as the scripting APIs.
The JSON protocol commands should remain as compatible as possible, and it
should probably accept the current way commands are delimited (line breaks)
forever.
The protocol may accept non-standard JSON extensions, but only standard JSON
(possibly with restrictions) is guaranteed for compatibility. Clients which want
to remain compatible should not use any extensions.
CLI
---
Things such as default key bindings do not necessarily require compatibility.
However, the release notes should be extremely clear on changes to "important"
key bindings. Bindings which restore the old behavior should be added to
restore-old-bindings.conf.
Some option parsing is CLI-only and not available from libmpv or scripting. No
compatibility guarantees come with them. However, the rules which mpv uses to
distinguish between options and filenames must remain consistent (if the
non-deprecated options syntax is used).
Terminal and log output
-----------------------
There are no compatibility guarantees for the terminal output, or the text
logged via ``MPV_EVENT_LOG_MESSAGE`` and similar APIs. In particular, scripts
invoking mpv CLI are extremely discouraged from trying to parse text output,
and should use other mechanisms such as the JSON IPC.
Protocols, filters, demuxers, etc.
----------------------------------
Which of these are present is generally not guaranteed, and can even depend
on compile time settings.
The filter list and their sub-options are considered part of the
command-interface.
libmpv C API
------------
The libmpv client API (such as ``<libmpv/client.h>``) mostly gives access to
the command interface. The API itself (if looked at as a component separate
from the command interface) is intended to be extremely stable.
All API changes are documented in client-api-changes.rst.
API compatibility
^^^^^^^^^^^^^^^^^
The API is *always* compatible. Incompatible changes are only allowed on major
API version changes (see ``MPV_CLIENT_API_VERSION``). A major version change is
an extremely rare event, which means usually no API symbols are ever removed.
Essentially removing API functions by making them always return an error, or
making it do nothing is allowed in cases where it is unlikely to break most
clients, but requires a deprecation period of 2 releases. (This has happened to
``mpv_suspend()`` for example.)
API symbols can be deprecated. This should be clearly marked in the doxygen
with ``@deprecated``, and if possible, the affected API symbols should not be
visible if the API user defines ``MPV_ENABLE_DEPRECATED`` to 0.
ABI compatibility
^^^^^^^^^^^^^^^^^
The ABI must never be broken, except on major API version changes. For example,
constants don't change their values.
Structs are tricky. If a struct can be allocated by a user (such as ``mpv_node``),
no fields can be added. (Unless it's an union, and the addition does not change
the offset or alignment of any of the fields or the struct itself. This has
happened to ``mpv_node`` in the past.) If a struct is allocated by libmpv only,
new fields can be appended to the end (for example ``mpv_event``).
The ABI is only backward compatible. This means if a host application is linked
to an older libmpv, and libmpv is updated to a newer version, it will still
work (as in not causing any undefined behavior).
Forward compatibility (an application would work with an older libmpv than it
was linked to) is not required.
+7 -3
View File
@@ -136,7 +136,7 @@ pacman -S git python $MINGW_PACKAGE_PREFIX-{pkg-config,gcc}
# Install the most important MinGW-w64 dependencies. libass and lcms2 are also
# pulled in as dependencies of ffmpeg.
pacman -S $MINGW_PACKAGE_PREFIX-{ffmpeg,libjpeg-turbo,lua51,angleproject-git}
pacman -S $MINGW_PACKAGE_PREFIX-{ffmpeg,libjpeg-turbo,lua51}
```
Building mpv
@@ -168,8 +168,12 @@ Or, compile and install both libmpv and mpv:
Linking libmpv with MSVC programs
---------------------------------
You can build C++ programs in Visual Studio and link them with libmpv. To do
this, you need a Visual Studio which supports ``stdint.h`` (recent ones do),
mpv/libmpv cannot be built with Visual Studio (Microsoft is too incompetent to
support C99/C11 properly and/or hates open source and Linux too much to
seriously do it). But you can build C++ programs in Visual Studio and link them
with a libmpv built with MinGW.
To do this, you need a Visual Studio which supports ``stdint.h`` (recent ones do),
and you need to create a import library for the mpv DLL:
```bash
+94 -30
View File
@@ -5,35 +5,60 @@ General
-------
The main contact for mpv development is IRC, specifically #mpv
and #mpv-devel on Freenode.
and #mpv-devel on Freenode. Github is used for code review and
long term discussions.
Sending patches
---------------
- Make a github pull request, or send a link to a plaintext patch created with
``git format-patch``. diffs posted as pastebins (especially if the http link
returns HTML) just cause extra work for everyone, because they lack commit
message and authorship information.
``git format-patch``.
- Plain diffs posted as pastebins are not acceptable! (Especially if the http
link returns HTML.) They only cause extra work for everyone, because they lack
commit message and authorship information.
- Never send patches to any of the developers email addresses.
- If your changes are not supposed to be merged immediately, mark them as
"[RFC]" in the commit message or the pull request title.
- Be sure to test your changes. If you didn't, please say so in the commit
message and the pull request text.
Copyright of contributions
--------------------------
- The copyright belongs to contributors. The project is a collaborative work. By
sending your changes, you agree to license your contributions according to the
requirements of this project.
- All new code must be LGPLv2.1+ licensed, or come with the implicit agreement
that it will be relicensed to LGPLv2.1+ later (see ``Copyright`` in the
repository root directory).
- 100% compatible licenses are allowed too.
- Changes in files with more liberal licenses (such as BSD, MIT, or ISC) are
assumed to be dual-licensed under LGPLv2.1+ and the license indicated in the
file header.
- You must be either the exclusive author of the patch, or acknowledge all
authors involved in the commit message. If you take 3rd party code, authorship
and copyright must be properly acknowledged. If the license of the code is not
LGPLv2.1+, this must be mentioned.
- Don't use fake names (something that looks like an actual names, and may be
and copyright must be properly acknowledged. If you're making changes on
behalf of your employer, and the employer owns the copyright, you must mention
this. If the license of the code is not LGPLv2.1+, you must mention this.
- These license statements are legally binding.
- Don't use fake names (something that looks like an actual name, and may be
someone else's name, but is not your legal name). Using a pseudonyms is
allowed if it can be used to identify or contact you, even if whatever
account you used to submit the patch dies.
- When creating pull requests, be sure to test your changes. If you didn't,
please say so in the pull request message.
- Do not add your name to the license header. This convention is not used by
this project, and neither copyright law nor any of the used licenses require
it.
Write good commit messages
--------------------------
- Write informative commit messages. Use present tense to describe the
situation with the patch applied, and past tense for the situation before
the change.
- The subject line (the first line in a commit message) should contain a
- The subject line (the first line in a commit message) must contain a
prefix identifying the sub system, followed by a short description what
impact this commit has. This subject line and the commit message body
shouldn't be longer than 72 characters per line, because it messes up the
must not be longer than 72 characters per line, because it messes up the
output of many git tools otherwise.
For example, you fixed a crash in af_volume.c:
@@ -43,7 +68,11 @@ Sending patches
Having a prefix gives context, and is especially useful when trying to find
a specific change by looking at the history, or when running ``git blame``.
- The body of the commit message (everything else after the subject line) should
- The first word after the ``:`` is lower case.
- Don't end the subject line with a ``.``.
- Put an empty line between the subject line and the commit message.
If this is missing, it will break display in common git tools.
- The body of the commit message (everything else after the subject line) must
be as informative as possible and contain everything that isn't obvious. Don't
hesitate to dump as much information as you can - it doesn't cost you
anything. Put some effort into it. If someone finds a bug months or years
@@ -52,25 +81,40 @@ Sending patches
information to test the original bug. The old bug might be reintroduced while
fixing the new bug.
The commit message should be wrapped on 72 characters per line, because git
The commit message must be wrapped on 72 characters per line, because git
tools usually do not break text automatically. On the other hand, you do not
need to break text that would be unnatural to break (like data for test cases,
or long URLs).
- Another summary of good conventions: https://chris.beams.io/posts/git-commit/
Important: put an empty line between the subject line and the commit message.
If this is missing, it will break display in common git tools.
Split changes into multiple commits
-----------------------------------
- Follow git good practices, and split independent changes into several commits.
It's usually OK to put them into a single pull request.
- Try to separate cosmetic and functional changes. It's ok to make a few
additional cosmetic changes in the same file you're working on. But don't do
something like reformatting a whole file, and hiding an actual functional
change in the same commit.
- Splitting changes does _not_ mean that you should make them as fine-grained
as possible. Commits should form logical steps in development. The way you
split changes is important for code review and analyzing bugs.
Touching user-visible parts may require updating the mpv docs
-------------------------------------------------------------
- Most user-visible things are normally documented in DOCS/man/. If your commit
touches documented behavior, list of sub-options, etc., you need to adjust the
documentation.
- These changes usually go into the same commit that changes the code.
- Changes to command line options (addition/modification/removal) must be
documented in options.rst. Changes to input properties or input commands must
be documented in input.rst. All changes to the user interface (options,
properties, commands) must be documented with a small note in
interface-changes.rst (although documenting additions is optional, and
obscure corner cases can potentially be skipped too). Changes to the libmpv
API must be reflected in the libmpv's headers doxygen, and should be
documented in client-api-changes.rst.
documented in options.rst.
- Changes to input properties or input commands must be documented in input.rst.
- All incompatible changes to the user interface (options, properties, commands)
must be documented with a small note in interface-changes.rst. (Additions may
be documented there as well, but this isn't required.)
- Changes to the libmpv API must be reflected in the libmpv's headers doxygen,
and in client-api-changes.rst.
Code formatting
---------------
@@ -80,7 +124,7 @@ mpv uses C99 with K&R formatting, with some exceptions.
- Use the K&R indent style.
- Use 4 spaces of indentation, never use tabs (except in Makefiles).
- Add a single space between keywords and binary operators. There are some other
cases where spaces should be added. Example:
cases where spaces must be added. Example:
```C
if ((a * b) > c) {
@@ -113,7 +157,7 @@ mpv uses C99 with K&R formatting, with some exceptions.
do_something();
}
```
- If the if has an else branch, both branches should use braces, even if they're
- If the if has an else branch, both branches must use braces, even if they're
technically redundant.
Example:
@@ -143,18 +187,31 @@ mpv uses C99 with K&R formatting, with some exceptions.
(If the if body is simple enough, this rule can be skipped.)
- Remove any trailing whitespace.
- Do not make stray whitespaces changes.
Header #include statement order
-------------------------------
The order of ``#include`` statements in the source code is not very consistent.
New code must follow the following conventions:
- Put standard includes (``#include <stdlib.h>`` etc.) on the top,
- then after a blank line, add library includes (``#include <zlib.h>`` etc.)
- then after a blank line, add internal includes (``#include "player/core.h"``)
- sort them alphabetically within these sections
General coding
--------------
- Use C99. Also freely make use of C99 features if it's appropriate, such as
stdbool.h.
- Don't use GNU-only features. In some cases they may be warranted, if they
are optional (such as attributes enabling printf-like format string checks).
But in general, standard C99 should be used.
stdbool.h. (Except VLA and complex number types.)
- Don't use non-standard language (such as GNU C-only features). In some cases
they may be warranted, if they are optional (such as attributes enabling
printf-like format string checks). "#pragma once" is allowed as an exception.
But in general, standard C99 must be used.
- The same applies to libc functions. We have to be Windows-compatible too. Use
functions guaranteed by C99 or POSIX only, unless your use is guarded by a
configure check.
configure check. There is some restricted use of C11 (ask on IRC for details).
- Prefer fusing declaration and initialization, rather than putting declarations
on the top of a block. Obvious data flow is more important than avoiding
mixing declarations and statements, which is just a C90 artifact.
@@ -162,6 +219,11 @@ General coding
channel first. There might be a better way to add a feature and it can avoid
wasted work.
Code of Conduct
---------------
We have one, but the document describing it got lost accidentally.
Rules for git push access
-------------------------
@@ -180,7 +242,9 @@ you got access, the following rules must be followed:
major bug fixes, or you're the original author of the code). If there is more
than one maintainer, you may need to come to an agreement with the others how
to handle this to avoid conflict.
- As a maintainer, you can approve pushes by others to "your" code.
- If you make a pull requests (especially if it's to code you maintain), and you
want reviews, explicitly ping the people from which you expect reviews.
- As a maintainer, you can approve pull requests by others to "your" code.
- If you approve or merge 3rd party changes, make sure they follow the general
development rules.
- Changes to user interface and public API must always be approved by the
+99
View File
@@ -100,6 +100,18 @@ entries affect all other file entries in the EDL file. Their format is highly
implementation specific. They should generally follow the file header, and come
before any file entries.
Disabling chapter generation and copying
========================================
By default, chapters from the source ranges are copied to the virtual file's
chapters. Also, a chapter is inserted after each range. This can be disabled
with the ``no_chapters`` header.
Example::
!no_chapters
MP4 DASH
========
@@ -131,6 +143,45 @@ The current implementation will
- not add segment boundaries as chapter points
- require full compatibility between all segments (same codec etc.)
Another header part of this mechanism is ``no_clip``. This header is similar
to ``mp4_dash``, but does not include on-demand opening/closing of segments,
and does not support init segments. It also exists solely to support internal
ytdl requirements.
The ``mp4_dash`` and ``no_clip`` headers are not part of the core EDL format.
They may be changed or removed at any time, depending on mpv's internal
requirements.
Separate files for tracks
=========================
The special ``new_stream`` header lets you specify separate parts and time
offsets for separate tracks. This can for example be used to source audio and
video track from separate files.
Example::
# mpv EDL v0
video.mkv
!new_stream
audio.mkv
This adds all tracks from both files to the virtual track list. Upon playback,
the tracks will be played at the same time, instead of appending them. The files
can contain more than 1 stream; the apparent effect is the same as if the second
part after the ``!new_stream`` part were in a separate ``.edl`` file and added
with ``--external-file``.
Note that all metadata between the stream sets created by ``new_stream`` is
disjoint. Global metadata is taken from the first part only.
In context of mpv, this is redundant to the ``--audio-file`` and
``--external-file`` options, but (as of this writing) has the advantage that
this will use a unified cache for all streams.
The ``new_stream`` header is not part of the core EDL format. It may be changed
or removed at any time, depending on mpv's internal requirements.
Timestamp format
================
@@ -147,6 +198,54 @@ Example::
Plays chapter 3 and ends with the start of chapter 7 (4 chapters later).
Implicit chapters
=================
mpv will add one chapter per segment entry to the virtual timeline.
By default, the chapter's titles will match the entries' filenames.
You can override set the ``title`` option to override the chapter title for
that segment.
Example::
# mpv EDL v0
cap.ts,5,240
OP.mkv,0,90,title=Show Opening
The virtual timeline will have two chapters, one called "cap.ts" from 0-240s
and a second one called "Show Opening" from 240-330s.
Entry which defines the track layout
====================================
Normally, you're supposed to put only files with compatible layouts into an EDL
file. However, at least the mpv implementation accepts entries that use
different codecs, or even have a different number of audio/video/subtitle
tracks. In this case, it's not obvious, which virtual tracks the EDL show should
expose when being played.
Currently, mpv will apply an arbitrary heuristic which tracks the EDL file
should expose. (Before mpv 0.30.0, it always used the first source file in the
segment list.)
You can set the ``layout`` option to ``this`` to make a specific entry define
the track layout.
Example::
# mpv EDL v0
file_with_2_streams.ts,5,240
file_with_5_streams.mkv,0,90,layout=this
The way the different virtual EDL tracks are associated with the per-segment
ones is highly implementation-defined, and uses a heuristic. If a segment is
missing a track, there will be a "hole", and bad behavior may result. Improving
this is subject to further development (due to being fringe cases, they don't
have a high priority).
If future versions of mpv change this again, this option may be ignored.
Syntax of EDL URIs
==================
+147 -2
View File
@@ -7,11 +7,16 @@ mpv provides access to its internals via the following means:
- commands
- properties
- events
- hooks
The sum of these mechanisms is sometimes called command interface.
All of these are important for interfacing both with end users and API users
(which include Lua scripts, libmpv, and the JSON IPC). As such, they constitute
a large part of the user interface and APIs.
Also see compatibility.rst.
This document lists changes to them. New changes are added to the top.
Interface changes
@@ -19,6 +24,145 @@ Interface changes
::
--- mpv 0.31.0 ---
- add `--resume-playback-check-mtime` to check consistent mtime when
restoring playback state.
- add `--d3d11-output-csp` to enable explicit selection of a D3D11
swap chain color space.
- the --sws- options and similar now affect vo_image and screenshot
conversion (does not matter as much for vo_gpu, which does most of this
with shaders)
- add a builtin "sw-fast" profile, which restores performance settings
for software video conversion. These were switched to higher quality since
mpv 0.30.0 (related to the previous changelog entry). This affects video
outputs like vo_x11 and vo_drm, and screenshots, but not much else.
- deprecate --input-file (there are no plans to remove this short-term,
but it will probably eventually go away)
- deprecate --video-sync=display-adrop (might be removed if it's in the way;
undeprecated or readded if it's not too much of a problem)
- deprecate all input section commands (these will be changed/removed, as
soon as mpv internals do not require them anymore)
- remove deprecated --playlist-pos alias (use --playlist-start)
- deprecate --display-fps, introduce --override-display-fps. The display-fps
property now is unavailable if no VO exists (or the VO did not return a
display FPS), instead of returning the option value in this case. The
property will keep existing, but writing to it is deprecated.
- the vf/af properties now do not reject the set value anymore, even if
filter chain initialization fails. Instead, the vf/af options are always
set to the user's value, even if it does not reflect the "runtime" vf/af
chain.
- the vid/aid/sid/secondary-sid properties (and their aliases: "audio",
"video", "sub") will now allow setting any track ID; before this change,
only IDs of actually existing tracks could be set (the restriction was
active the MPV_EVENT_FILE_LOADED/"file-loaded" event was sent). Setting
an ID for which no track exists is equivalent to disabling it. Note that
setting the properties to non-existing tracks may report it as selected
track for a small time window, until it's forced back to "no". The exact
details how this is handled may change in the future.
- remove old Apple Remote support, including --input-appleremote
- add MediaPlayer support and remove the old Media Key event tap on macOS.
this possibly also re-adds the Apple Remote support
- the "edition" property now strictly returns the value of the option,
instead of the runtime value. The new "current-edition" property needs to
be queried to read the runtime-chosen edition. This is a breaking change
for any users which expected "edition" to return the runtime-chosen
edition at default settings (--edition=auto).
- the "window-scale" property now strictly returns the value of the option,
instead of the actual size of the window. The new "current-window-scale"
property needs to be queried to read the value as indicated by the current
window size. This is a breaking change.
- explicitly deprecate passing more than 1 item to "-add" suffix in key/value
options (for example --script-opts-add). This was actually always
deprecated, like with other list options, but the option parser did not
print a warning in this particular case.
- deprecate -del for list options (use -remove instead, which is by content
instead of by integer index)
- if `--fs` is used but `--fs-screen` is not set, mpv will now use `--screen`
instead.
- change the default of --hwdec to "no" on RPI. The default used to be "mmal"
specifically if 'Raspberry Pi support' was enabled at configure time
(equivalent to --enable-rpi). Use --hwdec=mmal to get the old behavior.
--- mpv 0.30.0 ---
- add `--d3d11-output-format` to enable explicit selection of a D3D11
swap chain format.
- rewrite DVB channel switching to use an integer value
`--dvbin-channel-switch-offset` for switching instead of the old
stream controls which are now gone. Cycling this property up or down will
change the offset to the channel which was initially tuned to.
Example for `input.conf`: `H cycle dvbin-channel-switch-offset up`,
`K cycle dvbin-channel-switch-offset down`.
- adapt `stream_dvb` to support writing to `dvbin-prog` at runtime
and also to consistently use dvbin-configuration over URI parameters
when provided
- add `--d3d11-adapter` to enable explicit selection of a D3D11 rendering
adapter by name.
- rename `--drm-osd-plane-id` to `--drm-draw-plane`, `--drm-video-plane-id` to
`--drm-drmprime-video-plane` and `--drm-osd-size` to `--drm-draw-surface-size`
to better reflect what the options actually control, that the values they
accept aren't actually internal DRM ID's (like with similar options in
ffmpeg's KMS support), and that the video plane is only used when the drmprime
overlay hwdec interop is active, with the video being drawn to the draw plane
otherwise.
- in addition to the above, the `--drm-draw-plane` and `--drm-drmprime-video-plane`
options now accept either an integer index, or the values primary or overlay.
`--drm-draw-plane` now defaults to primary and `--drm-drmprime-video-plane`
defaults to overlay. This should be similar to previous behavior on most drivers
due to how planes are usually sorted.
- rename --opensles-frames-per-buffer to --opensles-frames-per-enqueue to
better reflect its purpose. In the past it overrides the buffer size the AO
requests (but not the default/value of the generic --audio-buffer option).
Now it only guarantees that the soft buffer size will not be smaller than
itself while setting the size per Enqueue.
- add --opensles-buffer-size-in-ms, allowing user to tune the soft buffer size.
It overrides the --audio-buffer option unless it's set to 0 (with the default
being 250).
- remove `--linear-scaling`, replaced by `--linear-upscaling` and
`--linear-downscaling`. This means that `--sigmoid-upscaling` no longer
implies linear light downscaling as well, which was confusing.
- the built-in `gpu-hq` profile now includes` --linear-downscaling`.
- support for `--spirv-compiler=nvidia` has been removed, leaving `shaderc`
as the only option. The `--spirv-compiler` option itself has been marked
as deprecated, and may be removed in the future.
- split up `--tone-mapping-desaturate`` into strength + exponent, instead of
only using a single value (which previously just controlled the exponent).
The strength now linearly blends between the linear and nonlinear tone
mapped versions of a color.
- add --hdr-peak-decay-rate and --hdr-scene-threshold-low/high
- add --tone-mapping-max-boost
- ipc: require that "request_id" fields are integers. Other types are still
accepted for compatibility, but this will stop in the future. Also, if no
request_id is provided, 0 will be assumed.
- mpv_command_node() and mp.command_native() now support named arguments
(see manpage). If you want to use them, use a new version of the manpage
as reference, which lists the definitive names.
- edition and disc title switching will now fully reload playback (may have
consequences for scripts, client API, or when using file-local options)
- with the removal of the stream cache, the following properties and options were
dropped: `cache`, `cache-size`, `cache-free`, `cache-used`, `--cache-default`,
`--cache-initial`, `--cache-seek-min`, `--cache-backbuffer`, `--cache-file`,
`--cache-file-size`
- the --cache option does not take a number value anymore
- remove async playback abort hack. This may make it impossible to abort
playback if --demuxer-thread=no is forced.
- remove `--macos-title-bar-style`, replaced by `--macos-title-bar-material`
and `--macos-title-bar-appearance`.
- The default for `--vulkan-async-compute` has changed to `yes` from `no`
with the move to libplacebo as the back-end for vulkan rendering.
- Remove "disc-titles", "disc-title", "disc-title-list", and "angle"
properties. dvd:// does not support title ranges anymore.
- Remove all "tv-..." options and properties, along with the classic Linux
analog TV support.
- remove "program" property (no replacement)
- always prefer EGL over GLX, which helps with AMD/vaapi, but will break
vdpau with --vo=gpu - use --gpu-context=x11 to be able to use vdpau. This
does not affect --vo=vdpau or --hwdec=vdpau-copy.
- remove deprecated --chapter option
- deprecate --record-file
- add `--demuxer-cue-codepage`
- add ``track-list/N/demux-bitrate``, ``track-list/N/demux-rotation`` and
``track-list/N/demux-par`` property
- Deprecate ``--video-aspect`` and add ``--video-aspect-override`` to
replace it. (The `video-aspect` option remains unchanged.)
--- mpv 0.29.0 ---
- drop --opensles-sample-rate, as --audio-samplerate should be used if desired
- drop deprecated --videotoolbox-format, --ff-aid, --ff-vid, --ff-sid,
@@ -103,10 +247,11 @@ Interface changes
of 3D content doesn't justify such an option anyway.
- change cycle-values command to use the current value, instead of an
internal counter that remembered the current position.
- edition and disc title switching will now fully reload playback (may have
consequences for scripts, client API, or when using file-local options)
- remove deprecated ao/vo auto profiles. Consider using scripts like
auto-profiles.lua instead.
- --[c]scale-[w]param[1|2] and --tone-mapping-param now accept "default",
and if set to that value, reading them as property will also return
"default", instead of float nan as in previous versions
--- mpv 0.28.0 ---
- rename --hwdec=mediacodec option to mediacodec-copy, to reflect
conventions followed by other hardware video decoding APIs
-38
View File
@@ -24,44 +24,6 @@ See ``--vf`` group of options for info on how ``--af-defaults``, ``--af-add``,
Available filters are:
``lavrresample[=option1:option2:...]``
This filter uses libavresample (or libswresample, depending on the build)
to change sample rate, sample format, or channel layout of the audio stream.
This filter is automatically enabled if the audio output does not support
the audio configuration of the file being played.
.. warning::
Deprecated. Either use the ``--audio-resample-...`` options to customize
resampling, or the libavfilter ``--af=aresample`` filter, which has its
own options.
It supports only the following sample formats: u8, s16, s32, float.
``filter-size=<length>``
Length of the filter with respect to the lower sampling rate. (default:
16)
``phase-shift=<count>``
Log2 of the number of polyphase entries. (..., 10->1024, 11->2048,
12->4096, ...) (default: 10->1024)
``cutoff=<cutoff>``
Cutoff frequency (0.0-1.0), default set depending upon filter length.
``linear``
If set then filters will be linearly interpolated between polyphase
entries. (default: no)
``no-detach``
Do not detach if input and output audio format/rate/channels match.
(If you just want to set defaults for this filter that will be used
even by automatically inserted lavrresample instances, you should
prefer setting them with the ``--audio-resample-...`` options.) This
does not do anything anymore and the filter will never detach.
``normalize=<yes|no|auto>``
Whether to normalize when remixing channel layouts (default: auto).
``auto`` uses the value set by ``--audio-normalize-downmix``.
``o=<string>``
Set AVOptions on the SwrContext or AVAudioResampleContext. These should
be documented by FFmpeg or Libav.
``lavcac3enc[=options]``
Encode multi-channel audio to AC-3 at runtime using libavcodec. Supports
16-bit native-endian input format, maximum 6 channels. The output is
+4
View File
@@ -152,6 +152,10 @@ Available audio output drivers are:
If you have stuttering video when using pulse, try to enable this
option. (Or try to update PulseAudio.)
``--pulse-allow-suspended=<yes|no>``
Allow mpv to use PulseAudio even if the sink is suspended (default: no).
Can be useful if PulseAudio is running as a bridge to jack and mpv has its sink-input set to the one jack is using.
``sdl``
SDL 1.2+ audio output driver. Should work on any platform supported by SDL
1.2, but may require the ``SDL_AUDIODRIVER`` environment variable to be set
+107
View File
@@ -0,0 +1,107 @@
CONSOLE
=======
The console is a REPL for mpv input commands. It is displayed on the video
window. It also shows log messages. It can be disabled entirely using the
``--load-osd-console=no`` option.
Keybindings
-----------
\`
Show the console.
ESC
Hide the console.
ENTER
Run the typed command.
Shift+ENTER
Type a literal newline character.
Ctrl+LEFT and Ctrl+RIGHT
Move cursor to previous/next word.
UP and DOWN
Navigate command history.
PGUP
Go to the first command in the history.
PGDN
Stop navigating command history.
INSERT
Toggle insert mode.
Shift+INSERT
Paste text (uses the primary selection on X11.)
TAB
Complete the command or property name at the cursor.
Ctrl+C
Clear current line.
Ctrl+K.
Delete text from the cursor to the end of the line.
Ctrl+L
Clear all log messages from the console.
Ctrl+U
Delete text from the cursor to the beginning of the line.
Ctrl+V
Paste text (uses the clipboard on X11.)
Ctrl+W
Delete text from the cursor to the beginning of the current word.
Commands
--------
``script-message-to console type <text>``
Show the console and pre-fill it with the provided text.
Known issues
------------
- Pasting text is slow on Windows
- Non-ASCII keyboard input has restrictions
- The cursor keys move between Unicode code-points, not grapheme clusters
Configuration
-------------
This script can be customized through a config file ``script-opts/console.conf``
placed in mpv's user directory and through the ``--script-opts`` command-line
option. The configuration syntax is described in `ON SCREEN CONTROLLER`_.
Key bindings can be changed in a standard way, see for example stats.lua
documentation.
Configurable Options
~~~~~~~~~~~~~~~~~~~~
``scale``
Default: 1
All drawing is scaled by this value, including the text borders and the
cursor.
If the VO backend in use has HiDPI scale reporting implemented, the option
value is scaled with the reported HiDPI scale.
``font``
Default: unset (picks a hardcoded font depending on detected platform)
Set the font used for the REPL and the console. This probably doesn't
have to be a monospaced font.
``font_size``
Default: 16
Set the font size used for the REPL and the console. This will be
multiplied by "scale."
+7 -6
View File
@@ -15,8 +15,7 @@ You can encode files from one format/codec to another using this facility.
Specifies the output format options for libavformat.
See ``--ofopts=help`` for a full list of supported options.
Options are managed in lists. There are a few commands to manage the
options list.
This is a key/value list option. See `List Options`_ for details.
``--ofopts-add=<options1[,options2,...]>``
Appends the options given as arguments to the options list.
@@ -41,8 +40,7 @@ You can encode files from one format/codec to another using this facility.
"``--oac=libmp3lame --oacopts=b=128000``"
selects 128 kbps MP3 encoding.
Options are managed in lists. There are a few commands to manage the
options list.
This is a key/value list option. See `List Options`_ for details.
``--oacopts-add=<options1[,options2,...]>``
Appends the options given as arguments to the options list.
@@ -74,8 +72,7 @@ You can encode files from one format/codec to another using this facility.
``"--ovc=libx264 --ovcopts=crf=23"``
selects VBR quality factor 23 for H.264 encoding.
Options are managed in lists. There are a few commands to manage the
options list.
This is a key/value list option. See `List Options`_ for details.
``--ovcopts-add=<options1[,options2,...]>``
Appends the options given as arguments to the options list.
@@ -103,6 +100,8 @@ You can encode files from one format/codec to another using this facility.
FLAC allow almost arbitrary keys, while support in MP4 and MP3 is more
limited.
This is a key/value list option. See `List Options`_ for details.
.. admonition:: Example
"``--oset-metadata=title="Output title",comment="Another tag"``"
@@ -112,6 +111,8 @@ You can encode files from one format/codec to another using this facility.
Specifies metadata to exclude from the output file when copying from the
input file.
This is a string list option. See `List Options`_ for details.
.. admonition:: Example
"``--oremove-metadata=comment,genre``"
+794 -226
View File
File diff suppressed because it is too large. Load diff
+40 -2
View File
@@ -74,6 +74,12 @@ some wrapper like .NET's NamedPipeClientStream.)
Protocol
--------
The protocol uses UTF-8-only JSON as defined by RFC-8259. Unlike standard JSON,
"\u" escape sequences are not allowed to construct surrogate pairs. To avoid
getting conflicts, encode all text characters including and above codepoint
U+0020 as UTF-8. mpv might output broken UTF-8 in corner cases (see "UTF-8"
section below).
Clients can execute commands on the player by sending JSON messages of the
following form:
@@ -108,7 +114,10 @@ Because events can occur at any time, it may be difficult at times to determine
which response goes with which command. Commands may optionally include a
``request_id`` which, if provided in the command request, will be copied
verbatim into the response. mpv does not intrepret the ``request_id`` in any
way; it is solely for the use of the requester.
way; it is solely for the use of the requester. The only requirement is that
the ``request_id`` field must be an integer (a number without fractional parts
in the range ``-2^63..2^63-1``). Using other types is deprecated and will
currently show a warning. In the future, this will raise an error.
For example, this request:
@@ -122,6 +131,11 @@ Would generate this response:
{ "error": "success", "data": 1.468135, "request_id": 100 }
If you don't specify a ``request_id``, command replies will set it to 0.
Commands may run asynchronously in the future, instead of blocking the socket
until a reply is sent.
All commands, replies, and events are separated from each other with a line
break character (``\n``).
@@ -258,4 +272,28 @@ sometimes sends invalid JSON. If that is a problem for the client application's
parser, it should filter the raw data for invalid UTF-8 sequences and perform
the desired replacement, before feeding the data to its JSON parser.
mpv will not attempt to construct invalid UTF-8 with broken escape sequences.
mpv will not attempt to construct invalid UTF-8 with broken "\u" escape
sequences. This includes surrogate pairs.
JSON extensions
---------------
The following non-standard extensions are supported:
- a list or object item can have a trailing ","
- object syntax accepts "=" in addition of ":"
- object keys can be unquoted, if they start with a character in "A-Za-z\_"
and contain only characters in "A-Za-z0-9\_"
- byte escapes with "\xAB" are allowed (with AB being a 2 digit hex number)
Example:
::
{ objkey = "value\x0A" }
Is equivalent to:
::
{ "objkey": "value\n" }
+30 -9
View File
@@ -88,7 +88,7 @@ Scripting APIs - identical to Lua
(LE) - Last-Error, indicates that ``mp.last_error()`` can be used after the
call to test for success (empty string) or failure (non empty reason string).
Otherwise, where the Lua APIs return ``nil`` on error, JS returns ``undefined``.
Where the Lua APIs use ``nil`` to indicate error, JS APIs use ``undefined``.
``mp.command(string)`` (LE)
@@ -96,6 +96,11 @@ Otherwise, where the Lua APIs return ``nil`` on error, JS returns ``undefined``.
``mp.command_native(table [,def])`` (LE)
``id = mp.command_native_async(table [,fn])`` (LE) Notes: ``id`` is true-thy on
success, ``fn`` is called always a-sync, ``error`` is empty string on success.
``mp.abort_async_command(id)``
``mp.get_property(name [,def])`` (LE)
``mp.get_property_osd(name [,def])`` (LE)
@@ -148,6 +153,10 @@ Otherwise, where the Lua APIs return ``nil`` on error, JS returns ``undefined``.
``mp.unregister_script_message(name)``
``mp.create_osd_overlay(format)``
``mp.get_osd_size()`` (returned object has properties: width, height, aspect)
``mp.msg.log(level, ...)``
``mp.msg.fatal(...)``
@@ -182,7 +191,8 @@ Otherwise, where the Lua APIs return ``nil`` on error, JS returns ``undefined``.
``mp.add_hook(type, priority, fn)``
``mp.options.read_options(obj [, identifier])`` (types: string/boolean/number)
``mp.options.read_options(obj [, identifier [, on_update]])`` (types:
string/boolean/number)
Additional utilities
--------------------
@@ -235,6 +245,9 @@ Note: ``read_file`` and ``write_file`` throw on errors, allow text content only.
anything from the filesystem), and returns it as a function. Very similar
to a ``Function`` constructor, but shows at stack traces as ``fname``.
``mp.module_paths``
Global modules search paths array for the ``require`` function (see below).
Timers (global)
---------------
@@ -273,9 +286,11 @@ CommonJS modules and ``require(id)``
------------------------------------
CommonJS Modules are a standard system where scripts can export common functions
for use by other scripts. A module is a script which adds properties (functions,
etc) to its invisible ``exports`` object, which another script can access by
loading it with ``require(module-id)`` - which returns that ``exports`` object.
for use by other scripts. Specifically, a module is a script which adds
properties (functions, etc) to its pre-existing ``exports`` object, which
another script can access with ``require(module-id)``. This runs the module and
returns its ``exports`` object. Further calls to ``require`` for the same module
will return its cached ``exports`` object without running the module again.
Modules and ``require`` are supported, standard compliant, and generally similar
to node.js. However, most node.js modules won't run due to missing modules such
@@ -288,10 +303,16 @@ will load the file ``./foo.js`` and return its ``exports`` object.
An id is relative (to the script which ``require``'d it) if it starts with
``./`` or ``../``. Otherwise, it's considered a "top-level id" (CommonJS term).
Top level id is evaluated as absolute filesystem path if possible (e.g. ``/x/y``
or ``~/x``). Otherwise, it's searched at ``scripts/modules.js/`` in mpv config
dirs - in normal config search order. E.g. ``require("x")`` is searched as file
``x.js`` at those dirs, and id ``foo/x`` is searched as file ``foo/x.js``.
Top level id is evaluated as absolute filesystem path if possible, e.g. ``/x/y``
or ``~/x``. Otherwise, it's considered a global module id and searched at
``scripts/modules.js/`` in mpv config dirs - in normal config search order. E.g.
``require("x")`` is searched as file ``x.js`` at those dirs, and id ``foo/x`` is
searched as file ``x.js`` inside dir ``foo`` at those dirs.
Search paths for global module id's are at the array ``mp.module_paths``, which
is searched in order. Initially it contains one item: ``~~/scripts/modules.js``
such that it behaves as described above. Modifying it will affect future
``require`` calls with global module id's which are not already loaded/cached.
No ``global`` variable, but a module's ``this`` at its top lexical scope is the
global object - also in strict mode. If you have a module which needs ``global``
+132 -47
View File
@@ -109,12 +109,43 @@ The ``mp`` module is preloaded, although it can be loaded manually with
``mp.command_native(table [,def])``
Similar to ``mp.commandv``, but pass the argument list as table. This has
the advantage that in at least some cases, arguments can be passed as
native types.
native types. It also allows you to use named argument.
If the table is an array, each array item is like an argument in
``mp.commandv()`` (but can be a native type instead of a string).
If the table contains string keys, it's interpreted as command with named
arguments. This requires at least an entry with the key ``name`` to be
present, which must be a string, and contains the command name. The special
entry ``_flags`` is optional, and if present, must be an array of
`Input Command Prefixes`_ to apply. All other entries are interpreted as
arguments.
Returns a result table on success (usually empty), or ``def, error`` on
error. ``def`` is the second parameter provided to the function, and is
nil if it's missing.
``mp.command_native_async(table [,fn])``
Like ``mp.command_native()``, but the command is ran asynchronously (as far
as possible), and upon completion, fn is called. fn has two arguments:
``fn(success, result, error)``. ``success`` is always a Boolean and is true
if the command was successful, otherwise false. The second parameter is
the result value (can be nil) in case of success, nil otherwise (as returned
by ``mp.command_native()``). The third parameter is the error string in case
of an error, nil otherwise.
Returns a table with undefined contents, which can be used as argument for
``mp.abort_async_command``.
If starting the command failed for some reason, ``nil, error`` is returned,
and ``fn`` is called indicating failure, using the same error value.
``mp.abort_async_command(t)``
Abort a ``mp.command_native_async`` call. The argument is the return value
of that command (which starts asynchronous execution of the command).
Whether this works and how long it takes depends on the command and the
situation. The abort call itself is asynchronous. Does not return anything.
``mp.get_property(name [,def])``
Return the value of the given property as string. These are the same
properties as used in input.conf. See `Properties`_ for a list of
@@ -209,7 +240,9 @@ The ``mp`` module is preloaded, although it can be loaded manually with
an example). The name should be unique across other bindings in the same
script - if not, the previous binding with the same name will be
overwritten. You can omit the name, in which case a random name is generated
internally.
internally. (Omitting works as follows: either pass ``nil`` for ``name``,
or pass the ``fn`` argument in place of the name. The latter is not
recommended and is handled for compatibility only.)
The last argument is used for optional flags. This is a table, which can
have the following entries:
@@ -220,11 +253,24 @@ The ``mp`` module is preloaded, although it can be loaded manually with
``complex``
If set to ``true``, then ``fn`` is called on both key up and down
events (as well as key repeat, if enabled), with the first
argument being a table. This table has an ``event`` entry, which
is set to one of the strings ``down``, ``repeat``, ``up`` or
``press`` (the latter if key up/down can't be tracked). It further
has an ``is_mouse`` entry, which tells whether the event was caused
by a mouse button.
argument being a table. This table has the following entries (and
may contain undocumented ones):
``event``
Set to one of the strings ``down``, ``repeat``, ``up`` or
``press`` (the latter if key up/down can't be tracked).
``is_mouse``
Boolean Whether the event was caused by a mouse button.
``key_name``
The name of they key that triggered this, or ``nil`` if invoked
artificially. If the key name is unknown, it's an empty string.
``key_text``
Text if triggered by a text key, otherwise ``nil``. See
description of ``script-binding`` command for details (this
field is equivalent to the 5th argument).
Internally, key bindings are dispatched via the ``script-message-to`` or
``script-binding`` input commands and ``mp.register_script_message``.
@@ -312,13 +358,21 @@ The ``mp`` module is preloaded, although it can be loaded manually with
of times in a row, only the last change triggers the change function. (The
exact behavior depends on timing and other things.)
If a property is unavailable, or on error, the value argument to ``fn`` is
``nil``. (The ``observe_property()`` call always succeeds, even if a
property does not exist.)
In some cases the function is not called even if the property changes.
Whether this can happen depends on the property.
This depends on the property, and it's a valid feature request to ask for
better update handling of a specific property.
If the ``type`` is ``none`` or ``nil``, sporadic property change events are
possible. This means the change function ``fn`` can be called even if the
property doesn't actually change.
You always get an initial change notification. This is meant to initialize
the user's state to the current value of the property.
``mp.unobserve_property(fn)``
Undo ``mp.observe_property(..., fn)``. This removes all property handlers
that are equal to the ``fn`` parameter. This uses normal Lua ``==``
@@ -373,7 +427,7 @@ The ``mp`` module is preloaded, although it can be loaded manually with
(``true``). This value is used when the timer expires (but before
the timer callback function fn is run).
Note that these are method, and you have to call them using ``:`` instead
Note that these are methods, and you have to call them using ``:`` instead
of ``.`` (Refer to http://www.lua.org/manual/5.2/manual.html#3.4.9 .)
Example:
@@ -482,6 +536,41 @@ are useful only in special situations.
Undo a previous registration with ``mp.register_script_message``. Does
nothing if the ``name`` wasn't registered.
``mp.create_osd_overlay(format)``
Create an OSD overlay. This is a very thin wrapper around the ``osd-overlay``
command. The function returns a table, which mostly contains fields that
will be passed to ``osd-overlay``. The ``format`` parameter is used to
initialize the ``format`` field. The ``data`` field contains the text to
be used as overlay. For details, see the ``osd-overlay`` command.
In addition, it provides the following methods:
``update()``
Commit the OSD overlay to the screen, or in other words, run the
``osd-overlay`` command with the current fields of the overlay table.
``remove()``
Remove the overlay from the screen. A ``update()`` call will add it
again.
Example:
::
ov = mp.create_osd_overlay("ass-events")
ov.data = "{\\an5}{\\b1}hello world!"
ov:update()
The advantage of using this wrapper (as opposed to running ``osd-overlay``
directly) is that the ``id`` field is allocated automatically.
``mp.get_osd_size()``
Returns a tuple of ``osd_width, osd_height, osd_par``. The first two give
the size of the OSD in pixels (for video ouputs like ``--vo=xv``, this may
be "scaled" pixels). The third is the display pixel aspect ratio.
May return invalid/nonsense values if OSD is not initialized yet.
mp.msg functions
----------------
@@ -512,14 +601,27 @@ command-line. All you have to do is to supply a table with default options to
the read_options function. The function will overwrite the default values
with values found in the config-file and the command-line (in that order).
``options.read_options(table [, identifier])``
``options.read_options(table [, identifier [, on_update]])``
A ``table`` with key-value pairs. The type of the default values is
important for converting the values read from the config file or
command-line back. Do not use ``nil`` as a default value!
The ``identifier`` is used to identify the config-file and the command-line
options. These needs to unique to avoid collisions with other scripts.
Defaults to ``mp.get_script_name()``.
Defaults to ``mp.get_script_name()`` if the parameter is ``nil`` or missing.
The ``on_update`` parameter enables run-time updates of all matching option
values via the ``script-opts`` option/property. If any of the matching
options changes, the values in the ``table`` (which was originally passed to
the function) are changed, and ``on_update(list)`` is called. ``list`` is
a table where each updated option has a ``list[option_name] = true`` entry.
There is no initial ``on_update()`` call. This never re-reads the config file.
``script-opts`` is always applied on the original config file, ignoring
previous ``script-opts`` values (for example, if an option is removed from
``script-opts`` at runtime, the option will have the value in the config
file). ``table`` entries are only written for option values whose values
effectively change (this is important if the script changes ``table``
entries independently).
Example implementation::
@@ -634,45 +736,25 @@ strictly part of the guaranteed API.
``utils.subprocess(t)``
Runs an external process and waits until it exits. Returns process status
and the captured output.
and the captured output. This is a legacy wrapper around calling the
``subprocess`` command with ``mp.command_native``. It does the following
things:
The parameter ``t`` is a table. The function reads the following entries:
- copy the table ``t``
- rename ``cancellable`` field to ``playback_only``
- rename ``max_size`` to ``capture_size``
- set ``capture_stdout`` field to ``true`` if unset
- set ``name`` field to ``subprocess``
- call ``mp.command_native(copied_t)``
- if the command failed, create a dummy result table
- copy ``error_string`` to ``error`` field if the string is non-empty
- return the result table
``args``
Array of strings. The first array entry is the executable. This
can be either an absolute path, or a filename with no path
components, in which case the ``PATH`` environment variable is
used to resolve the executable. The other array elements are
passed as command line arguments.
It is recommended to use ``mp.command_native`` or ``mp.command_native_async``
directly, instead of calling this legacy wrapper. It is for compatibility
only.
``cancellable``
Optional. If set to ``true`` (default), then if the user stops
playback or goes to the next file while the process is running,
the process will be killed.
``max_size``
Optional. The maximum size in bytes of the data that can be captured
from stdout. (Default: 16 MB.)
The function returns a table as result with the following entries:
``status``
The raw exit status of the process. It will be negative on error.
``stdout``
Captured output stream as string, limited to ``max_size``.
``error``
``nil`` on success. The string ``killed`` if the process was
terminated in an unusual way. The string ``init`` if the process
could not be started.
On Windows, ``killed`` is only returned when the process has been
killed by mpv as a result of ``cancellable`` being set to ``true``.
``killed_by_us``
Set to ``true`` if the process has been killed by mpv as a result
of ``cancellable`` being set to ``true``.
See the ``subprocess`` documentation for semantics and further parameters.
``utils.subprocess_detached(t)``
Runs an external process and detaches it from mpv's control.
@@ -685,6 +767,9 @@ strictly part of the guaranteed API.
The function returns ``nil``.
This is a legacy wrapper around calling the ``run`` command with
``mp.commandv`` and other functions.
``utils.getpid()``
Returns the process ID of the running mpv process. This can be used to identify
the calling mpv when launching (detached) subprocesses.
+180 -101
View File
@@ -210,14 +210,25 @@ Alt + and Alt -
Alt+BACKSPACE
Reset the pan/zoom settings.
F9
F8
Show the playlist and the current position in it (useful only if a UI window
is used, broken on the terminal).
F10
F9
Show the list of audio and subtitle streams (useful only if a UI window is
used, broken on the terminal).
i and I
Show/toggle an overlay displaying statistics about the currently playing
file such as codec, framerate, number of dropped frames and so on. See
`STATS`_ for more information.
del
Cycles visibility between never / auto (mouse-move) / always
\`
Show the console. (ESC closes it again. See `CONSOLE`_.)
(The following keys are valid only when using a video output that supports the
corresponding adjustment.)
@@ -263,10 +274,19 @@ in the mpv git repository.
Mouse Control
-------------
button 3 and button 4
Seek backward/forward 1 minute.
Left double click
Toggle fullscreen on/off.
button 5 and button 6
Right click
Toggle pause on/off.
Forward/Back button
Skip to next/previous entry in playlist.
Wheel up/down
Seek forward/backward 10 seconds.
Wheel left/right
Decrease/increase volume.
@@ -458,79 +478,98 @@ List Options
------------
Some options which store lists of option values can have action suffixes. For
example, you can set a ``,``-separated list of filters with ``--vf``, but the
option also allows you to append filters with ``--vf-append``.
example, the ``--display-tags`` option takes a ``,``-separated list of tags, but
the option also allows you to append a single tag with ``--display-tags-append``,
and the tag name can for example contain a literal ``,`` without the need for
escaping.
Options for filenames do not use ``,`` as separator, but ``:`` (Unix) or ``;``
(Windows).
String list and path list options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
String lists are separated by ``,``. The strings are not parsed or interpreted
by the option system itself. However, most
Path or file list options use ``:`` (Unix) or ``;`` (Windows) as separator,
instead of ``,``.
They support the following operations:
============= ===============================================
Suffix Meaning
============= ===============================================
-add Append 1 or more items (may become alias for -append)
-append Append single item (avoids need for escaping)
-clr Clear the option
-del Delete an existing item by integer index
-pre Prepend 1 or more items
-set Set a list of items
-toggle Append an item, or remove if if it already exists
-set Set a list of items (using the list separator, interprets escapes)
-append Append single item (does not interpret escapes)
-add Append 1 or more items (same syntax as -set)
-pre Prepend 1 or more items (same syntax as -set)
-clr Clear the option (remove all items)
-remove Delete item if present (does not interpret escapes)
-del Delete 1 or more items by integer index (deprecated)
-toggle Append an item, or remove if if it already exists (no escapes)
============= ===============================================
Although some operations allow specifying multiple ``,``-separated items, using
this is strongly discouraged and deprecated, except for ``-set``.
``-append`` is meant as a simple way to append a single item without having
to escape the argument (you may still need to escape on the shell level).
Without suffix, the action taken is normally ``-set``.
Key/value list options
~~~~~~~~~~~~~~~~~~~~~~
A key/value list is a list of key/value string pairs. In programming languages,
this type of data structure is often called a map or a dictionary. The order
normally does not matter, although in some cases the order might matter.
They support the following operations:
============= ===============================================
Suffix Meaning
============= ===============================================
-set Set a list of items (using ``,`` as separator)
-append Append a single item (escapes for the key, no escapes for the value)
-add Append 1 or more items (same syntax as -set)
-remove Delete item by key if present (does not interpret escapes)
============= ===============================================
Keys are unique within the list. If an already present key is set, the existing
key is removed before the new value is appended.
Filter options
~~~~~~~~~~~~~~
This is a very complex option type for the ``--af`` and ``--vf`` options only.
They often require complicated escaping. See `VIDEO FILTERS`_ for details. They
support the following operations:
============= ===============================================
Suffix Meaning
============= ===============================================
-set Set a list of filters (using ``,`` as separator)
-append Append single filter
-add Append 1 or more filters (same syntax as -set)
-pre Prepend 1 or more filters (same syntax as -set)
-clr Clear the option (remove all filters)
-remove Delete filter if present
-del Delete 1 or more filters by integer index or filter label (deprecated)
-toggle Append a filter, or remove if if it already exists
-help Pseudo operation that prints a help text to the terminal
============= ===============================================
General
~~~~~~~
Without suffix, the operation used is normally ``-set``.
Although some operations allow specifying multiple items, using this is strongly
discouraged and deprecated, except for ``-set``. There is a chance that
operations like ``-add`` and ``-pre`` will work like ``-append`` and accept a
single, unescaped item only (so the ``,`` separator will not be interpreted and
is passed on as part of the value).
Some options (like ``--sub-file``, ``--audio-file``, ``--glsl-shader``) are
aliases for the proper option with ``-append`` action. For example,
``--sub-file`` is an alias for ``--sub-files-append``.
Some options only support a subset of the above.
Options of this type can be changed at runtime using the ``change-list``
command, which takes the suffix as separate operation parameter.
Playing DVDs
------------
DVDs can be played with the ``dvd://[title]`` syntax. The optional
title specifier is a number which selects between separate video
streams on the DVD. If no title is given (``dvd://``) then the longest
title is selected automatically by the library. This is usually what
you want. mpv does not support DVD menus.
DVDs which have been copied on to a hard drive or other mounted
filesystem (by e.g. the ``dvdbackup`` tool) are accommodated by
specifying the path to the local copy: ``--dvd-device=PATH``.
Alternatively, running ``mpv PATH`` should auto-detect a DVD directory
tree and play the longest title.
.. note:: DVD library choices
mpv uses a different default DVD library than MPlayer. MPlayer
uses libdvdread by default, and mpv uses libdvdnav by default.
Both libraries are developed in parallel, but libdvdnav is
intended to support more sophisticated DVD features such as menus
and multi-angle playback. mpv uses libdvdnav for files specified
as either ``dvd://...`` or ``dvdnav://...``. To use libdvdread,
which will produce behavior more like MPlayer, specify
``dvdread://...`` instead. Some users have experienced problems
when using libdvdnav, in which playback gets stuck in a DVD menu
stream. These problems are reported to go away when auto-selecting
the title (``dvd://`` rather than ``dvd://1``) or when using
libdvdread (e.g. ``dvdread://0``). There are also outstanding bugs
in libdvdnav with seeking backwards and forwards in a video
stream. Specify ``dvdread://...`` to fix such problems.
.. note:: DVD subtitles
DVDs use image-based subtitles. Image subtitles are implemented as
a bitmap video stream which can be superimposed over the main
movie. mpv's subtitle styling and positioning options and keyboard
shortcuts generally do not work with image-based subtitles.
Exceptions include options like ``--stretch-dvd-subs`` and
``--stretch-image-subs-to-screen``.
command, which takes the suffix (without the ``-``) as separate operation
parameter.
CONFIGURATION FILES
===================
@@ -625,7 +664,8 @@ or at runtime with the ``apply-profile <name>`` command.
# a profile that can be enabled with --profile=big-cache
[big-cache]
cache=123400
cache=yes
demuxer-max-bytes=123400KiB
demuxer-readahead-secs=20
[slow]
@@ -652,12 +692,8 @@ Some profiles are loaded automatically. The following example demonstrates this:
::
[protocol.dvd]
profile-desc="profile for dvd:// streams"
alang=en
[extension.flv]
profile-desc="profile for .flv files"
[extension.mkv]
profile-desc="profile for .mkv files"
vf=flip
The profile name follows the schema ``type.name``, where type can be
@@ -667,6 +703,51 @@ and ``extension`` for the extension of the path of the currently played file
This feature is very limited, and there are no other auto profiles.
Using mpv from other programs or scripts
========================================
There are three choices for using mpv from other programs or scripts:
1. Calling it as UNIX process. If you do this, *do not parse terminal output*.
The terminal output is intended for humans, and may change any time. In
addition, terminal behavior itself may change any time. Compatibility
cannot be guaranteed.
Your code should work even if you pass ``--no-terminal``. Do not attempt
to simulate user input by sending terminal control codes to mpv's stdin.
If you need interactive control, using ``--input-ipc-server`` is
recommended. This gives you access to the `JSON IPC`_ over unix domain
sockets (or named pipes on Windows).
Depending on what you do, passing ``--no-config`` or ``--config-dir`` may
be a good idea to avoid conflicts with the normal mpv user configuration
intended for CLI playback.
Using ``--input-ipc-server`` is also suitable for purposes like remote
control (however, the IPC protocol itself is not "secure" and not
intended to be so).
2. Using libmpv. This is generally recommended when mpv is used as playback
backend for a completely different application. The provided C API is
very close to CLI mechanisms and the scripting API.
Note that even though libmpv has different defaults, it can be configured
to work exactly like the CLI player (except command line parsing is
unavailable).
See `EMBEDDING INTO OTHER PROGRAMS (LIBMPV)`_.
3. As a user script (`LUA SCRIPTING`_, `JAVASCRIPT`_, `C PLUGINS`_). This is
recommended when the goal is to "enhance" the CLI player. Scripts get
access to the entire client API of mpv.
This is the standard way to create third-party extensions for the player.
All these access the client API, which is the sum of the various mechanisms
provided by the player core, as documented here: `OPTIONS`_,
`List of Input Commands`_, `Properties`_, `List of events`_ (also see C API),
`Hooks`_.
TAKING SCREENSHOTS
==================
@@ -730,12 +811,10 @@ listed.
to the display as well, e.g.: ``Dropped: 4/34``. This happens only if
decoder frame dropping is enabled with the ``--framedrop`` options.
(``drop-frame-count`` property.)
- Cache state, e.g. ``Cache: 2s+134KB``. Visible if the stream cache is enabled.
- Cache state, e.g. ``Cache: 2s/134KB``. Visible if the stream cache is enabled.
The first value shows the amount of video buffered in the demuxer in seconds,
the second value shows the sum of the demuxer forward cache size and the
*additional* data buffered in the stream cache in kilobytes.
(``demuxer-cache-duration``, ``demuxer-cache-state``, ``cache-used``
properties.)
the second value shows the estimated size of the buffered amount in kilobytes.
(``demuxer-cache-duration`` and ``demuxer-cache-state`` properties.)
LOW LATENCY PLAYBACK
@@ -796,10 +875,10 @@ PROTOCOLS
``ytdl://...``
By default, the youtube-dl hook script (enabled by default for mpv CLI)
only looks at http URLs. Prefixing an URL with ``ytdl://`` forces it to
be always processed by the script. This can also be used to invoke special
youtube-dl functionality like playing a video by ID or invoking search.
By default, the youtube-dl hook script only looks at http(s) URLs. Prefixing
an URL with ``ytdl://`` forces it to be always processed by the script. This
can also be used to invoke special youtube-dl functionality like playing a
video by ID or invoking search.
Keep in mind that you can't pass youtube-dl command line options by this,
and you have to use ``--ytdl-raw-options`` instead.
@@ -824,29 +903,15 @@ PROTOCOLS
``bluray://`` is an alias.
``dvd://[title|[starttitle]-endtitle][/device]`` ``--dvd-device=PATH``
``dvd://[title][/device]`` ``--dvd-device=PATH``
Play a DVD. DVD menus are not supported. If no title is given, the longest
title is auto-selected.
title is auto-selected. Without ``--dvd-device``, it will probably try
to open an actual optical drive, if available and implemented for the OS.
``dvdnav://`` is an old alias for ``dvd://`` and does exactly the same
thing.
``dvdread://...:``
Play a DVD using the old libdvdread code. This is what MPlayer and
older mpv versions used for ``dvd://``. Use is discouraged. It's
provided only for compatibility and for transition, and to work
around outstanding dvdnav bugs (see "DVD library choices" above).
``tv://[channel][/input_id]`` ``--tv-...``
Analogue TV via V4L. Also useful for webcams. (Linux only.)
``pvr://`` ``--pvr-...``
PVR. (Linux only.)
``dvb://[cardnumber@]channel`` ``--dvbin-...``
Digital TV via DVB. (Linux only.)
@@ -870,9 +935,17 @@ PROTOCOLS
demuxer name, and ``options`` is the (pseudo-)filename passed to the
demuxer.
For example, ``mpv av://lavfi:mandelbrot`` makes use of the libavfilter
wrapper included in libavdevice, and will use the ``mandelbrot`` source
filter to generate input data.
.. admonition:: Example
::
mpv av://v4l2:/dev/video0 --profile=low-latency --untimed
This plays video from the first v4l input with nearly the lowest latency
possible. It's a good replacement for the removed ``tv://`` input.
Using ``--untimed`` is a hack to output a captured frame immediately,
instead of respecting the input framerate. (There may be better ways to
handle this in the future.)
``avdevice://`` is an alias.
@@ -985,6 +1058,8 @@ works like in older mpv releases. The profiles are currently defined as follows:
.. include:: stats.rst
.. include:: console.rst
.. include:: lua.rst
.. include:: javascript.rst
@@ -1022,7 +1097,11 @@ behavior of mpv.
of ``--v`` options passed to the command line.
``MPV_LEAK_REPORT``
If set to ``1``, enable internal talloc leak reporting.
If set to ``1``, enable internal talloc leak reporting. If set to another
value, disable leak reporting. If unset, use the default, which normally is
``0``. If mpv was built with ``--enable-ta-leak-report``, the default is
``1``. If leak reporting was disabled at compile time (``NDEBUG`` in
custom ``CFLAGS``), this environment variable is ignored.
``LADSPA_PATH``
Specifies the search path for LADSPA plugins. If it is unset, fully
+1183 -511
View File
File diff suppressed because it is too large. Load diff
+82 -8
View File
@@ -167,9 +167,14 @@ Configurable Options
``seekbarstyle``
Default: bar
Sets the style of the seekbar, slider (diamond marker), knob (circle
marker with guide), or bar (fill).
Default pre-0.21.0 was 'slider'.
Sets the style of the playback position marker and overall shape
of the seekbar: ``bar``, ``diamond`` or ``knob``.
``seekbarhandlesize``
Default: 0.6
Size ratio of the seek handle if ``seekbarstyle`` is set to ``dimaond``
or ``knob``. This is relative to the full height of the seekbar.
``seekbarkeyframes``
Default: yes
@@ -180,6 +185,28 @@ Configurable Options
useful in cases where keyframes cannot be found. Note that using exact
seeks can potentially make mouse dragging much slower.
``seekrangestyle``
Default: inverted
Display seekable ranges on the seekbar. ``bar`` shows them on the full
height of the bar, ``line`` as a thick line and ``inverted`` as a thin
line that is inverted over playback position markers. ``none`` will hide
them. Additionally, ``slider`` will show a permanent handle inside the seekbar
with cached ranges marked inside. Note that these will look differently
based on the seekbarstyle option. Also, ``slider`` does not work with
``seekbarstyle`` set to ``bar``.
``seekrangeseparate``
Default: yes
Controls whether to show line-style seekable ranges on top of the
seekbar or separately if ``seekbarstyle`` is set to ``bar``.
``seekrangealpha``
Default: 200
Alpha of the seekable ranges, 0 (opaque) to 255 (fully transparent).
``deadzonesize``
Default: 0.5
@@ -281,11 +308,6 @@ Configurable Options
Display timecodes with milliseconds
``seekranges``
Default: yes
Display seekable ranges on the seekbar
``visibility``
Default: auto (auto hide/show on mouse move)
@@ -299,6 +321,58 @@ Configurable Options
default is conservative to allow wide fonts to be used without overflow.
However, with many common fonts a bigger number can be used. YMMV.
``boxvideo``
Default: no
Whether to overlay the osc over the video (``no``), or to box the video
within the areas not covered by the osc (``yes``). If this option is set,
the osc may overwrite the ``--video-margin-ratio-*`` options, even if the
user has set them. (It will not overwrite them if all of them are set to
default values.)
Currently, this is supported for the ``bottombar`` and ``topbar`` layout
only. The other layouts do not change if this option is set. Separately,
if window controls are present (see below), they will be affected
regardless of which osc layout is in use.
The border is static and appears even if the OSC is configured to appear
only on mouse interaction. If the OSC is invisible, the border is simply
filled with the background color (black by default).
This currently still makes the OSC overlap with subtitles (if the
``--sub-use-margins`` option is set to ``yes``, the default). This may be
fixed later.
This does not work correctly with video outputs like ``--vo=xv``, which
render OSD into the unscaled video.
``windowcontrols``
Default: auto (Show window controls if there is no window border)
Whether to show window management controls over the video, and if so,
which side of the window to place them. This may be desirable when the
window has no decorations, either because they have been explicitly
disabled (``border=no``) or because the current platform doesn't support
them (eg: gnome-shell with wayland).
The set of window controls is fixed, offering ``minimize``, ``maximize``,
and ``quit``. Not all platforms implement ``minimize`` and ``maximize``,
but ``quit`` will always work.
``windowcontrols_alignment``
Default: right
If window controls are shown, indicates which side should they be aligned
to.
Supports ``left`` and ``right`` which will place the controls on those
respective sides.
``greenandgrumpy``
Default: no
Set to ``yes`` to reduce festivity (i.e. disable santa hat in December.)
Script Commands
~~~~~~~~~~~~~~~
+3
View File
@@ -23,6 +23,7 @@ stats:
==== ==================
1 Show usual stats
2 Show frame timings
3 Input cache stats
==== ==================
Font
@@ -53,6 +54,8 @@ Configurable Options
Default: 1
``key_page_2``
Default: 2
``key_page_3``
Default: 3
Key bindings for page switching while stats are displayed.
+269 -77
View File
@@ -16,7 +16,7 @@ The exact syntax is:
name is an arbitrary user-given name, which identifies the filter. This
is only needed if you want to toggle the filter at runtime.
A ``!`` before the filter name means the filter is enabled by default. It
A ``!`` before the filter name means the filter is disabled by default. It
will be skipped on filter creation. This is also useful for runtime filter
toggling.
@@ -85,6 +85,9 @@ libavfilter bridge.
Video filters are managed in lists. There are a few commands to manage the
filter list.
``--vf-append=filter``
Appends the filter given as arguments to the filter list.
``--vf-add=filter``
Appends the filter given as arguments to the filter list. (Passing multiple
filters is currently still possible, but deprecated.)
@@ -93,12 +96,24 @@ filter list.
Prepends the filters given as arguments to the filter list. (Passing
multiple filters is currently still possible, but deprecated.)
``--vf-remove=filter``
Deletes the filter from the list. The filter can be either given the way it
was added (filter name and its full argument list), or by label (prefixed
with ``@``). Matching of filters works as follows: if either of the compared
filters has a label set, only the labels are compared. If none of the
filters have a label, the filter name, arguments, and argument order are
compared. (Passing multiple filters is currently still possible, but
deprecated.)
``-vf-toggle=filter``
Add the given filter to the list if it was not present yet, or remove it
from the list if it was present. Matching of filters works as described in
``--vf-remove``.
``--vf-del=filter``
Deletes the filter. The filter can even given the way it was added (filter
name and its full argument list), by label (prefixed with ``@``), or as
index number. Index numbers start at 0, negative numbers address the end of
the list (-1 is the last). (Passing multiple filters is currently still
possible, but deprecated.)
Sort of like ``--vf-remove``, but also accepts an index number. Index
numbers start at 0, negative numbers address the end of the list (-1 is the
last). Deprecated.
``--vf-clr``
Completely empties the filter list.
@@ -112,15 +127,57 @@ With filters that support it, you can access parameters by their name.
Available mpv-only filters are:
``format=fmt=<value>:colormatrix=<value>:...``
Restricts the color space for the next filter without doing any conversion.
Use together with the scale filter for a real conversion.
.. note::
For a list of available formats, see ``format=fmt=help``.
Applies video parameter overrides, with optional conversion. By default,
this overrides the video's parameters without conversion (except for the
``fmt`` parameter), but can be made to perform an appropriate conversion
with ``convert=yes`` for parameters for which conversion is supported.
``<fmt>``
Format name, e.g. rgb15, bgr24, 420p, etc. (default: don't change).
Image format name, e.g. rgb15, bgr24, 420p, etc. (default: don't change).
This filter always performs conversion to the given format.
.. note::
For a list of available formats, use ``--vf=format=fmt=help``.
``<convert=yes|no>``
Force conversion of color parameters (default: no).
If this is disabled (the default), the only conversion that is possibly
performed is format conversion if ``<fmt>`` is set. All other parameters
(like ``<colormatrix>``) are forced without conversion. This mode is
typically useful when files have been incorrectly tagged.
If this is enabled, libswscale or zimg is used if any of the parameters
mismatch. zimg is used of the input/output image formats are supported
by mpv's zimg wrapper, and if ``--sws-allow-zimg=yes`` is used. Both
libraries may not support all kinds of conversions. This typically
results in silent incorrect conversion. zimg has in many cases a better
chance of performing the conversion correctly.
In both cases, the color parameters are set on the output stage of the
image format conversion (if ``fmt`` was set). The difference is that
with ``convert=no``, the color parameters are not passed on to the
converter.
If input and output video parameters are the same, conversion is always
skipped.
.. admonition:: Examples
``mpv test.mkv --vf=format:colormatrix=ycgco``
Results in incorrect colors (if test.mkv was tagged correctly).
``mpv test.mkv --vf=format:colormatrix=ycgco:convert=yes --sws-allow-zimg``
Results in true conversion to ``ycgco``, assuming the renderer
supports it (``--vo=gpu`` normally does). You can add ``--vo=xv``
to force a VO which definitely does not support it, which should
show incorrect colors as confirmation.
Using ``--sws-allow-zimg=no`` (or disabling zimg at build time)
will use libswscale, which cannot perform this conversion as
of this writing.
``<colormatrix>``
Controls the YUV to RGB color space conversion when playing video. There
@@ -216,7 +273,10 @@ Available mpv-only filters are:
:srgb: IEC 61966-2-4 (sRGB)
:linear: Linear light
:gamma1.8: Pure power curve (gamma 1.8)
:gamma2.0: Pure power curve (gamma 2.0)
:gamma2.2: Pure power curve (gamma 2.2)
:gamma2.4: Pure power curve (gamma 2.4)
:gamma2.6: Pure power curve (gamma 2.6)
:gamma2.8: Pure power curve (gamma 2.8)
:prophoto: ProPhoto RGB (ROMM) curve
:pq: ITU-R BT.2100 PQ (Perceptual quantizer) curve
@@ -249,12 +309,13 @@ Available mpv-only filters are:
:gamma1.2: Scene-referred using a pure power OOTF (gamma=1.2)
``<stereo-in>``
Set the stereo mode the video is assumed to be encoded in. Takes the
same values as the ``--video-stereo-mode`` option.
Set the stereo mode the video is assumed to be encoded in. Use
``--vf format:stereo-in=help`` to list all available modes. Check with
the ``stereo3d`` filter documentation to see what the names mean.
``<stereo-out>``
Set the stereo mode the video should be displayed as. Takes the
same values as the ``--video-stereo-mode`` option.
same values as the ``stereo-in`` option.
``<rotate>``
Set the rotation the video is assumed to be encoded with in degrees.
@@ -270,17 +331,6 @@ Available mpv-only filters are:
but values such as ``[16:9]`` can be passed too (``[...]`` for quoting
to prevent the option parser from interpreting the ``:`` character).
``<spherical-type>``
Type of the spherical projection:
:auto: As indicated by the file (default)
:none: Normal video
:equirect: Equirectangular
:unknown: Unknown projection
``<spherical-yaw>``, ``<spherical-pitch>``, ``<spherical-roll>``
Reference angle in degree, if spherical video is used.
``lavfi=graph[:sws-flags[:o=opts]]``
Filter video using FFmpeg's libavfilter.
@@ -360,22 +410,31 @@ Available mpv-only filters are:
of that will return errors. As such, you can't use the full power of
VapourSynth, but you can use certain filters.
If you just want to play video generated by a VapourSynth (i.e. using
a native VapourSynth video source), it's better to use ``vspipe`` and a
FIFO to feed the video to mpv. The same applies if the filter script
requires random frame access (see ``buffered-frames`` parameter).
.. warning::
This filter is experimental. If it turns out that it works well and is
used, it will be ported to libavfilter. Otherwise, it will be just removed.
Do not use this filter, unless you have expert knowledge in VapourSynth,
and know how to fix bugs in the mpv VapourSynth wrapper code.
If you just want to play video generated by VapourSynth (i.e. using
a native VapourSynth video source), it's better to use ``vspipe`` and a
pipe or FIFO to feed the video to mpv. The same applies if the filter script
requires random frame access (see ``buffered-frames`` parameter).
``file``
Filename of the script source. Currently, this is always a python
script. The variable ``video_in`` is set to the mpv video source,
and it is expected that the script reads video from it. (Otherwise,
mpv will decode no video, and the video packet queue will overflow,
eventually leading to audio being stopped.) The script is also
expected to pass through timestamps using the ``_DurationNum`` and
``_DurationDen`` frame properties.
script (``.vpy`` in VapourSynth convention).
The variable ``video_in`` is set to the mpv video source, and it is
expected that the script reads video from it. (Otherwise, mpv will
decode no video, and the video packet queue will overflow, eventually
leading to only audio playing, or worse.)
The filter graph created by the script is also expected to pass through
timestamps using the ``_DurationNum`` and ``_DurationDen`` frame
properties.
See the end of the option list for a full list of script variables
defined by mpv.
.. admonition:: Example:
@@ -393,21 +452,61 @@ Available mpv-only filters are:
``buffered-frames``
Maximum number of decoded video frames that should be buffered before
the filter (default: 4). This specifies the maximum number of frames
the script can request in reverse direction.
the script can request in backward direction.
E.g. if ``buffered-frames=5``, and the script just requested frame 15,
it can still request frame 10, but frame 9 is not available anymore.
If it requests frame 30, mpv will decode 15 more frames, and keep only
frames 25-30.
The only reason why this buffer exists is to serve the random access
requests the VapourSynth filter can make.
The VapourSynth API has a ``getFrameAsync`` function, which takes an
absolute frame number. Source filters must respond to all requests. For
example, a source filter can request frame 2432, and then frame 3.
Source filters typically implement this by pre-indexing the entire
file.
mpv on the other hand is stream oriented, and does not allow filters to
seek. (And it would not make sense to allow it, because it would ruin
performance.) Filters get frames sequentially in playback direction, and
cannot request them out of order.
To compensate for this mismatch, mpv allows the filter to access frames
within a certain window. ``buffered-frames`` controls the size of this
window. Most VapourSynth filters happen to work with this, because mpv
requests frames sequentially increasing from it, and most filters only
require frames "close" to the requested frame.
If the filter requests a frame that has a higher frame number than the
highest buffered frame, new frames will be decoded until the requested
frame number is reached. Excessive frames will be flushed out in a FIFO
manner (there are only at most ``buffered-frames`` in this buffer).
If the filter requests a frame that has a lower frame number than the
lowest buffered frame, the request cannot be satisfied, and an error
is returned to the filter. This kind of error is not supposed to happen
in a "proper" VapourSynth environment. What exactly happens depends on
the filters involved.
Increasing this buffer will not improve performance. Rather, it will
waste memory, and slow down seeks (when enough frames to fill the buffer
need to be decoded at once). It is only needed to prevent the error
described in the previous paragraph.
How many frames a filter requires depends on filter implementation
details, and mpv has no way of knowing. A scale filter might need only
1 frame, an interpolation filter may require a small number of frames,
and the ``Reverse`` filter will require an infinite number of frames.
If you want reliable operation to the full extend VapourSynth is
capable, use ``vspipe``.
The actual number of buffered frames also depends on the value of the
``concurrent-frames`` option. Currently, both option values are
multiplied to get the final buffer size.
(Normally, VapourSynth source filters must provide random access, but
mpv was made for playback, and does not provide frame-exact random
access. The way this video filter works is a compromise to make simple
filters work anyway.)
``concurrent-frames``
Number of frames that should be requested in parallel. The
level of concurrency depends on the filter and how quickly mpv can
@@ -416,15 +515,25 @@ Available mpv-only filters are:
making it higher than the number of cores can actually make it
slower.
Technically, mpv will call the VapourSynth ``getFrameAsync`` function
in a loop, until there are ``concurrent-frames`` frames that have not
been returned by the filter yet. This also assumes that the rest of the
mpv filter chain reads the output of the ``vapoursynth`` filter quickly
enough. (For example, if you pause the player, filtering will stop very
soon, because the filtered frames are waiting in a queue.)
Actual concurrency depends on many other factors.
By default, this uses the special value ``auto``, which sets the option
to the number of detected logical CPU cores.
The following variables are defined by mpv:
The following ``.vpy`` script variables are defined by mpv:
``video_in``
The mpv video source as vapoursynth clip. Note that this has no length
set, which confuses many filters. Using ``Trim`` on the clip with a
high dummy length can turn it into a finite clip.
The mpv video source as vapoursynth clip. Note that this has an
incorrect (very high) length set, which confuses many filters. This is
necessary, because the true number of frames is unknown. You can use the
``Trim`` filter on the clip to reduce the length.
``video_in_dw``, ``video_in_dh``
Display size of the video. Can be different from video size if the
@@ -434,7 +543,7 @@ Available mpv-only filters are:
FPS value as reported by file headers. This value can be wrong or
completely broken (e.g. 0 or NaN). Even if the value is correct,
if another filter changes the real FPS (by dropping or inserting
frames), the value of this variable might not be useful. Note that
frames), the value of this variable will not be useful. Note that
the ``--fps`` command line option overrides this value.
Useful for some filters which insist on having a FPS.
@@ -442,34 +551,10 @@ Available mpv-only filters are:
``display_fps``
Refresh rate of the current display. Note that this value can be 0.
``vapoursynth-lazy``
The same as ``vapoursynth``, but doesn't load Python scripts. Instead, a
custom backend using Lua and the raw VapourSynth API is used. The syntax
is completely different, and absolutely no convenience features are
provided. There's no type checking either, and you can trigger crashes.
.. admonition:: Example:
::
video_out = invoke("morpho", "Open", {clip = video_in})
The special variable ``video_in`` is the mpv video source, while the
special variable ``video_out`` is used to read video from. The 1st argument
is the plugin (queried with ``getPluginByNs``), the 2nd is the filter name,
and the 3rd argument is a table with the arguments. Positional arguments
are not supported. The types must match exactly. Since Lua is terrible and
can't distinguish integers and floats, integer arguments must be prefixed
with ``i_``, in which case the prefix is removed and the argument is cast
to an integer. Should the argument's name start with ``i_``, you're out of
luck.
Clips (VSNodeRef) are passed as light userdata, so trying to pass any
other userdata type will result in hard crashes.
``vavpp``
VA-AP-API video post processing. Works with ``--vo=vaapi`` and ``--vo=gpu``
only. Currently deinterlaces. This filter is automatically inserted if
VA-API video post processing. Requires the system to support VA-API,
i.e. Linux/BSD only. Works with ``--vo=vaapi`` and ``--vo=gpu`` only.
Currently deinterlaces. This filter is automatically inserted if
deinterlacing is requested (either using the ``d`` key, by default mapped to
the command ``cycle deinterlace``, or the ``--deinterlace`` option).
@@ -569,3 +654,110 @@ Available mpv-only filters are:
which algorithm is actually selected. ``none`` always falls back. On
most if not all hardware, this option will probably do nothing, because
a video processor usually supports all modes or none.
``fingerprint=...``
Compute video frame fingerprints and provide them as metadata. Actually, it
currently barely deserved to be called ``fingerprint``, because it does not
compute "proper" fingerprints, only tiny downscaled images (but which can be
used to compute image hashes or for similarity matching).
The main purpose of this filter is to support the ``skip-logo.lua`` script.
If this script is dropped, or mpv ever gains a way to load user-defined
filters (other than VapourSynth), this filter will be removed. Due to the
"special" nature of this filter, it will be removed without warning.
The intended way to read from the filter is using ``vf-metadata`` (also
see ``clear-on-query`` filter parameter). The property will return a list
of key/value pairs as follows:
::
fp0.pts = 1.2345
fp0.hex = 1234abcdef...bcde
fp1.pts = 1.4567
fp1.hex = abcdef1234...6789
...
fpN.pts = ...
fpN.hex = ...
type = gray-hex-16x16
Each ``fp<N>`` entry is for a frame. The ``pts`` entry specifies the
timestamp of the frame (within the filter chain; in simple cases this is
the same as the display timestamp). The ``hex`` field is the hex encoded
fingerprint, whose size and meaning depend on the ``type`` filter option.
The ``type`` field has the same value as the option the filter was created
with.
This returns the frames that were filtered since the last query of the
property. If ``clear-on-query=no`` was set, a query doesn't reset the list
of frames. In both cases, a maximum of 10 frames is returned. If there are
more frames, the oldest frames are discarded. Frames are returned in filter
order.
(This doesn't return a structured list for the per-frame details because the
internals of the ``vf-metadata`` mechanism suck. The returned format may
change in the future.)
This filter uses zimg for speed and profit. However, it will fallback to
libswscale in a number of situations: lesser pixel formats, unaligned data
pointers or strides, or if zimg fails to initialize for unknown reasons. In
these cases, the filter will use more CPU. Also, it will output different
fingerprints, because libswscale cannot perform the full range expansion we
normally request from zimg. As a consequence, the filter may be slower and
not work correctly in random situations.
``type=...``
What fingerprint to compute. Available types are:
:gray-hex-8x8: grayscale, 8 bit, 8x8 size
:gray-hex-16x16: grayscale, 8 bit, 16x16 size (default)
Both types simply remove all colors, downscale the image, concatenate
all pixel values to a byte array, and convert the array to a hex string.
``clear-on-query=yes|no``
Clear the list of frame fingerprints if the ``vf-metadata`` property for
this filter is queried (default: yes). This requires some care by the
user. Some types of accesses might query the filter multiple times,
which leads to lost frames.
``print=yes|no``
Print computed fingerprints the the terminal (default: no). This is
mostly for testing and such. Scripts should use ``vf-metadata`` to
read information from this filter instead.
``gpu=...``
Convert video to RGB using the OpenGL renderer normally used with
``--vo=gpu``. This requires that the EGL implementation supports off-screen
rendering on the default display. (This is the case with Mesa.)
Sub-options:
``w=<pixels>``, ``h=<pixels>``
Size of the output in pixels (default: 0). If not positive, this will
use the size of the first filtered input frame.
.. warning::
This is highly experimental. Performance is bad, and it will not work
everywhere in the first place. Some features are not supported.
.. warning::
This does not do OSD rendering. If you see OSD, then it has been
rendered by the VO backend. (Subtitles are rendered by the ``gpu``
filter, if possible.)
.. warning::
If you use this with encoding mode, keep in mind that encoding mode will
convert the RGB filter's output back to yuv420p in software, using the
configured software scaler. Using ``zimg`` might improve this, but in
any case it might go against your goals when using this filter.
.. warning::
Do not use this with ``--vo=gpu``. It will apply filtering twice, since
most ``--vo=gpu`` options are unconditionally applied to the ``gpu``
filter. There is no mechanism in mpv to prevent this.
+91 -28
View File
@@ -71,6 +71,9 @@ Available video output drivers are:
Shared memory video output driver without hardware acceleration that works
whenever X11 is present.
Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent
performance.
.. note:: This is a fallback only, and should not be normally used.
``vdpau`` (X11 only)
@@ -308,7 +311,7 @@ Available video output drivers are:
For tuning, refer to your copy of the file ``SDL_hints.h``.
.. note:: This driver is for compatibility with systems that don't provide
proper graphics drivers, or which support GLES only.
proper graphics drivers.
The following global options are supported by this video output:
@@ -383,6 +386,9 @@ Available video output drivers are:
Depends on support of true color by modern terminals to display the images
at full color range. On Windows it requires an ansi terminal such as mintty.
Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent
performance.
``--vo-tct-algo=<algo>``
Select how to write the pixels to the terminal.
@@ -415,6 +421,8 @@ Available video output drivers are:
JPEG files, extension .jpeg.
png
PNG files.
webp
WebP files.
``--vo-image-png-compression=<0-9>``
PNG compression factor (speed vs. file size tradeoff) (default: 7)
@@ -425,6 +433,12 @@ Available video output drivers are:
JPEG quality factor (default: 90)
``--vo-image-jpeg-optimize=<0-100>``
JPEG optimization factor (default: 100)
``--vo-image-webp-lossless=<yes|no>``
Enable writing lossless WebP files (default: no)
``--vo-image-webp-quality=<0-100>``
WebP quality (default: 75)
``--vo-image-webp-compression=<0-6>``
WebP compression factor (default: 4)
``--vo-image-outdir=<dirname>``
Specify the directory to save the image files to (default: ``./``).
@@ -474,52 +488,92 @@ Available video output drivers are:
environment (e.g. no X). Does not support hardware acceleration (if you
need this, check the ``drm`` backend for ``gpu`` VO).
Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent
performance.
The following global options are supported by this video output:
``--drm-connector=[<gpu_number>.]<name>``
Select the connector to use (usually this is a monitor.) If ``<name>``
is empty or ``auto``, mpv renders the output on the first available
connector. Use ``--drm-connector=help`` to get list of available
connector. Use ``--drm-connector=help`` to get a list of available
connectors. When using multiple graphic cards, use the ``<gpu_number>``
argument to disambiguate.
(default: empty)
``--drm-mode=<number>``
Mode ID to use (resolution and frame rate).
(default: 0)
``--drm-mode=<preferred|highest|N|WxH[@R]>``
Mode to use (resolution and frame rate).
Possible values:
``--drm-osd-plane-id=<number>``
Select the DRM plane index to use for OSD (or OSD and video).
Index is zero based, and related to crtc.
When using this option with the drm_prime renderer, it will only affect
the OSD contents. Otherwise it will set OSD & video plane.
(default: primary plane)
:preferred: Use the preferred mode for the screen on the selected
connector. (default)
:highest: Use the mode with the highest resolution available on the
selected connector.
:N: Select mode by index.
:WxH[@R]: Specify mode by width, height, and optionally refresh rate.
In case several modes match, selects the mode that comes
first in the EDID list of modes.
``--drm-video-plane-id=<number>``
Select the DRM plane index to use for video layer.
Index is zero based, and related to crtc.
This option only has effect when using the drm_prime renderer (which
supports several layers) together with ``vo=gpu`` and ``gpu-context=drm``.
(default: first overlay plane)
Use ``--drm-mode=help`` to get a list of available modes for all active
connectors.
``--drm-format=<xrgb8888,xrgb2101010>``
``--drm-atomic=<no|auto>``
Toggle use of atomic modesetting. Mostly useful for debugging.
:no: Use legacy modesetting.
:auto: Use atomic modesetting, falling back to legacy modesetting if
not available. (default)
Note: Only affects ``gpu-context=drm``. ``vo=drm`` supports legacy
modesetting only.
``--drm-draw-plane=<primary|overlay|N>``
Select the DRM plane to which video and OSD is drawn to, under normal
circumstances. The plane can be specified as ``primary``, which will
pick the first applicable primary plane; ``overlay``, which will pick
the first applicable overlay plane; or by index. The index is zero
based, and related to the CRTC.
(default: primary)
When using this option with the drmprime-drm hwdec interop, only the OSD
is rendered to this plane.
``--drm-drmprime-video-plane=<primary|overlay|N>``
Select the DRM plane to use for video with the drmprime-drm hwdec
interop (used by e.g. the rkmpp hwdec on RockChip SoCs, and v4l2 hwdec:s
on various other SoC:s). The plane is unused otherwise. This option
accepts the same values as ``--drm-draw-plane``. (default: overlay)
To be able to successfully play 4K video on various SoCs you might need
to set ``--drm-draw-plane=overlay --drm-drmprime-video-plane=primary``
and setting ``--drm-draw-surface-size=1920x1080``, to render the OSD at a
lower resolution (the video when handled by the hwdec will be on the
drmprime-video plane and at full 4K resolution)
``--drm-format=<xrgb8888|xrgb2101010>``
Select the DRM format to use (default: xrgb8888). This allows you to
choose the bit depth of the DRM mode. xrgb8888 is your usual 24 bit per
pixel/8 bits per channel packed RGB format with 8 bits of padding.
xrgb2101010 is a packed 30 bits per pixel/10 bits per channel packed RGB
format with 2 bits of padding.
Unless you have an intel graphics card, a recent kernel and a recent
version of mesa (>=18) xrgb2101010 is unlikely to work for you.
There are cases when xrgb2101010 will work with the ``drm`` VO, but not
with the ``drm`` backend for the ``gpu`` VO. This is because with the
``gpu`` VO, in addition to requiring support in your DRM driver,
requires support for xrgb2101010 in your EGL driver
This currently only has an effect when used together with the ``drm``
backend for the ``gpu`` VO. The ``drm`` VO always uses xrgb8888.
``--drm-draw-surface-size=<[WxH]>``
Sets the size of the surface used on the draw plane. The surface will
then be upscaled to the current screen resolution. This option can be
useful when used together with the drmprime-drm hwdec interop at high
resolutions, as it allows scaling the draw plane (which in this case
only handles the OSD) down to a size the GPU can handle.
``--drm-osd-size=<[WxH]>``
Sets the OSD OpenGL size to the specified size. OSD will then be upscaled
to the current screen resolution. This option can be useful when using
several layers in high resolutions with a GPU which cannot handle it.
Note : this option is only available with DRM atomic support.
When used without the drmprime-drm hwdec interop this option will just
cause the video to get rendered at a different resolution and then
scaled to screen size.
Note: this option is only available with DRM atomic support.
(default: display resolution)
``mediacodec_embed`` (Android)
@@ -531,5 +585,14 @@ Available video output drivers are:
many of mpv's features (subtitle rendering, OSD/OSC, video filters, etc)
are not available with this driver.
To use hardware decoding with ``--vo-gpu`` instead, use
To use hardware decoding with ``--vo=gpu`` instead, use
``--hwdec=mediacodec-copy`` along with ``--gpu-context=android``.
``wlshm`` (Wayland only)
Shared memory video output driver without hardware acceleration that works
whenever Wayland is present.
Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent
performance.
.. note:: This is a fallback only, and should not be normally used.
+1 -2
View File
@@ -144,7 +144,6 @@ Mac OS X
* Native OpenGL backend.
* Cocoa event loop is independent from MPlayer's event loop, so user
actions like accessing menus and live resizing do not block the playback.
* Apple Remote support.
* Media Keys support.
* VDA support using libavcodec hwaccel API instead of FFmpeg's decoder with up
to 2-2.5x reduction in CPU usage.
@@ -248,7 +247,7 @@ Command Line Switches
``-msglevel`` ``--msg-level`` (changed semantics)
``-msgmodule`` ``--msg-module``
``-name`` ``--x11-name``
``-noar`` ``--no-input-appleremote``
``-noar`` ``(removed; replaced by MediaPlayer framework)``
``-noautosub`` ``--no-sub-auto``
``-noconsolecontrols`` ``--no-input-terminal``
``-nosound`` ``--no-audio``
+7 -3
View File
@@ -20,24 +20,28 @@ Release procedure
While on master:
- Update the `RELEASE_NOTES` file.
- Update the `RELEASE_NOTES` file, replacing the previous release notes.
- Update the `VERSION` file.
- Update `DOCS/client-api-changes.rst` and `DOCS/interface-changes.rst`
(in particular, update the last version numbers if necessary)
- Commit changes.
- Create signed commit with changes.
- Create signed tag v0.X.Y.
- Add -UNKNOWN suffix to version in `VERSION` file.
- Commit changes, push branch and tag to GitHub.
- Commit changes, push release branch (`release/0.X`) and tag to GitHub.
- Create a new GitHub release using the content of `RELEASE_NOTES` related to
the new version.
If necessary (to e.g. exclude commits already on master), the release can
be done on a branch with different commit history. The release branch **must**
then be merged to master so `git describe` will pick up the tag.
Release notes template
----------------------
+425 -10
View File
@@ -15,7 +15,7 @@ player/*.c:
* parse command line, add files from the command line to playlist
(m_config_parse_mp_command_line())
* check help options etc. (call handle_help_options()), possibly exit
* call play_files() function that works down the playlist:
* call mp_play_files() function that works down the playlist:
* run idle loop (idle_loop()), until there are files in the
playlist or an exit command was given (only if --idle it set)
* actually load and play a file in play_current_file():
@@ -30,7 +30,7 @@ player/*.c:
* determine next entry on the playlist to play
* loop, or exit if no next file or quit is requested
(see enum stop_play_reason)
* call exit_player_with_rc()
* call mp_destroy()
* run_playloop():
* calls fill_audio_out_buffers()
This checks whether new audio needs to be decoded, and pushes it
@@ -44,9 +44,9 @@ player/*.c:
Things worth saying about the playback core:
- most state is in MPContext (core.h), which is not available to the
subsystems
subsystems (and should not be made available)
- the currently played tracks are in mpctx->current_tracks, and decoder
state in track.d_video/d_audio/d_sub
state in track.dec/d_sub
- the other subsystems rarely call back into the frontend, and the frontend
polls them instead (probably a good thing)
- one exceptions are wakeup callbacks, which notify a "higher" component
@@ -68,6 +68,7 @@ ta.h & ta.c:
as in it doesn't require valgrind.) You can enable it by setting the
MPV_LEAK_REPORT environment variable to "1":
export MPV_LEAK_REPORT=1
Or permanently by building with --enable-ta-leak-report.
This will list all unfree'd allocations on exit.
Documentation can be found here:
@@ -103,13 +104,45 @@ options/options.h, options/options.c
options.c. Most default values for options and MPOpts are in
mp_default_opts at the end of options.c.
MPOpts is unfortunately quite monolithic, and virtually accessed by
everything.But some components (like video outputs and video filters) have
their own sub-option tables separate from MPOpts.
MPOpts is unfortunately quite monolithic, but is being incrementally broken
up into sub-structs. Many components have their own sub-option structs
separate from MPOpts. New options should be bound to the component that uses
them. Add a new option table/struct if needed.
The global MPOpts still contains the sub-structs as fields, which serves to
link them to the option parser. For example, an entry like this may be
typical:
OPT_SUBSTRUCT("", demux_opts, demux_conf, 0),
This directs the option access code to include all options in demux_conf
into the global option list, with no prefix (""), and as part of the
MPOpts.demux_opts field. The MPOpts.demux_opts field is actually not
accessed anywhere, and instead demux.c does this:
struct m_config_cache *opts_cache =
m_config_cache_alloc(demuxer, global, &demux_conf);
struct demux_opts *opts = opts_cache->opts;
... to get a copy of its options.
See m_config.h (below) how to access options.
The actual option parser is spread over m_option.c, m_config.c, and
parse_commandline.c, and uses the option table in options.c.
options/m_config.h & m_config.c:
Code for querying and managing options. This (unfortunately) contains both
declarations for the "legacy-ish" global m_config struct, and ways to access
options in a threads-safe way anywhere, like m_config_cache_alloc().
m_config_cache_alloc() lets anyone read, observe, and write options in any
thread. The only state it needs is struct mpv_global, which is an opaque
type that can be passed "down" the component hierarchy. For safety reasons,
you should not pass down any pointers to option structs (like MPOpts), but
instead pass down mpv_global, and use m_config_cache_alloc() (or similar)
to get a synchronized copy of the options.
input/input.c:
This translates keyboard input coming from VOs and other sources (such
as remote control devices like Apple IR or client API commands) to the
@@ -139,9 +172,6 @@ stream/*:
Some stream inputs are just there to invoke special demuxers, like
stream_mf.c. (Basically to make the prefix "mf://" do something special.)
cache.c is a caching wrapper around streams implementations, needed for
smooth network playback.
demux/:
Demuxers split data streams into audio/video/sub streams, which in turn
are split in packets. Packets (see demux_packet.h) are mostly byte chunks
@@ -155,6 +185,10 @@ demux/:
There is a stream header for each audio/video/sub stream, and each of them
holds codec information about the stream and other information.
demux.c is a bit big, the main reason being that it contains the demuxer
cache, which is implemented as a list of packets. The cache is complex
because it support seeking, multiple ranges, prefetching, and so on.
video/:
This contains several things related to audio/video decoding, as well as
video filters.
@@ -240,3 +274,384 @@ sub/:
etc/:
The file input.conf is actually integrated into the mpv binary by the
build system. It contains the default keybindings.
Best practices and Concepts within mpv
======================================
General contribution etc.
-------------------------
See: DOCS/contribute.md
Error checking
--------------
If an error is relevant, it should be handled. If it's interesting, log the
error. However, mpv often keeps errors silent and reports failures somewhat
coarsely by propagating them upwards the caller chain. This is OK, as long as
the errors are not very interesting, or would require a developer to debug it
anyway (in which case using a debugger would be more convenient, and the
developer would need to add temporary debug printfs to get extremely detailed
information which would not be appropriate during normal operation).
Basically, keep a balance on error reporting. But always check them, unless you
have a good argument not to.
Memory allocation errors (OOM) are a special class of errors. Normally such
allocation failures are not handled "properly". Instead, abort() is called.
(New code should use MP_HANDLE_OOM() for this.) This is done out of laziness and
for convenience, and due to the fact that MPlayer/mplayer2 never handled it
correctly. (MPlayer varied between handling it correctly, trying to do so but
failing, and just not caring, while mplayer2 started using abort() for it.)
This is justifiable in a number of ways. Error handling paths are notoriously
untested and buggy, so merely having them won't make your program more reliable.
Having these error handling paths also complicates non-error code, due to the
need to roll back state at any point after a memory allocation.
Take any larger body of code, that is supposed to handle OOM, and test whether
the error paths actually work, for example by overriding malloc with a version
that randomly fails. You will find bugs quickly, and often they will be very
annoying to fix (if you can even reproduce them).
In addition, a clear indication that something went wrong may be missing. On
error your program may exhibit "degraded" behavior by design. Consider a video
encoder dropping frames somewhere in the middle of a video due to temporary
allocation failures, instead of just exiting with an errors. In other cases, it
may open conceptual security holes. Failing fast may be better.
mpv uses GPU APIs, which may be break on allocation errors (because driver
authors will have the same issues as described here), or don't even have a real
concept for dealing with OOM (OpenGL).
libmpv is often used by GUIs, which I predict always break if OOM happens.
Last but not least, OSes like Linux use "overcommit", which basically means that
your program may crash any time OOM happens, even if it doesn't use malloc() at
all!
But still, don't just assume malloc() always succeeds. Use MP_HANDLE_OOM(). The
ta* APIs do this for you. The reason for this is that dereferencing a NULL
pointer can have security relevant consequences if large offsets are involved.
Also, a clear error message is better than a random segfault.
Some big memory allocations are checked anyway. For example, all code must
assume that allocating video frames or packets can fail. (The above example
of dropping video frames during encoding is entirely possible in mpv.)
Undefined behavior
------------------
Undefined behavior (UB) is a concept in the C language. C is famous for being a
language that makes it almost impossible to write working code, because
undefined behavior is so easily triggered, compilers will happily abuse it to
generate "faster" code, debugging tools will shout at you, and sometimes it
even means your code doesn't work.
There is a lot of literature on this topic. Read it.
(In C's defense, UB exists in other languages too, but since they're not used
for low level infrastructure, and/or these languages are at times not rigorously
defined, simply nobody cares. However, the C standard committee is still guilty
for not addressing this. I'll admit that I can't even tell from the standard's
gibberish whether some specific behavior is UB or not. It's written like tax
law.)
In mpv, we generally try to avoid undefined behavior. For one, we want portable
and reliable operation. But more importantly, we want clean output from
debugging tools, in order to find real bugs more quickly and effectively.
Avoid the "works in practice" argument. Once debugging tools come into play, or
simply when "in practice" stops being true, this will all get back to you in a
bad way.
Global state, library safety
----------------------------
Mutable global state is when code uses global variables that are not read-only.
This must be avoided in mpv. Always use context structs that the caller of
your code needs to allocate, and whose pointers are passed to your functions.
Library safety means that your code (or library) can be used by a library
without causing conflicts with other library users in the same process. To any
piece of code, a "safe" library's API can simply be used, without having to
worry about other API users that may be around somewhere.
Libraries are often not library safe, because they they use global mutable state
or other "global" resources. Typical examples include use of signals, simple
global variables (like hsearch() in libc), or internal caches not protected by
locks.
A surprisingly high number of libraries are not library safe because they need
global initialization. Typically they provide an API function, which
"initializes" the library, and which must be called before calling any other
API functions. Often, you are to provide global configuration parameters, which
can change the behavior of the library. If two libraries A and B use library C,
but A and B initialize C with different parameters, something "bad" may happen.
In addition, these global initialization functions are often not thread-safe. So
if A and B try to initialize C at the same time (from different threads and
without knowing about each other), it may cause undefined behavior. (libcurl is
a good example of both of these issues. FFmpeg and some TLS libraries used to be
affected, but improved.)
This is so bad because library A and B from the previous example most likely
have no way to cooperate, because they're from different authors and have no
business knowing each others. They'd need a library D, which wraps library C
in a safe way. Unfortunately, typically something worse happens: libraries get
"infected" by the unsafeness of its sub-libraries, and export a global init API
just to initialize the sub-libraries. In the previous example, libraries A and B
would export global init APIs just to init library C, even though the rest of
A/B are clean and library safe. (Again, libcurl is an example of this, if you
subtract other historic anti-features.)
The main problem with library safety is that its lack propagates to all
libraries using the library.
We require libmpv to be library safe. This is not really possible, because some
libraries are not library safe (FFmpeg, Xlib, partially ALSA). However, for
ideological reasons, there is no global init API, and best effort is made to try
to avoid problems.
libmpv has some features that are not library safe, but which are disabled by
default (such as terminal usage aka stdout, or JSON IPC blocking SIGPIPE for
internal convenience).
A notable, very disgustingly library unsafe behavior of libmpv is calling
abort() on some memory allocation failure. See error checking section.
Logging
-------
All logging and terminal output in mpv goes through the functions and macros
provided in common/msg.h. This is in part for library safety, and in part to
make sure users can silence all output, or to redirect the output elsewhere,
like a log file or the internal console.lua script.
Locking
-------
See generally available literature. In mpv, we use pthread for this.
Always keep locking clean. Don't skip locking just because it will work "in
practice". (See undefined behavior section.) If your use case is simple, you may
use C11 atomics (osdep/atomic.h for partial C99 support), but most likely you
will only hurt yourself and others.
Always make clear which fields in a struct are protected by which lock. If a
field is immutable, or simply not thread-safe (e.g. state for a single worker
thread), document it as well.
Internal mpv APIs are assumed to be not thread-safe by default. If they have
special guarantees (such as being usable by more than one thread at a time),
these should be explicitly documented.
All internal mpv APIs must be free of global state. Even if a component is not
thread-safe, multiple threads can use _different_ instances of it without any
locking.
On a side note, recursive locks may seem convenient at first, but introduce
additional problems with condition variables and locking hierarchies. They
should be avoided.
Locking hierarchy
-----------------
A simple way to avoid deadlocks with classic locking is to define a locking
hierarchy or lock order. If all threads acquire locks in the same order, no
deadlocks will happen.
For example, a "leaf" lock is a lock that is below all other locks in the
hierarchy. You can acquire it any time, as long as you don't acquire other
locks while holding it.
Unfortunately, C has no way to declare or check the lock order, so you should at
least document it.
In addition, try to avoid exposing locks to the outside. Making the declaration
of a lock private to a specific .c file (and _not_ exporting accessors or
lock/unlock functions that manipulate the lock) is a good idea. Your component's
API may acquire internal locks, but should release them when returning. Keeping
the entire locking in a single file makes it easy to check it.
Avoiding callback hell
----------------------
mpv code is separated in components, like the "frontend" (i.e. MPContext mpctx),
VOs, AOs, demuxers, and more. The frontend usually calls "down" the usage
hierarchy: mpctx almost on top, then things like vo/ao, and utility code on the
very bottom.
"Callback hell" is when when components call both up and down the hierarchy,
which for example leads to accidentally recursion, reentrancy problems, or
locking nightmares. This is avoided by (mostly) calling only down the hierarchy.
Basically the call graph forms a DAG. The other direction is handled by event
queues, wakeup callbacks, and similar mechanisms.
Typically, a component provides an API, and does not know anything about its
user. The API user (component higher in the hierarchy) polls the state of the
lower component when needed.
This also enforces some level of modularization, and with some luck the locking
hierarchy. (Basically, locks of lower components automatically become leaf
locks.) Another positive effect is simpler memory management.
(Also see e.g.: http://250bpm.com/blog:24)
Wakeup callbacks
----------------
This is a common concept in mpv. Even the public API uses it. It's used when an
API has internal threads (or otherwise triggers asynchronous events), but the
component call hierarchy needs to be kept. The wakeup callback is the only
exception to the call hierarchy, and always calls up.
For example, vo spawns a thread that the API user (the mpv frontend) does not
need to know about. vo simply provides a single-threaded API (or that looks like
one). This API needs a way to notify the API user of new events. But the vo
event producer is on the vo thread - it can't simply invoke a callback back into
the API user, because then the API user has to deal with locking, despite not
using threads. In addition, this will probably cause problems like mentioned in
the "callback hell" section, especially lock order issues.
The solution is the wakeup callback. It merely unblocks the API user from
waiting, and the API user then uses the normal vo API to examine whether or
which state changed. As a concept, it documents what a wakeup callback is
allowed to do and what not, to avoid the aforementioned problems.
Generally, you are not allowed to call any API from the wakeup callback. You
just do whatever is needed to unblock your thread. For example, if it's waiting
on a mutex/condition variable, acquire the mutex, set a change flag, signal
the condition variable, unlock, return. (This mutex must not be held when
calling the API. It must be a leaf lock.)
Restricting the wakeup callback like this sidesteps any reentrancy issues and
other complexities. The API implementation can simply hold internal (and
non-recursive) locks while invoking the wakeup callback.
The API user still needs to deal with locking (probably), but there's only the
need to implement a single "receiver", that can handle the entire API of the
used component. (Or multiple APIs - MPContext for example has only 1 wakeup
callback that handles all AOs, VOs, input, demuxers, and more. It simple re-runs
the playloop.)
You could get something more advanced by turning this into a message queue. The
API would append a message to the queue, and the API user can read it. But then
you still need a way to "wakeup" the API user (unless you force the API user
to block on your API, which will make things inconvenient for the API user). You
also need to worry about what happens if the message queue overruns (you either
lose messages or have unbounded memory usage). In the mpv public API, the
distinction between message queue and wakeup callback is sort of blurry, because
it does provide a message queue, but an additional wakeup callback, so API
users are not required to call mpv_wait_event() with a high timeout.
mpv itself prefers using wakeup callbacks over a generic event queue, because
most times an event queue is not needed (or complicates things), and it is
better to do it manually.
(You could still abstract the API user side of wakeup callback handling, and
avoid reimplementing it all the time. Although mp_dispatch_queue already
provides mechanisms for this.)
Condition variables
-------------------
They're used whenever a thread needs to wait for something, without nonsense
like sleep calls or busy waiting. mpv uses the standard pthread API for this.
There's a lot of literature on it. Read it.
For initial understanding, it may be helpful to know that condition variables
are not variables that signal a condition. pthread_cond_t does not have any
state per-se. Maybe pthread_cond_t would better be named pthread_interrupt_t,
because its sole purpose is to interrupt a thread waiting via pthread_cond_wait()
(or similar). The "something" in "waiting for something" can be called
predicate (to avoid confusing it with "condition"). Consult literature for the
proper terms.
The very short version is...
Shared declarations:
pthread_mutex_t lock;
pthread_cond_t cond_var;
struct something state_var; // protected by lock, changes signaled by cond_var
Waiter thread:
pthread_mutex_lock(&lock);
// Wait for a change in state_var. We want to wait until predicate_fulfilled()
// returns true.
// Must be a loop for 2 reasons:
// 1. cond_var may be associated with other conditions too
// 2. pthread_cond_wait() can have sporadic wakeups
while (!predicate_fulfilled(&state_var)) {
// This unlocks, waits for cond_var to be signaled, and then locks again.
// The _whole_ point of cond_var is that unlocking and waiting for the
// signal happens atomically.
pthread_cond_wait(&cond_var, &lock);
}
// Here you may react to the state change. The state cannot change
// asynchronously as long as you still hold the lock (and didn't release
// and reacquire it).
// ...
pthread_mutex_unlock(&lock);
Signaler thread:
pthread_mutex_lock(&lock);
// Something changed. Update the shared variable with the new state.
update_state(&state_var);
// Notify that something changed. This will wake up the waiter thread if
// it's blocked in pthread_cond_wait(). If not, nothing happens.
pthread_cond_broadcast(&cond_var);
// Fun fact: good implementations wake up the waiter only when the lock is
// released, to reduce kernel scheduling overhead.
pthread_mutex_unlock(&lock);
Some basic rules:
1. Always access your state under proper locking
2. Always check your predicate before every call to pthread_cond_wait()
(And don't call pthread_cond_wait() if the predicate is fulfilled.)
3. Always call pthread_cond_wait() in a loop
(And only if your predicate failed without releasing the lock..)
4. Always call pthread_cond_broadcast()/_signal() inside of its associated
lock
mpv sometimes violates rule 3, and leaves "retrying" (i.e. looping) to the
caller.
Common pitfalls:
- Thinking that pthread_cond_t is some kind of semaphore, or holds any
application state or the user predicate (it _only_ wakes up threads
that are at the same time blocking on pthread_cond_wait() and friends,
nothing else)
- Changing the predicate, but not updating all pthread_cond_broadcast()/
_signal() calls correctly
- Forgetting that pthread_cond_wait() unlocks the lock (other threads can
and must acquire the lock)
- Holding multiple nested locks while trying to wait (=> deadlock, violates
the lock order anyway)
- Waiting for a predicate correctly, but unlocking/relocking before acting
on it (unlocking allows arbitrary state changes)
- Confusing which lock/condition var. is used to manage a bit of state
Generally available literature probably has better examples and explanations.
Using condition variables the proper way is generally preferred over using more
messy variants of them. (Just saying because on win32, "SetEvent" exists, and
it's inferior to condition variables. Try to avoid the win32 primitives, even if
you're dealing with Windows-only code.)
Threads
-------
Threading should be conservatively used. Normally, mpv code pretends to be
single-threaded, and provides thread-unsafe APIs. Threads are used coarsely,
and if you can avoid messing with threads, you should. For example, VOs and AOs
do not need to deal with threads normally, even though they run on separate
threads. The glue code "isolates" them from any threading issues.
+29 -61
View File
@@ -1,8 +1,6 @@
![http://mpv.io/](https://raw.githubusercontent.com/mpv-player/mpv.io/master/source/images/mpv-logo-128.png)
![mpv logo](https://raw.githubusercontent.com/mpv-player/mpv.io/master/source/images/mpv-logo-128.png)
## mpv
--------------
# mpv
* [External links](#external-links)
@@ -11,12 +9,9 @@
* [Downloads](#downloads)
* [Changelog](#changelog)
* [Compilation](#compilation)
* [FFmpeg vs. Libav](#ffmpeg-vs-libav)
* [FFmpeg ABI compatibility](#ffmpeg-abi-compatibility)
* [Release cycle](#release-cycle)
* [Bug reports](#bug-reports)
* [Contributing](#contributing)
* [Relation to MPlayer and mplayer2](#relation-to-mplayer-and-mplayer2)
* [License](#license)
* [Contact](#contact)
@@ -25,15 +20,17 @@
* [Wiki](https://github.com/mpv-player/mpv/wiki)
* [FAQ](https://github.com/mpv-player/mpv/wiki/FAQ)
* [FAQ][FAQ]
* [Manual](http://mpv.io/manual/master/)
## Overview
**mpv** is a media player based on MPlayer and mplayer2. It supports a wide
variety of video file formats, audio and video codecs, and subtitle types.
**mpv** is a free (as in freedom) media player for the command line. It supports
a wide variety of media file formats, audio and video codecs, and subtitle types.
There is a [FAQ][FAQ].
Releases can be found on the [release list][releases].
@@ -43,11 +40,14 @@ Releases can be found on the [release list][releases].
- A somewhat capable CPU. Hardware decoding might help if the CPU is too slow to
decode video in realtime, but must be explicitly enabled with the `--hwdec`
option.
- A not too crappy GPU. mpv is not intended to be used with bad GPUs. There are
many caveats with drivers or system compositors causing tearing, stutter,
etc. On Windows, you might want to make sure the graphics drivers are
current. In some cases, ancient fallback video output methods can help
(such as `--vo=xv` on Linux), but this use is not recommended or supported.
- A not too crappy GPU. mpv's focus is not on power-efficient playback on
embedded or integrated GPUs (for example, hardware decoding is not even
enabled by default). Low power GPUs may cause issues like tearing, stutter,
etc. The main video output uses shaders for video rendering and scaling,
rather than GPU fixed function hardware. On Windows, you might want to make
sure the graphics drivers are current. In some cases, ancient fallback video
output methods can help (such as `--vo=xv` on Linux), but this use is not
recommended or supported.
## Downloads
@@ -116,9 +116,9 @@ Essential dependencies (incomplete list):
- Lua (optional, required for the OSC pseudo-GUI and youtube-dl integration)
- libjpeg (optional, used for screenshots only)
- uchardet (optional, for subtitle charset detection)
- vdpau and vaapi libraries for hardware decoding on Linux (optional)
- nvdec and vaapi libraries for hardware decoding on Linux (optional)
Libass dependencies:
Libass dependencies (when building libass):
- gcc or clang, yasm on x86 and x86_64
- fribidi, freetype, fontconfig development headers (for libass)
@@ -126,17 +126,17 @@ Libass dependencies:
particularly for correct rendering of non-English text on OSX, and
Arabic/Indic scripts on any platform)
FFmpeg dependencies:
FFmpeg dependencies (when building FFmpeg):
- gcc or clang, yasm on x86 and x86_64
- OpenSSL or GnuTLS (have to be explicitly enabled when compiling FFmpeg)
- libx264/libmp3lame/libfdk-aac if you want to use encoding (have to be
explicitly enabled when compiling FFmpeg)
- For native DASH playback, FFmpeg needs to be built with --enable-libxml2
(although there are security implications).
(although there are security implications, and DASH support has lots of bugs).
- AV1 decoding support requires dav1d.
- For good nvidia support on Linux, make sure nv-codec-headers is installed
and can be found by configure.
- Libav support is broken. (See section below.)
Most of the above libraries are available in suitable versions on normal
Linux distributions. For ease of compiling the latest git master of everything,
@@ -149,28 +149,6 @@ or cross-compile from Linux with MinGW. See
[Windows compilation][windows_compilation].
## FFmpeg vs. Libav
Generally, mpv should work with the latest release as well as the git version
of FFmpeg. Libav support is currently broken, because they did not add certain
FFmpeg API changes which mpv relies on.
## FFmpeg ABI compatibility
mpv does not support linking against FFmpeg versions it was not built with, even
if the linked version is supposedly ABI-compatible with the version it was
compiled against. Expect malfunctions, crashes, and security issues if you
do it anyway.
The reason for not supporting this is because it creates far too much complexity
with little to no benefit, coupled with absurd and unusable FFmpeg API
artifacts.
Newer mpv versions will refuse to start if runtime and compile time FFmpeg
library versions mismatch.
## Release cycle
Every other month, an arbitrary git snapshot is made, and is assigned
@@ -207,42 +185,32 @@ You can check [the wiki](https://github.com/mpv-player/mpv/wiki/Stuff-to-do)
or the [issue tracker](https://github.com/mpv-player/mpv/issues?q=is%3Aopen+is%3Aissue+label%3A%22feature+request%22)
for ideas on what you could contribute with.
## Relation to MPlayer and mplayer2
mpv is a fork of MPlayer. Much has changed, and in general, mpv should be
considered a completely new program, rather than a MPlayer drop-in replacement.
For details see [FAQ entry](https://github.com/mpv-player/mpv/wiki/FAQ#How_is_mpv_related_to_MPlayer).
If you are wondering what's different from mplayer2 and MPlayer, an incomplete
and largely unmaintained list of changes is located [here][mplayer-changes].
## License
GPLv2 "or later" by default, LGPLv2.1 "or later" with `--enable-lgpl`.
See [details.](https://github.com/mpv-player/mpv/blob/master/Copyright)
## History
This software is based on the MPlayer project. Before mpv existed as a project,
the code base was briefly developed under the mplayer2 project. For details,
see the [FAQ][FAQ].
## Contact
Most activity happens on the IRC channel and the github issue tracker.
- **GitHub issue tracker**: [issue tracker][issue-tracker] (report bugs here)
- **User IRC Channel**: `#mpv` on `irc.freenode.net`
- **Developer IRC Channel**: `#mpv-devel` on `irc.freenode.net`
To contact the `mpv` team in private write to `mpv-team@googlegroups.com`. Use
only if discretion is required.
- **GitHub issue tracker**: [issue tracker][issue-tracker] (report bugs here)
- **User IRC Channel**: `#mpv` on `irc.freenode.net`
- **Developer IRC Channel**: `#mpv-devel` on `irc.freenode.net`
[FAQ]: https://github.com/mpv-player/mpv/wiki/FAQ
[releases]: https://github.com/mpv-player/mpv/releases
[mpv-build]: https://github.com/mpv-player/mpv-build
[homebrew-mpv]: https://github.com/mpv-player/homebrew-mpv
[issue-tracker]: https://github.com/mpv-player/mpv/issues
[ffmpeg_vs_libav]: https://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav
[release-policy]: https://github.com/mpv-player/mpv/blob/master/DOCS/release-policy.md
[windows_compilation]: https://github.com/mpv-player/mpv/blob/master/DOCS/compile-windows.md
[mplayer-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/mplayer-changes.rst
[interface-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/interface-changes.rst
[api-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/client-api-changes.rst
[restore-old-bindings]: https://github.com/mpv-player/mpv/blob/master/etc/restore-old-bindings.conf
+52 -84
View File
@@ -1,4 +1,4 @@
Release 0.29.0
Release 0.31.0
==============
This release requires FFmpeg 4.0 or newer.
@@ -10,40 +10,32 @@ Features
Added
~~~~~
- ao/openal: Add better sample format and channel layout selection
- ao/openal: Add support for direct channels output
- cocoa-cb: initial implementation via opengl-cb API
- context_drm_egl: Introduce 30bpp support (requires Mesa 18.0.0_rc4 or later)
- osx: add some more menu bar items as suggested by Apples's HIG
- vo_gpu: make screenshots use the GL renderer (#5498, #5240)
- x11: support Shift+TAB as an input key bind (#5849)
- ytdl_hook: support native dash demuxer, if present
- vo_gpu/d3d11: allow configurable swapchain color space for native HDR output
- player: add mechanisms for better logging as preperation for console.lua
- audio: add ao_audiotrack for Android
- input: introduce a pseudo key name that grabs all text input
- wayland: add grab zone for resizing window with mouse
- osc: implement pseudo client side decorations via OSC
- vf_gpu: add video filter using vo_gpu's renderer
- added console.lua: interactive REPL for input commands
- osc: display Santa hat for idle logo in December
- vd_lavc: add option to autoselect known good hwdec implementations
- mac: replace old event tap for media key support with MediaPlayer
Changed
~~~~~~~
- ao_alsa, ao_pulse: reduce requested buffer size
- audio: change format negotiation, remove channel remix fudging
- client API: deprecate opengl-cb API and introduce a replacement API
- demux: lower demuxer cache default sizes from 400MB/400MB to 50MB/150MB
- osx: always deactivate the early opengl flush on macOS
- scripting: change when/how player waits for scripts being loaded
- vo_gpu: various improvements to HDR peak detection
- vo_gpu: various improvements to HDR tone mapping
- wayland_common: update to stable xdg-shell
- ytdl_hook: parse youtube playlist urls to set start index if `--ytdl-raw-option=yes-playlist=` is specified
Deprecated
~~~~~~~~~~
- af_lavrresample: deprecate this filter
- input: disable gamepad code by default
- vo_gpu: allow vdpau usage under EGL
- stream, demux: redo origin policy
Removed
~~~~~~~
- build: drop support for SDL1 (only applied to ao_sdl)
- mac: remove Apple Remote support
- client API: deprecate tick event
Options and Commands
@@ -52,88 +44,64 @@ Options and Commands
Added
~~~~~
- add a number of --audio-resample-* options, which should from now on be used instead of --af-defaults=lavrresample:
- ao/openal: --openal-direct-channels
- command: add --osd-on-seek option defaulting to bar
- command: add a change-list command (#5435)
- options: add --http-proxy
- options: add a builtin low-latency profile
- vaapi: add option to select a non-default device path with --vaapi-device (#4320)
- video: add option to reduce latency by 1 or 2 frames
- vo_gpu: introduce --target-peak (#5521)
- vo_gpu/d3d11: add --d3d11-output-csp for configuring swap chain color space
- command: add command-list property
- command, input: add input-bindings property
- command: add --window-maximized and make --window-minimized settable
- command: add property returning hidpi scale
- command, lua: add a way to share data between scripts
- client API, lua: add new API for setting OSD overlays
Changed
~~~~~~~
- command: change cycle-value command behavior (#5772)
- config: replace config dir lua-settings/ with dir script-opts/
- options: --lavfi-complex now requires uniquely named filter pads.
- options: --ytdl is now always enabled, even for libmpv
- options: make --deinterlace=yes always deinterlace (#5219)
- options: slightly improve filter help output for lavfi bridge
- vo: rename --vo=opengl-cb to --vo=libmpv
- add a builtin "sw-fast" profile, which restores performance settings
for software video conversion. These were switched to higher quality.
This affects video outputs like vo_x11 and vo_drm, and screenshots.
- options: make --show-profile without parameters list all profiles
- wayland: support for --hidpi-window-scale option
- stream_lavf: set --network-timeout to 60 seconds by default
- x11: scale window-scale by DPI
Deprecated
~~~~~~~~~~
- encoding: deprecate a bunch of obscure options (--ovoffset, --oaoffset, --ovfirst, --oafirst)
- options: deprecate --vf-defaults and --af-defaults
- osx: --gpu-context=cocoa with --gpu-api=opengl is now deprecated in favour of --vo=libmpv
- deprecate --input-file
- deprecate --video-sync=display-adrop
- deprecate all input section commands
- deprecate --display-fps, replaced by --override-display-fps
Removed
~~~~~~~
- command: remove an old compatibility hack that allowed CLI aliases to be set as property, deprecated in 0.26.0
- input: remove legacy command handling for MPlayer commands that were deprecated in 2013
- options: drop --opensles-sample-rate, as --audio-samplerate should be used if desired
- options: drop deprecated --videotoolbox-format, --ff-aid, --ff-vid, --ff-sid, --ad-spdif-dtshd, --softvol options
- options: remove --video-stereo-mode
- options: remove deprecated ao/vo auto profiles
- options: remove the following encoding options: --ocopyts (now the default, old timestamp handling is gone), --oneverdrop (now default), --oharddup (you need to use --vf=fps=VALUE), --ofps, --oautofps, --omaxfps
- remove deprecated --playlist-pos alias
Fixes and Minor Enhancements
----------------------------
- HIDRemote: fix volume buttons on macOS 10.13 (#5721)
- TOOLS/autoload: Fix broken "disabled" option
- TOOLS/autoload: be more robust with slow directory listings (#5618)
- ao_sdl: fix default buffer size
- build: add static libraries to libmpv.pc
- build: bump waf to 2.0.9 (fixes Python 3.7 compatibility)
- build: manually add standard library search paths for linking (#5791)
- common: round all integer times to milliseconds
- demux, player: fix playback of sparse video streams (w/ still images)
- demux: support for some kinds of timed metadata (e.g. ICY)
- demux_mkv: add V_AV1 identifier for AV1
- demux_mkv: support Meridian Lossless Packing in Matroska (#5923)
- display additional metadata tags during video playback
- drm_atomic: Fix memory leaks in drm_atomic_create
- enable cache for FUSE filesystems on OpenBSD and FreeBSD
- gpu: prefer 16bit floating point FBO formats to 16bit integer ones
- hwdec_vaegl: Fix VAAPI EGL interop used with gpu-context=drm
- input.conf: use exact value for [ binding, which does the inverse of ]
- input: add a keybinding to toggle hardware decoding
- input: minor additions to default key bindings (#973)
- osc: fix accidentally skipping files when seeking with slider
- player: fix strange behavior on edition switching
- player: fix track autoselection of external files yet again
- terminal-unix: stop trying to read when terminal disappears (#5842)
- video: actually wait for last frame being rendered on EOF
- video: fix --video-rotate in some cases
- video: fix crash with vdpau when reinitializing rendering (#5447)
- vo_gpu: fix anamorphic screenshots (#5619)
- vo_vdpau: fix resizing and rotation problems
- vo_drm, vo_x11: allow use of zimg
- vo_sdl: Support mouse wheel input, Improve mouse button input
- video: fix track switching work for external images
- vo_gpu: fix infinite scaler reinit spam
- f_output_chain: fix possible crash when changing filters
- vo_gpu: opengl: add hack for ancient Mesa/GLX
- demux_lavf: export demuxer_id for more formats which have it
- lua: make later key bindings always have higher priority
- drm_common: fix display FPS estimation for interlaced modes
- vo_drm: fix incorrect pixel format possibly being picked for 30-bit
- zsh completion: fix pcre usage to really be optional
- options: increase consistency between list options and document them
- osc: reduce unnecesary CPU usage by using property notifications
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API, and DOCS/interface-changes.rst for a history
of changes to other user-visible interfaces.
A complete changelog can be seen by running `git log v0.28.2..v0.29.0`
A complete changelog can be seen by running `git log v0.30.0..v0.31.0`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.28.2...v0.29.0 or
https://git.srsfckn.biz/mpv/log/?qt=range&q=v0.28.2..v0.29.0
https://github.com/mpv-player/mpv/compare/v0.30.0...v0.31.0 or
https://git.srsfckn.biz/mpv/log/?qt=range&q=v0.30.0..v0.31.0
+1 -3
View File
@@ -10,11 +10,9 @@ export PYTHON=/usr/bin/python3
"$PYTHON" bootstrap.py
"$PYTHON" waf configure \
--check-c-compiler=gcc \
--disable-egl-angle-lib \
--enable-crossc \
--enable-spirv-cross \
--enable-d3d-hwaccel \
--enable-d3d11 \
--enable-egl-angle \
--enable-jpeg \
--enable-lcms2 \
--enable-libarchive \
+9 -9
View File
@@ -1,6 +1,8 @@
#!/usr/bin/bash
set -e
export PYTHON=/usr/bin/python3
# Write an empty fonts.conf to speed up fc-cache
export FONTCONFIG_FILE=/dummy-fonts.conf
cat >"$FONTCONFIG_FILE" <<EOF
@@ -12,12 +14,12 @@ EOF
# Install build dependencies for mpv
pacman -S --noconfirm --needed \
$MINGW_PACKAGE_PREFIX-toolchain \
$MINGW_PACKAGE_PREFIX-angleproject-git \
$MINGW_PACKAGE_PREFIX-cmake \
$MINGW_PACKAGE_PREFIX-lcms2 \
$MINGW_PACKAGE_PREFIX-libarchive \
$MINGW_PACKAGE_PREFIX-libass \
$MINGW_PACKAGE_PREFIX-libjpeg-turbo \
$MINGW_PACKAGE_PREFIX-libplacebo \
$MINGW_PACKAGE_PREFIX-lua51 \
$MINGW_PACKAGE_PREFIX-ninja \
$MINGW_PACKAGE_PREFIX-rubberband \
@@ -52,21 +54,19 @@ pacman -Sc --noconfirm
# Compile shaderc
(
git clone --depth=1 https://github.com/google/shaderc && cd shaderc
git clone --depth=1 https://github.com/google/glslang.git third_party/glslang
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Tools.git third_party/spirv-tools
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers.git third_party/spirv-headers
"$PYTHON" utils/git-sync-deps
mkdir build && cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DSHADERC_SKIP_TESTS=ON \
-DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX ..
ninja install
cp -f libshaderc/libshaderc_shared.dll $MINGW_PREFIX/bin/
)
# Compile crossc
# Compile SPIRV-Cross
(
git clone --depth=1 https://github.com/rossy/crossc && cd crossc
git submodule update --init
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Cross && cd SPIRV-Cross
make -j4 install prefix=$MINGW_PREFIX
mkdir build && cd build
cmake -GNinja -DSPIRV_CROSS_SHARED=ON -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX ..
ninja install
)
+57 -23
View File
@@ -20,19 +20,37 @@ def is_user_lib(objfile, libname):
not "libc." in libname and \
not "libgcc." in libname and \
not os.path.basename(libname) == 'Python' and \
not os.path.basename(objfile) in libname
not os.path.basename(objfile) in libname and \
not "libswift" in libname
def otool(objfile):
command = "otool -L %s | grep -e '\t' | awk '{ print $1 }'" % objfile
command = "otool -L '%s' | grep -e '\t' | awk '{ print $1 }'" % objfile
output = subprocess.check_output(command, shell = True, universal_newlines=True)
return set(filter(partial(is_user_lib, objfile), output.split()))
def get_rpaths_dev_tools(binary):
command = "otool -l '%s' | grep -A2 LC_RPATH | grep path | grep \"Xcode\|CommandLineTools\"" % binary
result = subprocess.check_output(command, shell = True, universal_newlines=True)
pathRe = re.compile("^\s*path (.*) \(offset \d*\)$")
output = []
for line in result.splitlines():
output.append(pathRe.search(line).group(1).strip())
return output
def install_name_tool_change(old, new, objfile):
subprocess.call(["install_name_tool", "-change", old, new, objfile])
def install_name_tool_id(name, objfile):
subprocess.call(["install_name_tool", "-id", name, objfile])
def install_name_tool_add_rpath(rpath, binary):
subprocess.call(["install_name_tool", "-add_rpath", rpath, binary])
def install_name_tool_delete_rpath(rpath, binary):
subprocess.call(["install_name_tool", "-delete_rpath", rpath, binary])
def libraries(objfile, result = dict()):
libs_list = otool(objfile)
result[objfile] = libs_list
@@ -43,29 +61,19 @@ def libraries(objfile, result = dict()):
return result
def leafs(libs_dict, processed = []):
result = []
processed = set(processed)
for objfile, libs in libs_dict.items():
if libs <= processed:
result.append(objfile)
return result
def lib_path(binary):
return os.path.join(os.path.dirname(binary), 'lib')
def lib_name(lib):
return os.path.join("@executable_path", "lib", os.path.basename(lib))
def process_libraries(libs_dict, binary, processed = []):
ls = leafs(libs_dict, processed)
diff = set(ls) - set(processed)
if diff == set([binary]):
return
def process_libraries(libs_dict, binary):
libs_set = set(libs_dict)
# Remove binary from libs_set to prevent a duplicate of the binary being
# added to the libs directory.
libs_set.remove(binary)
for src in diff:
for src in libs_set:
name = lib_name(src)
dst = os.path.join(lib_path(binary), os.path.basename(src))
@@ -76,21 +84,47 @@ def process_libraries(libs_dict, binary, processed = []):
if src in libs_dict[binary]:
install_name_tool_change(src, name, binary)
for p in processed:
for p in libs_set:
if p in libs_dict[src]:
install_name_tool_change(p, lib_name(p), dst)
return ls
def process_swift_libraries(binary):
command = ['xcrun', '--find', 'swift-stdlib-tool']
swiftStdlibTool = subprocess.check_output(command, universal_newlines=True).strip()
# from xcode11 on the dynamic swift libs reside in a separate directory from
# the std one, might need versioned paths for future swift versions
swiftLibPath = os.path.join(swiftStdlibTool, '../../lib/swift-5.0/macosx')
swiftLibPath = os.path.abspath(swiftLibPath)
command = [swiftStdlibTool, '--copy', '--platform', 'macosx', '--scan-executable', binary, '--destination', lib_path(binary)]
if os.path.exists(swiftLibPath):
command.extend(['--source-libraries', swiftLibPath])
subprocess.check_output(command, universal_newlines=True)
print(">> setting additional rpath for swift libraries")
install_name_tool_add_rpath("@executable_path/lib", binary)
def remove_dev_tools_rapths(binary):
for path in get_rpaths_dev_tools(binary):
install_name_tool_delete_rpath(path, binary)
def main():
binary = os.path.abspath(sys.argv[1])
if not os.path.exists(lib_path(binary)):
os.makedirs(lib_path(binary))
print(">> gathering all linked libraries")
libs = libraries(binary)
libs_processed = process_libraries(libs, binary)
while libs_processed is not None:
libs_processed = process_libraries(libs, binary, libs_processed)
print(">> copying and processing all linked libraries")
process_libraries(libs, binary)
print(">> removing rpath definitions towards dev tools")
remove_dev_tools_rapths(binary)
print(">> copying and processing swift libraries")
process_swift_libraries(binary)
if __name__ == "__main__":
main()
+42 -4
View File
@@ -5,6 +5,20 @@
-- the internal playlist. (It stops if the it would add an already existing
-- playlist entry at the same position - this makes it "stable".)
-- Add at most 5000 * 2 files when starting a file (before + after).
--[[
To configure this script use file autoload.conf in director script-opts (the "script-opts"
directory must be in the mpv configuration directory, typically ~/.config/mpv/).
Example configuration would be:
disabled=false
images=false
videos=true
audio=true
--]]
MAXENTRIES = 5000
local msg = require 'mp.msg'
@@ -12,7 +26,10 @@ local options = require 'mp.options'
local utils = require 'mp.utils'
o = {
disabled = false
disabled = false,
images = true,
videos = true,
audio = true
}
options.read_options(o)
@@ -22,11 +39,30 @@ function Set (t)
return set
end
EXTENSIONS = Set {
'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp',
'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus',
function SetUnion (a,b)
local res = {}
for k in pairs(a) do res[k] = true end
for k in pairs(b) do res[k] = true end
return res
end
EXTENSIONS_VIDEO = Set {
'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp'
}
EXTENSIONS_AUDIO = Set {
'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus'
}
EXTENSIONS_IMAGES = Set {
'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'webp', 'svg', 'bmp'
}
EXTENSIONS = Set {}
if o.videos then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO) end
if o.audio then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO) end
if o.images then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES) end
function add_files_at(index, files)
index = index - 1
local oldcount = mp.get_property_number("playlist-count", 1)
@@ -102,6 +138,7 @@ function find_and_add_entries()
-- check if this is a manually made playlist
if (pl_count > 1 and autoloaded == nil) or
(pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then
msg.verbose("stopping: manually made playlist")
return
else
autoloaded = true
@@ -114,6 +151,7 @@ function find_and_add_entries()
local files = utils.readdir(dir, "files")
if files == nil then
msg.verbose("no other files in directory")
return
end
table.filter(files, function (v, k)
+105
View File
@@ -0,0 +1,105 @@
-- Test script for some command API details.
local utils = require("mp.utils")
function join(sep, arr, count)
local r = ""
if count == nil then
count = #arr
end
for i = 1, count do
if i > 1 then
r = r .. sep
end
r = r .. utils.to_string(arr[i])
end
return r
end
mp.observe_property("vo-configured", "bool", function(_, v)
if v ~= true then
return
end
print("async expand-text")
mp.command_native_async({"expand-text", "hello ${path}!"},
function(res, val, err)
print("done async expand-text: " .. join(" ", {res, val, err}))
end)
-- make screenshot writing very slow
mp.set_property("screenshot-format", "png")
mp.set_property("screenshot-png-compression", "9")
timer = mp.add_periodic_timer(0.1, function() print("I'm alive") end)
timer:resume()
print("Slow screenshot command...")
res, err = mp.command_native({"screenshot"})
print("done, res: " .. utils.to_string(res))
print("Slow screenshot async command...")
res, err = mp.command_native_async({"screenshot"}, function(res)
print("done (async), res: " .. utils.to_string(res))
timer:kill()
end)
print("done (sending), res: " .. utils.to_string(res))
print("Broken screenshot async command...")
mp.command_native_async({"screenshot-to-file", "/nonexistent/bogus.png"},
function(res, val, err)
print("done err scr.: " .. join(" ", {res, val, err}))
end)
mp.command_native_async({name = "subprocess", args = {"sh", "-c", "echo hi && sleep 10s"}, capture_stdout = true},
function(res, val, err)
print("done subprocess: " .. join(" ", {res, val, err}))
end)
local x = mp.command_native_async({name = "subprocess", args = {"sleep", "inf"}},
function(res, val, err)
print("done sleep inf subprocess: " .. join(" ", {res, val, err}))
end)
mp.add_timeout(15, function()
print("aborting sleep inf subprocess after timeout")
mp.abort_async_command(x)
end)
-- (assuming this "freezes")
local y = mp.command_native_async({name = "sub-add", url = "-"},
function(res, val, err)
print("done sub-add stdin: " .. join(" ", {res, val, err}))
end)
mp.add_timeout(20, function()
print("aborting sub-add stdin after timeout")
mp.abort_async_command(y)
end)
-- This should get killed on script exit.
mp.command_native_async({name = "subprocess", playback_only = false,
args = {"sleep", "inf"}}, function()end)
-- Runs detached; should be killed on player exit (forces timeout)
mp.command_native({_flags={"async"}, name = "subprocess",
playback_only = false, args = {"sleep", "inf"}})
end)
function freeze_test(playback_only)
-- This "freezes" the script, should be killed via timeout.
counter = counter and counter + 1 or 0
print("freeze! " .. counter)
local x = mp.command_native({name = "subprocess",
playback_only = playback_only,
args = {"sleep", "inf"}})
print("done, killed=" .. utils.to_string(x.killed_by_us))
end
mp.register_event("shutdown", function()
freeze_test(false)
end)
mp.register_event("idle", function()
freeze_test(true)
end)
+37
View File
@@ -0,0 +1,37 @@
-- Test a float property which internally uses NaN.
-- Run with --no-config (or just scale-param1 not set).
local utils = require 'mp.utils'
prop_name = "scale-param1"
-- internal NaN, return string "default" instead of NaN
v = mp.get_property_native(prop_name, "fail")
print("Exp:", "string", "\"default\"")
print("Got:", type(v), utils.to_string(v))
v = mp.get_property(prop_name)
print("Exp:", "default")
print("Got:", v)
-- not representable -> return provided fallback value
v = mp.get_property_number(prop_name, -100)
print("Exp:", -100)
print("Got:", v)
mp.set_property_native(prop_name, 123)
v = mp.get_property_number(prop_name, -100)
print("Exp:", "number", 123)
print("Got:", type(v), utils.to_string(v))
-- try to set an actual NaN
st, msg = mp.set_property_number(prop_name, 0.0/0)
print("Exp:", nil, "<message>")
print("Got:", st, msg)
-- set default
mp.set_property(prop_name, "default")
v = mp.get_property(prop_name)
print("Exp:", "default")
print("Got:", v)
+266
View File
@@ -0,0 +1,266 @@
--[[
Automatically skip in files if video frames with pre-supplied fingerprints are
detected. This will skip ahead by a pre-configured amount of time if a matching
video frame is detected.
This requires the vf_fingerprint video filter to be compiled in. Read the
documentation of this filter for caveats (which will automatically apply to
this script as well), such as no support for zero-copy hardware decoding.
You need to manually gather and provide fingerprints for video frames and add
them to a configuration file in script-opts/skip-logo.conf (the "script-opts"
directory must be in the mpv configuration directory, typically ~/.config/mpv/).
Example script-opts/skip-logo.conf:
cases = {
{
-- Skip ahead 10 seconds if a black frame was detected
-- Note: this is dangerous non-sense. It's just for demonstration.
name = "black frame", -- print if matched
skip = 10, -- number of seconds to skip forward
score = 0.3, -- required score
fingerprint = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
},
{
-- Skip ahead 20 seconds if a white frame was detected
-- Note: this is dangerous non-sense. It's just for demonstration.
name = "fun2",
skip = 20,
fingerprint = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
},
}
This is actually a lua file. Lua was chosen because it seemed less of a pain to
parse. Future versions of this script may change the format.
The fingerprint is a video frame, converted to "gray" (8 bit per pixels), full
range, each pixel concatenated into an array, converted to a hex string. You
can produce these fingerprints by running this manually:
mpv --vf=fingerprint:print yourfile.mkv
This will log the fingerprint of each video frame to the console, along with its
timestamp. You find the fingerprint of a unique-enough looking frame, and add
it as entry to skip-logo.conf.
You can provide a score for "fuzziness". If no score is provided, a default
value of 0.3 is used. The score is inverse: 0 means exactly the same, while a
higher score means a higher difference. Currently, the score is computed as
euclidean distance between the video frame and the pre-provided fingerprint,
thus the highest score is 16. You probably want a score lower than 1 at least.
(This algorithm is very primitive, but also simple and fast to compute.)
There's always the danger of false positives, which might be quite annoying.
It's up to you what you hate more, the logo, or random skips if false positives
are detected. Also, it's always active, and might eat too much CPU with files
that have a high resolution or framerate. To temporarily disable the script,
having a keybind like this in your input.conf will be helpful:
ctrl+k vf toggle @skip-logo
This will disable/enable the fingerprint filter, which the script automatically
adds at start.
Another important caveat is that the script currently disables matching during
seeking or playback initialization, which means it cannot match the first few
frames of a video. This could be fixed, but the author was too lazy to do so.
--]]
local utils = require "mp.utils"
local msg = require "mp.msg"
local label = "skip-logo"
local meta_property = string.format("vf-metadata/%s", label)
local config = {}
local cases = {}
local cur_bmp
local seeking = false
local playback_start_pts = nil
-- Convert a hex string to an array. Convert each byte to a [0,1] float by
-- interpreting it as normalized uint8_t.
-- The data parameter, if not nil, may be used as storage (avoiding garbage).
local function hex_to_norm8(hex, data)
local size = math.floor(#hex / 2)
if #hex ~= size * 2 then
return nil
end
local res
if (data ~= nil) and (#data == size) then
res = data
else
res = {}
end
for i = 1, size do
local num = tonumber(hex:sub(i * 2, i * 2 + 1), 16)
if num == nil then
return nil
end
res[i] = num / 255.0
end
return res
end
local function compare_bmp(a, b)
if #a ~= #b then
return nil -- can't compare
end
local sum = 0
for i = 1, #a do
local diff = a[i] - b[i]
sum = sum + diff * diff
end
return math.sqrt(sum)
end
local function load_config()
local conf_file = mp.find_config_file("script-opts/skip-logo.conf")
local conf_fn
local err = nil
if conf_file then
if setfenv then
conf_fn, err = loadfile(conf_file)
if conf_fn then
setfenv(conf_fn, config)
end
else
msg.warn("Lua 5.2 was not tested, this might go wrong.")
conf_fn, err = loadfile(conf_file, "t", config)
end
else
err = "config file not found"
end
if conf_fn and (not err) then
local ok, err2 = pcall(conf_fn)
err = err2
end
if err then
msg.error("Failed to load config file:", err)
end
if config.cases then
for n, case in ipairs(config.cases) do
local err = nil
case.bitmap = hex_to_norm8(case.fingerprint)
if case.bitmap == nil then
err = "invalid or missing fingerprint field"
end
if case.score == nil then
case.score = 0.3
end
if type(case.score) ~= "number" then
err = "score field is not a number"
end
if type(case.skip) ~= "number" then
err = "skip field is not a number or missing"
end
if case.name == nil then
case.name = ("Entry %d"):format(n)
end
if err == nil then
cases[#cases + 1] = case
else
msg.error(("Entry %s: %s, ignoring."):format(case.name, err))
end
end
end
end
load_config()
-- Returns true on match and if something was done.
local function check_fingerprint(hex, pts)
local bmp = hex_to_norm8(hex, cur_bmp)
cur_bmp = bmp
-- If parsing the filter's result failed (well, it shouldn't).
assert(bmp ~= nil, "filter returned nonsense")
for _, case in ipairs(cases) do
local score = compare_bmp(case.bitmap, bmp)
if (score ~= nil) and (score <= case.score) then
msg.warn(("Matching %s: score=%f (required: %f) at %s, skipping %f seconds"):
format(case.name, score, case.score, mp.format_time(pts), case.skip))
mp.commandv("seek", pts + case.skip, "absolute+exact")
return true
end
end
return false
end
local function read_frames()
local result = mp.get_property_native(meta_property)
if result == nil then
return
end
-- Try to get all entries. Out of laziness, assume that there are at most
-- 100 entries. (In fact, vf_fingerprint limits it to 10.)
for i = 0, 99 do
local prefix = string.format("fp%d.", i)
local hex = result[prefix .. "hex"]
local pts = tonumber(result[prefix .. "pts"])
if (hex == nil) or (pts == nil) then
break
end
local skip = false -- blame Lua for not having "continue" or "goto", not me
-- If seeking just stopped, there will be frames before the seek target,
-- ignore them by checking the timestamps.
if playback_start_pts ~= nil then
if pts >= playback_start_pts then
playback_start_pts = nil -- just for robustness
else
skip = true
end
end
if not skip then
if check_fingerprint(hex, pts) then
break
end
end
end
end
mp.observe_property(meta_property, "none", function()
-- Ignore frames that are decoded/filtered during seeking.
if seeking then
return
end
read_frames()
end)
mp.observe_property("seeking", "bool", function(name, val)
seeking = val
if seeking == false then
playback_start_pts = mp.get_property_number("playback-time")
read_frames()
end
end)
local filters = mp.get_property_native("option-info/vf/choices", {})
local found = false
for _, f in ipairs(filters) do
if f == "fingerprint" then
found = true
break
end
end
if found then
mp.command(("no-osd vf add @%s:fingerprint"):format(label, filter))
else
msg.warn("vf_fingerprint not found")
end
+1 -1
View File
@@ -22,7 +22,7 @@ OS2Version: 3
OS2_WeightWidthSlopeOnly: 0
OS2_UseTypoMetrics: 0
CreationTime: 1408646554
ModificationTime: 1492879730
ModificationTime: 1576096543
PfmFamily: 81
TTFWeight: 400
TTFWidth: 5
+15
View File
@@ -0,0 +1,15 @@
StartChar: uniE112
Encoding: 57618 57618 30
Width: 768
VWidth: 1176
Flags: HW
LayerCount: 2
Fore
SplineSet
512 40 m 1
0 40 l 1
0 168 l 1
512 168 l 1
512 40 l 1
EndSplineSet
EndChar
+20
View File
@@ -0,0 +1,20 @@
StartChar: uniE113
Encoding: 57619 57619 31
Width: 622
VWidth: 1178
Flags: HW
LayerCount: 2
Fore
SplineSet
768 42 m 5
0 42 l 5
0 746 l 5
768 746 l 5
768 42 l 5
704 106 m 5
704 618 l 5
64 618 l 5
64 106 l 5
704 106 l 5
EndSplineSet
EndChar
+31
View File
@@ -0,0 +1,31 @@
StartChar: uniE114
Encoding: 57620 57620 32
Width: 896
VWidth: 1178
Flags: HW
LayerCount: 2
Fore
SplineSet
768 298 m 1
576 298 l 1
576 42 l 1
0 42 l 1
0 490 l 1
192 490 l 1
192 746 l 1
768 746 l 1
768 298 l 1
704 362 m 1
704 618 l 1
256 618 l 1
256 490 l 1
576 490 l 1
576 362 l 1
704 362 l 1
512 106 m 1
512 362 l 1
64 362 l 1
64 106 l 1
512 106 l 1
EndSplineSet
EndChar
+27
View File
@@ -0,0 +1,27 @@
StartChar: uniE115
Encoding: 57621 57621 33
Width: 844
VWidth: 1112
Flags: HW
LayerCount: 2
Fore
SplineSet
671 40 m 1
575 40 l 1
335 277 l 1
98 40 l 1
-1 40 l 1
-1 136 l 1
236 376 l 1
-1 613 l 1
-1 712 l 1
98 712 l 1
335 475 l 1
575 712 l 1
671 712 l 1
671 613 l 1
434 376 l 1
671 139 l 1
671 40 l 1
EndSplineSet
EndChar
+2 -2
View File
@@ -7,7 +7,7 @@ import fileinput
from optparse import OptionParser
def sh(command):
return os.popen(command).read()
return os.popen(command).read().strip()
def bundle_path(binary_name):
return "%s.app" % binary_name
@@ -80,7 +80,7 @@ def main():
if options.deps:
print("> bundling dependencies")
sh(" ".join(["TOOLS/dylib-unhell.py", target_binary(binary_name)]))
print(sh(" ".join(["TOOLS/dylib-unhell.py", target_binary(binary_name)])))
print("done.")
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh
if [ "x$LIBAV" != "xffmpeg-git" ] || [ "x$TRAVIS_OS_NAME" != "xlinux" ]; then
if [ "x$TARGET" != "xx86_64-w64-mingw32" ]; then
# trigger build only on one of the matrix nodes
exit;
fi
-283
View File
@@ -1,283 +0,0 @@
#!/usr/bin/perl
# Generate ZSH completion
#
# This file is part of mpv.
#
# mpv is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# mpv is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with mpv. If not, see <http://www.gnu.org/licenses/>.
#
use strict;
use warnings;
use warnings FATAL => 'uninitialized';
my $mpv = $ARGV[0] || 'mpv';
my @opts = parse_main_opts('--list-options', '^ (\-\-[^\s\*]*)\*?\s*(.*)');
die "Couldn't find any options" unless (@opts);
my @ao = parse_opts('--ao=help', '^ ([^\s\:]*)\s*(.*)');
my @vo = parse_opts('--vo=help', '^ ([^\s\:]*)\s*(.*)');
my @af = parse_opts('--af=help', '^ ([^\s\:]*)\s*(.*)');
my @vf = parse_opts('--vf=help', '^ ([^\s\:]*)\s*(.*)');
my @protos = parse_opts('--list-protocols', '^ ([^\s]*)');
my ($opts_str, $ao_str, $vo_str, $af_str, $vf_str, $protos_str);
$opts_str .= qq{ '$_' \\\n} foreach (@opts);
chomp $opts_str;
$ao_str .= qq{ '$_' \\\n} foreach (@ao);
chomp $ao_str;
$vo_str .= qq{ '$_' \\\n} foreach (@vo);
chomp $vo_str;
$af_str .= qq{ '$_' \\\n} foreach (@af);
chomp $af_str;
$vf_str .= qq{ '$_' \\\n} foreach (@vf);
chomp $vf_str;
$protos_str = join(' ', @protos);
my $runtime_completions = <<'EOS';
profile|show-profile)
local -a profiles
local current
for current in "${(@f)$($words[1] --profile=help)}"; do
current=${current//\*/\\\*}
current=${current//\:/\\\:}
current=${current//\[/\\\[}
current=${current//\]/\\\]}
if [[ $current =~ $'\t'([^$'\t']*)$'\t'(.*) ]]; then
if [[ -n $match[2] ]]; then
current="$match[1][$match[2]]"
else
current="$match[1]"
fi
profiles=($profiles $current)
fi
done
if [[ $state == show-profile ]]; then
# For --show-profile, only one allowed
if (( ${#profiles} > 0 )); then
_values 'profile' $profiles && rc=0
fi
else
# For --profile, multiple allowed
profiles=($profiles 'help[list profiles]')
_values -s , 'profile(s)' $profiles && rc=0
fi
;;
audio-device)
local -a audio_devices
local current
for current in "${(@f)$($words[1] --audio-device=help)}"; do
current=${current//\*/\\\*}
current=${current//\:/\\\:}
current=${current//\[/\\\[}
current=${current//\]/\\\]}
if [[ $current =~ ' '\'([^\']*)\'' \('(.*)'\)' ]]; then
audio_devices=($audio_devices "$match[1][$match[2]]")
fi
done
audio_devices=($audio_devices 'help[list audio devices]')
_values 'audio device' $audio_devices && rc=0
;;
EOS
chomp $runtime_completions;
my $tmpl = <<"EOS";
#compdef mpv
# For customization, see:
# https://github.com/mpv-player/mpv/wiki/Zsh-completion-customization
local curcontext="\$curcontext" state state_descr line
typeset -A opt_args
local -a match mbegin mend
local MATCH MBEGIN MEND
# By default, don't complete URLs unless no files match
local -a tag_order
zstyle -a ":completion:*:*:\$service:*" tag-order tag_order || \
zstyle ":completion:*:*:\$service:*" tag-order '!urls'
local rc=1
_arguments -C -S \\
$opts_str
'*:files:->mfiles' && rc=0
case \$state in
ao)
_values -s , 'audio outputs' \\
$ao_str
&& rc=0
;;
vo)
_values -s , 'video outputs' \\
$vo_str
&& rc=0
;;
af)
_values -s , 'audio filters' \\
$af_str
&& rc=0
;;
vf)
_values -s , 'video filters' \\
$vf_str
&& rc=0
;;
$runtime_completions
files)
compset -P '*,'
compset -S ',*'
_files -r ',/ \\t\\n\\-' && rc=0
;;
mfiles)
local expl
_tags files urls
while _tags; do
_requested files expl 'media file' _files && rc=0
if _requested urls; then
while _next_label urls expl URL; do
_urls "\$expl[@]" && rc=0
compadd -S '' "\$expl[@]" $protos_str && rc=0
done
fi
(( rc )) || return 0
done
;;
esac
return rc
EOS
print $tmpl;
sub parse_main_opts {
my ($cmd, $regex) = @_;
my @list;
my @lines = call_mpv($cmd);
foreach my $line (@lines) {
my ($name, $desc) = ($line =~ /^$regex/) or next;
next if ($desc eq 'removed' || $desc eq 'alias');
if ($desc =~ /^Flag/) {
push @list, $name;
$name =~ /^--(.*)/;
if ($1 !~ /^(\{|\}|v|list-options|really-quiet|no-.*)$/) {
push @list, "--no-$1";
}
} elsif ($desc =~ /^Print/) {
push @list, $name;
} else {
# Option takes argument
my $entry = $name;
$desc =~ s/\:/\\:/g;
$entry .= "=-:$desc:";
if ($desc =~ /^Choices\\: ([^(]*)/) {
my $choices = $1;
$choices =~ s/ +$//; # strip trailing space
$entry .= "($choices)";
# If "no" is one of the choices, it can also be
# negated like a flag (--no-whatever).
if ($choices =~ /\bno\b/) {
$name =~ s/^--/--no-/;
push @list, $name;
}
} elsif ($line =~ /\[file\]/) {
$entry .= '->files';
} elsif ($name =~ /^--(ao|vo|af|vf|profile|show-profile|audio-device)$/) {
$entry .= "->$1";
}
push @list, $entry;
}
}
# Sort longest first, because zsh won't complete an option listed
# after one that's a prefix of it.
@list = sort {
$a =~ /([^=]*)/; my $ma = $1;
$b =~ /([^=]*)/; my $mb = $1;
length($mb) <=> length($ma)
} @list;
return @list;
}
sub parse_opts {
my ($cmd, $regex) = @_;
my @list;
my @lines = call_mpv($cmd);
foreach my $line (@lines) {
if ($line !~ /^$regex/) {
next;
}
my $entry = $1;
if (defined $2) {
my $desc = $2;
$desc =~ s/\:/\\:/g;
$entry .= "[$desc]";
}
push @list, $entry
}
return @list;
}
sub call_mpv {
my ($cmd) = @_;
my $output = `"$mpv" --no-config $cmd`;
if ($? == -1) {
die "Could not run mpv: $!";
} elsif ((my $exit_code = $? >> 8) != 0) {
die "mpv returned $exit_code with output:\n$output";
}
return split /\n/, $output;
}
+1 -1
View File
@@ -1 +1 @@
0.29.0
0.31.0
+6
View File
@@ -15,6 +15,12 @@ shallow_clone: true
test: off
install:
# Support for Ada and Objective-C was removed from MSYS2. GCC won't update if
# these packages are installed.
- >-
C:\msys64\usr\bin\pacman -R --noconfirm --noprogressbar
mingw-w64-i686-gcc-ada mingw-w64-i686-gcc-objc mingw-w64-x86_64-gcc-ada
mingw-w64-x86_64-gcc-objc
# Update core packages
- C:\msys64\usr\bin\pacman -Syyuu --noconfirm --noprogressbar --ask=20
# Update non-core packages
+63 -3
View File
@@ -410,10 +410,16 @@ void mp_aframe_skip_samples(struct mp_aframe *f, int samples)
{
assert(samples >= 0 && samples <= mp_aframe_get_size(f));
if (av_frame_make_writable(f->av_frame) < 0)
return; // go complain to ffmpeg
int num_planes = mp_aframe_get_planes(f);
size_t sstride = mp_aframe_get_sstride(f);
for (int n = 0; n < num_planes; n++)
f->av_frame->extended_data[n] += samples * sstride;
for (int n = 0; n < num_planes; n++) {
memmove(f->av_frame->extended_data[n],
f->av_frame->extended_data[n] + samples * sstride,
(f->av_frame->nb_samples - samples) * sstride);
}
f->av_frame->nb_samples -= samples;
@@ -520,6 +526,56 @@ bool mp_aframe_set_silence(struct mp_aframe *f, int offset, int samples)
return true;
}
bool mp_aframe_reverse(struct mp_aframe *f)
{
int format = mp_aframe_get_format(f);
size_t bps = af_fmt_to_bytes(format);
if (!af_fmt_is_pcm(format) || bps > 16)
return false;
uint8_t **d = mp_aframe_get_data_rw(f);
if (!d)
return false;
int planes = mp_aframe_get_planes(f);
int samples = mp_aframe_get_size(f);
int channels = mp_aframe_get_channels(f);
size_t sstride = mp_aframe_get_sstride(f);
int plane_samples = channels;
if (af_fmt_is_planar(format))
plane_samples = 1;
for (int p = 0; p < planes; p++) {
for (int n = 0; n < samples / 2; n++) {
int s1_offset = n * sstride;
int s2_offset = (samples - 1 - n) * sstride;
for (int c = 0; c < plane_samples; c++) {
// Nobody said it'd be fast.
char tmp[16];
uint8_t *s1 = d[p] + s1_offset + c * bps;
uint8_t *s2 = d[p] + s2_offset + c * bps;
memcpy(tmp, s2, bps);
memcpy(s2, s1, bps);
memcpy(s1, tmp, bps);
}
}
}
return true;
}
int mp_aframe_approx_byte_size(struct mp_aframe *frame)
{
// God damn, AVFrame is too fucking annoying. Just go with the size that
// allocating a new frame would use.
int planes = mp_aframe_get_planes(frame);
size_t sstride = mp_aframe_get_sstride(frame);
int samples = frame->av_frame->nb_samples;
int plane_size = MP_ALIGN_UP(sstride * MPMAX(samples, 1), 32);
return plane_size * planes + sizeof(*frame);
}
struct mp_aframe_pool {
AVBufferPool *avpool;
int element_size;
@@ -542,7 +598,11 @@ int mp_aframe_pool_allocate(struct mp_aframe_pool *pool, struct mp_aframe *frame
{
int planes = mp_aframe_get_planes(frame);
size_t sstride = mp_aframe_get_sstride(frame);
int plane_size = MP_ALIGN_UP(sstride * MPMAX(samples, 1), 32);
// FFmpeg hardcodes similar hidden possibly-requirements in a number of
// places: av_frame_get_buffer(), libavcodec's get_buffer(), mem.c,
// probably more.
int align_samples = MP_ALIGN_UP(MPMAX(samples, 1), 32);
int plane_size = MP_ALIGN_UP(sstride * align_samples, 64);
int size = plane_size * planes;
if (size <= 0 || mp_aframe_is_allocated(frame))
+4
View File
@@ -51,6 +51,10 @@ int mp_aframe_get_planes(struct mp_aframe *frame);
int mp_aframe_get_total_plane_samples(struct mp_aframe *frame);
size_t mp_aframe_get_sstride(struct mp_aframe *frame);
bool mp_aframe_reverse(struct mp_aframe *frame);
int mp_aframe_approx_byte_size(struct mp_aframe *frame);
char *mp_aframe_format_str_buf(char *buf, size_t buf_size, struct mp_aframe *fmt);
#define mp_aframe_format_str(fmt) mp_aframe_format_str_buf((char[32]){0}, 32, (fmt))
+3
View File
@@ -87,6 +87,9 @@ static void copy_planes(struct mp_audio_buffer *ab,
uint8_t **dst, int dst_offset,
uint8_t **src, int src_offset, int length)
{
if (!length)
return;
for (int n = 0; n < ab->num_planes; n++) {
memmove((char *)dst[n] + dst_offset * ab->sstride,
(char *)src[n] + src_offset * ab->sstride,
+22 -18
View File
@@ -37,6 +37,7 @@
#include "demux/stheader.h"
#include "filters/f_decoder_wrapper.h"
#include "filters/filter_internal.h"
#include "options/m_config.h"
#include "options/options.h"
struct priv {
@@ -47,7 +48,7 @@ struct priv {
bool preroll_done;
double next_pts;
AVRational codec_timebase;
bool eof_returned;
struct lavc_state state;
struct mp_decoder public;
};
@@ -80,8 +81,9 @@ static bool init(struct mp_filter *da, struct mp_codec_params *codec,
const char *decoder)
{
struct priv *ctx = da->priv;
struct MPOpts *mpopts = da->global->opts;
struct ad_lavc_params *opts = mpopts->ad_lavc_params;
struct MPOpts *mpopts = mp_get_config_group(ctx, da->global, &mp_opt_root);
struct ad_lavc_params *opts =
mp_get_config_group(ctx, da->global, &ad_lavc_conf);
AVCodecContext *lavc_context;
AVCodec *lavc_codec;
@@ -157,10 +159,10 @@ static void reset(struct mp_filter *da)
ctx->trim_samples = 0;
ctx->preroll_done = false;
ctx->next_pts = MP_NOPTS_VALUE;
ctx->eof_returned = false;
ctx->state = (struct lavc_state){0};
}
static bool send_packet(struct mp_filter *da, struct demux_packet *mpkt)
static int send_packet(struct mp_filter *da, struct demux_packet *mpkt)
{
struct priv *priv = da->priv;
AVCodecContext *avctx = priv->avctx;
@@ -175,16 +177,12 @@ static bool send_packet(struct mp_filter *da, struct demux_packet *mpkt)
mp_set_av_packet(&pkt, mpkt, &priv->codec_timebase);
int ret = avcodec_send_packet(avctx, mpkt ? &pkt : NULL);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return false;
if (ret < 0)
MP_ERR(da, "Error decoding audio.\n");
return true;
return ret;
}
static bool receive_frame(struct mp_filter *da, struct mp_frame *out)
static int receive_frame(struct mp_filter *da, struct mp_frame *out)
{
struct priv *priv = da->priv;
AVCodecContext *avctx = priv->avctx;
@@ -196,7 +194,7 @@ static bool receive_frame(struct mp_filter *da, struct mp_frame *out)
// over in case we get new packets at some point in the future.
// (Dont' reset the filter itself, we want to keep other state.)
avcodec_flush_buffers(priv->avctx);
return false;
return ret;
} else if (ret < 0 && ret != AVERROR(EAGAIN)) {
MP_ERR(da, "Error decoding audio.\n");
}
@@ -207,13 +205,15 @@ static bool receive_frame(struct mp_filter *da, struct mp_frame *out)
#endif
if (!priv->avframe->buf[0])
return true;
return ret;
double out_pts = mp_pts_from_av(priv->avframe->pts, &priv->codec_timebase);
struct mp_aframe *mpframe = mp_aframe_from_avframe(priv->avframe);
if (!mpframe)
return true;
if (!mpframe) {
MP_ERR(da, "Converting libavcodec frame to mpv frame failed.\n");
return ret;
}
if (priv->force_channel_map.num)
mp_aframe_set_chmap(mpframe, &priv->force_channel_map);
@@ -252,18 +252,22 @@ static bool receive_frame(struct mp_filter *da, struct mp_frame *out)
priv->trim_samples -= trim;
}
*out = MAKE_FRAME(MP_FRAME_AUDIO, mpframe);
if (mp_aframe_get_size(mpframe) > 0) {
*out = MAKE_FRAME(MP_FRAME_AUDIO, mpframe);
} else {
talloc_free(mpframe);
}
av_frame_unref(priv->avframe);
return true;
return ret;
}
static void process(struct mp_filter *ad)
{
struct priv *priv = ad->priv;
lavc_process(ad, &priv->eof_returned, send_packet, receive_frame);
lavc_process(ad, &priv->state, send_packet, receive_frame);
}
static const struct mp_filter_info ad_lavc_filter = {
+11 -3
View File
@@ -208,13 +208,21 @@ static int init_filter(struct mp_filter *da, AVPacket *pkt)
break;
case AV_CODEC_ID_DTS: {
bool is_hd = profile == FF_PROFILE_DTS_HD_HRA ||
profile == FF_PROFILE_DTS_HD_MA ||
profile == FF_PROFILE_DTS_HD_MA ||
profile == FF_PROFILE_UNKNOWN;
// Apparently, DTS-HD over SPDIF is specified to be 7.1 (8 channels)
// for DTS-HD MA, and stereo (2 channels) for DTS-HD HRA. The bit
// streaming rate as well as the signaled channel count are defined
// based on this value.
int dts_hd_spdif_channel_count = profile == FF_PROFILE_DTS_HD_HRA ?
2 : 8;
if (spdif_ctx->use_dts_hd && is_hd) {
av_dict_set(&format_opts, "dtshd_rate", "768000", 0); // 4*192000
av_dict_set_int(&format_opts, "dtshd_rate",
dts_hd_spdif_channel_count * 96000, 0);
sample_format = AF_FORMAT_S_DTSHD;
samplerate = 192000;
num_channels = 2*4;
num_channels = dts_hd_spdif_channel_count;
} else {
sample_format = AF_FORMAT_S_DTS;
samplerate = 48000;
-112
View File
@@ -1,112 +0,0 @@
/*
* Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
*
* Based on Michael Niedermayer's lavcresample.
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include <assert.h>
#include "common/common.h"
#include "config.h"
#include "common/av_common.h"
#include "common/msg.h"
#include "filters/f_swresample.h"
#include "filters/filter_internal.h"
#include "filters/user_filters.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "options/options.h"
struct af_resample {
int allow_detach;
struct mp_resample_opts opts;
int global_normalize;
};
static void set_defaults(struct mpv_global *global, void *p)
{
struct af_resample *s = p;
struct mp_resample_opts *opts = &s->opts;
struct mp_resample_opts *src_opts =
mp_get_config_group(s, global, &resample_conf);
s->global_normalize = src_opts->normalize;
assert(!opts->avopts); // we don't set a default value, so it must be NULL
*opts = *src_opts;
opts->avopts = NULL;
struct m_option dummy = {.type = &m_option_type_keyvalue_list};
m_option_copy(&dummy, &opts->avopts, &src_opts->avopts);
}
#define OPT_BASE_STRUCT struct af_resample
static struct mp_filter *af_lavrresample_create(struct mp_filter *parent,
void *options)
{
struct af_resample *s = options;
if (s->opts.normalize < 0)
s->opts.normalize = s->global_normalize;
struct mp_swresample *swr = mp_swresample_create(parent, &s->opts);
if (!swr)
abort();
MP_WARN(swr->f, "This filter is deprecated! Use the --audio-resample- options"
" to customize resampling, or the --af=aresample filter.\n");
talloc_free(s);
return swr->f;
}
const struct mp_user_filter_entry af_lavrresample = {
.desc = {
.description = "Sample frequency conversion using libavresample",
.name = "lavrresample",
.priv_size = sizeof(struct af_resample),
.priv_defaults = &(const struct af_resample) {
.opts = MP_RESAMPLE_OPTS_DEF,
.allow_detach = 1,
},
.options = (const struct m_option[]) {
OPT_INTRANGE("filter-size", opts.filter_size, 0, 0, 32),
OPT_INTRANGE("phase-shift", opts.phase_shift, 0, 0, 30),
OPT_FLAG("linear", opts.linear, 0),
OPT_DOUBLE("cutoff", opts.cutoff, M_OPT_RANGE, .min = 0, .max = 1),
OPT_FLAG("detach", allow_detach, 0), // does nothing
OPT_CHOICE("normalize", opts.normalize, 0,
({"no", 0}, {"yes", 1}, {"auto", -1})),
OPT_KEYVALUELIST("o", opts.avopts, 0),
{0}
},
.set_defaults = set_defaults,
},
.create = af_lavrresample_create,
};
+2
View File
@@ -167,6 +167,7 @@ static void process(struct mp_filter *f)
if (eof) {
mp_pin_in_write(f->ppins[1], MP_EOF_FRAME);
rubberband_reset(p->rubber);
p->rubber_delay = 0;
TA_FREEP(&p->pending);
p->sent_final = false;
return;
@@ -263,6 +264,7 @@ static void reset(struct mp_filter *f)
if (p->rubber)
rubberband_reset(p->rubber);
p->rubber_delay = 0;
p->sent_final = false;
TA_FREEP(&p->pending);
}
-47
View File
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPLAYER_EQUALIZER_H
#define MPLAYER_EQUALIZER_H
/* Equalizer plugin header file defines struct used for setting or
getting the gain of a specific channel and frequency */
typedef struct equalizer_s
{
float gain; // Gain in dB -15 - 15
int channel; // Channel number 0 - 5
int band; // Frequency band 0 - 9
}equalizer_t;
/* The different frequency bands are:
nr. center frequency
0 31.25 Hz
1 62.50 Hz
2 125.0 Hz
3 250.0 Hz
4 500.0 Hz
5 1.000 kHz
6 2.000 kHz
7 4.000 kHz
8 8.000 kHz
9 16.00 kHz
*/
#endif /* MPLAYER_EQUALIZER_H */
+2
View File
@@ -27,12 +27,14 @@ static const struct {
{AV_SAMPLE_FMT_U8, AF_FORMAT_U8},
{AV_SAMPLE_FMT_S16, AF_FORMAT_S16},
{AV_SAMPLE_FMT_S32, AF_FORMAT_S32},
{AV_SAMPLE_FMT_S64, AF_FORMAT_S64},
{AV_SAMPLE_FMT_FLT, AF_FORMAT_FLOAT},
{AV_SAMPLE_FMT_DBL, AF_FORMAT_DOUBLE},
{AV_SAMPLE_FMT_U8P, AF_FORMAT_U8P},
{AV_SAMPLE_FMT_S16P, AF_FORMAT_S16P},
{AV_SAMPLE_FMT_S32P, AF_FORMAT_S32P},
{AV_SAMPLE_FMT_S64P, AF_FORMAT_S64P},
{AV_SAMPLE_FMT_FLTP, AF_FORMAT_FLOATP},
{AV_SAMPLE_FMT_DBLP, AF_FORMAT_DOUBLEP},
+18 -24
View File
@@ -29,6 +29,7 @@ int af_fmt_to_bytes(int format)
case AF_FORMAT_U8: return 1;
case AF_FORMAT_S16: return 2;
case AF_FORMAT_S32: return 4;
case AF_FORMAT_S64: return 8;
case AF_FORMAT_FLOAT: return 4;
case AF_FORMAT_DOUBLE: return 8;
}
@@ -55,12 +56,6 @@ bool af_fmt_is_int(int format)
return format && !af_fmt_is_spdif(format) && !af_fmt_is_float(format);
}
// false for interleaved and AF_FORMAT_UNKNOWN
bool af_fmt_is_planar(int format)
{
return format && af_fmt_to_planar(format) == format;
}
bool af_fmt_is_spdif(int format)
{
return af_format_sample_alignment(format) > 1;
@@ -75,27 +70,35 @@ static const int planar_formats[][2] = {
{AF_FORMAT_U8P, AF_FORMAT_U8},
{AF_FORMAT_S16P, AF_FORMAT_S16},
{AF_FORMAT_S32P, AF_FORMAT_S32},
{AF_FORMAT_S64P, AF_FORMAT_S64},
{AF_FORMAT_FLOATP, AF_FORMAT_FLOAT},
{AF_FORMAT_DOUBLEP, AF_FORMAT_DOUBLE},
};
bool af_fmt_is_planar(int format)
{
for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
if (planar_formats[n][0] == format)
return true;
}
return false;
}
// Return the planar format corresponding to the given format.
// If the format is already planar, return it.
// Return 0 if there's no equivalent.
// If the format is already planar or if there's no equivalent,
// return it.
int af_fmt_to_planar(int format)
{
for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
if (planar_formats[n][1] == format)
return planar_formats[n][0];
if (planar_formats[n][0] == format)
return format;
}
return 0;
return format;
}
// Return the interleaved format corresponding to the given format.
// If the format is already interleaved, return it.
// Always succeeds if format is actually planar; otherwise return 0.
// If the format is already interleaved or if there's no equivalent,
// return it.
int af_fmt_from_planar(int format)
{
for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
@@ -116,11 +119,13 @@ const char *af_fmt_to_str(int format)
case AF_FORMAT_U8: return "u8";
case AF_FORMAT_S16: return "s16";
case AF_FORMAT_S32: return "s32";
case AF_FORMAT_S64: return "s64";
case AF_FORMAT_FLOAT: return "float";
case AF_FORMAT_DOUBLE: return "double";
case AF_FORMAT_U8P: return "u8p";
case AF_FORMAT_S16P: return "s16p";
case AF_FORMAT_S32P: return "s32p";
case AF_FORMAT_S64P: return "s64p";
case AF_FORMAT_FLOATP: return "floatp";
case AF_FORMAT_DOUBLEP: return "doublep";
case AF_FORMAT_S_AAC: return "spdif-aac";
@@ -134,17 +139,6 @@ const char *af_fmt_to_str(int format)
return "??";
}
int af_fmt_seconds_to_bytes(int format, float seconds, int channels, int samplerate)
{
assert(!af_fmt_is_planar(format));
int bps = af_fmt_to_bytes(format);
int framelen = channels * bps;
int bytes = seconds * bps * samplerate;
if (bytes % framelen)
bytes += framelen - (bytes % framelen);
return bytes;
}
void af_fill_silence(void *dst, size_t bytes, int format)
{
memset(dst, af_fmt_is_unsigned(format) ? 0x80 : 0, bytes);
+2 -3
View File
@@ -27,6 +27,7 @@ enum af_format {
AF_FORMAT_U8,
AF_FORMAT_S16,
AF_FORMAT_S32,
AF_FORMAT_S64,
AF_FORMAT_FLOAT,
AF_FORMAT_DOUBLE,
@@ -34,6 +35,7 @@ enum af_format {
AF_FORMAT_U8P,
AF_FORMAT_S16P,
AF_FORMAT_S32P,
AF_FORMAT_S64P,
AF_FORMAT_FLOATP,
AF_FORMAT_DOUBLEP,
@@ -64,9 +66,6 @@ bool af_fmt_is_pcm(int format);
int af_fmt_to_planar(int format);
int af_fmt_from_planar(int format);
// Amount of bytes that contain audio of the given duration, aligned to frames.
int af_fmt_seconds_to_bytes(int format, float seconds, int channels, int samplerate);
void af_fill_silence(void *dst, size_t bytes, int format);
void af_get_best_sample_formats(int src_format, int *out_formats);
+41 -4
View File
@@ -36,6 +36,7 @@
#include "common/global.h"
extern const struct ao_driver audio_out_oss;
extern const struct ao_driver audio_out_audiotrack;
extern const struct ao_driver audio_out_audiounit;
extern const struct ao_driver audio_out_coreaudio;
extern const struct ao_driver audio_out_coreaudio_exclusive;
@@ -54,6 +55,9 @@ extern const struct ao_driver audio_out_sdl;
static const struct ao_driver * const audio_out_drivers[] = {
// native:
#if HAVE_ANDROID
&audio_out_audiotrack,
#endif
#if HAVE_AUDIOUNIT
&audio_out_audiounit,
#endif
@@ -82,7 +86,7 @@ static const struct ao_driver * const audio_out_drivers[] = {
#if HAVE_OPENSLES
&audio_out_opensles,
#endif
#if HAVE_SDL2
#if HAVE_SDL2_AUDIO
&audio_out_sdl,
#endif
#if HAVE_SNDIO
@@ -120,7 +124,7 @@ static bool get_desc(struct m_obj_desc *dst, int index)
}
// For the ao option
const struct m_obj_list ao_obj_list = {
static const struct m_obj_list ao_obj_list = {
.get_desc = get_desc,
.description = "audio outputs",
.allow_unknown_entries = true,
@@ -129,13 +133,30 @@ const struct m_obj_list ao_obj_list = {
.use_global_options = true,
};
#define OPT_BASE_STRUCT struct ao_opts
const struct m_sub_options ao_conf = {
.opts = (const struct m_option[]) {
OPT_SETTINGSLIST("ao", audio_driver_list, UPDATE_AUDIO, &ao_obj_list, ),
OPT_STRING("audio-device", audio_device, UPDATE_AUDIO),
OPT_STRING("audio-client-name", audio_client_name, UPDATE_AUDIO),
OPT_DOUBLE("audio-buffer", audio_buffer,
UPDATE_AUDIO | M_OPT_MIN | M_OPT_MAX, .min = 0, .max = 10),
{0}
},
.size = sizeof(OPT_BASE_STRUCT),
.defaults = &(const OPT_BASE_STRUCT){
.audio_buffer = 0.2,
.audio_device = "auto",
.audio_client_name = "mpv",
},
};
static struct ao *ao_alloc(bool probing, struct mpv_global *global,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
char *name)
{
assert(wakeup_cb);
struct MPOpts *opts = global->opts;
struct mp_log *log = mp_log_new(NULL, global->log, "ao");
struct m_obj_desc desc;
if (!m_obj_list_find(&desc, &ao_obj_list, bstr0(name))) {
@@ -143,6 +164,7 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global,
talloc_free(log);
return NULL;
};
struct ao_opts *opts = mp_get_config_group(NULL, global, &ao_conf);
struct ao *ao = talloc_ptrtype(NULL, ao);
talloc_steal(ao, log);
*ao = (struct ao) {
@@ -155,6 +177,7 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global,
.def_buffer = opts->audio_buffer,
.client_name = talloc_strdup(ao, opts->audio_client_name),
};
talloc_free(opts);
ao->priv = m_config_group_from_desc(ao, ao->log, global, &desc, name);
if (!ao->priv)
goto error;
@@ -267,8 +290,8 @@ struct ao *ao_init_best(struct mpv_global *global,
struct encode_lavc_context *encode_lavc_ctx,
int samplerate, int format, struct mp_chmap channels)
{
struct MPOpts *opts = global->opts;
void *tmp = talloc_new(NULL);
struct ao_opts *opts = mp_get_config_group(tmp, global, &ao_conf);
struct mp_log *log = mp_log_new(tmp, global->log, "ao");
struct ao *ao = NULL;
struct m_obj_settings *ao_list = NULL;
@@ -383,6 +406,7 @@ void ao_reset(struct ao *ao)
{
if (ao->api->reset)
ao->api->reset(ao);
atomic_fetch_and(&ao->events_, ~(unsigned int)AO_EVENT_UNDERRUN);
}
// Pause playback. Keep the current buffer. ao_get_delay() must return the
@@ -438,6 +462,14 @@ void ao_hotplug_event(struct ao *ao)
ao_add_events(ao, AO_EVENT_HOTPLUG);
}
void ao_underrun_event(struct ao *ao)
{
// Racy check, but it's just for the message.
if (!(atomic_load(&ao->events_) & AO_EVENT_UNDERRUN))
MP_WARN(ao, "Device underrun detected.\n");
ao_add_events(ao, AO_EVENT_UNDERRUN);
}
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map)
{
@@ -498,6 +530,11 @@ const char *ao_get_description(struct ao *ao)
return ao->driver->description;
}
bool ao_get_reports_underruns(struct ao *ao)
{
return ao->driver->reports_underruns;
}
bool ao_untimed(struct ao *ao)
{
return ao->untimed;
+9 -4
View File
@@ -35,10 +35,6 @@ enum aocontrol {
AOCONTROL_SET_MUTE,
// Has char* as argument, which contains the desired stream title.
AOCONTROL_UPDATE_STREAM_TITLE,
// the AO does the equivalent of af_volume (return CONTROL_TRUE if yes)
AOCONTROL_HAS_SOFT_VOLUME,
// like above, but volume persists (per app), mpv won't restore volume
AOCONTROL_HAS_PER_APP_VOLUME,
};
// If set, then the queued audio data is the last. Note that after a while, new
@@ -49,6 +45,7 @@ enum {
AO_EVENT_RELOAD = 1,
AO_EVENT_HOTPLUG = 2,
AO_EVENT_INITIAL_UNBLOCK = 4,
AO_EVENT_UNDERRUN = 8,
};
enum {
@@ -83,6 +80,13 @@ struct mpv_global;
struct input_ctx;
struct encode_lavc_context;
struct ao_opts {
struct m_obj_settings *audio_driver_list;
char *audio_device;
char *audio_client_name;
double audio_buffer;
};
struct ao *ao_init_best(struct mpv_global *global,
int init_flags,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
@@ -93,6 +97,7 @@ void ao_get_format(struct ao *ao,
int *samplerate, int *format, struct mp_chmap *channels);
const char *ao_get_name(struct ao *ao);
const char *ao_get_description(struct ao *ao);
bool ao_get_reports_underruns(struct ao *ao);
bool ao_untimed(struct ao *ao);
int ao_play(struct ao *ao, void **data, int samples, int flags);
int ao_control(struct ao *ao, enum aocontrol cmd, void *arg);
+42 -15
View File
@@ -94,6 +94,7 @@ struct priv {
snd_pcm_format_t alsa_fmt;
bool can_pause;
bool paused;
bool final_chunk_written;
snd_pcm_sframes_t prepause_frames;
double delay_before_pause;
snd_pcm_uframes_t buffersize;
@@ -135,6 +136,19 @@ static bool check_device_present(struct ao *ao, int alsa_err)
return false;
}
static void handle_underrun(struct ao *ao)
{
struct priv *p = ao->priv;
if (!p->final_chunk_written) {
ao_underrun_event(ao);
int err = snd_pcm_prepare(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
alsa_error: ;
}
}
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
struct priv *p = ao->priv;
@@ -940,20 +954,27 @@ static int get_space(struct ao *ao)
{
struct priv *p = ao->priv;
// in case of pausing or the device still being configured,
// just return our buffer size.
if (p->paused || snd_pcm_state(p->alsa) == SND_PCM_STATE_SETUP)
return p->buffersize;
snd_pcm_sframes_t space = snd_pcm_avail(p->alsa);
if (space < 0) {
MP_ERR(ao, "Error received from snd_pcm_avail (%ld, %s)!\n",
space, snd_strerror(space));
if (space == -EPIPE) // EOF
return p->buffersize;
if (space < 0 && space != -EPIPE) {
MP_ERR(ao, "Error received from snd_pcm_avail "
"(%ld, %s with ALSA state %s)!\n",
space, snd_strerror(space),
snd_pcm_state_name(snd_pcm_state(p->alsa)));
// request a reload of the AO if device is not present,
// then error out.
check_device_present(ao, space);
goto alsa_error;
}
if (space == -EPIPE)
handle_underrun(ao);
if (space > p->buffersize) // Buffer underrun?
if (space > p->buffersize || space < 0) // Buffer underrun?
space = p->buffersize;
return space / p->outburst * p->outburst;
@@ -970,8 +991,12 @@ static double get_delay(struct ao *ao)
if (p->paused)
return p->delay_before_pause;
if (snd_pcm_delay(p->alsa, &delay) < 0)
int err = snd_pcm_delay(p->alsa, &delay);
if (err < 0) {
if (err == -EPIPE)
handle_underrun(ao);
return 0;
}
if (delay < 0) {
/* underrun - move the application pointer forward to catch up */
@@ -1077,6 +1102,7 @@ static void reset(struct ao *ao)
p->paused = false;
p->prepause_frames = 0;
p->delay_before_pause = 0;
p->final_chunk_written = false;
if (ao->stream_silence) {
soft_reset(ao);
@@ -1094,11 +1120,13 @@ static int play(struct ao *ao, void **data, int samples, int flags)
{
struct priv *p = ao->priv;
snd_pcm_sframes_t res = 0;
if (!(flags & AOPLAY_FINAL_CHUNK))
bool final_chunk = flags & AOPLAY_FINAL_CHUNK;
if (!final_chunk)
samples = samples / p->outburst * p->outburst;
if (samples == 0)
return 0;
goto done;
ao_convert_inplace(&p->convert, data, samples);
do {
@@ -1116,15 +1144,11 @@ static int play(struct ao *ao, void **data, int samples, int flags)
if (res == -ESTRPIPE) { /* suspend */
resume_device(ao);
} else if (res == -EPIPE) {
// For some reason, writing a smaller fragment at the end
// immediately underruns.
if (!(flags & AOPLAY_FINAL_CHUNK))
MP_WARN(ao, "Device underrun detected.\n");
handle_underrun(ao);
} else {
MP_ERR(ao, "Write error: %s\n", snd_strerror(res));
}
res = snd_pcm_prepare(p->alsa);
int err = res;
int err = snd_pcm_prepare(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
res = 0;
}
@@ -1132,6 +1156,8 @@ static int play(struct ao *ao, void **data, int samples, int flags)
p->paused = false;
done:
p->final_chunk_written = res == samples && final_chunk;
return res < 0 ? -1 : res;
alsa_error:
@@ -1238,6 +1264,7 @@ const struct ao_driver audio_out_alsa = {
.wait = audio_wait,
.wakeup = ao_wakeup_poll,
.list_devs = list_devs,
.reports_underruns = true,
.priv_size = sizeof(struct priv),
.global_opts = &ao_alsa_conf,
};
+717
View File
@@ -0,0 +1,717 @@
/*
* Android AudioTrack audio output driver.
* Copyright (C) 2018 Aman Gupta <aman@tmm1.net>
* Copyright (C) 2012-2015 VLC authors and VideoLAN, VideoLabs
* Authors: Thomas Guillem <thomas@gllm.fr>
* Ming Hu <tewilove@gmail.com>
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ao.h"
#include "internal.h"
#include "common/msg.h"
#include "audio/format.h"
#include "options/m_option.h"
#include "osdep/threads.h"
#include "osdep/timer.h"
#include "misc/jni.h"
struct priv {
jobject audiotrack;
jint samplerate;
jint channel_config;
jint format;
jint size;
jobject timestamp;
int64_t timestamp_fetched;
bool timestamp_set;
int timestamp_stable;
uint32_t written_frames; /* requires uint32_t rollover semantics */
uint32_t playhead_pos;
uint32_t playhead_offset;
bool reset_pending;
void *chunk;
int chunksize;
jbyteArray bytearray;
jshortArray shortarray;
jfloatArray floatarray;
jobject bbuf;
int cfg_pcm_float;
int cfg_session_id;
bool needs_timestamp_offset;
int64_t timestamp_offset;
bool thread_terminate;
bool thread_created;
pthread_t thread;
pthread_mutex_t lock;
pthread_cond_t wakeup;
};
struct JNIByteBuffer {
jclass clazz;
jmethodID clear;
struct MPJniField mapping[];
} ByteBuffer = {.mapping = {
#define OFFSET(member) offsetof(struct JNIByteBuffer, member)
{"java/nio/ByteBuffer", NULL, NULL, MP_JNI_CLASS, OFFSET(clazz), 1},
{"java/nio/ByteBuffer", "clear", "()Ljava/nio/Buffer;", MP_JNI_METHOD, OFFSET(clear), 1},
{0},
#undef OFFSET
}};
struct JNIAudioTrack {
jclass clazz;
jmethodID ctor;
jmethodID release;
jmethodID getState;
jmethodID getPlayState;
jmethodID play;
jmethodID stop;
jmethodID flush;
jmethodID pause;
jmethodID write;
jmethodID writeFloat;
jmethodID writeV23;
jmethodID writeShortV23;
jmethodID writeBufferV21;
jmethodID getPlaybackHeadPosition;
jmethodID getTimestamp;
jmethodID getLatency;
jmethodID getMinBufferSize;
jmethodID getNativeOutputSampleRate;
jint STATE_INITIALIZED;
jint PLAYSTATE_STOPPED;
jint PLAYSTATE_PAUSED;
jint PLAYSTATE_PLAYING;
jint MODE_STREAM;
jint ERROR;
jint ERROR_BAD_VALUE;
jint ERROR_INVALID_OPERATION;
jint WRITE_BLOCKING;
jint WRITE_NON_BLOCKING;
struct MPJniField mapping[];
} AudioTrack = {.mapping = {
#define OFFSET(member) offsetof(struct JNIAudioTrack, member)
{"android/media/AudioTrack", NULL, NULL, MP_JNI_CLASS, OFFSET(clazz), 1},
{"android/media/AudioTrack", "<init>", "(IIIIIII)V", MP_JNI_METHOD, OFFSET(ctor), 1},
{"android/media/AudioTrack", "release", "()V", MP_JNI_METHOD, OFFSET(release), 1},
{"android/media/AudioTrack", "getState", "()I", MP_JNI_METHOD, OFFSET(getState), 1},
{"android/media/AudioTrack", "getPlayState", "()I", MP_JNI_METHOD, OFFSET(getPlayState), 1},
{"android/media/AudioTrack", "play", "()V", MP_JNI_METHOD, OFFSET(play), 1},
{"android/media/AudioTrack", "stop", "()V", MP_JNI_METHOD, OFFSET(stop), 1},
{"android/media/AudioTrack", "flush", "()V", MP_JNI_METHOD, OFFSET(flush), 1},
{"android/media/AudioTrack", "pause", "()V", MP_JNI_METHOD, OFFSET(pause), 1},
{"android/media/AudioTrack", "write", "([BII)I", MP_JNI_METHOD, OFFSET(write), 1},
{"android/media/AudioTrack", "write", "([FIII)I", MP_JNI_METHOD, OFFSET(writeFloat), 1},
{"android/media/AudioTrack", "write", "([BIII)I", MP_JNI_METHOD, OFFSET(writeV23), 0},
{"android/media/AudioTrack", "write", "([SIII)I", MP_JNI_METHOD, OFFSET(writeShortV23), 0},
{"android/media/AudioTrack", "write", "(Ljava/nio/ByteBuffer;II)I", MP_JNI_METHOD, OFFSET(writeBufferV21), 1},
{"android/media/AudioTrack", "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", MP_JNI_METHOD, OFFSET(getTimestamp), 1},
{"android/media/AudioTrack", "getPlaybackHeadPosition", "()I", MP_JNI_METHOD, OFFSET(getPlaybackHeadPosition), 1},
{"android/media/AudioTrack", "getLatency", "()I", MP_JNI_METHOD, OFFSET(getLatency), 1},
{"android/media/AudioTrack", "getMinBufferSize", "(III)I", MP_JNI_STATIC_METHOD, OFFSET(getMinBufferSize), 1},
{"android/media/AudioTrack", "getNativeOutputSampleRate", "(I)I", MP_JNI_STATIC_METHOD, OFFSET(getNativeOutputSampleRate), 1},
{"android/media/AudioTrack", "WRITE_BLOCKING", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(WRITE_BLOCKING), 0},
{"android/media/AudioTrack", "WRITE_NON_BLOCKING", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(WRITE_NON_BLOCKING), 0},
{"android/media/AudioTrack", "STATE_INITIALIZED", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(STATE_INITIALIZED), 1},
{"android/media/AudioTrack", "PLAYSTATE_STOPPED", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(PLAYSTATE_STOPPED), 1},
{"android/media/AudioTrack", "PLAYSTATE_PAUSED", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(PLAYSTATE_PAUSED), 1},
{"android/media/AudioTrack", "PLAYSTATE_PLAYING", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(PLAYSTATE_PLAYING), 1},
{"android/media/AudioTrack", "MODE_STREAM", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(MODE_STREAM), 1},
{"android/media/AudioTrack", "ERROR", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ERROR), 1},
{"android/media/AudioTrack", "ERROR_BAD_VALUE", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ERROR_BAD_VALUE), 1},
{"android/media/AudioTrack", "ERROR_INVALID_OPERATION", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ERROR_INVALID_OPERATION), 1},
{0}
#undef OFFSET
}};
struct JNIAudioFormat {
jclass clazz;
jint ENCODING_PCM_8BIT;
jint ENCODING_PCM_16BIT;
jint ENCODING_PCM_FLOAT;
jint ENCODING_IEC61937;
jint ENCODING_AC3;
jint CHANNEL_OUT_MONO;
jint CHANNEL_OUT_STEREO;
jint CHANNEL_OUT_FRONT_LEFT;
jint CHANNEL_OUT_FRONT_RIGHT;
jint CHANNEL_OUT_BACK_LEFT;
jint CHANNEL_OUT_BACK_RIGHT;
jint CHANNEL_OUT_FRONT_CENTER;
jint CHANNEL_OUT_LOW_FREQUENCY;
jint CHANNEL_OUT_BACK_CENTER;
jint CHANNEL_OUT_5POINT1;
jint CHANNEL_OUT_SIDE_LEFT;
jint CHANNEL_OUT_SIDE_RIGHT;
struct MPJniField mapping[];
} AudioFormat = {.mapping = {
#define OFFSET(member) offsetof(struct JNIAudioFormat, member)
{"android/media/AudioFormat", NULL, NULL, MP_JNI_CLASS, OFFSET(clazz), 1},
{"android/media/AudioFormat", "ENCODING_PCM_8BIT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ENCODING_PCM_8BIT), 1},
{"android/media/AudioFormat", "ENCODING_PCM_16BIT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ENCODING_PCM_16BIT), 1},
{"android/media/AudioFormat", "ENCODING_PCM_FLOAT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ENCODING_PCM_FLOAT), 1},
{"android/media/AudioFormat", "ENCODING_AC3", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ENCODING_AC3), 0},
{"android/media/AudioFormat", "ENCODING_IEC61937", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ENCODING_IEC61937), 0},
{"android/media/AudioFormat", "CHANNEL_OUT_MONO", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_MONO), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_STEREO", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_STEREO), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_5POINT1", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_5POINT1), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_FRONT_LEFT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_FRONT_LEFT), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_FRONT_RIGHT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_FRONT_RIGHT), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_FRONT_CENTER", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_FRONT_CENTER), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_LOW_FREQUENCY", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_LOW_FREQUENCY), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_BACK_LEFT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_BACK_LEFT), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_BACK_RIGHT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_BACK_RIGHT), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_BACK_CENTER", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_BACK_CENTER), 1},
{"android/media/AudioFormat", "CHANNEL_OUT_SIDE_LEFT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_SIDE_LEFT), 0},
{"android/media/AudioFormat", "CHANNEL_OUT_SIDE_RIGHT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(CHANNEL_OUT_SIDE_RIGHT), 0},
{0}
#undef OFFSET
}};
struct JNIAudioManager {
jclass clazz;
jint ERROR_DEAD_OBJECT;
jint STREAM_MUSIC;
struct MPJniField mapping[];
} AudioManager = {.mapping = {
#define OFFSET(member) offsetof(struct JNIAudioManager, member)
{"android/media/AudioManager", NULL, NULL, MP_JNI_CLASS, OFFSET(clazz), 1},
{"android/media/AudioManager", "STREAM_MUSIC", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(STREAM_MUSIC), 1},
{"android/media/AudioManager", "ERROR_DEAD_OBJECT", "I", MP_JNI_STATIC_FIELD_AS_INT, OFFSET(ERROR_DEAD_OBJECT), 0},
{0}
#undef OFFSET
}};
struct JNIAudioTimestamp {
jclass clazz;
jmethodID ctor;
jfieldID framePosition;
jfieldID nanoTime;
struct MPJniField mapping[];
} AudioTimestamp = {.mapping = {
#define OFFSET(member) offsetof(struct JNIAudioTimestamp, member)
{"android/media/AudioTimestamp", NULL, NULL, MP_JNI_CLASS, OFFSET(clazz), 1},
{"android/media/AudioTimestamp", "<init>", "()V", MP_JNI_METHOD, OFFSET(ctor), 1},
{"android/media/AudioTimestamp", "framePosition", "J", MP_JNI_FIELD, OFFSET(framePosition), 1},
{"android/media/AudioTimestamp", "nanoTime", "J", MP_JNI_FIELD, OFFSET(nanoTime), 1},
{0}
#undef OFFSET
}};
static int AudioTrack_New(struct ao *ao)
{
struct priv *p = ao->priv;
JNIEnv *env = MP_JNI_GET_ENV(ao);
jobject audiotrack = MP_JNI_NEW(
AudioTrack.clazz,
AudioTrack.ctor,
AudioManager.STREAM_MUSIC,
p->samplerate,
p->channel_config,
p->format,
p->size,
AudioTrack.MODE_STREAM,
p->cfg_session_id
);
if (!audiotrack || MP_JNI_EXCEPTION_LOG(ao) < 0) {
MP_FATAL(ao, "AudioTrack Init failed\n");
return -1;
}
if (MP_JNI_CALL_INT(audiotrack, AudioTrack.getState) != AudioTrack.STATE_INITIALIZED) {
MP_JNI_CALL_VOID(audiotrack, AudioTrack.release);
MP_JNI_EXCEPTION_LOG(ao);
(*env)->DeleteLocalRef(env, audiotrack);
MP_ERR(ao, "AudioTrack.getState failed\n");
return -1;
}
p->audiotrack = (*env)->NewGlobalRef(env, audiotrack);
(*env)->DeleteLocalRef(env, audiotrack);
if (!p->audiotrack)
return -1;
return 0;
}
static int AudioTrack_Recreate(struct ao *ao)
{
struct priv *p = ao->priv;
JNIEnv *env = MP_JNI_GET_ENV(ao);
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.release);
MP_JNI_EXCEPTION_LOG(ao);
(*env)->DeleteGlobalRef(env, p->audiotrack);
p->audiotrack = NULL;
return AudioTrack_New(ao);
}
static uint32_t AudioTrack_getPlaybackHeadPosition(struct ao *ao)
{
struct priv *p = ao->priv;
if (!p->audiotrack)
return 0;
JNIEnv *env = MP_JNI_GET_ENV(ao);
uint32_t pos = 0;
int64_t now = mp_raw_time_us();
int state = MP_JNI_CALL_INT(p->audiotrack, AudioTrack.getPlayState);
int stable_count = 20;
int64_t wait = p->timestamp_stable < stable_count ? 50000 : 3000000;
if (state == AudioTrack.PLAYSTATE_PLAYING && p->format != AudioFormat.ENCODING_IEC61937 &&
(p->timestamp_fetched == 0 || now - p->timestamp_fetched >= wait)) {
if (!p->timestamp_fetched)
p->timestamp_stable = 0;
int64_t utime1 = MP_JNI_GET_LONG(p->timestamp, AudioTimestamp.nanoTime) / 1000;
if (MP_JNI_CALL_BOOL(p->audiotrack, AudioTrack.getTimestamp, p->timestamp)) {
p->timestamp_set = true;
p->timestamp_fetched = now;
if (p->timestamp_stable < stable_count) {
uint32_t fpos = 0xFFFFFFFFL & MP_JNI_GET_LONG(p->timestamp, AudioTimestamp.framePosition);
int64_t utime2 = MP_JNI_GET_LONG(p->timestamp, AudioTimestamp.nanoTime) / 1000;
//MP_VERBOSE(ao, "getTimestamp: fpos= %u / time= %"PRId64" / now= %"PRId64" / stable= %d\n", fpos, utime2, now, p->timestamp_stable);
if (utime1 != utime2 && utime2 != 0 && fpos != 0) {
p->timestamp_stable++;
}
}
}
}
/* AudioTrack's framePosition and playbackHeadPosition return a signed integer,
* but documentation states it should be interpreted as a 32-bit unsigned integer.
*/
if (p->timestamp_set) {
pos = 0xFFFFFFFFL & MP_JNI_GET_LONG(p->timestamp, AudioTimestamp.framePosition);
uint32_t fpos = pos;
int64_t utime = MP_JNI_GET_LONG(p->timestamp, AudioTimestamp.nanoTime) / 1000;
if (utime == 0)
fpos = pos = 0;
if (p->needs_timestamp_offset) {
if (utime != 0 && !p->timestamp_offset)
p->timestamp_offset = now - utime;
utime += p->timestamp_offset;
}
if (fpos != 0 && utime != 0 && state == AudioTrack.PLAYSTATE_PLAYING) {
double diff = (double)(now - utime) / 1e6;
pos += diff * ao->samplerate;
}
//MP_VERBOSE(ao, "position = %u via getTimestamp (state = %d / fpos= %u / time= %"PRId64")\n", pos, state, fpos, utime);
} else {
pos = 0xFFFFFFFFL & MP_JNI_CALL_INT(p->audiotrack, AudioTrack.getPlaybackHeadPosition);
//MP_VERBOSE(ao, "playbackHeadPosition = %u (reset_pending=%d)\n", pos, p->reset_pending);
}
if (p->format == AudioFormat.ENCODING_IEC61937) {
if (p->reset_pending) {
// after a flush(), playbackHeadPosition will not reset to 0 right away.
// sometimes, it will never reset at all.
// save the initial offset after the reset, to subtract it going forward.
if (p->playhead_offset == 0)
p->playhead_offset = pos;
p->reset_pending = false;
MP_VERBOSE(ao, "IEC/playbackHead offset = %d\n", pos);
}
// usually shortly after a flush(), playbackHeadPosition will reset to 0.
// clear out the position and offset to avoid regular "rollover" below
if (pos == 0 && p->playhead_offset != 0) {
MP_VERBOSE(ao, "IEC/playbackHeadPosition %d -> %d (flush)\n", p->playhead_pos, pos);
p->playhead_offset = 0;
p->playhead_pos = 0;
}
// sometimes on a new AudioTrack instance, playbackHeadPosition will reset
// to 0 shortly after playback starts for no reason.
if (pos == 0 && p->playhead_pos != 0) {
MP_VERBOSE(ao, "IEC/playbackHeadPosition %d -> %d (reset)\n", p->playhead_pos, pos);
p->playhead_offset = 0;
p->playhead_pos = 0;
p->written_frames = 0;
}
}
p->playhead_pos = pos;
return p->playhead_pos - p->playhead_offset;
}
static double AudioTrack_getLatency(struct ao *ao)
{
JNIEnv *env = MP_JNI_GET_ENV(ao);
struct priv *p = ao->priv;
if (!p->audiotrack)
return 0;
uint32_t playhead = AudioTrack_getPlaybackHeadPosition(ao);
uint32_t diff = p->written_frames - playhead;
double delay = diff / (double)(ao->samplerate);
if (!p->timestamp_set &&
p->format != AudioFormat.ENCODING_IEC61937)
delay += (double)MP_JNI_CALL_INT(p->audiotrack, AudioTrack.getLatency)/1000.0;
if (delay > 1.0) {
//MP_WARN(ao, "getLatency: written=%u playhead=%u diff=%u delay=%f\n", p->written_frames, playhead, diff, delay);
p->timestamp_fetched = 0;
return 0;
}
return MPCLAMP(delay, 0.0, 1.0);
}
static int AudioTrack_write(struct ao *ao, int len)
{
struct priv *p = ao->priv;
if (!p->audiotrack)
return -1;
JNIEnv *env = MP_JNI_GET_ENV(ao);
void *buf = p->chunk;
jint ret;
if (p->format == AudioFormat.ENCODING_IEC61937) {
(*env)->SetShortArrayRegion(env, p->shortarray, 0, len / 2, buf);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
ret = MP_JNI_CALL_INT(p->audiotrack, AudioTrack.writeShortV23, p->shortarray, 0, len / 2, AudioTrack.WRITE_BLOCKING);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
if (ret > 0) ret *= 2;
} else if (p->format == AudioFormat.ENCODING_PCM_FLOAT) {
(*env)->SetFloatArrayRegion(env, p->floatarray, 0, len / sizeof(float), buf);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
ret = MP_JNI_CALL_INT(p->audiotrack, AudioTrack.writeFloat, p->floatarray, 0, len / sizeof(float), AudioTrack.WRITE_BLOCKING);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
if (ret > 0) ret *= sizeof(float);
} else if (AudioTrack.writeBufferV21) {
jobject bbuf = MP_JNI_CALL_OBJECT(p->bbuf, ByteBuffer.clear);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
(*env)->DeleteLocalRef(env, bbuf);
ret = MP_JNI_CALL_INT(p->audiotrack, AudioTrack.writeBufferV21, p->bbuf, len, AudioTrack.WRITE_BLOCKING);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
} else {
(*env)->SetByteArrayRegion(env, p->bytearray, 0, len, buf);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
ret = MP_JNI_CALL_INT(p->audiotrack, AudioTrack.write, p->bytearray, 0, len);
if (MP_JNI_EXCEPTION_LOG(ao) < 0) return -1;
}
return ret;
}
static void uninit_jni(struct ao *ao)
{
JNIEnv *env = MP_JNI_GET_ENV(ao);
mp_jni_reset_jfields(env, &AudioTrack, AudioTrack.mapping, 1, ao->log);
mp_jni_reset_jfields(env, &AudioTimestamp, AudioTimestamp.mapping, 1, ao->log);
mp_jni_reset_jfields(env, &AudioManager, AudioManager.mapping, 1, ao->log);
mp_jni_reset_jfields(env, &AudioFormat, AudioFormat.mapping, 1, ao->log);
mp_jni_reset_jfields(env, &ByteBuffer, ByteBuffer.mapping, 1, ao->log);
}
static int init_jni(struct ao *ao)
{
JNIEnv *env = MP_JNI_GET_ENV(ao);
if (mp_jni_init_jfields(env, &AudioTrack, AudioTrack.mapping, 1, ao->log) < 0 ||
mp_jni_init_jfields(env, &ByteBuffer, ByteBuffer.mapping, 1, ao->log) < 0 ||
mp_jni_init_jfields(env, &AudioTimestamp, AudioTimestamp.mapping, 1, ao->log) < 0 ||
mp_jni_init_jfields(env, &AudioManager, AudioManager.mapping, 1, ao->log) < 0 ||
mp_jni_init_jfields(env, &AudioFormat, AudioFormat.mapping, 1, ao->log) < 0) {
uninit_jni(ao);
return -1;
}
return 0;
}
static void *playthread(void *arg)
{
struct ao *ao = arg;
struct priv *p = ao->priv;
JNIEnv *env = MP_JNI_GET_ENV(ao);
mpthread_set_name("audiotrack");
pthread_mutex_lock(&p->lock);
while (!p->thread_terminate) {
int state = AudioTrack.PLAYSTATE_PAUSED;
if (p->audiotrack) {
state = MP_JNI_CALL_INT(p->audiotrack, AudioTrack.getPlayState);
}
if (state == AudioTrack.PLAYSTATE_PLAYING) {
int read_samples = p->chunksize / ao->sstride;
int64_t ts = mp_time_us();
ts += (read_samples / (double)(ao->samplerate)) * 1e6;
ts += AudioTrack_getLatency(ao) * 1e6;
int samples = ao_read_data(ao, &p->chunk, read_samples, ts);
int write_samples = read_samples;
int ret = AudioTrack_write(ao, write_samples * ao->sstride);
if (ret >= 0) {
p->written_frames += ret / ao->sstride;
} else if (ret == AudioManager.ERROR_DEAD_OBJECT) {
MP_WARN(ao, "AudioTrack.write failed with ERROR_DEAD_OBJECT. Recreating AudioTrack...\n");
if (AudioTrack_Recreate(ao) < 0) {
MP_ERR(ao, "AudioTrack_Recreate failed\n");
}
} else {
MP_ERR(ao, "AudioTrack.write failed with %d\n", ret);
}
} else {
struct timespec wait = mp_rel_time_to_timespec(0.300);
pthread_cond_timedwait(&p->wakeup, &p->lock, &wait);
}
}
pthread_mutex_unlock(&p->lock);
return NULL;
}
static void uninit(struct ao *ao)
{
struct priv *p = ao->priv;
JNIEnv *env = MP_JNI_GET_ENV(ao);
if (p->audiotrack) {
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.stop);
MP_JNI_EXCEPTION_LOG(ao);
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.flush);
MP_JNI_EXCEPTION_LOG(ao);
}
pthread_mutex_lock(&p->lock);
p->thread_terminate = true;
pthread_cond_signal(&p->wakeup);
pthread_mutex_unlock(&p->lock);
if (p->thread_created)
pthread_join(p->thread, NULL);
if (p->audiotrack) {
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.release);
MP_JNI_EXCEPTION_LOG(ao);
(*env)->DeleteGlobalRef(env, p->audiotrack);
p->audiotrack = NULL;
}
if (p->bytearray) {
(*env)->DeleteGlobalRef(env, p->bytearray);
p->bytearray = NULL;
}
if (p->shortarray) {
(*env)->DeleteGlobalRef(env, p->shortarray);
p->shortarray = NULL;
}
if (p->floatarray) {
(*env)->DeleteGlobalRef(env, p->floatarray);
p->floatarray = NULL;
}
if (p->bbuf) {
(*env)->DeleteGlobalRef(env, p->bbuf);
p->bbuf = NULL;
}
if (p->timestamp) {
(*env)->DeleteGlobalRef(env, p->timestamp);
p->timestamp = NULL;
}
if (p->chunk) {
free(p->chunk);
p->chunk = NULL;
}
pthread_cond_destroy(&p->wakeup);
pthread_mutex_destroy(&p->lock);
uninit_jni(ao);
}
static int init(struct ao *ao)
{
struct priv *p = ao->priv;
JNIEnv *env = MP_JNI_GET_ENV(ao);
if (!env)
return -1;
pthread_mutex_init(&p->lock, NULL);
pthread_cond_init(&p->wakeup, NULL);
if (init_jni(ao) < 0)
return -1;
if (af_fmt_is_spdif(ao->format)) {
p->format = AudioFormat.ENCODING_IEC61937;
} else if (ao->format == AF_FORMAT_U8) {
p->format = AudioFormat.ENCODING_PCM_8BIT;
} else if (p->cfg_pcm_float && (ao->format == AF_FORMAT_FLOAT || ao->format == AF_FORMAT_FLOATP)) {
ao->format = AF_FORMAT_FLOAT;
p->format = AudioFormat.ENCODING_PCM_FLOAT;
} else {
ao->format = AF_FORMAT_S16;
p->format = AudioFormat.ENCODING_PCM_16BIT;
}
if (AudioTrack.getNativeOutputSampleRate) {
jint samplerate = MP_JNI_CALL_STATIC_INT(
AudioTrack.clazz,
AudioTrack.getNativeOutputSampleRate,
AudioManager.STREAM_MUSIC
);
if (MP_JNI_EXCEPTION_LOG(ao) == 0) {
ao->samplerate = samplerate;
MP_VERBOSE(ao, "AudioTrack.nativeOutputSampleRate = %d\n", samplerate);
}
}
p->samplerate = ao->samplerate;
if (p->format == AudioFormat.ENCODING_IEC61937) {
p->channel_config = AudioFormat.CHANNEL_OUT_STEREO;
} else if (ao->channels.num == 1) {
p->channel_config = AudioFormat.CHANNEL_OUT_MONO;
} else if (ao->channels.num == 6) {
p->channel_config = AudioFormat.CHANNEL_OUT_5POINT1;
ao->channels = (struct mp_chmap)MP_CHMAP6(FL, FR, FC, LFE, BL, BR);
} else {
p->channel_config = AudioFormat.CHANNEL_OUT_STEREO;
ao->channels = (struct mp_chmap)MP_CHMAP_INIT_STEREO;
}
jint buffer_size = MP_JNI_CALL_STATIC_INT(
AudioTrack.clazz,
AudioTrack.getMinBufferSize,
p->samplerate,
p->channel_config,
p->format
);
if (buffer_size <= 0 || MP_JNI_EXCEPTION_LOG(ao) < 0) {
MP_FATAL(ao, "AudioTrack.getMinBufferSize returned an invalid size: %d", buffer_size);
return -1;
}
p->chunksize = buffer_size;
p->chunk = malloc(buffer_size);
int min = 0.200 * p->samplerate * af_fmt_to_bytes(ao->format);
int max = min * 3 / 2;
p->size = MPCLAMP(buffer_size * 2, min, max);
MP_VERBOSE(ao, "Setting bufferSize = %d (driver=%d, min=%d, max=%d)\n", p->size, buffer_size, min, max);
ao->device_buffer = p->size / af_fmt_to_bytes(ao->format);
jobject timestamp = MP_JNI_NEW(AudioTimestamp.clazz, AudioTimestamp.ctor);
if (!timestamp || MP_JNI_EXCEPTION_LOG(ao) < 0) {
MP_FATAL(ao, "AudioTimestamp could not be created\n");
return -1;
}
p->timestamp = (*env)->NewGlobalRef(env, timestamp);
(*env)->DeleteLocalRef(env, timestamp);
if (p->format == AudioFormat.ENCODING_IEC61937) {
jshortArray shortarray = (*env)->NewShortArray(env, p->chunksize / 2);
p->shortarray = (*env)->NewGlobalRef(env, shortarray);
(*env)->DeleteLocalRef(env, shortarray);
} else if (p->format == AudioFormat.ENCODING_PCM_FLOAT) {
jfloatArray floatarray = (*env)->NewFloatArray(env, p->chunksize / sizeof(float));
p->floatarray = (*env)->NewGlobalRef(env, floatarray);
(*env)->DeleteLocalRef(env, floatarray);
} else if (AudioTrack.writeBufferV21) {
jobject bbuf = (*env)->NewDirectByteBuffer(env, p->chunk, p->chunksize);
p->bbuf = (*env)->NewGlobalRef(env, bbuf);
(*env)->DeleteLocalRef(env, bbuf);
} else {
jbyteArray bytearray = (*env)->NewByteArray(env, p->chunksize);
p->bytearray = (*env)->NewGlobalRef(env, bytearray);
(*env)->DeleteLocalRef(env, bytearray);
}
/* create AudioTrack object */
if (AudioTrack_New(ao) != 0) {
MP_FATAL(ao, "Failed to create AudioTrack\n");
goto error;
}
if (pthread_create(&p->thread, NULL, playthread, ao)) {
MP_ERR(ao, "pthread creation failed\n");
goto error;
}
p->thread_created = true;
return 1;
error:
uninit(ao);
return -1;
}
static void stop(struct ao *ao)
{
struct priv *p = ao->priv;
if (!p->audiotrack) {
MP_ERR(ao, "AudioTrack does not exist to stop!\n");
return;
}
JNIEnv *env = MP_JNI_GET_ENV(ao);
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.pause);
MP_JNI_EXCEPTION_LOG(ao);
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.flush);
MP_JNI_EXCEPTION_LOG(ao);
p->playhead_offset = 0;
p->reset_pending = true;
p->written_frames = 0;
p->timestamp_fetched = 0;
p->timestamp_set = false;
p->timestamp_offset = 0;
}
static void start(struct ao *ao)
{
struct priv *p = ao->priv;
if (!p->audiotrack) {
MP_ERR(ao, "AudioTrack does not exist to start!\n");
return;
}
JNIEnv *env = MP_JNI_GET_ENV(ao);
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.play);
MP_JNI_EXCEPTION_LOG(ao);
pthread_cond_signal(&p->wakeup);
}
#define OPT_BASE_STRUCT struct priv
const struct ao_driver audio_out_audiotrack = {
.description = "Android AudioTrack audio output",
.name = "audiotrack",
.init = init,
.uninit = uninit,
.reset = stop,
.resume = start,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_FLAG("pcm-float", cfg_pcm_float, 0),
OPT_INT("session-id", cfg_session_id, 0),
{0}
},
.options_prefix = "audiotrack",
};
+3 -3
View File
@@ -49,8 +49,8 @@ static OSStatus render_cb_lpcm(void *ctx, AudioUnitRenderActionFlags *aflags,
planes[n] = buffer_list->mBuffers[n].mData;
int64_t end = mp_time_us();
end += ca_frames_to_us(ao, frames);
end += p->device_latency * 1e6;
end += ca_get_latency(ts) + ca_frames_to_us(ao, frames);
ao_read_data(ao, planes, frames, end);
return noErr;
}
@@ -155,7 +155,7 @@ static void start(struct ao *ao)
struct priv *p = ao->priv;
AVAudioSession *instance = AVAudioSession.sharedInstance;
p->device_latency = [instance outputLatency];
p->device_latency = [instance outputLatency] + [instance IOBufferDuration];
OSStatus err = AudioOutputUnitStart(p->audio_unit);
CHECK_CA_WARN("can't start audio unit");
@@ -192,7 +192,7 @@ const struct ao_driver audio_out_audiounit = {
.name = "audiounit",
.uninit = uninit,
.init = init,
.pause = stop,
.reset = stop,
.resume = start,
.priv_size = sizeof(struct priv),
};
-2
View File
@@ -117,8 +117,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
return get_volume(ao, arg);
case AOCONTROL_SET_VOLUME:
return set_volume(ao, arg);
case AOCONTROL_HAS_SOFT_VOLUME:
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
+17 -1
View File
@@ -31,6 +31,8 @@
#if HAVE_COREAUDIO
#include "audio/out/ao_coreaudio_properties.h"
#include <CoreAudio/HostTime.h>
#else
#include <mach/mach_time.h>
#endif
CFStringRef cfstr_from_cstr(char *str)
@@ -310,9 +312,9 @@ int64_t ca_frames_to_us(struct ao *ao, uint32_t frames)
return frames / (float) ao->samplerate * 1e6;
}
#if HAVE_COREAUDIO
int64_t ca_get_latency(const AudioTimeStamp *ts)
{
#if HAVE_COREAUDIO
uint64_t out = AudioConvertHostTimeToNanos(ts->mHostTime);
uint64_t now = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
@@ -320,8 +322,22 @@ int64_t ca_get_latency(const AudioTimeStamp *ts)
return 0;
return (out - now) * 1e-3;
#else
static mach_timebase_info_data_t timebase;
if (timebase.denom == 0)
mach_timebase_info(&timebase);
uint64_t out = ts->mHostTime;
uint64_t now = mach_absolute_time();
if (now > out)
return 0;
return (out - now) * timebase.numer / timebase.denom / 1e3;
#endif
}
#if HAVE_COREAUDIO
bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream)
{
AudioStreamRangedDescription *formats = NULL;
-2
View File
@@ -65,9 +65,7 @@ bool ca_asbd_is_better(AudioStreamBasicDescription *req,
AudioStreamBasicDescription *new);
int64_t ca_frames_to_us(struct ao *ao, uint32_t frames);
#if HAVE_COREAUDIO
int64_t ca_get_latency(const AudioTimeStamp *ts);
#endif
#if HAVE_COREAUDIO
bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream);
+2 -1
View File
@@ -143,7 +143,8 @@ connect_to_outports(struct ao *ao)
if (!port_name)
port_flags |= JackPortIsPhysical;
matching_ports = jack_get_ports(p->client, port_name, NULL, port_flags);
const char *port_type = JACK_DEFAULT_AUDIO_TYPE; // exclude MIDI ports
matching_ports = jack_get_ports(p->client, port_name, port_type, port_flags);
if (!matching_ports || !matching_ports[0]) {
MP_FATAL(ao, "no ports to connect to\n");
+2 -2
View File
@@ -146,7 +146,7 @@ static int init(struct ao *ao)
// enough frames for at least 0.25 seconds
ac->framecount = ceil(ao->samplerate * 0.25 / ac->aframesize);
// but at least one!
ac->framecount = FFMAX(ac->framecount, 1);
ac->framecount = MPMAX(ac->framecount, 1);
ac->savepts = AV_NOPTS_VALUE;
ac->lastpts = AV_NOPTS_VALUE;
@@ -324,7 +324,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
talloc_free(tempdata);
int taken = FFMIN(bufpos, orig_samples);
int taken = MPMIN(bufpos, orig_samples);
ectx->samples_since_last_pts += taken;
pthread_mutex_unlock(&ectx->lock);
-16
View File
@@ -24,19 +24,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#ifdef __APPLE__
#ifndef AL_FORMAT_MONO_FLOAT32
#define AL_FORMAT_MONO_FLOAT32 0x10010
#endif
#ifndef AL_FORMAT_STEREO_FLOAT32
#define AL_FORMAT_STEREO_FLOAT32 0x10011
#endif
#ifndef AL_FORMAT_MONO_DOUBLE_EXT
#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012
#endif
#include <OpenAL/MacOSX_OALExtensions.h>
#else
#ifdef OPENAL_AL_H
#include <OpenAL/alc.h>
#include <OpenAL/al.h>
@@ -46,7 +33,6 @@
#include <AL/al.h>
#include <AL/alext.h>
#endif
#endif // __APPLE__
#include "common/msg.h"
@@ -107,8 +93,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
return CONTROL_TRUE;
}
case AOCONTROL_HAS_SOFT_VOLUME:
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
+51 -45
View File
@@ -35,18 +35,13 @@ struct priv {
SLBufferQueueItf buffer_queue;
SLEngineItf engine;
SLPlayItf play;
char *buf;
size_t buffer_size;
void *buf;
int bytes_per_enqueue;
pthread_mutex_t buffer_lock;
double audio_latency;
int cfg_frames_per_buffer;
};
static const int fmtmap[][2] = {
{ AF_FORMAT_U8, SL_PCMSAMPLEFORMAT_FIXED_8 },
{ AF_FORMAT_S16, SL_PCMSAMPLEFORMAT_FIXED_16 },
{ 0 }
int frames_per_enqueue;
int buffer_size_in_ms;
};
#define DESTROY(thing) \
@@ -71,7 +66,6 @@ static void uninit(struct ao *ao)
free(p->buf);
p->buf = NULL;
p->buffer_size = 0;
}
#undef DESTROY
@@ -81,26 +75,22 @@ static void buffer_callback(SLBufferQueueItf buffer_queue, void *context)
struct ao *ao = context;
struct priv *p = ao->priv;
SLresult res;
void *data[1];
double delay;
pthread_mutex_lock(&p->buffer_lock);
data[0] = p->buf;
delay = 2 * p->buffer_size / (double)ao->bps;
delay = p->frames_per_enqueue / (double)ao->samplerate;
delay += p->audio_latency;
ao_read_data(ao, data, p->buffer_size / ao->sstride,
ao_read_data(ao, &p->buf, p->frames_per_enqueue,
mp_time_us() + 1000000LL * delay);
res = (*buffer_queue)->Enqueue(buffer_queue, p->buf, p->buffer_size);
res = (*buffer_queue)->Enqueue(buffer_queue, p->buf, p->bytes_per_enqueue);
if (res != SL_RESULT_SUCCESS)
MP_ERR(ao, "Failed to Enqueue: %d\n", res);
pthread_mutex_unlock(&p->buffer_lock);
}
#define DEFAULT_BUFFER_SIZE_MS 250
#define CHK(stmt) \
{ \
SLresult res = stmt; \
@@ -115,7 +105,7 @@ static int init(struct ao *ao)
struct priv *p = ao->priv;
SLDataLocator_BufferQueue locator_buffer_queue;
SLDataLocator_OutputMix locator_output_mix;
SLDataFormat_PCM pcm;
SLAndroidDataFormat_PCM_EX pcm;
SLDataSource audio_source;
SLDataSink audio_sink;
@@ -129,43 +119,55 @@ static int init(struct ao *ao)
CHK((*p->output_mix)->Realize(p->output_mix, SL_BOOLEAN_FALSE));
locator_buffer_queue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
locator_buffer_queue.numBuffers = 1;
locator_buffer_queue.numBuffers = 8;
pcm.formatType = SL_DATAFORMAT_PCM;
pcm.numChannels = 2;
int compatible_formats[AF_FORMAT_COUNT + 1];
af_get_best_sample_formats(ao->format, compatible_formats);
pcm.bitsPerSample = 0;
for (int i = 0; compatible_formats[i] && !pcm.bitsPerSample; ++i)
for (int j = 0; fmtmap[j][0]; ++j)
if (compatible_formats[i] == fmtmap[j][0]) {
ao->format = fmtmap[j][0];
pcm.bitsPerSample = fmtmap[j][1];
break;
}
if (!pcm.bitsPerSample) {
MP_ERR(ao, "Cannot find compatible audio format\n");
goto error;
if (af_fmt_is_int(ao->format)) {
// Be future-proof
if (af_fmt_to_bytes(ao->format) > 2)
ao->format = AF_FORMAT_S32;
else
ao->format = af_fmt_from_planar(ao->format);
pcm.formatType = SL_DATAFORMAT_PCM;
} else {
ao->format = AF_FORMAT_FLOAT;
pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
}
pcm.containerSize = 8 * af_fmt_to_bytes(ao->format);
pcm.numChannels = ao->channels.num;
pcm.containerSize = pcm.bitsPerSample = 8 * af_fmt_to_bytes(ao->format);
pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
pcm.sampleRate = ao->samplerate * 1000;
// samplesPerSec is misnamed, actually it's samples per ms
pcm.samplesPerSec = ao->samplerate * 1000;
if (p->buffer_size_in_ms) {
ao->device_buffer = ao->samplerate * p->buffer_size_in_ms / 1000;
// As the purpose of buffer_size_in_ms is to request a specific
// soft buffer size:
ao->def_buffer = 0;
}
if (p->cfg_frames_per_buffer)
ao->device_buffer = p->cfg_frames_per_buffer;
else
ao->device_buffer = ao->samplerate * DEFAULT_BUFFER_SIZE_MS / 1000;
p->buffer_size = ao->device_buffer * ao->channels.num *
// But it does not make sense if it is smaller than the enqueue size:
if (p->frames_per_enqueue) {
ao->device_buffer = MPMAX(ao->device_buffer, p->frames_per_enqueue);
} else {
if (ao->device_buffer) {
p->frames_per_enqueue = ao->device_buffer;
} else if (ao->def_buffer) {
p->frames_per_enqueue = ao->def_buffer * ao->samplerate;
} else {
MP_ERR(ao, "Enqueue size is not set and can neither be derived\n");
goto error;
}
}
p->bytes_per_enqueue = p->frames_per_enqueue * ao->channels.num *
af_fmt_to_bytes(ao->format);
p->buf = calloc(1, p->buffer_size);
p->buf = calloc(1, p->bytes_per_enqueue);
if (!p->buf) {
MP_ERR(ao, "Failed to allocate device buffer\n");
goto error;
}
int r = pthread_mutex_init(&p->buffer_lock, NULL);
if (r) {
MP_ERR(ao, "Failed to initialize the mutex: %d\n", r);
@@ -248,8 +250,12 @@ const struct ao_driver audio_out_opensles = {
.resume = resume,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.buffer_size_in_ms = 250,
},
.options = (const struct m_option[]) {
OPT_INTRANGE("frames-per-buffer", cfg_frames_per_buffer, 0, 1, 96000),
OPT_INTRANGE("frames-per-enqueue", frames_per_enqueue, 0, 1, 96000),
OPT_INTRANGE("buffer-size-in-ms", buffer_size_in_ms, 0, 0, 500),
{0}
},
.options_prefix = "opensles",
+11 -11
View File
@@ -204,10 +204,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
}
return CONTROL_ERROR;
}
#ifdef SNDCTL_DSP_GETPLAYVOL
case AOCONTROL_HAS_SOFT_VOLUME:
return CONTROL_TRUE;
#endif
}
return CONTROL_UNKNOWN;
}
@@ -336,19 +332,23 @@ static int reopen_device(struct ao *ao, bool allow_format_changes)
mp_chmap_sel_add_map(&sel, &oss_layouts[n]);
if (!ao_chmap_sel_adjust(ao, &sel, &channels))
goto fail;
int reqchannels = channels.num;
int c, nchannels, reqchannels;
nchannels = reqchannels = channels.num;
// We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
if (reqchannels > 2) {
int nchannels = reqchannels;
if (ioctl(p->audio_fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1 ||
nchannels != reqchannels)
{
if (ioctl(p->audio_fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1) {
MP_ERR(ao, "Failed to set audio device to %d channels.\n",
reqchannels);
goto fail;
}
if (nchannels != reqchannels) {
// Fallback to stereo
nchannels = 2;
goto stereo;
}
} else {
int c = reqchannels - 1;
stereo:
c = nchannels - 1;
if (ioctl(p->audio_fd, SNDCTL_DSP_STEREO, &c) == -1) {
MP_ERR(ao, "Failed to set audio device to %d channels.\n",
reqchannels);
@@ -649,7 +649,7 @@ const struct ao_driver audio_out_oss = {
.oss_mixer_device = PATH_DEV_MIXER,
},
.options = (const struct m_option[]) {
OPT_STRING("mixer-device", oss_mixer_device, 0),
OPT_STRING("mixer-device", oss_mixer_device, M_OPT_FILE),
OPT_STRING("mixer-channel", cfg_oss_mixer_channel, 0),
{0}
},
+17 -13
View File
@@ -61,6 +61,7 @@ struct priv {
char *cfg_host;
int cfg_buffer;
int cfg_latency_hacks;
int cfg_allow_suspended;
};
#define GENERIC_ERR_MSG(str) \
@@ -201,13 +202,18 @@ static const struct format_map {
static pa_encoding_t map_digital_format(int format)
{
switch (format) {
case AF_FORMAT_S_AC3: return PA_ENCODING_AC3_IEC61937;
case AF_FORMAT_S_EAC3: return PA_ENCODING_EAC3_IEC61937;
case AF_FORMAT_S_MP3: return PA_ENCODING_MPEG_IEC61937;
case AF_FORMAT_S_DTS:
case AF_FORMAT_S_DTSHD: return PA_ENCODING_DTS_IEC61937;
case AF_FORMAT_S_AC3: return PA_ENCODING_AC3_IEC61937;
case AF_FORMAT_S_EAC3: return PA_ENCODING_EAC3_IEC61937;
case AF_FORMAT_S_MP3: return PA_ENCODING_MPEG_IEC61937;
case AF_FORMAT_S_DTS: return PA_ENCODING_DTS_IEC61937;
#ifdef PA_ENCODING_DTSHD_IEC61937
case AF_FORMAT_S_DTSHD: return PA_ENCODING_DTSHD_IEC61937;
#endif
#ifdef PA_ENCODING_MPEG2_AAC_IEC61937
case AF_FORMAT_S_AAC: return PA_ENCODING_MPEG2_AAC_IEC61937;
case AF_FORMAT_S_AAC: return PA_ENCODING_MPEG2_AAC_IEC61937;
#endif
#ifdef PA_ENCODING_TRUEHD_IEC61937
case AF_FORMAT_S_TRUEHD: return PA_ENCODING_TRUEHD_IEC61937;
#endif
default:
if (af_fmt_is_spdif(format))
@@ -454,11 +460,11 @@ static int init(struct ao *ao)
pa_stream_set_write_callback(priv->stream, stream_request_cb, ao);
pa_stream_set_latency_update_callback(priv->stream,
stream_latency_update_cb, ao);
int buf_size = af_fmt_seconds_to_bytes(ao->format, priv->cfg_buffer / 1000.0,
ao->channels.num, ao->samplerate);
uint32_t buf_size = ao->samplerate * (priv->cfg_buffer / 1000.0) *
af_fmt_to_bytes(ao->format) * ao->channels.num;
pa_buffer_attr bufattr = {
.maxlength = -1,
.tlength = buf_size > 0 ? buf_size : (uint32_t)-1,
.tlength = buf_size > 0 ? buf_size : -1,
.prebuf = -1,
.minreq = -1,
.fragsize = -1,
@@ -482,7 +488,7 @@ static int init(struct ao *ao)
pa_threaded_mainloop_wait(priv->mainloop);
}
if (pa_stream_is_suspended(priv->stream)) {
if (pa_stream_is_suspended(priv->stream) && !priv->cfg_allow_suspended) {
MP_ERR(ao, "The stream is suspended. Bailing out.\n");
goto unlock_and_fail;
}
@@ -743,9 +749,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
return CONTROL_OK;
}
case AOCONTROL_HAS_PER_APP_VOLUME:
return CONTROL_TRUE;
case AOCONTROL_UPDATE_STREAM_TITLE: {
char *title = (char *)arg;
pa_threaded_mainloop_lock(priv->mainloop);
@@ -837,6 +840,7 @@ const struct ao_driver audio_out_pulse = {
OPT_STRING("host", cfg_host, 0),
OPT_CHOICE_OR_INT("buffer", cfg_buffer, 0, 1, 2000, ({"native", 0})),
OPT_FLAG("latency-hacks", cfg_latency_hacks, 0),
OPT_FLAG("allow-suspended", cfg_allow_suspended, 0),
{0}
},
.options_prefix = "pulse",
+1
View File
@@ -205,6 +205,7 @@ const struct ao_driver audio_out_sdl = {
.uninit = uninit,
.reset = reset,
.resume = resume,
.reports_underruns = true,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.buflen = 0, // use SDL default
-2
View File
@@ -61,8 +61,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
return CONTROL_FALSE;
sio_setvol(p->hdl, vol->left * SIO_MAXVOL / 100);
break;
case AOCONTROL_HAS_SOFT_VOLUME:
return CONTROL_TRUE;
default:
return CONTROL_UNKNOWN;
}
-4
View File
@@ -340,8 +340,6 @@ static int thread_control_exclusive(struct ao *ao, enum aocontrol cmd, void *arg
if (!(state->vol_hw_support & ENDPOINT_HARDWARE_SUPPORT_MUTE))
return CONTROL_FALSE;
break;
case AOCONTROL_HAS_PER_APP_VOLUME:
return CONTROL_FALSE;
}
float volume;
@@ -400,8 +398,6 @@ static int thread_control_shared(struct ao *ao, enum aocontrol cmd, void *arg)
mute = *(bool *)arg;
ISimpleAudioVolume_SetMute(state->pAudioVolume, mute, NULL);
return CONTROL_OK;
case AOCONTROL_HAS_PER_APP_VOLUME:
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
+8 -2
View File
@@ -68,7 +68,7 @@ struct ao {
char *redirect;
// Internal events (use ao_request_reload(), ao_hotplug_event())
atomic_int events_;
atomic_uint events_;
// Float gain multiplicator
mp_atomic_float gain;
@@ -134,6 +134,11 @@ struct ao_driver {
// first play() call is done. Encode mode uses this, and push mode
// respects it automatically (don't use with pull mode).
bool initially_blocked;
// Whether underruns are strictly _always_ reported via ao_underrun_event().
// Do not set this to true if underruns may be missed in some way. If the
// AO can't guarantee to play silence after underruns, it may be better not
// to set this.
bool reports_underruns;
// Init the device using ao->format/ao->channels/ao->samplerate. If the
// device doesn't accept these parameters, you can attempt to negotiate
// fallback parameters, and set the ao format fields accordingly.
@@ -143,7 +148,7 @@ struct ao_driver {
void (*uninit)(struct ao *ao);
// push based: see ao_reset()
// pull based: stop the audio callback
void (*reset)(struct ao*ao);
void (*reset)(struct ao *ao);
// push based: see ao_pause()
void (*pause)(struct ao *ao);
// push based: see ao_resume()
@@ -206,6 +211,7 @@ struct pollfd;
int ao_wait_poll(struct ao *ao, struct pollfd *fds, int num_fds,
pthread_mutex_t *lock);
void ao_wakeup_poll(struct ao *ao);
void ao_underrun_event(struct ao *ao);
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map);
+7 -2
View File
@@ -153,8 +153,13 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_us)
int buffered_bytes = mp_ring_buffered(p->buffers[0]);
bytes = MPMIN(buffered_bytes, full_bytes);
if (buffered_bytes < bytes && !atomic_load(&p->draining))
atomic_fetch_add(&p->underflow, (bytes - buffered_bytes) / ao->sstride);
if (full_bytes > bytes && !atomic_load(&p->draining)) {
if (ao->driver->reports_underruns) {
ao_underrun_event(ao);
} else {
atomic_fetch_add(&p->underflow, (full_bytes - bytes) / ao->sstride);
}
}
if (bytes > 0)
atomic_store(&p->end_time_us, out_time_us);
+5 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# This script simply downloads waf to the current directory
@@ -16,6 +16,10 @@ if os.path.exists("waf"):
print("Found 'waf', skipping download.")
sys.exit(0)
if "--no-download" in sys.argv[1:]:
print("Did not find {} and no download was requested.".format(WAFRELEASE))
sys.exit(1)
try:
from urllib.request import urlopen, URLError
except:
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
FFMPEG_SYSROOT="${HOME}/deps/sysroot"
MPV_INSTALL_PREFIX="${HOME}/out/mpv"
MPV_VARIANT="${TRAVIS_OS_NAME}"
if [[ -d "./build/${MPV_VARIANT}" ]] ; then
rm -rf "./build/${MPV_VARIANT}"
fi
if [[ ! -e "./waf" ]] ; then
python3 ./bootstrap.py
fi
PKG_CONFIG_PATH="${FFMPEG_SYSROOT}/lib/pkgconfig/" CC="${CC}" CXX="${CXX}" python3 \
./waf configure \
--variant="${MPV_VARIANT}" \
--prefix="${MPV_INSTALL_PREFIX}" \
--enable-{gl,iconv,lcms2,libass,libass-osd,libmpv-shared,lua,jpeg,plain-gl,zlib} \
--enable-{cocoa,coreaudio,gl-cocoa,macos-cocoa-cb,macos-touchbar,videotoolbox-gl}
python3 ./waf build --variant="${MPV_VARIANT}" -j4
python3 ./waf install --variant="${MPV_VARIANT}"
+2 -4
View File
@@ -16,8 +16,7 @@ export RANLIB=$TARGET-ranlib
export CFLAGS="-O2 -mtune=intel -g -ggdb -pipe -Wall --param=ssp-buffer-size=4 -mms-bitfields -fmessage-length=0 -D_FORTIFY_SOURCE=2 -fexceptions -fasynchronous-unwind-tables -fstack-protector-strong -fno-ident"
export LDFLAGS="-Wl,--no-keep-memory -fstack-protector-strong"
./bootstrap.py
./waf configure \
python3 ./waf configure \
--enable-static-build \
--enable-libmpv-shared \
--enable-lua \
@@ -25,11 +24,10 @@ export LDFLAGS="-Wl,--no-keep-memory -fstack-protector-strong"
--enable-libarchive \
--enable-libass \
--enable-libbluray \
--enable-dvdread \
--enable-dvdnav \
--enable-uchardet \
--enable-vulkan \
--enable-shaderc \
--enable-rubberband \
--enable-lcms2
./waf build --verbose
python3 ./waf build --verbose
+3 -6
View File
@@ -1,17 +1,14 @@
#!/bin/sh
set -e
./bootstrap.py
./waf configure \
python3 ./waf configure \
--enable-cdda \
--enable-dvbin \
--enable-dvdnav \
--enable-dvdread \
--enable-libarchive \
--enable-libmpv-shared \
--enable-libsmbclient \
--enable-manpage-build \
--enable-shaderc \
--enable-vulkan \
--enable-zsh-comp
./waf build --verbose
--enable-vulkan
python3 ./waf build --verbose
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -e
FFMPEG_SRC_DIR="${HOME}/deps/src/ffmpeg"
FFMPEG_BUILD_DIR="${FFMPEG_SRC_DIR}/${TRAVIS_OS_NAME}"
FFMPEG_SYSROOT="${HOME}/deps/sysroot"
FFMPEG_HASH="18928e2bb4568cbe5e9061c3e6b63559392af3d2"
# Get the sauce if not around
if [[ ! -d "${FFMPEG_SRC_DIR}" ]] ; then
git clone "https://git.videolan.org/git/ffmpeg.git" "${FFMPEG_SRC_DIR}"
fi
# pop into FFmpeg's source dir and clean up & check out our wanted revision
pushd "${FFMPEG_SRC_DIR}"
git reset --hard HEAD && git clean -dfx
git checkout "${FFMPEG_HASH}"
popd
# If a build dir of the same type is around, clean it up
if [[ -d "${FFMPEG_BUILD_DIR}" ]] ; then
rm -rf "${FFMPEG_BUILD_DIR}"
fi
# Create and move into the build dir, configure and build!
mkdir -p "${FFMPEG_BUILD_DIR}" && pushd "${FFMPEG_BUILD_DIR}"
PKG_CONFIG_PATH="${FFMPEG_SYSROOT}/lib/pkgconfig/" ../configure \
--disable-{autodetect,stripping} \
--cc="${CC}" \
--cxx="${CXX}" \
--prefix="${FFMPEG_SYSROOT}" \
--enable-{zlib,securetransport,videotoolbox}
make -j4 && make install && popd
exit 0
+7
View File
@@ -292,6 +292,13 @@ const char *mp_codec_from_av_codec_id(int codec_id)
return name;
}
bool mp_codec_is_lossless(const char *codec)
{
const AVCodecDescriptor *desc =
avcodec_descriptor_get(mp_codec_to_av_codec_id(codec));
return desc && (desc->props & AV_CODEC_PROP_LOSSLESS);
}
// kv is in the format as by OPT_KEYVALUELIST(): kv[0]=key0, kv[1]=val0, ...
// Copy them to the dict.
void mp_set_avdict(AVDictionary **dict, char **kv)
+2
View File
@@ -19,6 +19,7 @@
#define MP_AVCOMMON_H
#include <inttypes.h>
#include <stdbool.h>
#include <libavutil/avutil.h>
#include <libavutil/rational.h>
@@ -44,6 +45,7 @@ void mp_add_lavc_encoders(struct mp_decoder_list *list);
char **mp_get_lavf_demuxers(void);
int mp_codec_to_av_codec_id(const char *codec);
const char *mp_codec_from_av_codec_id(int codec_id);
bool mp_codec_is_lossless(const char *codec);
void mp_set_avdict(struct AVDictionary **dict, char **kv);
void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d);
int mp_set_avopts(struct mp_log *log, void *avobj, char **kv);
+5 -2
View File
@@ -177,7 +177,9 @@ void uninit_libav(struct mpv_global *global)
pthread_mutex_unlock(&log_lock);
}
#define V(x) (x)>>16, (x)>>8 & 255, (x) & 255
#define V(x) AV_VERSION_MAJOR(x), \
AV_VERSION_MINOR(x), \
AV_VERSION_MICRO(x)
struct lib {
const char *name;
@@ -208,7 +210,8 @@ bool print_libav_versions(struct mp_log *log, int v)
mp_msg(log, v, " %-15s %d.%d.%d", l->name, V(l->buildv));
if (l->buildv != l->runv) {
mp_msg(log, v, " (runtime %d.%d.%d)", V(l->runv));
mismatch = true;
mismatch = l->buildv > l->runv ||
AV_VERSION_MAJOR(l->buildv) != AV_VERSION_MAJOR(l->runv);
}
mp_msg(log, v, "\n");
}
+40 -8
View File
@@ -96,10 +96,10 @@ char *mp_format_time(double time, bool fractions)
// Set rc to the union of rc and rc2
void mp_rect_union(struct mp_rect *rc, const struct mp_rect *rc2)
{
rc->x0 = FFMIN(rc->x0, rc2->x0);
rc->y0 = FFMIN(rc->y0, rc2->y0);
rc->x1 = FFMAX(rc->x1, rc2->x1);
rc->y1 = FFMAX(rc->y1, rc2->y1);
rc->x0 = MPMIN(rc->x0, rc2->x0);
rc->y0 = MPMIN(rc->y0, rc2->y0);
rc->x1 = MPMAX(rc->x1, rc2->x1);
rc->y1 = MPMAX(rc->y1, rc2->y1);
}
// Returns whether or not a point is contained by rc
@@ -112,10 +112,10 @@ bool mp_rect_contains(struct mp_rect *rc, int x, int y)
// Return false if the result is empty.
bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2)
{
rc->x0 = FFMAX(rc->x0, rc2->x0);
rc->y0 = FFMAX(rc->y0, rc2->y0);
rc->x1 = FFMIN(rc->x1, rc2->x1);
rc->y1 = FFMIN(rc->y1, rc2->y1);
rc->x0 = MPMAX(rc->x0, rc2->x0);
rc->y0 = MPMAX(rc->y0, rc2->y0);
rc->x1 = MPMIN(rc->x1, rc2->x1);
rc->y1 = MPMIN(rc->y1, rc2->y1);
return rc->x1 > rc->x0 && rc->y1 > rc->y0;
}
@@ -318,3 +318,35 @@ char **mp_dup_str_array(void *tctx, char **s)
MP_TARRAY_APPEND(tctx, r, num_r, NULL);
return r;
}
// Return rounded down integer log 2 of v, i.e. position of highest set bit.
// mp_log2(0) == 0
// mp_log2(1) == 0
// mp_log2(31) == 4
// mp_log2(32) == 5
unsigned int mp_log2(uint32_t v)
{
#if defined(__GNUC__) && __GNUC__ >= 4
return v ? 31 - __builtin_clz(v) : 0;
#else
for (int x = 31; x >= 0; x--) {
if (v & (((uint32_t)1) << x))
return x;
}
return 0;
#endif
}
// If a power of 2, return it, otherwise return the next highest one, or 0.
// mp_round_next_power_of_2(65) == 128
// mp_round_next_power_of_2(64) == 64
// mp_round_next_power_of_2(0) == 1
// mp_round_next_power_of_2(UINT32_MAX) == 0
uint32_t mp_round_next_power_of_2(uint32_t v)
{
for (int n = 0; n < 30; n++) {
if ((1 << n) >= v)
return 1 << n;
}
return 0;
}
+13
View File
@@ -43,6 +43,16 @@
// align must be a power of two (align >= 1), x >= 0
#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
#define MP_IS_ALIGNED(x, align) (!((x) & ((align) - 1)))
#define MP_IS_POWER_OF_2(x) ((x) > 0 && !((x) & ((x) - 1)))
// Return "a", or if that is NOPTS, return "def".
#define MP_PTS_OR_DEF(a, def) ((a) == MP_NOPTS_VALUE ? (def) : (a))
// If one of the values is NOPTS, always pick the other one.
#define MP_PTS_MIN(a, b) MPMIN(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
#define MP_PTS_MAX(a, b) MPMAX(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
// Return a+b, unless a is NOPTS. b must not be NOPTS.
#define MP_ADD_PTS(a, b) ((a) == MP_NOPTS_VALUE ? (a) : ((a) + (b)))
#define CONTROL_OK 1
#define CONTROL_TRUE 1
@@ -78,6 +88,9 @@ bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2);
bool mp_rect_contains(struct mp_rect *rc, int x, int y);
bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2);
unsigned int mp_log2(uint32_t v);
uint32_t mp_round_next_power_of_2(uint32_t v);
int mp_snprintf_cat(char *str, size_t size, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
+27 -21
View File
@@ -77,25 +77,25 @@ struct mux_stream {
#define OPT_BASE_STRUCT struct encode_opts
const struct m_sub_options encode_config = {
.opts = (const m_option_t[]) {
OPT_STRING("o", file, M_OPT_FIXED | CONF_NOCFG | CONF_PRE_PARSE | M_OPT_FILE),
OPT_STRING("of", format, M_OPT_FIXED),
OPT_KEYVALUELIST("ofopts", fopts, M_OPT_FIXED | M_OPT_HAVE_HELP),
OPT_STRING("ovc", vcodec, M_OPT_FIXED),
OPT_KEYVALUELIST("ovcopts", vopts, M_OPT_FIXED | M_OPT_HAVE_HELP),
OPT_STRING("oac", acodec, M_OPT_FIXED),
OPT_KEYVALUELIST("oacopts", aopts, M_OPT_FIXED | M_OPT_HAVE_HELP),
OPT_FLOATRANGE("ovoffset", voffset, M_OPT_FIXED, -1000000.0, 1000000.0,
OPT_STRING("o", file, CONF_NOCFG | CONF_PRE_PARSE | M_OPT_FILE),
OPT_STRING("of", format, 0),
OPT_KEYVALUELIST("ofopts", fopts, M_OPT_HAVE_HELP),
OPT_STRING("ovc", vcodec, 0),
OPT_KEYVALUELIST("ovcopts", vopts, M_OPT_HAVE_HELP),
OPT_STRING("oac", acodec, 0),
OPT_KEYVALUELIST("oacopts", aopts, M_OPT_HAVE_HELP),
OPT_FLOATRANGE("ovoffset", voffset, 0, -1000000.0, 1000000.0,
.deprecation_message = "--audio-delay (once unbroken)"),
OPT_FLOATRANGE("oaoffset", aoffset, M_OPT_FIXED, -1000000.0, 1000000.0,
OPT_FLOATRANGE("oaoffset", aoffset, 0, -1000000.0, 1000000.0,
.deprecation_message = "--audio-delay (once unbroken)"),
OPT_FLAG("orawts", rawts, M_OPT_FIXED),
OPT_FLAG("ovfirst", video_first, M_OPT_FIXED,
OPT_FLAG("orawts", rawts, 0),
OPT_FLAG("ovfirst", video_first, 0,
.deprecation_message = "no replacement"),
OPT_FLAG("oafirst", audio_first, M_OPT_FIXED,
OPT_FLAG("oafirst", audio_first, 0,
.deprecation_message = "no replacement"),
OPT_FLAG("ocopy-metadata", copy_metadata, M_OPT_FIXED),
OPT_KEYVALUELIST("oset-metadata", set_metadata, M_OPT_FIXED),
OPT_STRINGLIST("oremove-metadata", remove_metadata, M_OPT_FIXED),
OPT_FLAG("ocopy-metadata", copy_metadata, 0),
OPT_KEYVALUELIST("oset-metadata", set_metadata, 0),
OPT_STRINGLIST("oremove-metadata", remove_metadata, 0),
OPT_REMOVED("ocopyts", "ocopyts is now the default"),
OPT_REMOVED("oneverdrop", "no replacement"),
@@ -422,6 +422,11 @@ static struct mux_stream *encode_lavc_add_stream(struct encode_lavc_context *ctx
dst->encoder_timebase = info->timebase;
dst->st->time_base = info->timebase; // lavf will change this on muxer init
// Some muxers (e.g. Matroska one) expect the sample_aspect_ratio to be
// set on the AVStream.
if (info->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
dst->st->sample_aspect_ratio = info->codecpar->sample_aspect_ratio;
if (avcodec_parameters_copy(dst->st->codecpar, info->codecpar) < 0)
MP_HANDLE_OOM(0);
@@ -436,7 +441,7 @@ done:
return dst;
}
// Write a packet. Callee will create new pkt refs as needed.
// Write a packet. This will take over ownership of `pkt`
static void encode_lavc_add_packet(struct mux_stream *dst, AVPacket *pkt)
{
struct encode_lavc_context *ctx = dst->ctx;
@@ -476,14 +481,14 @@ static void encode_lavc_add_packet(struct mux_stream *dst, AVPacket *pkt)
if (av_interleaved_write_frame(p->muxer, pkt) < 0) {
MP_ERR(p, "Writing packet failed.\n");
p->failed = true;
goto done;
}
pkt = NULL;
done:
pthread_mutex_unlock(&ctx->lock);
av_packet_free(&pkt);
if (pkt)
av_packet_unref(pkt);
}
void encode_lavc_discontinuity(struct encode_lavc_context *ctx)
@@ -715,7 +720,7 @@ int encode_lavc_getstatus(struct encode_lavc_context *ctx,
double now = mp_time_sec();
float minutes, megabytes, fps, x;
float f = FFMAX(0.0001, relative_position);
float f = MPMAX(0.0001, relative_position);
pthread_mutex_lock(&ctx->lock);
@@ -825,7 +830,9 @@ static void encoder_2pass_prepare(struct encoder_context *p)
if (p->encoder->flags & AV_CODEC_FLAG_PASS2) {
MP_INFO(p, "Reading 2-pass log: %s\n", filename);
struct stream *s = stream_open(filename, p->global);
struct stream *s = stream_create(filename,
STREAM_ORIGIN_DIRECT | STREAM_READ,
NULL, p->global);
if (s) {
struct bstr content = stream_read_complete(s, p, 1000000000);
if (content.start) {
@@ -949,7 +956,6 @@ bool encoder_encode(struct encoder_context *p, AVFrame *frame)
break;
encode_lavc_add_packet(p->mux_stream, &packet);
av_packet_unref(&packet);
}
return true;
+1 -4
View File
@@ -8,10 +8,7 @@ struct mpv_global {
struct mp_log *log;
struct m_config_shadow *config;
struct mp_client_api *client_api;
// Using this is deprecated and should be avoided (missing synchronization).
// Use m_config_cache to access mpv_global.config instead.
struct MPOpts *opts;
char *configdir;
};
#endif
+128 -63
View File
@@ -30,7 +30,6 @@
#include "osdep/atomic.h"
#include "common/common.h"
#include "common/global.h"
#include "misc/ring.h"
#include "misc/bstr.h"
#include "options/options.h"
#include "options/path.h"
@@ -43,6 +42,8 @@
#include "msg.h"
#include "msg_control.h"
#define TERM_BUF 100
struct mp_log_root {
struct mpv_global *global;
// --- protected by mp_msg_lock
@@ -50,7 +51,6 @@ struct mp_log_root {
bool use_terminal; // make accesses to stderr/stdout
bool module;
bool show_time;
bool termosd; // use terminal control codes for status line
int blank_lines; // number of lines usable by status
int status_lines; // number of current status lines
bool color;
@@ -59,6 +59,7 @@ struct mp_log_root {
bool force_stderr;
struct mp_log_buffer **buffers;
int num_buffers;
struct mp_log_buffer *early_buffer;
FILE *log_file;
FILE *stats_file;
char *log_path;
@@ -84,8 +85,13 @@ struct mp_log {
struct mp_log_buffer {
struct mp_log_root *root;
struct mp_ring *ring;
struct mp_log_buffer_entry **entries; // ringbuffer
int capacity; // total space in entries[]
int entry0; // first (oldest) entry index
int num_entries; // number of valid entries after entry0
uint64_t dropped; // number of skipped entries
int level;
bool silent;
void (*wakeup_cb)(void *ctx);
void *wakeup_cb_ctx;
};
@@ -117,8 +123,11 @@ static void update_loglevel(struct mp_log *log)
log->level = mp_msg_find_level(root->msg_levels[n * 2 + 1]);
}
log->terminal_level = log->level;
for (int n = 0; n < log->root->num_buffers; n++)
log->level = MPMAX(log->level, log->root->buffers[n]->level);
for (int n = 0; n < log->root->num_buffers; n++) {
int buffer_level = log->root->buffers[n]->level;
if (buffer_level != MP_LOG_BUFFER_MSGL_TERM)
log->level = MPMAX(log->level, buffer_level);
}
if (log->root->log_file)
log->level = MPMAX(log->level, MSGL_DEBUG);
if (log->root->stats_file)
@@ -127,19 +136,19 @@ static void update_loglevel(struct mp_log *log)
pthread_mutex_unlock(&mp_msg_lock);
}
// Return whether the message at this verbosity level would be actually printed.
// Get the current effective msg level.
// Thread-safety: see mp_msg().
bool mp_msg_test(struct mp_log *log, int lev)
int mp_msg_level(struct mp_log *log)
{
struct mp_log_root *root = log->root;
if (!root)
return false;
return -1;
if (atomic_load_explicit(&log->reload_counter, memory_order_relaxed) !=
atomic_load_explicit(&root->reload_counter, memory_order_relaxed))
{
update_loglevel(log);
}
return lev <= log->level;
return log->level;
}
// Reposition cursor and clear lines for outputting the status line. In certain
@@ -295,6 +304,15 @@ static void write_log_file(struct mp_log *log, int lev, char *text)
fflush(root->log_file);
}
static struct mp_log_buffer_entry *log_buffer_read(struct mp_log_buffer *buffer)
{
assert(buffer->num_entries);
struct mp_log_buffer_entry *res = buffer->entries[buffer->entry0];
buffer->entry0 = (buffer->entry0 + 1) % buffer->capacity;
buffer->num_entries -= 1;
return res;
}
static void write_msg_to_buffers(struct mp_log *log, int lev, char *text)
{
struct mp_log_root *root = log->root;
@@ -304,27 +322,21 @@ static void write_msg_to_buffers(struct mp_log *log, int lev, char *text)
if (buffer_level == MP_LOG_BUFFER_MSGL_TERM)
buffer_level = log->terminal_level;
if (lev <= buffer_level && lev != MSGL_STATUS) {
// Assuming a single writer (serialized by msg lock)
int avail = mp_ring_available(buffer->ring) / sizeof(void *);
if (avail < 1)
continue;
struct mp_log_buffer_entry *entry = talloc_ptrtype(NULL, entry);
if (avail > 1) {
*entry = (struct mp_log_buffer_entry) {
.prefix = talloc_strdup(entry, log->verbose_prefix),
.level = lev,
.text = talloc_strdup(entry, text),
};
} else {
// write overflow message to signal that messages might be lost
*entry = (struct mp_log_buffer_entry) {
.prefix = "overflow",
.level = MSGL_FATAL,
.text = "log message buffer overflow\n",
};
if (buffer->num_entries == buffer->capacity) {
struct mp_log_buffer_entry *skip = log_buffer_read(buffer);
talloc_free(skip);
buffer->dropped += 1;
}
mp_ring_write(buffer->ring, (unsigned char *)&entry, sizeof(entry));
if (buffer->wakeup_cb)
struct mp_log_buffer_entry *entry = talloc_ptrtype(NULL, entry);
*entry = (struct mp_log_buffer_entry) {
.prefix = talloc_strdup(entry, log->verbose_prefix),
.level = lev,
.text = talloc_strdup(entry, text),
};
int pos = (buffer->entry0 + buffer->num_entries) % buffer->capacity;
buffer->entries[pos] = entry;
buffer->num_entries += 1;
if (buffer->wakeup_cb && !buffer->silent)
buffer->wakeup_cb(buffer->wakeup_cb_ctx);
}
}
@@ -361,7 +373,7 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va)
} else if (lev == MSGL_STATUS && !test_terminal_level(log, lev)) {
/* discard */
} else {
if (lev == MSGL_STATUS && root->termosd)
if (lev == MSGL_STATUS)
prepare_status_line(root, text);
// Split away each line. Normally we require full lines; buffer partial
@@ -382,7 +394,7 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va)
if (lev == MSGL_STATUS) {
if (text[0])
print_terminal_line(log, lev, text, root->termosd ? "\r" : "\n");
print_terminal_line(log, lev, text, "\r");
} else if (text[0]) {
int size = strlen(text) + 1;
if (talloc_get_size(log->partial) < size)
@@ -460,8 +472,6 @@ void mp_msg_init(struct mpv_global *global)
struct mp_log *log = mp_log_new(root, &dummy, "");
global->log = log;
mp_msg_update_msglevels(global);
}
// If opt is different from *current_path, reopen *file and update *current_path.
@@ -501,13 +511,9 @@ static void reopen_file(char *opt, char **current_path, FILE **file,
talloc_free(tmp);
}
void mp_msg_update_msglevels(struct mpv_global *global)
void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts)
{
struct mp_log_root *root = global->log->root;
struct MPOpts *opts = global->opts;
if (!opts)
return;
pthread_mutex_lock(&mp_msg_lock);
@@ -516,14 +522,11 @@ void mp_msg_update_msglevels(struct mpv_global *global)
root->module = opts->msg_module;
root->use_terminal = opts->use_terminal;
root->show_time = opts->msg_time;
if (root->use_terminal) {
if (root->use_terminal)
root->color = opts->msg_color && isatty(STDOUT_FILENO);
root->termosd = isatty(STDERR_FILENO);
}
m_option_type_msglevels.free(&root->msg_levels);
m_option_type_msglevels.copy(NULL, &root->msg_levels,
&global->opts->msg_levels);
m_option_type_msglevels.copy(NULL, &root->msg_levels, &opts->msg_levels);
atomic_fetch_add(&root->reload_counter, 1);
pthread_mutex_unlock(&mp_msg_lock);
@@ -558,6 +561,9 @@ bool mp_msg_has_log_file(struct mpv_global *global)
void mp_msg_uninit(struct mpv_global *global)
{
struct mp_log_root *root = global->log->root;
if (root->early_buffer)
mp_msg_log_buffer_destroy(root->early_buffer);
assert(root->num_buffers == 0);
if (root->stats_file)
fclose(root->stats_file);
talloc_free(root->stats_path);
@@ -569,6 +575,32 @@ void mp_msg_uninit(struct mpv_global *global)
global->log = NULL;
}
void mp_msg_set_early_logging(struct mpv_global *global, bool enable)
{
struct mp_log_root *root = global->log->root;
pthread_mutex_lock(&mp_msg_lock);
if (enable != !!root->early_buffer) {
if (enable) {
pthread_mutex_unlock(&mp_msg_lock);
struct mp_log_buffer *buf =
mp_msg_log_buffer_new(global, TERM_BUF, MP_LOG_BUFFER_MSGL_TERM,
NULL, NULL);
pthread_mutex_lock(&mp_msg_lock);
assert(!root->early_buffer); // no concurrent calls to this function
root->early_buffer = buf;
} else {
struct mp_log_buffer *buf = root->early_buffer;
root->early_buffer = NULL;
pthread_mutex_unlock(&mp_msg_lock);
mp_msg_log_buffer_destroy(buf);
return;
}
}
pthread_mutex_unlock(&mp_msg_lock);
}
struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
int size, int level,
void (*wakeup_cb)(void *ctx),
@@ -576,22 +608,36 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
{
struct mp_log_root *root = global->log->root;
#if !HAVE_ATOMICS
return NULL;
#endif
pthread_mutex_lock(&mp_msg_lock);
if (level == MP_LOG_BUFFER_MSGL_TERM) {
size = TERM_BUF;
// The first thing which creates a terminal-level log buffer gets the
// early log buffer, if it exists. This is supposed to enable a script
// to grab log messages from before it was initialized. It's OK that
// this works only for 1 script and only once.
if (root->early_buffer) {
struct mp_log_buffer *buffer = root->early_buffer;
root->early_buffer = NULL;
buffer->wakeup_cb = wakeup_cb;
buffer->wakeup_cb_ctx = wakeup_cb_ctx;
pthread_mutex_unlock(&mp_msg_lock);
return buffer;
}
}
assert(size > 0);
struct mp_log_buffer *buffer = talloc_ptrtype(NULL, buffer);
*buffer = (struct mp_log_buffer) {
.root = root,
.level = level,
.ring = mp_ring_new(buffer, sizeof(void *) * size),
.entries = talloc_array(buffer, struct mp_log_buffer_entry *, size),
.capacity = size,
.wakeup_cb = wakeup_cb,
.wakeup_cb_ctx = wakeup_cb_ctx,
};
if (!buffer->ring)
abort();
MP_TARRAY_APPEND(root, root->buffers, root->num_buffers, buffer);
@@ -601,6 +647,13 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
return buffer;
}
void mp_msg_log_buffer_set_silent(struct mp_log_buffer *buffer, bool silent)
{
pthread_mutex_lock(&mp_msg_lock);
buffer->silent = silent;
pthread_mutex_unlock(&mp_msg_lock);
}
void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer)
{
if (!buffer)
@@ -620,12 +673,8 @@ void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer)
found:
while (1) {
struct mp_log_buffer_entry *e = mp_msg_log_buffer_read(buffer);
if (!e)
break;
talloc_free(e);
}
while (buffer->num_entries)
talloc_free(log_buffer_read(buffer));
talloc_free(buffer);
atomic_fetch_add(&root->reload_counter, 1);
@@ -636,13 +685,29 @@ found:
// Thread-safety: one buffer can be read by a single thread only.
struct mp_log_buffer_entry *mp_msg_log_buffer_read(struct mp_log_buffer *buffer)
{
void *ptr = NULL;
int read = mp_ring_read(buffer->ring, (unsigned char *)&ptr, sizeof(ptr));
if (read == 0)
return NULL;
if (read != sizeof(ptr))
abort();
return ptr;
struct mp_log_buffer_entry *res = NULL;
pthread_mutex_lock(&mp_msg_lock);
if (!buffer->silent && buffer->num_entries) {
if (buffer->dropped) {
res = talloc_ptrtype(NULL, res);
*res = (struct mp_log_buffer_entry) {
.prefix = "overflow",
.level = MSGL_FATAL,
.text = talloc_asprintf(res,
"log message buffer overflow: %"PRId64" messages skipped\n",
buffer->dropped),
};
buffer->dropped = 0;
} else {
res = log_buffer_read(buffer);
}
}
pthread_mutex_unlock(&mp_msg_lock);
return res;
}
// Thread-safety: fully thread-safe, but keep in mind that the lifetime of
+15 -9
View File
@@ -32,14 +32,15 @@ extern struct mp_log *const mp_null_log;
// Verbosity levels.
enum {
MSGL_FATAL, // will exit/abort (note: msg.c doesn't exit or abort)
MSGL_ERR, // continues
MSGL_WARN, // only warning
MSGL_INFO, // -quiet
MSGL_STATUS, // exclusively for the playback status line
MSGL_V, // -v
MSGL_DEBUG, // -v -v
MSGL_TRACE, // -v -v -v
MSGL_FATAL, // only errors (difference to MSGL_ERR isn't too clear)
MSGL_ERR, // only errors
MSGL_WARN, // only warnings
MSGL_INFO, // what you normally see on the terminal
MSGL_STATUS, // exclusively for the playback status line (-quiet disables)
MSGL_V, // -v | slightly more information than default
MSGL_DEBUG, // -v -v | full debug information; this and numerically below
// should not produce "per frame" output
MSGL_TRACE, // -v -v -v | anything that might flood the terminal
MSGL_STATS, // dumping fine grained stats (--dump-stats)
MSGL_MAX = MSGL_STATS,
@@ -52,7 +53,12 @@ void mp_msg(struct mp_log *log, int lev, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va);
bool mp_msg_test(struct mp_log *log, int lev);
int mp_msg_level(struct mp_log *log);
static inline bool mp_msg_test(struct mp_log *log, int lev)
{
return lev <= mp_msg_level(log);
}
// Convenience macros.
#define mp_fatal(log, ...) mp_msg(log, MSGL_FATAL, __VA_ARGS__)
+4 -1
View File
@@ -4,12 +4,14 @@
#include <stdbool.h>
struct mpv_global;
struct MPOpts;
void mp_msg_init(struct mpv_global *global);
void mp_msg_uninit(struct mpv_global *global);
void mp_msg_update_msglevels(struct mpv_global *global);
void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts);
void mp_msg_force_stderr(struct mpv_global *global, bool force_stderr);
bool mp_msg_has_status_line(struct mpv_global *global);
bool mp_msg_has_log_file(struct mpv_global *global);
void mp_msg_set_early_logging(struct mpv_global *global, bool enable);
void mp_msg_flush_status_line(struct mp_log *log);
@@ -29,6 +31,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
void *wakeup_cb_ctx);
void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer);
struct mp_log_buffer_entry *mp_msg_log_buffer_read(struct mp_log_buffer *buffer);
void mp_msg_log_buffer_set_silent(struct mp_log_buffer *buffer, bool silent);
int mp_msg_find_level(const char *s);
+9 -4
View File
@@ -32,6 +32,7 @@ struct playlist_entry *playlist_entry_new(const char *filename)
struct playlist_entry *e = talloc_zero(NULL, struct playlist_entry);
char *local_filename = mp_file_url_to_filename(e, bstr0(filename));
e->filename = local_filename ? local_filename : talloc_strdup(e, filename);
e->stream_flags = STREAM_ORIGIN_DIRECT;
return e;
}
@@ -275,13 +276,17 @@ struct playlist_entry *playlist_entry_from_index(struct playlist *pl, int index)
}
}
struct playlist *playlist_parse_file(const char *file, struct mpv_global *global)
struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel,
struct mpv_global *global)
{
struct mp_log *log = mp_log_new(NULL, global->log, "!playlist_parser");
mp_verbose(log, "Parsing playlist file %s...\n", file);
struct demuxer_params p = {.force_format = "playlist"};
struct demuxer *d = demux_open_url(file, &p, NULL, global);
struct demuxer_params p = {
.force_format = "playlist",
.stream_flags = STREAM_ORIGIN_DIRECT,
};
struct demuxer *d = demux_open_url(file, &p, cancel, global);
if (!d) {
talloc_free(log);
return NULL;
@@ -296,7 +301,7 @@ struct playlist *playlist_parse_file(const char *file, struct mpv_global *global
"pass it to the player\ndirectly. Don't use --playlist.\n");
}
}
free_demuxer_and_stream(d);
demux_free(d);
if (ret) {
mp_verbose(log, "Playlist successfully parsed\n");
+4 -7
View File
@@ -53,11 +53,8 @@ struct playlist_entry {
// Additional refcount. Normally (reserved==0), the entry is owned by the
// playlist, and this can be used to keep the entry alive.
int reserved;
// Any flags from STREAM_ORIGIN_FLAGS. 0 if unknown.
// Used to reject loading of unsafe entries from external playlists.
// Can have any of the following bit flags set:
// STREAM_SAFE_ONLY: only allow streams marked with is_safe
// STREAM_NETWORK_ONLY: only allow streams marked with is_network
// The value 0 allows everything.
int stream_flags;
};
@@ -69,8 +66,6 @@ struct playlist {
// current_was_replaced is set to true.
struct playlist_entry *current;
bool current_was_replaced;
bool disable_safety;
};
void playlist_entry_add_param(struct playlist_entry *e, bstr name, bstr value);
@@ -101,8 +96,10 @@ int playlist_entry_to_index(struct playlist *pl, struct playlist_entry *e);
int playlist_entry_count(struct playlist *pl);
struct playlist_entry *playlist_entry_from_index(struct playlist *pl, int index);
struct mp_cancel;
struct mpv_global;
struct playlist *playlist_parse_file(const char *file, struct mpv_global *global);
struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel,
struct mpv_global *global);
void playlist_entry_unref(struct playlist_entry *e);
+18 -16
View File
@@ -28,8 +28,6 @@
#include "recorder.h"
#define PTS_ADD(a, b) ((a) == MP_NOPTS_VALUE ? (a) : ((a) + (b)))
// Maximum number of packets we buffer at most to attempt to resync streams.
// Essentially, this should be higher than the highest supported keyframe
// interval.
@@ -198,10 +196,10 @@ static void mux_packet(struct mp_recorder_sink *rst,
struct demux_packet mpkt = *pkt;
double diff = priv->rebase_ts - priv->base_ts;
mpkt.pts = PTS_ADD(mpkt.pts, diff);
mpkt.dts = PTS_ADD(mpkt.dts, diff);
mpkt.pts = MP_ADD_PTS(mpkt.pts, diff);
mpkt.dts = MP_ADD_PTS(mpkt.dts, diff);
rst->max_out_pts = MPMAX(rst->max_out_pts, pkt->pts);
rst->max_out_pts = MP_PTS_MAX(rst->max_out_pts, pkt->pts);
AVPacket avpkt;
mp_set_av_packet(&avpkt, &mpkt, &rst->av_stream->time_base);
@@ -254,13 +252,13 @@ static void check_restart(struct mp_recorder *priv)
if (priv->muxing)
return;
double min_ts = INFINITY;
double min_ts = MP_NOPTS_VALUE;
double rebase_ts = 0;
for (int n = 0; n < priv->num_streams; n++) {
struct mp_recorder_sink *rst = priv->streams[n];
int min_packets = rst->sh->type == STREAM_VIDEO ? QUEUE_MIN_PACKETS : 1;
rebase_ts = MPMAX(rebase_ts, rst->max_out_pts);
rebase_ts = MP_PTS_MAX(rebase_ts, rst->max_out_pts);
if (rst->num_packets < min_packets) {
if (!rst->proper_eof && rst->sh->type != STREAM_SUB)
@@ -269,11 +267,11 @@ static void check_restart(struct mp_recorder *priv)
}
for (int i = 0; i < min_packets; i++)
min_ts = MPMIN(min_ts, rst->packets[i]->pts);
min_ts = MP_PTS_MIN(min_ts, rst->packets[i]->pts);
}
// Subtitle only stream (wait longer) or stream without any PTS (fuck it).
if (!isfinite(min_ts))
if (min_ts == MP_NOPTS_VALUE)
return;
priv->rebase_ts = rebase_ts;
@@ -295,8 +293,6 @@ void mp_recorder_destroy(struct mp_recorder *priv)
if (priv->opened) {
for (int n = 0; n < priv->num_streams; n++) {
struct mp_recorder_sink *rst = priv->streams[n];
if (!rst->proper_eof)
continue;
mux_packets(rst, true);
}
@@ -322,6 +318,7 @@ void mp_recorder_mark_discontinuity(struct mp_recorder *priv)
for (int n = 0; n < priv->num_streams; n++) {
struct mp_recorder_sink *rst = priv->streams[n];
mux_packets(rst, true);
rst->discont = true;
rst->proper_eof = false;
}
@@ -331,12 +328,17 @@ void mp_recorder_mark_discontinuity(struct mp_recorder *priv)
}
// Get a stream for writing. The pointer is valid until mp_recorder is
// destroyed. The stream is the index referencing the stream passed to
// mp_recorder_create().
struct mp_recorder_sink *mp_recorder_get_sink(struct mp_recorder *r, int stream)
// destroyed. The stream ptr. is the same as one passed to
// mp_recorder_create() (returns NULL if it wasn't).
struct mp_recorder_sink *mp_recorder_get_sink(struct mp_recorder *r,
struct sh_stream *stream)
{
assert(stream >= 0 && stream < r->num_streams);
return r->streams[stream];
for (int n = 0; n < r->num_streams; n++) {
struct mp_recorder_sink *rst = r->streams[n];
if (rst->sh == stream)
return rst;
}
return NULL;
}
// Pass a packet to the given stream. The function does not own the packet, but
+2 -1
View File
@@ -14,7 +14,8 @@ struct mp_recorder *mp_recorder_create(struct mpv_global *global,
void mp_recorder_destroy(struct mp_recorder *r);
void mp_recorder_mark_discontinuity(struct mp_recorder *r);
struct mp_recorder_sink *mp_recorder_get_sink(struct mp_recorder *r, int stream);
struct mp_recorder_sink *mp_recorder_get_sink(struct mp_recorder *r,
struct sh_stream *stream);
void mp_recorder_feed_packet(struct mp_recorder_sink *s,
struct demux_packet *pkt);
+323
View File
@@ -0,0 +1,323 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "cache.h"
#include "common/msg.h"
#include "common/av_common.h"
#include "demux.h"
#include "options/path.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "osdep/io.h"
struct demux_cache_opts {
char *cache_dir;
int unlink_files;
};
#define OPT_BASE_STRUCT struct demux_cache_opts
const struct m_sub_options demux_cache_conf = {
.opts = (const struct m_option[]){
OPT_STRING("cache-dir", cache_dir, M_OPT_FILE),
OPT_CHOICE("cache-unlink-files", unlink_files, 0,
({"immediate", 2}, {"whendone", 1}, {"no", 0})),
{0}
},
.size = sizeof(struct demux_cache_opts),
.defaults = &(const struct demux_cache_opts){
.unlink_files = 2,
},
};
struct demux_cache {
struct mp_log *log;
struct demux_cache_opts *opts;
char *filename;
bool need_unlink;
int fd;
int64_t file_pos;
uint64_t file_size;
};
struct pkt_header {
uint32_t data_len;
uint32_t av_flags;
uint32_t num_sd;
};
struct sd_header {
uint32_t av_type;
uint32_t len;
};
static void cache_destroy(void *p)
{
struct demux_cache *cache = p;
if (cache->fd >= 0)
close(cache->fd);
if (cache->need_unlink && cache->opts->unlink_files >= 1) {
if (unlink(cache->filename))
MP_ERR(cache, "Failed to delete cache temporary file.\n");
}
}
// Create a cache. This also initializes the cache file from the options. The
// log parameter must stay valid until demux_cache is destroyed.
// Free with talloc_free().
struct demux_cache *demux_cache_create(struct mpv_global *global,
struct mp_log *log)
{
struct demux_cache *cache = talloc_zero(NULL, struct demux_cache);
talloc_set_destructor(cache, cache_destroy);
cache->opts = mp_get_config_group(cache, global, &demux_cache_conf);
cache->log = log;
cache->fd = -1;
char *cache_dir = cache->opts->cache_dir;
if (!(cache_dir && cache_dir[0])) {
MP_ERR(cache, "No cache data directory supplied.\n");
goto fail;
}
cache->filename = mp_path_join(cache, cache_dir, "mpv-cache-XXXXXX.dat");
cache->fd = mp_mkostemps(cache->filename, 4, O_CLOEXEC);
if (cache->fd < 0) {
MP_ERR(cache, "Failed to create cache temporary file.\n");
goto fail;
}
cache->need_unlink = true;
if (cache->opts->unlink_files >= 2) {
if (unlink(cache->filename)) {
MP_ERR(cache, "Failed to unlink cache temporary file after creation.\n");
} else {
cache->need_unlink = false;
}
}
return cache;
fail:
talloc_free(cache);
return NULL;
}
uint64_t demux_cache_get_size(struct demux_cache *cache)
{
return cache->file_size;
}
static bool do_seek(struct demux_cache *cache, uint64_t pos)
{
if (cache->file_pos == pos)
return true;
off_t res = lseek(cache->fd, pos, SEEK_SET);
if (res == (off_t)-1) {
MP_ERR(cache, "Failed to seek in cache file.\n");
cache->file_pos = -1;
} else {
cache->file_pos = res;
}
return cache->file_pos >= 0;
}
static bool write_raw(struct demux_cache *cache, void *ptr, size_t len)
{
ssize_t res = write(cache->fd, ptr, len);
if (res < 0) {
MP_ERR(cache, "Failed to write to cache file: %s\n", mp_strerror(errno));
return false;
}
cache->file_pos += res;
cache->file_size = MPMAX(cache->file_size, cache->file_pos);
// Should never happen, unless the disk is full, or someone succeeded to
// trick us to write into a pipe or a socket.
if (res != len) {
MP_ERR(cache, "Could not write all data.\n");
return false;
}
return true;
}
static bool read_raw(struct demux_cache *cache, void *ptr, size_t len)
{
ssize_t res = read(cache->fd, ptr, len);
if (res < 0) {
MP_ERR(cache, "Failed to read cache file: %s\n", mp_strerror(errno));
return false;
}
cache->file_pos += res;
// Should never happen, unless the file was cut short, or someone succeeded
// to rick us to write into a pipe or a socket.
if (res != len) {
MP_ERR(cache, "Could not read all data.\n");
return false;
}
return true;
}
// Serialize a packet to the cache file. Returns the packet position, which can
// be passed to demux_cache_read() to read the packet again.
// Returns a negative value on errors, i.e. writing the file failed.
int64_t demux_cache_write(struct demux_cache *cache, struct demux_packet *dp)
{
assert(dp->avpacket);
// AV_PKT_FLAG_TRUSTED usually means there are embedded pointers and such
// in the packet data. The pointer will become invalid if the packet is
// unreferenced.
if (dp->avpacket->flags & AV_PKT_FLAG_TRUSTED) {
MP_ERR(cache, "Cannot serialize this packet to cache file.\n");
return -1;
}
assert(!dp->is_cached);
assert(dp->len >= 0 && dp->len <= INT32_MAX);
assert(dp->avpacket->flags >= 0 && dp->avpacket->flags <= INT32_MAX);
assert(dp->avpacket->side_data_elems >= 0 &&
dp->avpacket->side_data_elems <= INT32_MAX);
if (!do_seek(cache, cache->file_size))
return -1;
uint64_t pos = cache->file_pos;
struct pkt_header hd = {
.data_len = dp->len,
.av_flags = dp->avpacket->flags,
.num_sd = dp->avpacket->side_data_elems,
};
if (!write_raw(cache, &hd, sizeof(hd)))
goto fail;
if (!write_raw(cache, dp->buffer, dp->len))
goto fail;
// The handling of FFmpeg side data requires an extra long comment to
// explain why this code is fragile and insane.
// FFmpeg packet side data is per-packet out of band data, that contains
// further information for the decoder (extra metadata and such), which is
// not part of the codec itself and thus isn't contained in the packet
// payload. All types use a flat byte array. The format of this byte array
// is non-standard and FFmpeg-specific, and depends on the side data type
// field. The side data type is of course a FFmpeg ABI artifact.
// In some cases, the format is described as fixed byte layout. In others,
// it contains a struct, i.e. is bound to FFmpeg ABI. Some newer types make
// the format explicitly internal (and _not_ part of the ABI), and you need
// to use separate accessors to turn it into complex data structures.
// As of now, FFmpeg fortunately adheres to the idea that side data can not
// contain embedded pointers (due to API rules, but also because they forgot
// adding a refcount field, and can't change this until they break ABI).
// We rely on this. We hope that FFmpeg won't silently change their
// semantics, and add refcounting and embedded pointers. This way we can
// for example dump the data in a disk cache, even though we can't use the
// data from another process or if this process is restarted (unless we're
// absolutely sure the FFmpeg internals didn't change). The data has to be
// treated as a memory dump.
for (int n = 0; n < dp->avpacket->side_data_elems; n++) {
AVPacketSideData *sd = &dp->avpacket->side_data[n];
assert(sd->size >= 0 && sd->size <= INT32_MAX);
assert(sd->type >= 0 && sd->type <= INT32_MAX);
struct sd_header sd_hd = {
.av_type = sd->type,
.len = sd->size,
};
if (!write_raw(cache, &sd_hd, sizeof(sd_hd)))
goto fail;
if (!write_raw(cache, sd->data, sd->size))
goto fail;
}
return pos;
fail:
// Reset file_size (try not to append crap forever).
do_seek(cache, pos);
cache->file_size = cache->file_pos;
return -1;
}
struct demux_packet *demux_cache_read(struct demux_cache *cache, uint64_t pos)
{
if (!do_seek(cache, pos))
return NULL;
struct pkt_header hd;
if (!read_raw(cache, &hd, sizeof(hd)))
return NULL;
if (hd.data_len >= (size_t)-1)
return NULL;
struct demux_packet *dp = new_demux_packet(hd.data_len);
if (!dp)
goto fail;
if (!read_raw(cache, dp->buffer, dp->len))
goto fail;
dp->avpacket->flags = hd.av_flags;
for (uint32_t n = 0; n < hd.num_sd; n++) {
struct sd_header sd_hd;
if (!read_raw(cache, &sd_hd, sizeof(sd_hd)))
goto fail;
if (sd_hd.len > INT_MAX)
goto fail;
uint8_t *sd = av_packet_new_side_data(dp->avpacket, sd_hd.av_type,
sd_hd.len);
if (!sd)
goto fail;
if (!read_raw(cache, sd, sd_hd.len))
goto fail;
}
return dp;
fail:
talloc_free(dp);
return NULL;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
struct demux_packet;
struct mp_log;
struct mpv_global;
struct demux_cache;
struct demux_cache *demux_cache_create(struct mpv_global *global,
struct mp_log *log);
int64_t demux_cache_write(struct demux_cache *cache, struct demux_packet *pkt);
struct demux_packet *demux_cache_read(struct demux_cache *cache, uint64_t pos);
uint64_t demux_cache_get_size(struct demux_cache *cache);
+4 -14
View File
@@ -50,14 +50,8 @@ static const char *lookup_tag(int type, uint32_t tag)
return id == AV_CODEC_ID_NONE ? NULL : mp_codec_from_av_codec_id(id);
}
static const unsigned char guid_pcm[16] =
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
static const unsigned char guid_float[16] =
{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
// Corresponds to FF_MEDIASUBTYPE_BASE_GUID (plus 4 bytes of padding).
static const unsigned char guid_ffext[16] =
// Corresponds to WMMEDIASUBTYPE_Base.
static const unsigned char guid_ext_base[16] =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71};
@@ -74,18 +68,14 @@ static void map_audio_pcm_tag(struct mp_codec_params *c)
// WAVEFORMATEXTENSIBLE.SubFormat
unsigned char *subformat = c->extradata + 6;
if (memcmp(subformat + 4, guid_ffext + 4, 12) == 0) {
if (memcmp(subformat + 4, guid_ext_base + 4, 12) == 0) {
c->codec_tag = AV_RL32(subformat);
c->codec = lookup_tag(c->type, c->codec_tag);
}
if (memcmp(subformat, guid_pcm, 16) == 0)
c->codec_tag = 0x0;
if (memcmp(subformat, guid_float, 16) == 0)
c->codec_tag = 0x3;
// Compressed formats might use this.
c->extradata += 22;
c->extradata_size += 22;
c->extradata_size -= 22;
}
int bits = c->bits_per_coded_sample;
+8 -7
View File
@@ -113,16 +113,17 @@ static struct bstr strip_quotes(struct bstr data)
return data;
}
// Read a 2 digit unsigned decimal integer.
// Read an unsigned decimal integer.
// Optionally check if it is 2 digit.
// Return -1 on failure.
static int read_int_2(struct bstr *data)
static int read_int(struct bstr *data, bool two_digit)
{
*data = bstr_lstrip(*data);
if (data->len && data->start[0] == '-')
return -1;
struct bstr s = *data;
int res = (int)bstrtoll(s, &s, 10);
if (data->len == s.len || data->len - s.len > 2)
if (data->len == s.len || (two_digit && data->len - s.len > 2))
return -1;
*data = s;
return res;
@@ -132,11 +133,11 @@ static double read_time(struct bstr *data)
{
struct bstr s = *data;
bool ok = true;
double t1 = read_int_2(&s);
double t1 = read_int(&s, false);
ok = eat_char(&s, ':') && ok;
double t2 = read_int_2(&s);
double t2 = read_int(&s, true);
ok = eat_char(&s, ':') && ok;
double t3 = read_int_2(&s);
double t3 = read_int(&s, true);
ok = ok && t1 >= 0 && t2 >= 0 && t3 >= 0;
return ok ? t1 * 60.0 + t2 + t3 * SECS_PER_CUE_FRAME : 0;
}
@@ -205,7 +206,7 @@ struct cue_file *mp_parse_cue(struct bstr data)
break;
}
case CUE_INDEX: {
int type = read_int_2(&param);
int type = read_int(&param, true);
double time = read_time(&param);
if (cur_track) {
if (type == 1) {
+2347 -990
View File
File diff suppressed because it is too large. Load diff
Loaded 100 of 470 files, more files were not shown because too many files have changed in this diff. Show more